From 0329642ba5438db854c82b8a77486bf2a5af1113 Mon Sep 17 00:00:00 2001 From: Sruthi Chandran Date: Sat, 2 Mar 2019 22:35:43 +0530 Subject: [PATCH] New upstream version 11.8.0 --- .babelrc.js | 1 + .gitignore | 1 + .gitlab-ci.yml | 141 +- .../issue_templates/Coding style proposal.md | 16 + .gitlab/issue_templates/Feature proposal.md | 31 +- .gitlab/issue_templates/Security Release.md | 69 + .../Security developer workflow.md | 22 +- .../Security Release.md | 31 + .rubocop.yml | 1 + .rubocop_todo.yml | 27 - CHANGELOG.md | 322 +- GITALY_SERVER_VERSION | 2 +- GITLAB_PAGES_VERSION | 2 +- GITLAB_WORKHORSE_VERSION | 2 +- Gemfile | 25 +- Gemfile.lock | 84 +- PROCESS.md | 2 +- VERSION | 2 +- app/assets/javascripts/api.js | 7 + app/assets/javascripts/awards_handler.js | 2 +- .../badges/components/badge_list_row.vue | 4 +- app/assets/javascripts/behaviors/gl_emoji.js | 21 +- .../behaviors/markdown/copy_as_gfm.js | 439 +- .../behaviors/markdown/editor_extensions.js | 106 + .../behaviors/markdown/marks/bold.js | 11 + .../behaviors/markdown/marks/code.js | 11 + .../behaviors/markdown/marks/inline_diff.js | 41 + .../behaviors/markdown/marks/inline_html.js | 46 + .../behaviors/markdown/marks/italic.js | 11 + .../behaviors/markdown/marks/link.js | 21 + .../behaviors/markdown/marks/math.js | 41 + .../behaviors/markdown/marks/strike.js | 15 + .../behaviors/markdown/nodes/blockquote.js | 13 + .../behaviors/markdown/nodes/bullet_list.js | 11 + .../behaviors/markdown/nodes/code_block.js | 99 + .../markdown/nodes/description_details.js | 28 + .../markdown/nodes/description_list.js | 28 + .../markdown/nodes/description_term.js | 28 + .../behaviors/markdown/nodes/details.js | 28 + .../behaviors/markdown/nodes/doc.js | 15 + .../behaviors/markdown/nodes/emoji.js | 41 + .../behaviors/markdown/nodes/hard_break.js | 10 + .../behaviors/markdown/nodes/heading.js | 13 + .../markdown/nodes/horizontal_rule.js | 11 + .../behaviors/markdown/nodes/image.js | 52 + .../behaviors/markdown/nodes/list_item.js | 11 + .../behaviors/markdown/nodes/ordered_list.js | 10 + .../markdown/nodes/ordered_task_list.js | 28 + .../behaviors/markdown/nodes/paragraph.js | 24 + .../behaviors/markdown/nodes/reference.js | 52 + .../behaviors/markdown/nodes/summary.js | 27 + .../behaviors/markdown/nodes/table.js | 25 + .../behaviors/markdown/nodes/table_body.js | 24 + .../behaviors/markdown/nodes/table_cell.js | 35 + .../behaviors/markdown/nodes/table_head.js | 24 + .../markdown/nodes/table_header_row.js | 43 + .../markdown/nodes/table_of_contents.js | 33 + .../behaviors/markdown/nodes/table_row.js | 38 + .../behaviors/markdown/nodes/task_list.js | 28 + .../markdown/nodes/task_list_item.js | 49 + .../behaviors/markdown/nodes/text.js | 20 + .../behaviors/markdown/nodes/video.js | 54 + .../javascripts/behaviors/markdown/schema.js | 24 + .../behaviors/markdown/serializer.js | 24 + .../javascripts/behaviors/preview_markdown.js | 15 +- .../behaviors/shortcuts/shortcuts_issuable.js | 41 +- .../boards/components/board_card.vue | 2 +- .../boards/components/board_new_issue.vue | 2 +- .../boards/components/issue_card_inner.vue | 2 +- .../boards/components/modal/empty_state.vue | 2 +- .../boards/components/modal/footer.vue | 2 +- .../boards/components/modal/header.vue | 2 +- .../boards/components/modal/list.vue | 2 +- .../components/modal/lists_dropdown.vue | 2 +- .../boards/components/modal/tabs.vue | 4 +- .../boards/components/project_select.vue | 2 +- .../javascripts/clusters/clusters_bundle.js | 53 +- .../clusters/components/application_row.vue | 192 +- .../clusters/components/applications.vue | 3 + app/assets/javascripts/clusters/constants.js | 9 +- .../clusters/stores/clusters_store.js | 16 +- app/assets/javascripts/commons/jquery.js | 1 - app/assets/javascripts/contextual_sidebar.js | 24 +- .../deploy_keys/components/key.vue | 2 +- .../javascripts/diffs/components/app.vue | 4 + .../diffs/components/compare_versions.vue | 83 +- .../components/compare_versions_dropdown.vue | 16 +- .../diffs/components/diff_content.vue | 2 +- .../diffs/components/diff_discussions.vue | 2 +- .../diffs/components/diff_file_header.vue | 5 +- .../components/diff_line_gutter_content.vue | 2 +- .../diffs/components/diff_line_note_form.vue | 6 + .../diffs/components/diff_stats.vue | 52 + .../diffs/components/image_diff_overlay.vue | 4 +- .../components/inline_diff_comment_row.vue | 1 + .../components/parallel_diff_comment_row.vue | 1 + .../diffs/components/settings_dropdown.vue | 92 + .../diffs/components/tree_list.vue | 153 +- app/assets/javascripts/diffs/constants.js | 4 + app/assets/javascripts/diffs/index.js | 64 +- app/assets/javascripts/diffs/store/actions.js | 39 +- app/assets/javascripts/diffs/store/getters.js | 20 +- .../diffs/store/modules/diff_state.js | 5 + .../javascripts/diffs/store/mutation_types.js | 5 + .../javascripts/diffs/store/mutations.js | 18 +- app/assets/javascripts/diffs/store/utils.js | 75 +- .../javascripts/diffs/workers/tree_worker.js | 14 + .../dirty_submit/dirty_submit_form.js | 7 +- app/assets/javascripts/due_date_select.js | 2 + .../environments/components/container.vue | 10 +- .../components/environment_actions.vue | 2 +- .../components/environment_item.vue | 10 +- .../components/environments_app.vue | 11 +- .../components/environments_table.vue | 14 +- .../folder/environments_folder_bundle.js | 8 +- .../folder/environments_folder_view.vue | 5 - app/assets/javascripts/environments/index.js | 2 - .../environments/mixins/environments_mixin.js | 2 +- .../services/environments_service.js | 4 +- .../environments/stores/environments_store.js | 3 +- .../feature_highlight/feature_highlight.js | 4 +- .../recent_searches_dropdown_content.vue | 4 +- .../filtered_search_manager.js | 2 +- .../filtered_search_token_keys.js | 6 +- .../filtered_search_visual_tokens.js | 2 +- .../issuable_filtered_search_token_keys.js | 22 +- app/assets/javascripts/fly_out_nav.js | 5 +- .../frequent_items/components/app.vue | 6 + .../javascripts/frequent_items/index.js | 6 +- app/assets/javascripts/groups_select.js | 174 +- app/assets/javascripts/header.js | 6 +- .../ide/components/activity_bar.vue | 6 +- .../ide/components/commit_sidebar/list.vue | 2 +- .../commit_sidebar/message_field.vue | 4 +- .../components/commit_sidebar/radio_group.vue | 4 +- .../commit_sidebar/stage_button.vue | 6 +- .../commit_sidebar/unstage_button.vue | 2 +- .../ide/components/editor_mode_dropdown.vue | 4 +- .../components/file_templates/dropdown.vue | 2 +- app/assets/javascripts/ide/components/ide.vue | 46 +- .../ide/components/ide_status_bar.vue | 15 +- .../javascripts/ide/components/ide_tree.vue | 4 +- .../ide/components/jobs/detail.vue | 2 +- .../ide/components/merge_requests/list.vue | 4 +- .../ide/components/new_dropdown/index.vue | 10 +- .../ide/components/new_dropdown/modal.vue | 2 +- .../ide/components/panes/right.vue | 2 +- .../ide/components/repo_editor.vue | 4 +- .../javascripts/ide/components/repo_tab.vue | 4 +- .../ide/components/resizable_panel.vue | 4 +- .../ide/components/shared/tokened_input.vue | 4 +- app/assets/javascripts/ide/constants.js | 5 - app/assets/javascripts/ide/ide_router.js | 2 +- app/assets/javascripts/ide/index.js | 20 +- .../javascripts/ide/lib/common/model.js | 6 +- .../ide/stores/modules/commit/actions.js | 2 +- .../issuable/auto_width_dropdown_select.js | 12 +- app/assets/javascripts/issuable_context.js | 12 +- app/assets/javascripts/issuable_form.js | 61 +- .../javascripts/issue_show/components/app.vue | 62 +- .../issue_show/components/description.vue | 24 + .../components/fields/description.vue | 6 - .../issue_show/components/form.vue | 6 - .../javascripts/issue_show/stores/index.js | 11 +- .../jobs/components/commit_block.vue | 2 +- .../javascripts/jobs/components/job_app.vue | 11 +- .../javascripts/jobs/components/sidebar.vue | 70 +- .../jobs/components/stages_dropdown.vue | 6 +- app/assets/javascripts/jobs/store/getters.js | 16 - app/assets/javascripts/label_manager.js | 13 +- app/assets/javascripts/layout_nav.js | 65 +- app/assets/javascripts/lazy_loader.js | 1 + .../javascripts/lib/utils/common_utils.js | 68 +- .../javascripts/lib/utils/datetime_utility.js | 160 +- .../javascripts/lib/utils/file_upload.js | 3 + app/assets/javascripts/lib/utils/grammar.js | 40 + .../javascripts/lib/utils/icon_utils.js | 18 + .../javascripts/lib/utils/text_utility.js | 23 + .../javascripts/lib/utils/url_utility.js | 53 +- app/assets/javascripts/lib/utils/webpack.js | 10 + app/assets/javascripts/locale/sprintf.js | 4 +- app/assets/javascripts/main.js | 142 +- .../javascripts/member_expiration_date.js | 1 + app/assets/javascripts/merge_request.js | 9 + app/assets/javascripts/merge_request_tabs.js | 2 +- .../monitoring/components/charts/area.vue | 153 +- .../monitoring/components/dashboard.vue | 89 +- .../monitoring/components/graph.vue | 329 - .../monitoring/components/graph/axis.vue | 118 - .../components/graph/deployment.vue | 48 - .../monitoring/components/graph/flag.vue | 151 - .../monitoring/components/graph/legend.vue | 62 - .../monitoring/components/graph/path.vue | 65 - .../components/graph/track_info.vue | 28 - .../components/graph/track_line.vue | 33 - .../javascripts/monitoring/event_hub.js | 3 - .../monitoring/mixins/monitoring_mixins.js | 86 - .../monitoring/stores/monitoring_store.js | 14 +- .../monitoring/utils/date_time_formatters.js | 42 - .../monitoring/utils/measurements.js | 44 - .../monitoring/utils/multiple_time_series.js | 223 - app/assets/javascripts/mr_notes/index.js | 3 + .../javascripts/notebook/cells/code.vue | 15 +- .../javascripts/notebook/cells/code/index.vue | 3 +- .../notebook/cells/output/html.vue | 15 +- .../notebook/cells/output/image.vue | 20 +- .../notebook/cells/output/index.vue | 106 +- .../javascripts/notebook/cells/prompt.vue | 10 +- app/assets/javascripts/notebook/index.vue | 4 +- app/assets/javascripts/notes.js | 4 +- .../notes/components/comment_form.vue | 24 +- .../notes/components/diff_with_note.vue | 7 +- .../notes/components/discussion_filter.vue | 25 +- .../discussion_jump_to_next_button.vue | 28 + .../discussion_reply_placeholder.vue | 17 + .../components/discussion_resolve_button.vue | 28 + .../notes/components/note_actions.vue | 29 +- .../components/note_actions/reply_button.vue | 40 + .../notes/components/note_awards_list.vue | 12 +- .../notes/components/note_body.vue | 2 +- .../notes/components/note_form.vue | 23 +- .../notes/components/noteable_discussion.vue | 63 +- .../notes/components/noteable_note.vue | 55 +- .../notes/components/notes_app.vue | 18 +- app/assets/javascripts/notes/index.js | 3 - .../javascripts/notes/stores/actions.js | 3 + .../notes/stores/mutation_types.js | 1 + .../javascripts/notes/stores/mutations.js | 12 +- app/assets/javascripts/notes/stores/utils.js | 4 + .../admin/application_settings/show/index.js | 3 + app/assets/javascripts/pages/admin/index.js | 6 +- .../pages/dashboard/projects/index.js | 2 - .../pages/explore/projects/index.js | 4 +- .../groups/clusters/{update => edit}/index.js | 0 .../javascripts/pages/profiles/show/index.js | 12 + .../clusters/{update => edit}/index.js | 0 .../projects/environments/metrics/index.js | 2 +- .../pages/projects/graphs/charts/index.js | 18 +- .../components/interval_pattern_input.vue | 8 +- .../javascripts/pages/sessions/new/index.js | 5 + .../pages/sessions/new/oauth_remember_me.js | 5 +- .../sessions/new/preserve_url_fragment.js | 32 + .../pages/users/activity_calendar.js | 10 +- .../pages/users/user_overview_block.js | 5 +- .../javascripts/pages/users/user_tabs.js | 2 +- .../components/graph/graph_component.vue | 45 +- .../pipelines/components/graph/job_item.vue | 2 +- .../components/pipelines_actions.vue | 2 +- .../pipelines/components/stage.vue | 2 - .../pipelines/mixins/graph_component_mixin.js | 44 + app/assets/javascripts/project_select.js | 178 +- .../project_select_combo_button.js | 10 +- .../components/gke_machine_type_dropdown.vue | 4 +- .../components/gke_project_id_dropdown.vue | 2 +- .../components/gke_zone_dropdown.vue | 4 +- .../javascripts/projects/project_new.js | 26 +- .../registry/components/table_registry.vue | 8 +- .../javascripts/releases/components/app.vue | 6 +- .../releases/components/release_block.vue | 2 +- .../reports/components/modal_open_name.vue | 2 +- .../reports/components/test_issue_body.vue | 2 +- .../serverless/components/environment_row.vue | 65 + .../components/function_details.vue | 56 + .../serverless/components/function_row.vue | 48 +- .../serverless/components/functions.vue | 56 +- .../serverless/components/pod_box.vue | 36 + .../javascripts/serverless/components/url.vue | 38 + .../serverless/serverless_bundle.js | 67 +- .../stores/serverless_details_store.js | 11 + .../serverless/stores/serverless_store.js | 11 +- .../set_status_modal_wrapper.vue | 2 +- .../components/lock/lock_issue_sidebar.vue | 4 +- .../components/time_tracking/time_tracker.vue | 4 +- app/assets/javascripts/task_list.js | 72 +- app/assets/javascripts/terminal/terminal.js | 3 + app/assets/javascripts/users_select.js | 188 +- .../source_branch_removal_status.vue | 2 +- .../components/states/commit_edit.vue | 40 + .../states/commit_message_dropdown.vue | 38 + .../components/states/commits_header.vue | 91 + .../components/states/mr_widget_conflicts.vue | 70 +- ...mr_widget_merge_when_pipeline_succeeds.vue | 6 +- .../components/states/mr_widget_merged.vue | 10 +- .../components/states/ready_to_merge.vue | 291 +- .../components/states/squash_before_merge.vue | 34 +- .../ee_switch_mr_widget_options.js | 3 - .../vue_merge_request_widget/index.js | 2 +- .../mr_widget_options.vue | 18 +- .../services/ee_switch_mr_widget_service.js | 3 - .../stores/ee_switch_get_state_key.js | 3 - .../stores/ee_switch_mr_widget_store.js | 3 - .../stores/ee_switch_state_maps.js | 3 - .../stores/get_state_key.js | 4 +- .../stores/mr_widget_store.js | 10 +- .../vue_shared/components/bar_chart.vue | 4 +- .../components/deprecated_modal.vue | 6 +- .../diff_viewer/viewers/image_diff_viewer.vue | 6 +- .../components/file_finder/index.vue | 140 +- .../components/file_finder/item.vue | 26 +- .../vue_shared/components/file_row.vue | 48 +- .../vue_shared/components/file_row_header.vue | 25 + .../components/filtered_search_dropdown.vue | 34 +- .../vue_shared/components/gl_modal.vue | 6 +- .../components/header_ci_component.vue | 2 +- .../vue_shared/components/markdown/field.vue | 20 +- .../vue_shared/components/markdown/header.vue | 9 +- .../components/markdown/suggestion_diff.vue | 2 +- .../markdown/suggestion_diff_header.vue | 2 +- .../components/markdown/suggestions.vue | 2 +- .../vue_shared/components/navigation_tabs.vue | 2 +- .../components/notes/system_note.vue | 2 +- .../vue_shared/components/pikaday.vue | 1 + .../vue_shared/components/recaptcha_modal.vue | 2 +- .../components/sidebar/date_picker.vue | 2 +- .../components/table_pagination.vue | 2 +- .../user_avatar/user_avatar_image.vue | 3 +- .../user_avatar/user_avatar_list.vue | 8 +- .../vuex_shared/modules/modal/actions.js | 3 + .../stylesheets/bootstrap_migration.scss | 2 +- .../components/related_items_list.scss | 381 + .../stylesheets/framework/animations.scss | 10 +- app/assets/stylesheets/framework/awards.scss | 2 +- app/assets/stylesheets/framework/buttons.scss | 6 +- app/assets/stylesheets/framework/common.scss | 36 +- .../stylesheets/framework/dropdowns.scss | 6 +- app/assets/stylesheets/framework/files.scss | 20 +- app/assets/stylesheets/framework/forms.scss | 2 +- .../stylesheets/framework/gitlab_theme.scss | 40 +- app/assets/stylesheets/framework/header.scss | 4 + app/assets/stylesheets/framework/icons.scss | 4 +- app/assets/stylesheets/framework/images.scss | 3 + .../stylesheets/framework/markdown_area.scss | 4 +- app/assets/stylesheets/framework/mixins.scss | 4 - .../framework/responsive_tables.scss | 2 +- .../framework/stacked_progress_bar.scss | 8 +- .../stylesheets/framework/typography.scss | 3 +- .../stylesheets/framework/variables.scss | 41 +- .../framework/variables_overrides.scss | 13 +- app/assets/stylesheets/highlight/none.scss | 28 +- app/assets/stylesheets/page_bundles/ide.scss | 53 +- app/assets/stylesheets/pages/boards.scss | 30 +- app/assets/stylesheets/pages/builds.scss | 30 +- app/assets/stylesheets/pages/clusters.scss | 14 + app/assets/stylesheets/pages/diff.scss | 67 +- .../stylesheets/pages/environments.scss | 24 +- app/assets/stylesheets/pages/graph.scss | 6 +- app/assets/stylesheets/pages/groups.scss | 110 +- app/assets/stylesheets/pages/issuable.scss | 2 +- app/assets/stylesheets/pages/issues.scss | 14 +- .../pages/issues/issue_count_badge.scss | 6 +- app/assets/stylesheets/pages/labels.scss | 10 +- .../stylesheets/pages/merge_requests.scss | 85 +- app/assets/stylesheets/pages/milestone.scss | 2 +- app/assets/stylesheets/pages/note_form.scss | 10 +- app/assets/stylesheets/pages/notes.scss | 2 +- app/assets/stylesheets/pages/pipelines.scss | 118 +- app/assets/stylesheets/pages/profile.scss | 10 + .../pages/profiles/preferences.scss | 4 +- app/assets/stylesheets/pages/projects.scss | 189 +- app/assets/stylesheets/pages/reports.scss | 2 +- app/assets/stylesheets/pages/serverless.scss | 3 + app/assets/stylesheets/pages/settings.scss | 4 +- app/controllers/application_controller.rb | 8 +- .../clusters/clusters_controller.rb | 2 + app/controllers/concerns/boards_responses.rb | 10 +- app/controllers/concerns/issuable_actions.rb | 6 +- .../concerns/issuable_collections.rb | 4 +- ...tion.rb => issuable_collections_action.rb} | 33 +- .../concerns/merge_requests_action.rb | 25 - app/controllers/concerns/preview_markdown.rb | 2 - .../concerns/record_user_last_activity.rb | 27 + app/controllers/concerns/send_file_upload.rb | 19 +- app/controllers/concerns/service_params.rb | 2 +- app/controllers/concerns/uploads_actions.rb | 12 +- .../dashboard/application_controller.rb | 1 + .../dashboard/milestones_controller.rb | 6 +- .../dashboard/projects_controller.rb | 3 + app/controllers/dashboard_controller.rb | 3 +- .../explore/projects_controller.rb | 9 +- app/controllers/groups/boards_controller.rb | 1 + app/controllers/groups/children_controller.rb | 2 +- .../groups/milestones_controller.rb | 2 +- app/controllers/groups_controller.rb | 4 +- app/controllers/import/base_controller.rb | 2 + .../import/bitbucket_server_controller.rb | 11 +- app/controllers/import/github_controller.rb | 31 +- .../notification_settings_controller.rb | 7 +- .../omniauth_callbacks_controller.rb | 21 +- app/controllers/passwords_controller.rb | 2 +- .../profiles/preferences_controller.rb | 12 +- .../projects/artifacts_controller.rb | 9 +- app/controllers/projects/badges_controller.rb | 13 +- app/controllers/projects/blob_controller.rb | 2 +- .../projects/build_artifacts_controller.rb | 9 +- app/controllers/projects/commit_controller.rb | 4 +- .../projects/discussions_controller.rb | 2 +- .../projects/environments_controller.rb | 40 +- .../projects/error_tracking_controller.rb | 40 + app/controllers/projects/issues_controller.rb | 7 +- app/controllers/projects/jobs_controller.rb | 14 +- .../projects/lfs_locks_api_controller.rb | 10 +- .../merge_requests/application_controller.rb | 3 +- .../projects/merge_requests_controller.rb | 13 +- .../projects/milestones_controller.rb | 4 +- app/controllers/projects/pages_controller.rb | 2 +- .../projects/pipelines_controller.rb | 6 +- .../projects/pipelines_settings_controller.rb | 2 +- .../serverless/functions_controller.rb | 31 +- app/controllers/projects_controller.rb | 17 +- app/controllers/uploads_controller.rb | 4 + app/finders/issuable_finder.rb | 26 +- app/finders/issues_finder.rb | 1 + app/finders/merge_requests_finder.rb | 1 + app/finders/milestones_finder.rb | 21 +- .../projects/serverless/functions_finder.rb | 31 +- app/graphql/resolvers/issues_resolver.rb | 4 + app/graphql/types/merge_request_type.rb | 3 +- app/graphql/types/permission_types/project.rb | 2 +- app/helpers/application_helper.rb | 11 + app/helpers/application_settings_helper.rb | 4 +- app/helpers/auth_helper.rb | 9 +- app/helpers/auto_devops_helper.rb | 37 - app/helpers/environments_helper.rb | 8 + app/helpers/import_helper.rb | 4 +- app/helpers/issuables_helper.rb | 4 +- app/helpers/markup_helper.rb | 6 - app/helpers/members_helper.rb | 2 +- app/helpers/notes_helper.rb | 3 +- app/helpers/preferences_helper.rb | 15 + app/helpers/profiles_helper.rb | 4 + app/helpers/projects_helper.rb | 4 - app/helpers/sorting_helper.rb | 20 +- app/helpers/users_helper.rb | 9 + app/models/application_record.rb | 18 + app/models/application_setting.rb | 8 +- app/models/board.rb | 4 + app/models/ci/bridge.rb | 21 + app/models/ci/build.rb | 70 +- app/models/ci/build_metadata.rb | 2 +- app/models/ci/job_artifact.rb | 2 + app/models/ci/pipeline.rb | 2 + app/models/ci/stage.rb | 1 + app/models/clusters/applications/ingress.rb | 2 +- app/models/clusters/applications/knative.rb | 20 +- .../clusters/applications/prometheus.rb | 27 +- app/models/clusters/applications/runner.rb | 2 +- app/models/clusters/cluster.rb | 41 +- .../clusters/concerns/application_status.rb | 17 +- .../clusters/concerns/application_version.rb | 8 +- app/models/clusters/platforms/kubernetes.rb | 4 +- app/models/commit.rb | 2 +- app/models/commit_collection.rb | 13 + app/models/commit_status.rb | 1 + app/models/concerns/cache_markdown_field.rb | 44 +- app/models/concerns/ci/metadatable.rb | 69 + app/models/concerns/ci/processable.rb | 27 + app/models/concerns/has_status.rb | 10 +- app/models/concerns/issuable.rb | 45 +- .../concerns/manual_inverse_association.rb | 4 +- app/models/concerns/noteable.rb | 15 +- app/models/concerns/taskable.rb | 8 +- app/models/container_repository.rb | 11 +- app/models/dashboard_group_milestone.rb | 7 +- app/models/discussion.rb | 6 + app/models/email.rb | 2 +- app/models/environment.rb | 12 + .../project_error_tracking_setting.rb | 85 +- app/models/external_issue.rb | 8 +- app/models/global_milestone.rb | 1 + app/models/gpg_signature.rb | 7 +- app/models/group.rb | 6 +- app/models/group_milestone.rb | 3 +- app/models/identity.rb | 2 +- app/models/individual_note_discussion.rb | 8 + app/models/internal_id.rb | 17 +- app/models/issue.rb | 5 +- app/models/label.rb | 1 + app/models/member.rb | 2 +- app/models/merge_request.rb | 36 +- app/models/merge_request_diff.rb | 116 +- app/models/merge_request_diff_file.rb | 14 +- app/models/milestone.rb | 59 +- app/models/namespace.rb | 2 +- app/models/pool_repository.rb | 10 +- app/models/programming_language.rb | 6 + app/models/project.rb | 108 +- app/models/project_auto_devops.rb | 6 + app/models/project_import_data.rb | 4 + app/models/project_services/bamboo_service.rb | 32 +- app/models/project_services/irker_service.rb | 2 +- .../project_services/teamcity_service.rb | 6 +- app/models/project_wiki.rb | 4 +- app/models/releases/link.rb | 2 +- app/models/repository.rb | 10 +- app/models/sent_notification.rb | 25 +- app/models/snippet.rb | 4 +- app/models/ssh_host_key.rb | 1 + app/models/storage/hashed_project.rb | 2 +- app/models/storage/legacy_project.rb | 11 +- app/models/user.rb | 11 +- app/policies/base_policy.rb | 4 + app/policies/board_policy.rb | 16 + app/policies/container_repository_policy.rb | 5 + app/policies/personal_snippet_policy.rb | 2 + app/policies/project_snippet_policy.rb | 11 +- app/presenters/merge_request_presenter.rb | 4 + app/presenters/project_presenter.rb | 16 +- app/serializers/base_serializer.rb | 10 +- app/serializers/cluster_application_entity.rb | 2 + .../container_repository_entity.rb | 2 +- app/serializers/container_tag_entity.rb | 2 +- app/serializers/deployment_entity.rb | 10 +- .../error_tracking/project_entity.rb | 7 + .../error_tracking/project_serializer.rb | 7 + app/serializers/merge_request_basic_entity.rb | 1 + app/serializers/merge_request_diff_entity.rb | 8 + .../merge_request_widget_commit_entity.rb | 7 + .../merge_request_widget_entity.rb | 27 +- app/serializers/pipeline_entity.rb | 2 +- .../projects/serverless/service_entity.rb | 36 +- ...ntainer_registry_authentication_service.rb | 3 +- app/services/boards/issues/move_service.rb | 2 +- app/services/boards/lists/destroy_service.rb | 2 +- app/services/ci/create_pipeline_service.rb | 19 +- .../destroy_expired_job_artifacts_service.rb | 38 + app/services/ci/destroy_pipeline_service.rb | 2 - app/services/ci/pipeline_trigger_service.rb | 10 + app/services/ci/process_pipeline_service.rb | 16 +- .../applications/base_helm_service.rb | 4 + .../check_installation_progress_service.rb | 23 +- .../schedule_installation_service.rb | 12 + .../clusters/applications/upgrade_service.rb | 28 + .../concerns/exclusive_lease_guard.rb | 13 +- app/services/delete_branch_service.rb | 2 +- .../error_tracking/list_projects_service.rb | 44 + app/services/groups/create_service.rb | 6 + app/services/groups/update_service.rb | 6 + app/services/import/base_service.rb | 35 + app/services/import/github_service.rb | 48 + .../issuable/common_system_notes_service.rb | 2 +- app/services/issuable_base_service.rb | 63 +- app/services/issues/update_service.rb | 9 +- app/services/labels/create_service.rb | 2 +- app/services/labels/promote_service.rb | 2 +- app/services/labels/update_service.rb | 3 +- app/services/lfs/locks_finder_service.rb | 2 +- app/services/members/create_service.rb | 14 +- app/services/merge_requests/base_service.rb | 1 + app/services/merge_requests/merge_service.rb | 31 +- app/services/merge_requests/squash_service.rb | 33 +- app/services/merge_requests/update_service.rb | 7 +- app/services/milestones/promote_service.rb | 4 +- app/services/notes/build_service.rb | 2 + app/services/notes/create_service.rb | 4 + app/services/preview_markdown_service.rb | 11 +- app/services/projects/after_rename_service.rb | 33 +- app/services/projects/autocomplete_service.rb | 2 +- .../cleanup_tags_service.rb | 94 + .../projects/create_from_template_service.rb | 2 +- app/services/projects/destroy_service.rb | 24 +- .../hashed_storage/base_repository_service.rb | 57 + .../migrate_attachments_service.rb | 26 +- .../migrate_repository_service.rb | 46 +- .../hashed_storage/migration_service.rb | 39 + .../hashed_storage_migration_service.rb | 27 - app/services/projects/import_service.rb | 2 +- .../protect_default_branch_service.rb | 67 + .../update_pages_configuration_service.rb | 34 +- app/services/projects/update_service.rb | 9 +- .../protected_branches/api_service.rb | 8 - app/services/search/global_service.rb | 14 +- app/services/task_list_toggle_service.rb | 72 + app/services/users/update_service.rb | 2 +- app/uploaders/external_diff_uploader.rb | 23 + app/uploaders/personal_file_uploader.rb | 18 +- app/uploaders/records_uploads.rb | 20 +- app/views/admin/appearances/_form.html.haml | 174 +- app/views/admin/appearances/show.html.haml | 7 +- .../_account_and_limit.html.haml | 4 +- .../application_settings/_ci_cd.html.haml | 2 +- .../_localization.html.haml | 11 + .../_repository_storage.html.haml | 1 - .../preferences.html.haml | 11 + .../admin/application_settings/show.html.haml | 2 +- app/views/admin/groups/show.html.haml | 2 +- app/views/admin/runners/_runner.html.haml | 6 +- app/views/admin/runners/index.html.haml | 4 +- app/views/admin/users/_user.html.haml | 55 +- app/views/admin/users/_user_detail.html.haml | 17 + app/views/admin/users/index.html.haml | 96 +- app/views/award_emoji/_awards_block.html.haml | 4 +- .../ci/status/_dropdown_graph_badge.html.haml | 4 +- app/views/clusters/clusters/_form.html.haml | 46 + .../_gcp_signup_offer_banner.html.haml | 2 +- .../clusters/_integration_form.html.haml | 31 - .../clusters/clusters/gcp/_show.html.haml | 50 - app/views/clusters/clusters/index.html.haml | 8 +- app/views/clusters/clusters/new.html.haml | 4 +- app/views/clusters/clusters/show.html.haml | 15 +- .../clusters/clusters/user/_show.html.haml | 39 - .../platforms/kubernetes/_form.html.haml | 58 + app/views/dashboard/_projects_head.html.haml | 2 + app/views/dashboard/groups/index.html.haml | 2 +- .../dashboard/milestones/index.html.haml | 2 + app/views/devise/passwords/edit.html.haml | 2 +- app/views/devise/sessions/_new_ldap.html.haml | 2 + app/views/devise/sessions/new.html.haml | 2 +- .../devise/sessions/two_factor.html.haml | 2 +- .../devise/shared/_omniauth_box.html.haml | 2 +- .../doorkeeper/authorizations/new.html.haml | 2 +- .../rejection.html.haml | 2 +- .../rejection.text.haml | 2 +- app/views/events/_events.html.haml | 16 +- app/views/events/event/_note.html.haml | 2 +- app/views/groups/_home_panel.html.haml | 71 +- .../groups/group_members/index.html.haml | 2 +- app/views/groups/labels/index.html.haml | 7 +- app/views/groups/merge_requests.html.haml | 2 +- app/views/groups/milestones/_form.html.haml | 17 +- app/views/groups/milestones/index.html.haml | 1 + .../groups/runners/_group_runners.html.haml | 2 +- app/views/groups/show.html.haml | 83 +- app/views/ide/_show.html.haml | 2 +- .../import/bitbucket_server/status.html.haml | 2 +- .../_callout.html.haml | 6 +- .../_card.html.haml | 4 +- .../_no_data.html.haml | 6 +- .../index.html.haml | 4 +- app/views/layouts/_head.html.haml | 28 +- .../_init_client_detection_flags.html.haml | 7 + app/views/layouts/application.html.haml | 3 +- app/views/layouts/group.html.haml | 2 +- .../layouts/header/_help_dropdown.html.haml | 4 +- app/views/layouts/header/_new_dropdown.haml | 2 +- app/views/layouts/nav/_dashboard.html.haml | 2 +- .../layouts/nav/sidebar/_admin.html.haml | 2 +- .../layouts/nav/sidebar/_group.html.haml | 2 +- .../layouts/nav/sidebar/_profile.html.haml | 2 +- .../layouts/nav/sidebar/_project.html.haml | 14 +- app/views/layouts/snippets.html.haml | 2 +- app/views/profiles/accounts/show.html.haml | 34 +- app/views/profiles/preferences/show.html.haml | 21 +- app/views/profiles/show.html.haml | 6 +- app/views/projects/_export.html.haml | 4 +- app/views/projects/_home_panel.html.haml | 36 +- .../projects/_issuable_by_email.html.haml | 4 +- .../projects/_new_project_fields.html.haml | 2 +- app/views/projects/_wiki.html.haml | 2 +- .../projects/artifacts/_tree_file.html.haml | 2 +- .../projects/badges/badge_flat-square.svg.erb | 17 + app/views/projects/blob/edit.html.haml | 2 +- app/views/projects/blob/preview.html.haml | 2 +- .../projects/blob/viewers/_markup.html.haml | 4 +- app/views/projects/branches/_branch.html.haml | 2 +- app/views/projects/branches/_panel.html.haml | 2 +- app/views/projects/branches/index.html.haml | 2 +- .../projects/buttons/_dropdown.html.haml | 4 +- app/views/projects/ci/builds/_build.html.haml | 22 +- app/views/projects/ci/lints/_create.html.haml | 26 +- app/views/projects/ci/lints/show.html.haml | 12 +- .../projects/commit/_commit_box.html.haml | 2 +- app/views/projects/commit/show.html.haml | 2 +- app/views/projects/compare/show.html.haml | 2 +- .../projects/deploy_keys/_index.html.haml | 2 +- app/views/projects/diffs/_diffs.html.haml | 4 +- app/views/projects/diffs/_file.html.haml | 4 +- app/views/projects/edit.html.haml | 4 +- .../projects/environments/folder.html.haml | 5 +- .../projects/environments/index.html.haml | 1 - app/views/projects/issues/_form.html.haml | 3 +- .../projects/issues/_merge_requests.html.haml | 68 +- .../issues/_merge_requests_status.html.haml | 25 + .../projects/issues/_new_branch.html.haml | 2 +- .../issues/import_csv/_modal.html.haml | 2 +- app/views/projects/issues/show.html.haml | 5 +- app/views/projects/jobs/index.html.haml | 4 - app/views/projects/labels/index.html.haml | 7 +- .../projects/merge_requests/_form.html.haml | 3 +- .../merge_requests/_merge_request.html.haml | 1 + .../projects/merge_requests/show.html.haml | 3 +- app/views/projects/milestones/_form.html.haml | 23 +- app/views/projects/milestones/edit.html.haml | 10 +- app/views/projects/milestones/index.html.haml | 9 +- app/views/projects/milestones/new.html.haml | 10 +- app/views/projects/milestones/show.html.haml | 28 +- app/views/projects/new.html.haml | 5 +- .../projects/pages_domains/_form.html.haml | 13 +- .../projects/pages_domains/edit.html.haml | 4 +- .../projects/pages_domains/new.html.haml | 8 +- .../projects/pages_domains/show.html.haml | 27 +- .../pipeline_schedules/_form.html.haml | 2 +- .../project_members/_groups.html.haml | 3 +- .../_new_project_group.html.haml | 5 +- .../_new_project_member.html.haml | 15 +- .../projects/project_members/_team.html.haml | 9 +- .../projects/project_members/import.html.haml | 12 +- .../projects/project_members/index.html.haml | 23 +- .../_built_in_templates.html.haml | 6 +- .../shared/_protected_branch.html.haml | 2 +- .../projects/runners/_group_runners.html.haml | 2 +- .../serverless/functions/index.html.haml | 2 +- .../serverless/functions/show.html.haml | 16 + .../services/prometheus/_show.html.haml | 2 + .../settings/ci_cd/_autodevops_form.html.haml | 19 +- .../projects/settings/ci_cd/_form.html.haml | 3 + .../projects/tags/releases/edit.html.haml | 3 +- .../projects/tree/_tree_header.html.haml | 21 +- app/views/projects/wikis/_form.html.haml | 16 +- app/views/projects/wikis/_sidebar.html.haml | 2 +- app/views/projects/wikis/show.html.haml | 2 +- app/views/search/_category.html.haml | 26 +- app/views/search/_filter.html.haml | 20 +- app/views/search/_form.html.haml | 6 +- app/views/search/_results.html.haml | 6 +- app/views/search/results/_empty.html.haml | 2 +- app/views/search/results/_issue.html.haml | 2 +- .../search/results/_merge_request.html.haml | 4 +- app/views/search/results/_note.html.haml | 8 +- .../search/results/_snippet_blob.html.haml | 6 +- .../search/results/_snippet_title.html.haml | 2 +- app/views/search/show.html.haml | 2 +- .../sent_notifications/unsubscribe.html.haml | 13 +- .../shared/_mini_pipeline_graph.html.haml | 1 - .../shared/boards/components/_board.html.haml | 2 +- .../boards/components/_sidebar.html.haml | 2 +- .../shared/empty_states/_issues.html.haml | 18 + .../shared/empty_states/_labels.html.haml | 2 +- .../empty_states/_merge_requests.html.haml | 19 + .../empty_states/_priority_labels.html.haml | 2 +- .../empty_states/_profile_tabs.html.haml | 19 + .../shared/empty_states/_wikis.html.haml | 2 +- .../empty_states/_wikis_layout.html.haml | 2 +- app/views/shared/groups/_list.html.haml | 14 +- app/views/shared/icons/_express.svg | 1 - app/views/shared/icons/_rails.svg | 1 - app/views/shared/icons/_spring.svg | 1 - .../_board_create_list_dropdown.html.haml | 2 +- .../issuable/_bulk_update_sidebar.html.haml | 3 +- .../shared/issuable/_search_bar.html.haml | 20 +- .../issuable/form/_merge_params.html.haml | 2 +- app/views/shared/labels/_nav.html.haml | 4 + .../members/_access_request_buttons.html.haml | 20 - .../shared/milestones/_form_dates.html.haml | 6 +- .../shared/milestones/_search_form.html.haml | 8 + .../shared/notes/_comment_button.html.haml | 4 +- app/views/shared/notes/_note.html.haml | 2 +- .../shared/notifications/_button.html.haml | 2 +- .../notifications/_new_button.html.haml} | 12 +- app/views/shared/projects/_list.html.haml | 27 +- app/views/shared/projects/_project.html.haml | 41 +- app/views/shared/snippets/_form.html.haml | 3 +- app/views/snippets/_snippets.html.haml | 13 +- app/views/users/_overview.html.haml | 30 +- app/views/users/show.html.haml | 4 +- app/workers/all_queues.yml | 8 +- app/workers/build_finished_worker.rb | 26 +- .../cleanup_container_repository_worker.rb | 53 + app/workers/cluster_upgrade_app_worker.rb | 13 + .../delete_container_repository_worker.rb | 2 + app/workers/expire_build_artifacts_worker.rb | 14 +- app/workers/expire_pipeline_cache_worker.rb | 28 +- app/workers/git_garbage_collect_worker.rb | 1 + app/workers/hashed_storage/migrator_worker.rb | 16 + .../notification_service_worker.rb | 31 +- .../namespaceless_project_destroy_worker.rb | 2 +- app/workers/object_pool/join_worker.rb | 11 +- .../project_migrate_hashed_storage_worker.rb | 21 +- app/workers/repository_fork_worker.rb | 10 +- app/workers/storage_migrator_worker.rb | 10 - bin/changelog | 10 +- bin/secpick | 178 +- config.ru | 2 +- config/application.rb | 3 + config/gitlab.yml.example | 33 + config/initializers/1_settings.rb | 9 + config/initializers/8_devise.rb | 2 +- .../initializers/doorkeeper_openid_connect.rb | 23 +- ...tive_record_relation_methods_with_limit.rb | 41 + config/initializers/kubeclient.rb | 22 - config/initializers/new_framework_defaults.rb | 2 - config/initializers/postgresql_cte.rb | 2 +- config/initializers/sentry.rb | 2 +- .../sprockets_base_file_digest_key.rb | 3 + config/initializers/tracing.rb | 37 + config/jsdocs.config.js | 14 + config/locales/de.yml | 1 + config/locales/doorkeeper.en.yml | 6 + config/locales/en.yml | 1 + config/locales/es.yml | 1 + config/routes/project.rb | 12 +- config/routes/repository.rb | 2 +- config/sidekiq_queues.yml | 4 +- config/webpack.config.js | 3 + danger/commit_messages/Dangerfile | 12 +- danger/documentation/Dangerfile | 2 +- db/fixtures/development/04_project.rb | 190 +- db/fixtures/development/10_merge_requests.rb | 3 + .../20140502125220_migrate_repo_size.rb | 2 +- ..._add_ci_builds_index_for_jobscontroller.rb | 2 +- ...d_first_day_of_week_to_user_preferences.rb | 9 + ...rst_day_of_week_to_application_settings.rb | 16 + ...82041_cleanup_legacy_artifact_migration.rb | 34 + ...ial_index_from_ci_builds_artifacts_file.rb | 18 + ...153125_add_merge_request_external_diffs.rb | 25 + .../20190114172110_add_domain_to_cluster.rb | 9 + ...columns_project_error_tracking_settings.rb | 16 + ...1_add_sorting_fields_to_user_preference.rb | 21 + ...91630_add_local_cached_markdown_version.rb | 11 + ...221153951_rename_reserved_project_names.rb | 10 +- ...3418_rename_more_reserved_project_names.rb | 10 +- ...317162059_update_upload_paths_to_system.rb | 2 +- ...elete_inconsistent_internal_id_records2.rb | 43 + ...rate_delete_container_repository_worker.rb | 15 + ..._migrate_storage_migrator_sidekiq_queue.rb | 18 + .../20190131122559_fix_null_type_labels.rb | 23 + ...e_auto_dev_ops_domain_to_cluster_domain.rb | 49 + db/schema.rb | 22 +- doc/README.md | 7 +- doc/administration/auth/ldap.md | 2 +- doc/administration/container_registry.md | 12 +- doc/administration/gitaly/index.md | 31 +- doc/administration/high_availability/redis.md | 8 +- .../high_availability/redis_source.md | 8 +- doc/administration/housekeeping.md | 19 +- doc/administration/index.md | 9 +- doc/administration/integration/terminal.md | 39 +- .../invalidate_markdown_cache.md | 16 + doc/administration/issue_closing_pattern.md | 2 +- doc/administration/merge_request_diffs.md | 154 + .../performance/grafana_configuration.md | 2 +- .../monitoring/prometheus/gitlab_metrics.md | 2 + .../operations/filesystem_benchmarking.md | 87 +- doc/administration/operations/unicorn.md | 12 +- doc/administration/pages/index.md | 38 +- doc/administration/raketasks/check.md | 6 +- .../reply_by_email_postfix_setup.md | 2 +- .../repository_storage_types.md | 4 +- doc/administration/troubleshooting/debug.md | 6 +- doc/api/README.md | 12 +- doc/api/applications.md | 47 +- doc/api/avatar.md | 38 +- doc/api/award_emoji.md | 197 +- doc/api/branches.md | 211 +- doc/api/container_registry.md | 202 + doc/api/features.md | 5 +- doc/api/group_labels.md | 201 + doc/api/groups.md | 2 + doc/api/import.md | 33 + doc/api/issues.md | 20 + doc/api/lint.md | 7 +- doc/api/merge_requests.md | 5 + doc/api/oauth2.md | 1 + doc/api/project_clusters.md | 23 +- doc/api/projects.md | 17 +- doc/api/repositories.md | 2 +- doc/api/settings.md | 12 +- doc/api/tags.md | 3 + doc/api/users.md | 1 + doc/ci/caching/index.md | 12 +- doc/ci/docker/using_docker_build.md | 8 +- doc/ci/docker/using_kaniko.md | 2 +- doc/ci/environments.md | 84 +- .../examples/artifactory_and_gitlab/index.md | 6 +- doc/ci/examples/browser_performance.md | 2 +- doc/ci/examples/code_quality.md | 2 +- doc/ci/examples/container_scanning.md | 6 +- doc/ci/examples/dast.md | 2 +- .../index.md | 4 +- doc/ci/examples/deployment/README.md | 4 +- ...and-deploy-python-application-to-heroku.md | 2 +- ...t-and-deploy-ruby-application-to-heroku.md | 2 +- doc/ci/interactive_web_terminal/index.md | 16 +- doc/ci/junit_test_reports.md | 6 +- doc/ci/merge_request_pipelines/index.md | 43 + doc/ci/pipelines.md | 8 +- doc/ci/quick_start/README.md | 2 +- .../img/view_on_env_blob.png | Bin .../{ => review_apps}/img/view_on_env_mr.png | Bin .../img/view_on_mr_widget.png | Bin doc/ci/review_apps/index.md | 85 + doc/ci/runners/README.md | 8 + doc/ci/triggers/README.md | 2 +- doc/ci/variables/README.md | 87 +- doc/ci/variables/img/variables.png | Bin 34838 -> 0 bytes doc/ci/yaml/README.md | 644 +- doc/development/README.md | 5 + doc/development/adding_database_indexes.md | 4 +- doc/development/api_styleguide.md | 6 +- doc/development/automatic_ce_ee_merge.md | 4 +- doc/development/background_migrations.md | 6 +- doc/development/contributing/index.md | 34 +- .../contributing/issue_workflow.md | 20 +- .../contributing/merge_request_workflow.md | 19 +- doc/development/contributing/style_guides.md | 1 + doc/development/documentation/index.md | 2 +- .../documentation/site_architecture/index.md | 2 +- doc/development/documentation/styleguide.md | 79 +- doc/development/ee_features.md | 14 + doc/development/fe_guide/components.md | 7 +- doc/development/fe_guide/droplab/droplab.md | 36 +- .../fe_guide/droplab/plugins/ajax.md | 8 +- .../fe_guide/droplab/plugins/filter.md | 4 +- .../fe_guide/droplab/plugins/input_setter.md | 6 +- doc/development/fe_guide/index.md | 12 +- doc/development/fe_guide/performance.md | 4 +- doc/development/fe_guide/vue.md | 6 +- doc/development/fe_guide/vuex.md | 4 +- doc/development/file_storage.md | 18 +- doc/development/gitaly.md | 2 +- doc/development/github_importer.md | 22 +- doc/development/go_guide/index.md | 216 + doc/development/gotchas.md | 4 +- doc/development/i18n/externalization.md | 10 + doc/development/i18n/index.md | 2 +- doc/development/i18n/merging_translations.md | 2 +- doc/development/import_export.md | 352 + doc/development/instrumentation.md | 10 +- .../merge_request_performance_guidelines.md | 4 +- doc/development/migration_style_guide.md | 10 +- .../new_fe_guide/development/components.md | 14 +- .../new_fe_guide/development/performance.md | 8 +- .../new_fe_guide/development/testing.md | 22 +- doc/development/new_fe_guide/modules/index.md | 4 +- doc/development/ordering_table_columns.md | 7 +- doc/development/performance.md | 26 +- doc/development/policies.md | 22 +- doc/development/polymorphic_associations.md | 12 +- doc/development/post_deployment_migrations.md | 6 +- doc/development/rake_tasks.md | 8 + doc/development/reusing_abstractions.md | 18 +- ...rolling_out_changes_using_feature_flags.md | 8 +- doc/development/sidekiq_debugging.md | 9 +- doc/development/sql.md | 34 +- .../testing_guide/best_practices.md | 4 +- doc/development/testing_guide/flaky_tests.md | 73 +- .../testing_guide/frontend_testing.md | 20 +- .../img/review_apps_cicd_architecture.png | Bin 0 -> 73240 bytes doc/development/testing_guide/review_apps.md | 107 +- .../testing_guide/testing_levels.md | 12 +- .../understanding_explain_plans.md | 10 +- doc/development/utilities.md | 14 +- .../verifying_database_capabilities.md | 6 +- doc/gitlab-basics/create-project.md | 105 +- .../img/create_new_project_button.png | Bin 3702 -> 0 bytes .../img/create_new_project_info.png | Bin 71608 -> 0 bytes doc/gitlab-basics/start-using-git.md | 48 + doc/install/aws/index.md | 4 +- doc/install/google_cloud_platform/index.md | 6 +- doc/install/installation.md | 649 +- doc/install/kubernetes/gitlab_omnibus.md | 2 +- doc/install/structure.md | 8 +- doc/integration/akismet.md | 2 +- doc/integration/auth0.md | 8 +- doc/integration/azure.md | 8 +- .../gmail_action_buttons_for_gitlab.md | 8 +- doc/integration/oauth_provider.md | 9 +- doc/integration/omniauth.md | 4 +- doc/integration/saml.md | 2 +- doc/integration/twitter.md | 4 +- doc/migrate_ci_to_ce/README.md | 4 +- doc/policy/maintenance.md | 50 +- doc/raketasks/backup_restore.md | 7 +- doc/security/crime_vulnerability.md | 10 +- doc/security/webhooks.md | 6 +- doc/ssh/README.md | 20 +- doc/system_hooks/system_hooks.md | 6 +- doc/topics/autodevops/index.md | 54 +- doc/topics/autodevops/quick_start_guide.md | 4 +- doc/university/glossary/README.md | 2 +- .../high-availability/aws/README.md | 12 +- doc/university/training/end-user/README.md | 23 +- doc/university/training/topics/env_setup.md | 2 +- .../training/topics/getting_started.md | 14 +- doc/university/training/topics/git_add.md | 10 +- doc/university/training/topics/git_intro.md | 4 +- doc/university/training/topics/git_log.md | 10 +- .../training/topics/merge_conflicts.md | 9 +- .../training/topics/rollback_commits.md | 14 +- doc/university/training/topics/stash.md | 15 +- doc/university/training/topics/subtree.md | 18 +- doc/university/training/topics/unstage.md | 8 +- doc/update/10.0-to-10.1.md | 2 +- doc/update/10.1-to-10.2.md | 2 +- doc/update/10.2-to-10.3.md | 2 +- doc/update/10.3-to-10.4.md | 2 +- doc/update/10.4-to-10.5.md | 2 +- doc/update/10.5-to-10.6.md | 2 +- doc/update/10.6-to-10.7.md | 2 +- doc/update/10.7-to-10.8.md | 2 +- doc/update/10.8-to-11.0.md | 2 +- doc/update/11.0-to-11.1.md | 2 +- doc/update/11.1-to-11.2.md | 2 +- doc/update/11.2-to-11.3.md | 2 +- doc/update/11.3-to-11.4.md | 2 +- doc/update/11.4-to-11.5.md | 4 +- doc/update/11.5-to-11.6.md | 12 +- doc/update/11.6-to-11.7.md | 12 +- doc/update/11.7-to-11.8.md | 394 + doc/update/5.1-to-5.2.md | 6 +- doc/update/5.1-to-5.4.md | 4 +- doc/update/5.1-to-6.0.md | 4 +- doc/update/5.2-to-5.3.md | 4 +- doc/update/5.3-to-5.4.md | 4 +- doc/update/5.4-to-6.0.md | 4 +- doc/update/6.0-to-6.1.md | 4 +- doc/update/6.1-to-6.2.md | 6 +- doc/update/6.2-to-6.3.md | 4 +- doc/update/6.9-to-7.0.md | 6 +- doc/update/6.x-or-7.x-to-7.14.md | 18 +- doc/update/7.0-to-7.1.md | 2 +- doc/update/7.1-to-7.2.md | 4 +- doc/update/7.2-to-7.3.md | 4 +- doc/update/7.3-to-7.4.md | 6 +- doc/update/7.4-to-7.5.md | 4 +- doc/update/7.5-to-7.6.md | 4 +- doc/update/7.6-to-7.7.md | 4 +- doc/update/7.7-to-7.8.md | 6 +- doc/update/7.8-to-7.9.md | 6 +- doc/update/7.9-to-7.10.md | 6 +- doc/update/8.10-to-8.11.md | 2 +- doc/update/8.11-to-8.12.md | 2 +- doc/update/8.12-to-8.13.md | 2 +- doc/update/8.13-to-8.14.md | 2 +- doc/update/8.14-to-8.15.md | 2 +- doc/update/8.15-to-8.16.md | 2 +- doc/update/8.16-to-8.17.md | 2 +- doc/update/8.17-to-9.0.md | 2 +- doc/update/9.0-to-9.1.md | 2 +- doc/update/9.1-to-9.2.md | 2 +- doc/update/9.2-to-9.3.md | 2 +- doc/update/9.3-to-9.4.md | 2 +- doc/update/9.4-to-9.5.md | 2 +- doc/update/9.5-to-10.0.md | 2 +- .../upgrading_postgresql_using_slony.md | 10 +- doc/user/admin_area/broadcast_messages.md | 51 + .../admin_area/custom_project_templates.md | 23 +- .../admin_area/img/broadcast_messages.png | Bin 0 -> 68535 bytes doc/user/admin_area/settings/index.md | 4 + .../admin_area/settings/usage_statistics.md | 6 +- doc/user/award_emojis.md | 32 +- doc/user/discussions/index.md | 2 +- doc/user/gitlab_com/index.md | 12 +- doc/user/group/clusters/index.md | 15 +- doc/user/group/custom_project_templates.md | 23 +- doc/user/group/subgroups/index.md | 12 +- doc/user/index.md | 44 +- doc/user/instance_statistics/user_cohorts.md | 5 +- doc/user/markdown.md | 27 +- doc/user/permissions.md | 13 +- .../account/two_factor_authentication.md | 12 +- doc/user/profile/index.md | 2 +- doc/user/profile/preferences.md | 8 + doc/user/project/clusters/index.md | 18 + .../clusters/serverless/img/app-domain.png | Bin 0 -> 209263 bytes .../serverless/img/serverless-page.png | Bin 194708 -> 62369 bytes doc/user/project/clusters/serverless/index.md | 56 +- doc/user/project/container_registry.md | 8 +- doc/user/project/import/github.md | 26 +- doc/user/project/import/index.md | 7 + doc/user/project/index.md | 13 +- doc/user/project/integrations/bamboo.md | 2 +- .../project/integrations/emails_on_push.md | 8 +- doc/user/project/integrations/hipchat.md | 2 +- doc/user/project/integrations/irker.md | 4 +- doc/user/project/integrations/jira.md | 24 +- .../integrations/jira_cloud_configuration.md | 2 +- doc/user/project/integrations/mattermost.md | 4 +- doc/user/project/integrations/prometheus.md | 19 +- .../integrations/prometheus_library/index.md | 2 +- .../prometheus_library/kubernetes.md | 2 +- .../prometheus_library/nginx_ingress.md | 4 +- doc/user/project/integrations/slack.md | 52 +- doc/user/project/issues/csv_import.md | 26 +- .../project/issues/img/import_csv_button.png | Bin 4342 -> 0 bytes doc/user/project/issues/index.md | 16 +- doc/user/project/members/index.md | 2 +- .../merge_requests/allow_collaboration.md | 66 +- .../img/allow_collaboration.png | Bin 21522 -> 11028 bytes .../img/allow_collaboration_after_save.png | Bin 0 -> 5415 bytes .../merge_requests/img/checkout_button.png | Bin 0 -> 5977 bytes .../merge_requests/img/squash_mr_message.png | Bin 0 -> 150302 bytes doc/user/project/merge_requests/index.md | 31 +- .../merge_requests/squash_and_merge.md | 29 +- .../project/new_ci_build_permissions_model.md | 2 +- doc/user/project/operations/error_tracking.md | 9 +- doc/user/project/operations/index.md | 11 + .../project/pages/getting_started_part_one.md | 10 +- .../pages/getting_started_part_three.md | 25 +- .../project/pages/getting_started_part_two.md | 20 +- doc/user/project/pages/index.md | 4 +- doc/user/project/pages/introduction.md | 60 +- doc/user/project/pipelines/job_artifacts.md | 5 +- doc/user/project/pipelines/schedules.md | 2 +- doc/user/project/pipelines/settings.md | 91 +- doc/user/project/repository/branches/index.md | 16 +- .../project/settings/img/general_settings.png | Bin 35871 -> 154764 bytes doc/user/project/settings/index.md | 2 +- doc/user/search/index.md | 12 +- doc/workflow/lfs/lfs_administration.md | 22 +- .../lfs/manage_large_binaries_with_git_lfs.md | 26 +- doc/workflow/releases.md | 1 - doc/workflow/repository_mirroring.md | 31 +- doc/workflow/time_tracking.md | 16 +- lib/api/api.rb | 4 + lib/api/container_registry.rb | 143 + lib/api/deployments.rb | 2 +- lib/api/entities.rb | 34 +- lib/api/entities/container_registry.rb | 29 + lib/api/environments.rb | 4 +- lib/api/features.rb | 17 +- lib/api/group_labels.rb | 63 + lib/api/helpers.rb | 31 +- lib/api/helpers/label_helpers.rb | 82 + lib/api/helpers/pagination.rb | 19 +- lib/api/helpers/runner.rb | 2 +- lib/api/import_github.rb | 46 + lib/api/issues.rb | 9 +- lib/api/job_artifacts.rb | 7 +- lib/api/jobs.rb | 2 +- lib/api/labels.rb | 85 +- lib/api/merge_requests.rb | 7 +- lib/api/pipeline_schedules.rb | 6 +- lib/api/pipelines.rb | 6 +- lib/api/project_clusters.rb | 2 +- lib/api/projects.rb | 6 +- lib/api/projects_relation_builder.rb | 2 +- lib/api/releases.rb | 2 +- lib/api/services.rb | 4 +- lib/api/settings.rb | 3 +- lib/api/subscriptions.rb | 87 +- lib/api/tags.rb | 7 +- lib/api/todos.rb | 2 +- lib/api/triggers.rb | 10 +- lib/api/users.rb | 6 +- lib/api/variables.rb | 2 +- lib/api/wikis.rb | 6 +- lib/backup/files.rb | 10 +- lib/backup/manager.rb | 1 + lib/backup/repository.rb | 2 +- lib/banzai/filter/autolink_filter.rb | 6 +- lib/banzai/filter/emoji_filter.rb | 1 + lib/banzai/filter/footnote_filter.rb | 77 + lib/banzai/filter/image_lazy_load_filter.rb | 1 + lib/banzai/filter/image_link_filter.rb | 1 + lib/banzai/filter/inline_diff_filter.rb | 1 + .../filter/markdown_engines/common_mark.rb | 15 +- .../filter/markdown_engines/redcarpet.rb | 34 - lib/banzai/filter/markdown_filter.rb | 2 +- lib/banzai/filter/math_filter.rb | 3 + lib/banzai/filter/mermaid_filter.rb | 1 + .../filter/milestone_reference_filter.rb | 4 +- lib/banzai/filter/reference_filter.rb | 1 + lib/banzai/filter/relative_link_filter.rb | 2 + lib/banzai/filter/sanitization_filter.rb | 32 +- lib/banzai/filter/spaced_link_filter.rb | 5 +- lib/banzai/filter/suggestion_filter.rb | 1 + lib/banzai/filter/syntax_highlight_filter.rb | 2 +- lib/banzai/filter/table_of_contents_filter.rb | 1 + lib/banzai/filter/task_list_filter.rb | 4 + lib/banzai/filter/video_link_filter.rb | 1 + lib/banzai/pipeline/atom_pipeline.rb | 3 +- .../pipeline/broadcast_message_pipeline.rb | 6 + lib/banzai/pipeline/email_pipeline.rb | 3 +- lib/banzai/pipeline/gfm_pipeline.rb | 11 +- lib/banzai/pipeline/single_line_pipeline.rb | 6 + lib/banzai/renderer/redcarpet/html.rb | 17 - lib/bitbucket_server/client.rb | 14 - lib/bitbucket_server/connection.rb | 17 + lib/container_registry/tag.rb | 38 +- lib/feature.rb | 38 + lib/gitlab.rb | 18 +- lib/gitlab/access/branch_protection.rb | 42 + lib/gitlab/auth.rb | 5 +- lib/gitlab/auth/ldap/adapter.rb | 19 +- lib/gitlab/auth/ldap/person.rb | 4 +- lib/gitlab/auth/o_auth/user.rb | 2 +- lib/gitlab/background_migration.rb | 28 +- .../backfill_project_repositories.rb | 14 +- .../migrate_stage_status.rb | 8 +- lib/gitlab/bitbucket_import/importer.rb | 6 +- lib/gitlab/bitbucket_import/wiki_formatter.rb | 25 + lib/gitlab/ci/ansi2html.rb | 18 +- lib/gitlab/ci/config/entry/job.rb | 14 +- lib/gitlab/ci/config/entry/jobs.rb | 6 +- lib/gitlab/ci/config/entry/policy.rb | 5 +- lib/gitlab/ci/config/entry/retry.rb | 3 - lib/gitlab/ci/config/entry/variables.rb | 2 +- lib/gitlab/ci/config/normalizer.rb | 3 +- lib/gitlab/ci/cron_parser.rb | 7 +- lib/gitlab/ci/pipeline/chain/build.rb | 1 - .../ci/pipeline/chain/limit/activity.rb | 21 + lib/gitlab/ci/pipeline/chain/limit/size.rb | 21 + lib/gitlab/ci/pipeline/chain/populate.rb | 4 + .../chain/remove_unwanted_chat_jobs.rb | 19 + lib/gitlab/ci/pipeline/seed/build.rb | 10 +- lib/gitlab/ci/pipeline/seed/stage.rb | 8 +- lib/gitlab/ci/status/bridge/common.rb | 1 - lib/gitlab/ci/status/external/common.rb | 2 +- .../templates/Android-Fastlane.gitlab-ci.yml | 121 + lib/gitlab/ci/templates/Android.gitlab-ci.yml | 2 + .../ci/templates/Auto-DevOps.gitlab-ci.yml | 77 +- lib/gitlab/ci/templates/dotNET.gitlab-ci.yml | 1 + lib/gitlab/ci/trace/stream.rb | 2 +- lib/gitlab/ci/yaml_processor.rb | 7 +- lib/gitlab/config/entry/configurable.rb | 1 + lib/gitlab/config/entry/factory.rb | 17 +- lib/gitlab/config/entry/node.rb | 4 +- lib/gitlab/config/entry/simplifiable.rb | 7 +- lib/gitlab/content_disposition.rb | 54 + lib/gitlab/diff/lines_unfolder.rb | 11 +- lib/gitlab/error_tracking/project.rb | 16 + lib/gitlab/etag_caching/middleware.rb | 2 +- lib/gitlab/gfm/reference_rewriter.rb | 2 +- lib/gitlab/git/object_pool.rb | 9 +- lib/gitlab/git/repository.rb | 7 +- lib/gitlab/gitaly_client.rb | 15 +- .../gitaly_client/repository_service.rb | 33 +- lib/gitlab/gitaly_client/util.rb | 8 +- lib/gitlab/github_import/bulk_importing.rb | 4 +- .../github_import/importer/issue_importer.rb | 6 +- .../importer/milestones_importer.rb | 12 +- .../importer/pull_request_importer.rb | 30 + .../importer/repository_importer.rb | 9 +- .../representation/pull_request.rb | 4 +- lib/gitlab/gon_helper.rb | 1 + lib/gitlab/gpg/commit.rb | 7 +- lib/gitlab/hashed_storage/migrator.rb | 24 +- lib/gitlab/import/merge_request_helpers.rb | 4 - lib/gitlab/import_export/import_export.yml | 6 + lib/gitlab/kubernetes/helm.rb | 2 +- lib/gitlab/kubernetes/helm/api.rb | 11 +- lib/gitlab/kubernetes/helm/install_command.rb | 34 +- lib/gitlab/kubernetes/helm/upgrade_command.rb | 65 - lib/gitlab/kubernetes/kube_client.rb | 5 +- lib/gitlab/legacy_github_import/importer.rb | 2 +- .../legacy_github_import/wiki_formatter.rb | 4 + lib/gitlab/lfs_token.rb | 4 +- lib/gitlab/loop_helpers.rb | 24 + lib/gitlab/metrics/influx_db.rb | 4 +- .../metrics/samplers/unicorn_sampler.rb | 8 +- lib/gitlab/middleware/basic_health_check.rb | 2 +- lib/gitlab/middleware/go.rb | 2 +- lib/gitlab/middleware/read_only/controller.rb | 24 +- lib/gitlab/pages_client.rb | 2 +- .../patch/sprockets_base_file_digest_key.rb | 22 + lib/gitlab/project_template.rb | 19 +- lib/gitlab/request_context.rb | 2 +- lib/gitlab/seeder.rb | 13 + lib/gitlab/sentry.rb | 8 - lib/gitlab/shell.rb | 67 +- .../sidekiq_logging/structured_logger.rb | 17 + lib/gitlab/sql/union.rb | 2 +- lib/gitlab/task_helpers.rb | 8 +- lib/gitlab/tracing.rb | 17 + lib/gitlab/tracing/common.rb | 69 + lib/gitlab/tracing/factory.rb | 61 + lib/gitlab/tracing/grpc_interceptor.rb | 54 + lib/gitlab/tracing/jaeger_factory.rb | 97 + lib/gitlab/tracing/rack_middleware.rb | 46 + .../tracing/rails/action_view_subscriber.rb | 75 + .../tracing/rails/active_record_subscriber.rb | 49 + lib/gitlab/tracing/rails/rails_common.rb | 24 + .../tracing/sidekiq/client_middleware.rb | 26 + .../tracing/sidekiq/server_middleware.rb | 26 + lib/gitlab/tracing/sidekiq/sidekiq_common.rb | 22 + lib/gitlab/usage_data.rb | 15 +- lib/gitlab/utils/merge_hash.rb | 2 + lib/gitlab/utils/override.rb | 2 + lib/gitlab/utils/strong_memoize.rb | 2 + lib/sentry/client.rb | 58 +- lib/system_check/base_check.rb | 8 +- lib/tasks/gitlab/assets.rake | 18 +- lib/tasks/gitlab/backup.rake | 92 +- lib/tasks/gitlab/bulk_add_permission.rake | 6 +- lib/tasks/gitlab/db.rake | 5 +- lib/tasks/gitlab/storage.rake | 2 +- locale/ar_SA/gitlab.po | 2372 ++- locale/bg/gitlab.po | 2336 ++- locale/ca_ES/gitlab.po | 2708 +++- locale/cs_CZ/gitlab.po | 2348 ++- locale/cy_GB/gitlab.po | 2372 ++- locale/da_DK/gitlab.po | 2324 ++- locale/de/gitlab.po | 2680 +++- locale/el_GR/gitlab.po | 2324 ++- locale/eo/gitlab.po | 2336 ++- locale/es/gitlab.po | 4884 +++++-- locale/et_EE/gitlab.po | 2324 ++- locale/fil_PH/gitlab.po | 2324 ++- locale/fr/gitlab.po | 2516 +++- locale/gitlab.pot | 810 +- locale/gl_ES/gitlab.po | 2324 ++- locale/he_IL/gitlab.po | 2348 ++- locale/hi_IN/gitlab.po | 11801 +++++++++++++++ locale/hr_HR/gitlab.po | 11867 ++++++++++++++++ locale/hu_HU/gitlab.po | 2324 ++- locale/id_ID/gitlab.po | 2312 ++- locale/it/gitlab.po | 2396 +++- locale/ja/gitlab.po | 2980 +++- locale/ko/gitlab.po | 3304 ++++- locale/mn_MN/gitlab.po | 2324 ++- locale/nb_NO/gitlab.po | 2324 ++- locale/nl_NL/gitlab.po | 2374 +++- locale/pa_IN/gitlab.po | 11801 +++++++++++++++ locale/pl_PL/gitlab.po | 2624 +++- locale/pt_BR/gitlab.po | 3398 +++-- locale/pt_PT/gitlab.po | 2324 ++- locale/ro_RO/gitlab.po | 2336 ++- locale/ru/gitlab.po | 3078 +++- locale/sk_SK/gitlab.po | 2348 ++- locale/sq_AL/gitlab.po | 2324 ++- locale/sr_CS/gitlab.po | 2336 ++- locale/sr_SP/gitlab.po | 2336 ++- locale/sv_SE/gitlab.po | 11801 +++++++++++++++ locale/sw_KE/gitlab.po | 11801 +++++++++++++++ locale/tr_TR/gitlab.po | 2328 ++- locale/uk/gitlab.po | 3098 +++- locale/zh_CN/gitlab.po | 2888 +++- locale/zh_HK/gitlab.po | 2324 ++- locale/zh_TW/gitlab.po | 5288 ++++--- package.json | 75 +- qa/Gemfile | 2 +- qa/Gemfile.lock | 8 +- qa/README.md | 23 +- qa/Rakefile | 6 + qa/qa.rb | 24 + qa/qa/git/repository.rb | 147 +- qa/qa/page/admin/menu.rb | 9 + .../settings/component/account_and_limit.rb | 26 + qa/qa/page/admin/settings/general.rb | 23 + qa/qa/page/base.rb | 12 + qa/qa/page/component/lazy_loader.rb | 15 + qa/qa/page/component/select2.rb | 6 + qa/qa/page/group/show.rb | 2 +- qa/qa/page/label/index.rb | 21 +- qa/qa/page/main/login.rb | 32 +- qa/qa/page/main/menu.rb | 8 +- qa/qa/page/merge_request/show.rb | 28 +- qa/qa/page/project/branches/show.rb | 64 + qa/qa/page/project/job/show.rb | 10 +- qa/qa/page/project/menu.rb | 155 +- qa/qa/page/project/new.rb | 7 +- .../project/operations/kubernetes/show.rb | 2 +- qa/qa/page/project/pipeline/show.rb | 6 +- qa/qa/page/project/settings/ci_cd.rb | 5 +- qa/qa/page/project/settings/deploy_keys.rb | 37 +- qa/qa/page/project/sub_menus/ci_cd.rb | 25 + qa/qa/page/project/sub_menus/common.rb | 23 + qa/qa/page/project/sub_menus/issues.rb | 52 + qa/qa/page/project/sub_menus/operations.rb | 47 + qa/qa/page/project/sub_menus/repository.rb | 44 + qa/qa/page/project/sub_menus/settings.rb | 61 + qa/qa/page/project/web_ide/edit.rb | 22 +- qa/qa/page/project/wiki/new.rb | 40 +- qa/qa/page/settings/common.rb | 2 +- qa/qa/resource/base.rb | 12 +- qa/qa/resource/deploy_key.rb | 6 +- qa/qa/resource/fork.rb | 9 + qa/qa/resource/kubernetes_cluster.rb | 6 +- qa/qa/resource/merge_request_from_fork.rb | 2 +- qa/qa/resource/project.rb | 12 +- qa/qa/resource/repository/push.rb | 27 +- qa/qa/runtime/browser.rb | 62 +- qa/qa/runtime/env.rb | 46 + qa/qa/runtime/namespace.rb | 4 +- qa/qa/scenario/test/integration/oauth.rb | 13 + .../1_manage/login/login_via_oauth_spec.rb | 16 + .../1_manage/project/create_project_spec.rb | 3 +- .../project/view_project_activity_spec.rb | 3 +- .../create_merge_request_spec.rb | 4 +- .../merge_merge_request_from_fork_spec.rb | 8 +- .../rebase_merge_request_spec.rb | 10 +- .../squash_merge_request_spec.rb | 3 +- .../add_list_delete_branches_spec.rb | 93 + .../push_http_private_token_spec.rb | 2 +- .../push_mirroring_over_http_spec.rb | 2 +- .../push_over_http_file_size_spec.rb | 71 + .../repository/push_over_http_spec.rb | 2 +- .../wiki/create_edit_clone_push_wiki_spec.rb | 16 +- .../ci_variable/add_ci_variable_spec.rb | 3 +- .../deploy_key/add_deploy_key_spec.rb | 13 +- .../deploy_key/clone_using_deploy_key_spec.rb | 9 +- .../create_project_with_auto_devops_spec.rb | 63 +- qa/qa/support/api.rb | 18 + qa/qa/support/page/logging.rb | 27 + qa/qa/tools/delete_subgroups.rb | 66 + qa/qa/vendor/github/page/base.rb | 14 + qa/qa/vendor/github/page/login.rb | 23 + qa/spec/git/repository_spec.rb | 146 +- qa/spec/page/logging_spec.rb | 26 +- qa/spec/resource/base_spec.rb | 36 + qa/spec/runtime/env_spec.rb | 59 + .../scenario/test/integration/oauth_spec.rb | 9 + qa/spec/spec_helper.rb | 61 + qa/spec/spec_helper_spec.rb | 304 + qa/spec/support/stub_env.rb | 2 +- .../cop/inject_enterprise_edition_module.rb | 10 +- rubocop/spec_helpers.rb | 11 +- scripts/clean-old-cached-assets | 6 + scripts/review_apps/review-apps.sh | 37 +- spec/bin/changelog_spec.rb | 2 +- .../application_controller_spec.rb | 4 +- .../boards/issues_controller_spec.rb | 12 +- .../boards/lists_controller_spec.rb | 7 +- .../concerns/checks_collaboration_spec.rb | 2 +- .../concerns/issuable_collections_spec.rb | 45 + .../concerns/send_file_upload_spec.rb | 50 +- .../dashboard/milestones_controller_spec.rb | 27 +- .../groups/children_controller_spec.rb | 6 +- .../groups/clusters_controller_spec.rb | 21 +- .../groups/milestones_controller_spec.rb | 31 +- .../bitbucket_server_controller_spec.rb | 24 +- .../omniauth_callbacks_controller_spec.rb | 57 + .../profiles/avatars_controller_spec.rb | 2 +- .../profiles/preferences_controller_spec.rb | 3 +- .../projects/artifacts_controller_spec.rb | 16 +- .../projects/badges_controller_spec.rb | 41 +- .../projects/branches_controller_spec.rb | 6 +- .../projects/commit_controller_spec.rb | 2 +- .../projects/environments_controller_spec.rb | 116 +- .../error_tracking_controller_spec.rb | 114 +- .../projects/issues_controller_spec.rb | 30 +- .../projects/jobs_controller_spec.rb | 44 - .../creations_controller_spec.rb | 2 +- .../merge_requests_controller_spec.rb | 30 +- .../projects/milestones_controller_spec.rb | 12 +- .../projects/pages_controller_spec.rb | 4 +- .../projects/pipelines_controller_spec.rb | 2 +- .../projects/registry/tags_controller_spec.rb | 2 +- .../serverless/functions_controller_spec.rb | 40 +- .../projects/services_controller_spec.rb | 10 + .../projects/snippets_controller_spec.rb | 2 +- spec/controllers/projects_controller_spec.rb | 55 +- spec/controllers/search_controller_spec.rb | 2 +- spec/controllers/uploads_controller_spec.rb | 16 +- spec/factories/ci/bridge.rb | 12 + spec/factories/ci/builds.rb | 2 +- spec/factories/clusters/clusters.rb | 4 + spec/factories/commits.rb | 10 + spec/factories/container_repositories.rb | 2 +- spec/factories/error_tracking/project.rb | 15 + spec/factories/group_members.rb | 2 +- .../project_error_tracking_settings.rb | 2 + spec/factories/projects.rb | 2 +- spec/factories/wiki_pages.rb | 2 +- .../admin/admin_abuse_reports_spec.rb | 2 +- spec/features/admin/admin_appearance_spec.rb | 12 +- spec/features/admin/admin_projects_spec.rb | 2 +- spec/features/admin/admin_settings_spec.rb | 2 +- spec/features/admin/admin_users_spec.rb | 42 +- spec/features/atom/dashboard_issues_spec.rb | 2 +- spec/features/atom/dashboard_spec.rb | 2 +- spec/features/atom/issues_spec.rb | 2 +- spec/features/atom/users_spec.rb | 2 +- spec/features/boards/boards_spec.rb | 8 +- spec/features/boards/modal_filter_spec.rb | 6 +- .../clusters/cluster_detail_page_spec.rb | 69 + spec/features/container_registry_spec.rb | 2 +- spec/features/cycle_analytics_spec.rb | 2 +- .../dashboard/datetime_on_tooltips_spec.rb | 4 +- spec/features/dashboard/help_spec.rb | 14 +- spec/features/dashboard/projects_spec.rb | 3 + spec/features/dashboard/shortcuts_spec.rb | 2 +- spec/features/dashboard/todos/todos_spec.rb | 12 +- .../dashboard/user_filters_projects_spec.rb | 2 +- spec/features/groups/empty_states_spec.rb | 44 +- spec/features/groups/group_settings_spec.rb | 8 +- spec/features/groups_spec.rb | 14 +- spec/features/ics/dashboard_issues_spec.rb | 2 +- spec/features/ics/group_issues_spec.rb | 2 +- spec/features/ics/project_issues_spec.rb | 2 +- .../internal_references_spec.rb | 4 +- .../filtered_search/dropdown_assignee_spec.rb | 6 +- .../filtered_search/dropdown_author_spec.rb | 2 +- .../filtered_search/dropdown_emoji_spec.rb | 6 +- .../filtered_search/dropdown_label_spec.rb | 4 +- .../dropdown_milestone_spec.rb | 10 +- .../filtered_search/filter_issues_spec.rb | 10 +- .../filtered_search/visual_tokens_spec.rb | 6 +- spec/features/issues/gfm_autocomplete_spec.rb | 2 +- .../issues/resource_label_events_spec.rb | 2 +- ...r_creates_branch_and_merge_request_spec.rb | 2 +- spec/features/labels_hierarchy_spec.rb | 4 +- spec/features/markdown/copy_as_gfm_spec.rb | 263 +- spec/features/markdown/markdown_spec.rb | 27 +- spec/features/markdown/math_spec.rb | 2 +- .../user_accepts_merge_request_spec.rb | 8 +- .../user_comments_on_diff_spec.rb | 1 + .../merge_request/user_creates_mr_spec.rb | 2 +- ...er_customizes_merge_commit_message_spec.rb | 10 +- .../user_merges_immediately_spec.rb | 2 + ...user_merges_when_pipeline_succeeds_spec.rb | 10 +- .../merge_request/user_posts_notes_spec.rb | 32 + .../user_resolves_conflicts_spec.rb | 2 + ...diff_notes_and_discussions_resolve_spec.rb | 1 + .../user_sees_discussions_spec.rb | 12 + .../user_sees_merge_widget_spec.rb | 2 +- .../user_sees_mini_pipeline_graph_spec.rb | 46 +- .../merge_request/user_sees_versions_spec.rb | 31 +- .../user_toggles_whitespace_changes_spec.rb | 12 +- .../merge_request/user_views_diffs_spec.rb | 4 + .../merge_requests/user_mass_updates_spec.rb | 2 +- .../user_squashes_merge_request_spec.rb | 4 +- spec/features/milestone_spec.rb | 2 +- .../profiles/user_edit_profile_spec.rb | 63 +- .../artifacts/user_browses_artifacts_spec.rb | 4 +- .../user_downloads_artifacts_spec.rb | 2 +- .../features/projects/blobs/blob_show_spec.rb | 19 +- spec/features/projects/blobs/edit_spec.rb | 11 - .../projects/clusters/applications_spec.rb | 10 +- spec/features/projects/commit/builds_spec.rb | 2 +- .../projects/commit/cherry_pick_spec.rb | 4 +- spec/features/projects/deploy_keys_spec.rb | 2 +- .../projects/files/undo_template_spec.rb | 2 +- spec/features/projects/jobs_spec.rb | 33 +- .../labels/update_prioritization_spec.rb | 2 +- .../projects/pipelines/pipeline_spec.rb | 50 +- .../projects/pipelines/pipelines_spec.rb | 2 +- .../releases/user_views_releases_spec.rb | 46 + .../projects/serverless/functions_spec.rb | 9 +- .../settings/pipelines_settings_spec.rb | 25 - .../settings/repository_settings_spec.rb | 10 +- .../settings/user_tags_project_spec.rb | 6 +- .../snippets/user_comments_on_snippet_spec.rb | 2 +- .../projects/wiki/markdown_preview_spec.rb | 14 - spec/features/projects_spec.rb | 47 +- spec/features/protected_branches_spec.rb | 2 +- spec/features/runners_spec.rb | 4 +- spec/features/security/admin_access_spec.rb | 2 +- .../security/dashboard_access_spec.rb | 2 +- spec/features/security/profile_access_spec.rb | 2 +- .../security/project/internal_access_spec.rb | 2 +- .../security/project/private_access_spec.rb | 2 +- .../security/project/public_access_spec.rb | 2 +- .../project/snippet/internal_access_spec.rb | 2 +- .../project/snippet/private_access_spec.rb | 4 +- .../project/snippet/public_access_spec.rb | 2 +- spec/features/snippets/show_spec.rb | 29 - spec/features/task_lists_spec.rb | 66 - spec/features/users/overview_spec.rb | 4 +- spec/features/users/terms_spec.rb | 2 +- spec/finders/groups_finder_spec.rb | 20 +- spec/finders/issues_finder_spec.rb | 27 +- ...erge_request_target_project_finder_spec.rb | 2 +- spec/finders/milestones_finder_spec.rb | 6 + spec/finders/notes_finder_spec.rb | 2 +- .../serverless/functions_finder_spec.rb | 25 +- spec/finders/projects_finder_spec.rb | 2 +- spec/finders/snippets_finder_spec.rb | 2 +- spec/fixtures/api/schemas/cluster_status.json | 4 +- .../schemas/entities/merge_request_basic.json | 3 +- .../entities/merge_request_widget.json | 10 +- .../schemas/error_tracking/list_projects.json | 13 + .../api/schemas/error_tracking/project.json | 19 + .../schemas/public_api/v4/group_labels.json | 18 + .../api/schemas/registry/repository.json | 9 +- spec/fixtures/api/schemas/registry/tag.json | 7 + spec/fixtures/markdown.md.erb | 2 +- .../sentry/list_projects_sample_response.json | 81 + .../file_row_header_spec.js.snap | 37 + .../components/file_row_header_spec.js | 36 + .../graphql/resolvers/issues_resolver_spec.rb | 20 + .../project_pipelines_resolver_spec.rb | 2 +- .../base_permission_type_spec.rb | 2 +- .../types/permission_types/project_spec.rb | 2 +- spec/graphql/types/project_type_spec.rb | 2 +- spec/helpers/application_helper_spec.rb | 15 + spec/helpers/auto_devops_helper_spec.rb | 35 - spec/helpers/import_helper_spec.rb | 4 + spec/helpers/issuables_helper_spec.rb | 9 +- spec/helpers/issues_helper_spec.rb | 2 +- spec/helpers/markup_helper_spec.rb | 21 - spec/helpers/notes_helper_spec.rb | 4 +- spec/helpers/preferences_helper_spec.rb | 24 + spec/helpers/projects_helper_spec.rb | 12 - spec/helpers/search_helper_spec.rb | 2 +- spec/helpers/submodule_helper_spec.rb | 2 +- spec/helpers/users_helper_spec.rb | 70 +- spec/javascripts/api_spec.js | 16 + .../javascripts/behaviors/copy_as_gfm_spec.js | 33 +- .../shortcuts/shortcuts_issuable_spec.js | 126 +- .../clusters/clusters_bundle_spec.js | 57 +- .../components/application_row_spec.js | 187 +- .../clusters/stores/clusters_store_spec.js | 3 + .../compare_versions_dropdown_spec.js | 33 + .../diffs/components/compare_versions_spec.js | 41 +- .../diffs/components/diff_file_header_spec.js | 4 + .../diffs/components/diff_stats_spec.js | 33 + .../components/settings_dropdown_spec.js | 167 + .../diffs/components/tree_list_spec.js | 84 +- .../diffs/mock_data/merge_request_diffs.js | 52 +- spec/javascripts/diffs/store/actions_spec.js | 53 + spec/javascripts/diffs/store/getters_spec.js | 23 +- .../javascripts/diffs/store/mutations_spec.js | 46 + spec/javascripts/diffs/store/utils_spec.js | 184 +- .../dirty_submit_collection_spec.js | 6 +- .../dirty_submit/dirty_submit_form_spec.js | 28 +- spec/javascripts/dirty_submit/helper.js | 29 +- .../environments/environment_item_spec.js | 2 - .../environments/environment_table_spec.js | 1 - .../environments/environments_app_spec.js | 1 - .../folder/environments_folder_view_spec.js | 1 - .../filtered_search_visual_tokens_spec.js | 11 + .../fixtures/oauth_remember_me.html.haml | 1 + spec/javascripts/fixtures/sessions.rb | 26 + .../helpers/vue_test_utils_helper.js | 19 + .../helpers/vue_test_utils_helper_spec.js | 48 + spec/javascripts/ide/components/ide_spec.js | 68 - .../ide/components/ide_status_bar_spec.js | 3 + .../ide/lib/decorations/controller_spec.js | 4 +- .../issue_show/components/app_spec.js | 194 +- .../issue_show/components/description_spec.js | 23 +- spec/javascripts/issue_show/mock_data.js | 2 + .../jobs/components/sidebar_spec.js | 4 +- spec/javascripts/jobs/store/getters_spec.js | 24 - .../lib/utils/common_utils_spec.js | 249 +- .../lib/utils/datetime_utility_spec.js | 40 +- .../javascripts/lib/utils/file_upload_spec.js | 46 +- spec/javascripts/lib/utils/grammar_spec.js | 35 + spec/javascripts/lib/utils/icon_utils_spec.js | 67 + .../lib/utils/text_utility_spec.js | 16 + .../javascripts/lib/utils/url_utility_spec.js | 81 +- spec/javascripts/matchers.js | 39 + spec/javascripts/merge_request_spec.js | 54 +- .../monitoring/charts/area_spec.js | 220 + spec/javascripts/monitoring/dashboard_spec.js | 28 +- .../javascripts/monitoring/graph/axis_spec.js | 65 - .../monitoring/graph/deployment_spec.js | 53 - .../javascripts/monitoring/graph/flag_spec.js | 133 - .../monitoring/graph/legend_spec.js | 44 - .../monitoring/graph/track_info_spec.js | 44 - .../monitoring/graph/track_line_spec.js | 52 - .../javascripts/monitoring/graph_path_spec.js | 56 - spec/javascripts/monitoring/graph_spec.js | 127 - spec/javascripts/monitoring/mock_data.js | 81 +- .../utils/multiple_time_series_spec.js | 22 - .../notebook/cells/output/html_spec.js | 2 + .../notebook/cells/output/index_spec.js | 27 +- .../components/discussion_counter_spec.js | 2 + .../components/discussion_filter_spec.js | 46 +- .../discussion_jump_to_next_button_spec.js | 33 + .../discussion_reply_placeholder_spec.js | 34 + .../discussion_resolve_button_spec.js | 74 + .../note_actions/reply_button_spec.js | 46 + .../notes/components/note_actions_spec.js | 183 +- .../notes/components/note_app_spec.js | 165 +- .../components/noteable_discussion_spec.js | 153 +- spec/javascripts/notes/mock_data.js | 1 - spec/javascripts/notes/stores/actions_spec.js | 14 + .../javascripts/notes/stores/mutation_spec.js | 39 +- spec/javascripts/notes_spec.js | 19 +- spec/javascripts/oauth_remember_me_spec.js | 7 + .../new/preserve_url_fragment_spec.js | 61 + .../releases/components/release_block_spec.js | 12 + .../components/environment_row_spec.js | 81 + .../components/function_row_spec.js | 33 + .../serverless/components/functions_spec.js | 68 + .../serverless/components/url_spec.js | 28 + spec/javascripts/serverless/mock_data.js | 79 + .../stores/serverless_store_spec.js | 36 + spec/javascripts/task_list_spec.js | 156 + spec/javascripts/test_bundle.js | 11 + .../components/states/commit_edit_spec.js | 85 + .../mr_widget_commit_message_dropdown_spec.js | 61 + .../states/mr_widget_commits_header_spec.js | 110 + .../states/mr_widget_conflicts_spec.js | 131 +- ...idget_merge_when_pipeline_succeeds_spec.js | 14 +- .../states/mr_widget_merged_spec.js | 20 +- .../states/mr_widget_ready_to_merge_spec.js | 197 +- .../mr_widget_squash_before_merge_spec.js | 100 + spec/javascripts/vue_mr_widget/mock_data.js | 6 +- .../vue_mr_widget/mr_widget_options_spec.js | 28 +- .../stores/get_state_key_spec.js | 24 + .../components/file_finder/index_spec.js | 200 +- .../components/file_finder/item_spec.js | 6 +- .../vue_shared/components/file_row_spec.js | 43 +- .../filtered_search_dropdown_spec.js | 99 + .../markdown/suggestion_diff_header_spec.js | 6 + .../components/markdown/suggestions_spec.js | 2 +- .../user_avatar/user_avatar_list_spec.js | 54 +- spec/lib/api/helpers/pagination_spec.rb | 99 +- spec/lib/api/helpers_spec.rb | 36 +- spec/lib/backup/manager_spec.rb | 1 + spec/lib/banzai/color_parser_spec.rb | 2 +- .../lib/banzai/filter/autolink_filter_spec.rb | 7 + .../commit_range_reference_filter_spec.rb | 2 +- .../lib/banzai/filter/footnote_filter_spec.rb | 50 + .../filter/issue_reference_filter_spec.rb | 2 +- .../filter/label_reference_filter_spec.rb | 2 +- .../lib/banzai/filter/markdown_filter_spec.rb | 38 +- .../filter/project_reference_filter_spec.rb | 2 +- .../filter/relative_link_filter_spec.rb | 54 + .../banzai/filter/sanitization_filter_spec.rb | 52 +- .../banzai/filter/spaced_link_filter_spec.rb | 5 - spec/lib/banzai/object_renderer_spec.rb | 2 +- .../pipeline/description_pipeline_spec.rb | 4 + .../lib/banzai/pipeline/full_pipeline_spec.rb | 34 + spec/lib/bitbucket_server/client_spec.rb | 6 - spec/lib/bitbucket_server/connection_spec.rb | 18 + spec/lib/feature_spec.rb | 14 + .../gitlab/access/branch_protection_spec.rb | 54 + .../auth/o_auth/identity_linker_spec.rb | 2 +- .../lib/gitlab/auth/user_auth_finders_spec.rb | 2 +- spec/lib/gitlab/auth_spec.rb | 4 +- .../backfill_project_repositories_spec.rb | 18 +- ...eate_gpg_key_subkeys_from_gpg_keys_spec.rb | 2 +- .../delete_diff_files_spec.rb | 2 + ...ze_merge_request_diffs_and_commits_spec.rb | 2 + ...rate_events_to_push_event_payloads_spec.rb | 2 + ...grate_system_uploads_to_new_folder_spec.rb | 2 + .../move_personal_snippet_files_spec.rb | 2 + ...cluster_kubernetes_namespace_table_spec.rb | 63 +- .../populate_external_pipeline_source_spec.rb | 2 + .../populate_import_state_spec.rb | 2 +- ...e_request_metrics_with_events_data_spec.rb | 2 + .../rollback_import_state_data_spec.rb | 2 +- spec/lib/gitlab/background_migration_spec.rb | 76 + .../bare_repository_import/repository_spec.rb | 2 +- .../gitlab/bitbucket_import/importer_spec.rb | 10 +- .../bitbucket_import/wiki_formatter_spec.rb | 29 + .../cache/ci/project_pipeline_status_spec.rb | 2 +- .../lib/gitlab/ci/config/entry/global_spec.rb | 6 +- spec/lib/gitlab/ci/config/entry/job_spec.rb | 3 +- spec/lib/gitlab/ci/config/entry/jobs_spec.rb | 6 +- .../lib/gitlab/ci/config/entry/policy_spec.rb | 27 +- spec/lib/gitlab/ci/config/normalizer_spec.rb | 20 + spec/lib/gitlab/ci/config_spec.rb | 4 +- .../gitlab/ci/pipeline/chain/populate_spec.rb | 37 +- .../lib/gitlab/ci/pipeline/seed/build_spec.rb | 44 +- .../lib/gitlab/ci/pipeline/seed/stage_spec.rb | 14 +- .../gitlab/ci/status/external/common_spec.rb | 18 +- spec/lib/gitlab/ci/yaml_processor_spec.rb | 35 +- .../gitlab/config/entry/configurable_spec.rb | 10 +- spec/lib/gitlab/data_builder/pipeline_spec.rb | 2 +- spec/lib/gitlab/diff/lines_unfolder_spec.rb | 115 +- spec/lib/gitlab/diff/position_tracer_spec.rb | 18 +- .../email/handler/create_note_handler_spec.rb | 26 +- spec/lib/gitlab/git/blame_spec.rb | 2 +- spec/lib/gitlab/git/blob_spec.rb | 2 +- spec/lib/gitlab/git/branch_spec.rb | 4 +- spec/lib/gitlab/git/commit_spec.rb | 4 +- spec/lib/gitlab/git/compare_spec.rb | 4 +- spec/lib/gitlab/git/diff_spec.rb | 2 +- spec/lib/gitlab/git/merge_base_spec.rb | 2 +- spec/lib/gitlab/git/remote_repository_spec.rb | 16 +- spec/lib/gitlab/git/repository_spec.rb | 97 +- spec/lib/gitlab/git/tag_spec.rb | 2 +- spec/lib/gitlab/git/tree_spec.rb | 2 +- spec/lib/gitlab/git_access_spec.rb | 23 +- .../gitaly_client/remote_service_spec.rb | 2 +- spec/lib/gitlab/gitaly_client/util_spec.rb | 4 +- spec/lib/gitlab/gitaly_client_spec.rb | 9 + .../github_import/bulk_importing_spec.rb | 12 - .../importer/issue_importer_spec.rb | 22 - .../importer/milestones_importer_spec.rb | 14 +- .../importer/pull_request_importer_spec.rb | 48 +- .../importer/repository_importer_spec.rb | 14 +- .../representation/pull_request_spec.rb | 2 +- .../connections/keyset_connection_spec.rb | 2 +- .../gitlab/hashed_storage/migrator_spec.rb | 28 +- spec/lib/gitlab/import_export/all_models.yml | 2 + .../lib/gitlab/import_export/importer_spec.rb | 2 +- spec/lib/gitlab/import_export/reader_spec.rb | 2 +- .../import_export/safe_model_attributes.yml | 3 +- spec/lib/gitlab/kubernetes/helm/api_spec.rb | 45 - .../kubernetes/helm/install_command_spec.rb | 84 +- spec/lib/gitlab/kubernetes/helm/pod_spec.rb | 6 +- .../kubernetes/helm/upgrade_command_spec.rb | 140 - .../lib/gitlab/kubernetes/kube_client_spec.rb | 32 + .../wiki_formatter_spec.rb | 8 +- spec/lib/gitlab/loop_helpers_spec.rb | 45 + .../metrics/samplers/unicorn_sampler_spec.rb | 4 +- spec/lib/gitlab/middleware/read_only_spec.rb | 34 +- spec/lib/gitlab/project_template_spec.rb | 7 +- spec/lib/gitlab/request_context_spec.rb | 2 +- spec/lib/gitlab/shell_spec.rb | 17 +- .../sidekiq_logging/structured_logger_spec.rb | 33 +- .../gitlab/slash_commands/issue_new_spec.rb | 2 +- spec/lib/gitlab/tracing/factory_spec.rb | 43 + .../gitlab/tracing/grpc_interceptor_spec.rb | 47 + .../lib/gitlab/tracing/jaeger_factory_spec.rb | 71 + .../gitlab/tracing/rack_middleware_spec.rb | 62 + .../rails/action_view_subscriber_spec.rb | 147 + .../rails/active_record_subscriber_spec.rb | 73 + .../tracing/sidekiq/client_middleware_spec.rb | 43 + .../tracing/sidekiq/server_middleware_spec.rb | 43 + spec/lib/gitlab/tree_summary_spec.rb | 2 +- spec/lib/gitlab/usage_data_spec.rb | 10 + spec/lib/gitlab_spec.rb | 1 + spec/lib/omni_auth/strategies/jwt_spec.rb | 2 + spec/lib/safe_zip/extract_spec.rb | 2 +- spec/lib/sentry/client_spec.rb | 159 +- spec/mailers/emails/pages_domains_spec.rb | 2 +- spec/mailers/notify_spec.rb | 2 +- spec/migrations/README.md | 76 +- .../add_foreign_keys_to_todos_spec.rb | 6 +- spec/migrations/clean_up_for_members_spec.rb | 4 + .../cleanup_legacy_artifact_migration_spec.rb | 52 + ...espaceless_pending_delete_projects_spec.rb | 12 +- ...e_inconsistent_internal_id_records_spec.rb | 2 +- spec/migrations/fix_null_type_labels_spec.rb | 36 + ...o_dev_ops_domain_to_cluster_domain_spec.rb | 114 + ...ate_storage_migrator_sidekiq_queue_spec.rb | 47 + ...rename_more_reserved_project_names_spec.rb | 5 +- .../rename_reserved_project_names_spec.rb | 5 +- spec/models/application_record_spec.rb | 36 + spec/models/application_setting_spec.rb | 7 + spec/models/ci/build_spec.rb | 24 +- spec/models/ci/pipeline_spec.rb | 23 + .../applications/cert_manager_spec.rb | 17 +- .../clusters/applications/ingress_spec.rb | 20 +- .../clusters/applications/jupyter_spec.rb | 16 +- .../clusters/applications/knative_spec.rb | 52 +- .../clusters/applications/prometheus_spec.rb | 113 +- .../clusters/applications/runner_spec.rb | 20 +- spec/models/clusters/cluster_spec.rb | 132 +- .../clusters/kubernetes_namespace_spec.rb | 2 +- .../clusters/platforms/kubernetes_spec.rb | 13 + spec/models/commit_collection_spec.rb | 36 +- .../concerns/cache_markdown_field_spec.rb | 270 +- .../concerns/cacheable_attributes_spec.rb | 4 + .../concerns/discussion_on_diff_spec.rb | 2 +- spec/models/concerns/issuable_spec.rb | 74 +- .../manual_inverse_association_spec.rb | 4 +- spec/models/concerns/redactable_spec.rb | 4 + spec/models/environment_spec.rb | 70 + .../project_error_tracking_setting_spec.rb | 176 +- spec/models/event_spec.rb | 5 +- spec/models/external_issue_spec.rb | 2 +- spec/models/global_milestone_spec.rb | 6 + spec/models/gpg_key_spec.rb | 2 +- spec/models/gpg_signature_spec.rb | 35 + spec/models/group_spec.rb | 36 + spec/models/identity_spec.rb | 34 + spec/models/internal_id_spec.rb | 23 + spec/models/issue_spec.rb | 45 +- spec/models/label_note_spec.rb | 4 +- spec/models/lfs_file_lock_spec.rb | 2 +- spec/models/members/project_member_spec.rb | 2 +- spec/models/merge_request_diff_commit_spec.rb | 2 +- spec/models/merge_request_diff_spec.rb | 205 +- spec/models/merge_request_spec.rb | 101 +- spec/models/milestone_spec.rb | 122 +- spec/models/project_import_data_spec.rb | 11 + .../project_services/bamboo_service_spec.rb | 26 +- .../project_services/drone_ci_service_spec.rb | 2 +- .../project_services/teamcity_service_spec.rb | 2 +- spec/models/project_spec.rb | 286 +- spec/models/project_wiki_spec.rb | 4 +- spec/models/releases/link_spec.rb | 10 + spec/models/repository_spec.rb | 2 + spec/models/resource_label_event_spec.rb | 6 +- spec/models/sent_notification_spec.rb | 38 +- spec/models/ssh_host_key_spec.rb | 23 + spec/models/user_preference_spec.rb | 25 +- spec/policies/board_policy_spec.rb | 67 + spec/policies/personal_snippet_policy_spec.rb | 11 + spec/policies/project_policy_spec.rb | 4 +- spec/presenters/blob_presenter_spec.rb | 2 +- .../settings/deploy_keys_presenter_spec.rb | 2 +- spec/requests/api/avatar_spec.rb | 2 +- spec/requests/api/award_emoji_spec.rb | 4 +- spec/requests/api/boards_spec.rb | 2 +- spec/requests/api/container_registry_spec.rb | 224 + spec/requests/api/discussions_spec.rb | 2 +- spec/requests/api/features_spec.rb | 34 + spec/requests/api/files_spec.rb | 5 +- spec/requests/api/group_labels_spec.rb | 258 + spec/requests/api/group_milestones_spec.rb | 2 +- spec/requests/api/groups_spec.rb | 14 + spec/requests/api/import_github_spec.rb | 56 + spec/requests/api/internal_spec.rb | 8 +- spec/requests/api/issues_spec.rb | 332 +- spec/requests/api/jobs_spec.rb | 4 +- spec/requests/api/markdown_spec.rb | 2 + spec/requests/api/merge_requests_spec.rb | 43 +- spec/requests/api/notes_spec.rb | 4 +- .../requests/api/pages/private_access_spec.rb | 2 +- spec/requests/api/pages/public_access_spec.rb | 2 +- spec/requests/api/pipelines_spec.rb | 4 +- spec/requests/api/project_clusters_spec.rb | 17 + spec/requests/api/project_milestones_spec.rb | 2 +- spec/requests/api/projects_spec.rb | 96 +- spec/requests/api/repositories_spec.rb | 5 +- .../api/resource_label_events_spec.rb | 2 +- spec/requests/api/runner_spec.rb | 8 +- spec/requests/api/settings_spec.rb | 6 +- spec/requests/api/submodules_spec.rb | 4 +- spec/requests/api/tags_spec.rb | 12 + spec/requests/api/users_spec.rb | 4 +- spec/requests/api/wikis_spec.rb | 2 +- spec/requests/git_http_spec.rb | 4 +- spec/requests/lfs_locks_api_spec.rb | 15 +- spec/requests/openid_connect_spec.rb | 44 +- .../projects/cycle_analytics_events_spec.rb | 2 +- spec/requests/request_profiler_spec.rb | 2 +- spec/requests/user_activity_spec.rb | 114 + spec/routing/project_routing_spec.rb | 4 + .../inject_enterprise_edition_module_spec.rb | 35 + .../cluster_application_entity_spec.rb | 14 +- .../container_repository_entity_spec.rb | 2 +- spec/serializers/container_tag_entity_spec.rb | 2 +- spec/serializers/deployment_entity_spec.rb | 32 +- .../environment_serializer_spec.rb | 4 + spec/serializers/group_child_entity_spec.rb | 1 + ...merge_request_widget_commit_entity_spec.rb | 21 + .../merge_request_widget_entity_spec.rb | 22 +- .../update_service_spec.rb | 4 +- .../boards/issues/list_service_spec.rb | 4 +- .../boards/issues/move_service_spec.rb | 4 +- ...troy_expired_job_artifacts_service_spec.rb | 104 + .../ci/destroy_pipeline_service_spec.rb | 4 +- .../ci/process_pipeline_service_spec.rb | 2 +- ...heck_installation_progress_service_spec.rb | 129 +- .../applications/create_service_spec.rb | 17 + .../schedule_installation_service_spec.rb | 24 + .../applications/upgrade_service_spec.rb | 128 + .../list_projects_service_spec.rb | 149 + spec/services/event_create_service_spec.rb | 2 +- spec/services/git_push_service_spec.rb | 4 +- spec/services/issues/create_service_spec.rb | 2 +- spec/services/issues/update_service_spec.rb | 2 + .../labels/find_or_create_service_spec.rb | 2 +- spec/services/labels/promote_service_spec.rb | 4 +- spec/services/lfs/unlock_file_service_spec.rb | 2 +- spec/services/members/create_service_spec.rb | 9 + spec/services/members/destroy_service_spec.rb | 2 +- .../merge_requests/create_service_spec.rb | 20 +- .../merge_requests/merge_service_spec.rb | 2 +- .../merge_requests/refresh_service_spec.rb | 10 +- .../merge_requests/squash_service_spec.rb | 73 +- .../merge_requests/update_service_spec.rb | 2 + spec/services/notes/build_service_spec.rb | 40 + spec/services/notes/create_service_spec.rb | 37 + .../services/preview_markdown_service_spec.rb | 19 - .../projects/after_rename_service_spec.rb | 124 +- .../cleanup_tags_service_spec.rb | 162 + spec/services/projects/create_service_spec.rb | 12 +- .../services/projects/destroy_service_spec.rb | 34 + spec/services/projects/fork_service_spec.rb | 2 +- .../migrate_attachments_service_spec.rb | 34 +- .../migrate_repository_service_spec.rb | 32 +- .../migration_service_spec.rb} | 2 +- spec/services/projects/import_service_spec.rb | 2 +- .../lfs_pointers/lfs_download_service_spec.rb | 2 +- .../protect_default_branch_service_spec.rb | 242 + .../projects/transfer_service_spec.rb | 2 +- ...update_pages_configuration_service_spec.rb | 32 +- spec/services/projects/update_service_spec.rb | 2 +- .../change_labels_service_spec.rb | 2 +- .../merge_into_notes_service_spec.rb | 8 +- spec/services/system_note_service_spec.rb | 8 +- .../services/task_list_toggle_service_spec.rb | 116 + spec/services/todo_service_spec.rb | 2 +- .../destroy/entity_leave_service_spec.rb | 8 +- .../destroy/group_private_service_spec.rb | 2 +- .../migrate_to_ghost_user_service_spec.rb | 2 +- spec/services/web_hook_service_spec.rb | 4 +- spec/sidekiq/cron/job_gem_dependency_spec.rb | 4 +- spec/simplecov_env.rb | 6 +- spec/spec_helper.rb | 7 +- ...g_discussions_in_issues_shared_examples.rb | 2 +- spec/support/helpers/api_helpers.rb | 7 + .../features/responsive_table_helpers.rb | 32 + spec/support/helpers/graphql_helpers.rb | 2 +- spec/support/helpers/kubernetes_helpers.rb | 46 +- spec/support/helpers/login_helpers.rb | 2 +- spec/support/helpers/rake_helpers.rb | 2 +- spec/support/helpers/select2_helper.rb | 6 + spec/support/helpers/stub_configuration.rb | 4 + spec/support/helpers/stub_env.rb | 2 +- spec/support/helpers/stub_gitlab_calls.rb | 34 +- spec/support/helpers/stub_object_storage.rb | 7 + .../migrations_helpers/cluster_helpers.rb | 71 + spec/support/redis/redis_shared_examples.rb | 4 +- .../issuable_notes_filter_shared_examples.rb | 22 +- .../repository_lfs_file_load_examples.rb | 10 +- ...er_from_user_preference_shared_examples.rb | 10 +- .../dirty_submit_form_shared_examples.rb | 26 +- .../editable_merge_request_shared_examples.rb | 4 +- .../issuable_shared_examples.rb | 73 + .../backfill_project_repositories_examples.rb | 4 +- .../malicious_regexp_shared_examples.rb | 2 +- .../mentionable_shared_examples.rb | 4 +- .../cluster_application_initial_status.rb | 29 + ...ster_application_status_shared_examples.rb | 93 +- ...ter_application_version_shared_examples.rb | 20 + .../shared_examples/url_validator_examples.rb | 2 +- spec/tasks/gitlab/backup_rake_spec.rb | 36 +- spec/tasks/gitlab/storage_rake_spec.rb | 10 +- spec/uploaders/external_diff_uploader_spec.rb | 67 + spec/uploaders/file_uploader_spec.rb | 2 +- spec/uploaders/import_export_uploader_spec.rb | 2 +- spec/uploaders/personal_file_uploader_spec.rb | 32 +- spec/validators/js_regex_validator_spec.rb | 2 - .../instance_configuration.html.haml_spec.rb | 6 +- .../projects/_home_panel.html.haml_spec.rb | 2 +- .../projects/commit/show.html.haml_spec.rb | 4 +- .../_merge_requests_status.html.haml_spec.rb | 22 + .../projects/issues/show.html.haml_spec.rb | 51 + .../ci_cd/_autodevops_form.html.haml_spec.rb | 53 +- ...leanup_container_repository_worker_spec.rb | 47 + .../expire_build_artifacts_worker_spec.rb | 14 + .../git_garbage_collect_worker_spec.rb | 11 + .../migrator_worker_spec.rb} | 4 +- .../notification_service_worker_spec.rb | 51 +- spec/workers/post_receive_spec.rb | 15 +- ...ject_migrate_hashed_storage_worker_spec.rb | 23 +- spec/workers/prune_old_events_worker_spec.rb | 4 +- spec/workers/repository_fork_worker_spec.rb | 7 +- vendor/project_templates/gitbook.tar.gz | Bin 0 -> 13808 bytes vendor/project_templates/hexo.tar.gz | Bin 0 -> 548020 bytes vendor/project_templates/hugo.tar.gz | Bin 0 -> 1048753 bytes vendor/project_templates/jekyll.tar.gz | Bin 0 -> 60703 bytes vendor/project_templates/plainhtml.tar.gz | Bin 0 -> 12079 bytes yarn.lock | 1973 ++- 2015 files changed, 177081 insertions(+), 29694 deletions(-) create mode 100644 .gitlab/issue_templates/Coding style proposal.md create mode 100644 .gitlab/issue_templates/Security Release.md create mode 100644 .gitlab/merge_request_templates/Security Release.md create mode 100644 app/assets/javascripts/behaviors/markdown/editor_extensions.js create mode 100644 app/assets/javascripts/behaviors/markdown/marks/bold.js create mode 100644 app/assets/javascripts/behaviors/markdown/marks/code.js create mode 100644 app/assets/javascripts/behaviors/markdown/marks/inline_diff.js create mode 100644 app/assets/javascripts/behaviors/markdown/marks/inline_html.js create mode 100644 app/assets/javascripts/behaviors/markdown/marks/italic.js create mode 100644 app/assets/javascripts/behaviors/markdown/marks/link.js create mode 100644 app/assets/javascripts/behaviors/markdown/marks/math.js create mode 100644 app/assets/javascripts/behaviors/markdown/marks/strike.js create mode 100644 app/assets/javascripts/behaviors/markdown/nodes/blockquote.js create mode 100644 app/assets/javascripts/behaviors/markdown/nodes/bullet_list.js create mode 100644 app/assets/javascripts/behaviors/markdown/nodes/code_block.js create mode 100644 app/assets/javascripts/behaviors/markdown/nodes/description_details.js create mode 100644 app/assets/javascripts/behaviors/markdown/nodes/description_list.js create mode 100644 app/assets/javascripts/behaviors/markdown/nodes/description_term.js create mode 100644 app/assets/javascripts/behaviors/markdown/nodes/details.js create mode 100644 app/assets/javascripts/behaviors/markdown/nodes/doc.js create mode 100644 app/assets/javascripts/behaviors/markdown/nodes/emoji.js create mode 100644 app/assets/javascripts/behaviors/markdown/nodes/hard_break.js create mode 100644 app/assets/javascripts/behaviors/markdown/nodes/heading.js create mode 100644 app/assets/javascripts/behaviors/markdown/nodes/horizontal_rule.js create mode 100644 app/assets/javascripts/behaviors/markdown/nodes/image.js create mode 100644 app/assets/javascripts/behaviors/markdown/nodes/list_item.js create mode 100644 app/assets/javascripts/behaviors/markdown/nodes/ordered_list.js create mode 100644 app/assets/javascripts/behaviors/markdown/nodes/ordered_task_list.js create mode 100644 app/assets/javascripts/behaviors/markdown/nodes/paragraph.js create mode 100644 app/assets/javascripts/behaviors/markdown/nodes/reference.js create mode 100644 app/assets/javascripts/behaviors/markdown/nodes/summary.js create mode 100644 app/assets/javascripts/behaviors/markdown/nodes/table.js create mode 100644 app/assets/javascripts/behaviors/markdown/nodes/table_body.js create mode 100644 app/assets/javascripts/behaviors/markdown/nodes/table_cell.js create mode 100644 app/assets/javascripts/behaviors/markdown/nodes/table_head.js create mode 100644 app/assets/javascripts/behaviors/markdown/nodes/table_header_row.js create mode 100644 app/assets/javascripts/behaviors/markdown/nodes/table_of_contents.js create mode 100644 app/assets/javascripts/behaviors/markdown/nodes/table_row.js create mode 100644 app/assets/javascripts/behaviors/markdown/nodes/task_list.js create mode 100644 app/assets/javascripts/behaviors/markdown/nodes/task_list_item.js create mode 100644 app/assets/javascripts/behaviors/markdown/nodes/text.js create mode 100644 app/assets/javascripts/behaviors/markdown/nodes/video.js create mode 100644 app/assets/javascripts/behaviors/markdown/schema.js create mode 100644 app/assets/javascripts/behaviors/markdown/serializer.js create mode 100644 app/assets/javascripts/diffs/components/diff_stats.vue create mode 100644 app/assets/javascripts/diffs/components/settings_dropdown.vue create mode 100644 app/assets/javascripts/diffs/workers/tree_worker.js create mode 100644 app/assets/javascripts/lib/utils/grammar.js create mode 100644 app/assets/javascripts/lib/utils/icon_utils.js create mode 100644 app/assets/javascripts/lib/utils/webpack.js delete mode 100644 app/assets/javascripts/monitoring/components/graph.vue delete mode 100644 app/assets/javascripts/monitoring/components/graph/axis.vue delete mode 100644 app/assets/javascripts/monitoring/components/graph/deployment.vue delete mode 100644 app/assets/javascripts/monitoring/components/graph/flag.vue delete mode 100644 app/assets/javascripts/monitoring/components/graph/legend.vue delete mode 100644 app/assets/javascripts/monitoring/components/graph/path.vue delete mode 100644 app/assets/javascripts/monitoring/components/graph/track_info.vue delete mode 100644 app/assets/javascripts/monitoring/components/graph/track_line.vue delete mode 100644 app/assets/javascripts/monitoring/event_hub.js delete mode 100644 app/assets/javascripts/monitoring/mixins/monitoring_mixins.js delete mode 100644 app/assets/javascripts/monitoring/utils/date_time_formatters.js delete mode 100644 app/assets/javascripts/monitoring/utils/measurements.js delete mode 100644 app/assets/javascripts/monitoring/utils/multiple_time_series.js create mode 100644 app/assets/javascripts/notes/components/discussion_jump_to_next_button.vue create mode 100644 app/assets/javascripts/notes/components/discussion_reply_placeholder.vue create mode 100644 app/assets/javascripts/notes/components/discussion_resolve_button.vue create mode 100644 app/assets/javascripts/notes/components/note_actions/reply_button.vue create mode 100644 app/assets/javascripts/pages/admin/application_settings/show/index.js rename app/assets/javascripts/pages/groups/clusters/{update => edit}/index.js (100%) rename app/assets/javascripts/pages/projects/clusters/{update => edit}/index.js (100%) create mode 100644 app/assets/javascripts/pages/sessions/new/preserve_url_fragment.js create mode 100644 app/assets/javascripts/pipelines/mixins/graph_component_mixin.js create mode 100644 app/assets/javascripts/serverless/components/environment_row.vue create mode 100644 app/assets/javascripts/serverless/components/function_details.vue create mode 100644 app/assets/javascripts/serverless/components/pod_box.vue create mode 100644 app/assets/javascripts/serverless/components/url.vue create mode 100644 app/assets/javascripts/serverless/stores/serverless_details_store.js create mode 100644 app/assets/javascripts/vue_merge_request_widget/components/states/commit_edit.vue create mode 100644 app/assets/javascripts/vue_merge_request_widget/components/states/commit_message_dropdown.vue create mode 100644 app/assets/javascripts/vue_merge_request_widget/components/states/commits_header.vue delete mode 100644 app/assets/javascripts/vue_merge_request_widget/ee_switch_mr_widget_options.js delete mode 100644 app/assets/javascripts/vue_merge_request_widget/services/ee_switch_mr_widget_service.js delete mode 100644 app/assets/javascripts/vue_merge_request_widget/stores/ee_switch_get_state_key.js delete mode 100644 app/assets/javascripts/vue_merge_request_widget/stores/ee_switch_mr_widget_store.js delete mode 100644 app/assets/javascripts/vue_merge_request_widget/stores/ee_switch_state_maps.js rename app/assets/javascripts/{ide => vue_shared}/components/file_finder/index.vue (67%) rename app/assets/javascripts/{ide => vue_shared}/components/file_finder/item.vue (77%) create mode 100644 app/assets/javascripts/vue_shared/components/file_row_header.vue create mode 100644 app/assets/stylesheets/components/related_items_list.scss create mode 100644 app/assets/stylesheets/pages/serverless.scss rename app/controllers/concerns/{issues_action.rb => issuable_collections_action.rb} (50%) delete mode 100644 app/controllers/concerns/merge_requests_action.rb create mode 100644 app/controllers/concerns/record_user_last_activity.rb create mode 100644 app/models/concerns/ci/metadatable.rb create mode 100644 app/models/concerns/ci/processable.rb create mode 100644 app/policies/board_policy.rb create mode 100644 app/policies/container_repository_policy.rb create mode 100644 app/serializers/error_tracking/project_entity.rb create mode 100644 app/serializers/error_tracking/project_serializer.rb create mode 100644 app/serializers/merge_request_widget_commit_entity.rb create mode 100644 app/services/ci/destroy_expired_job_artifacts_service.rb create mode 100644 app/services/clusters/applications/upgrade_service.rb create mode 100644 app/services/error_tracking/list_projects_service.rb create mode 100644 app/services/import/base_service.rb create mode 100644 app/services/import/github_service.rb create mode 100644 app/services/projects/container_repository/cleanup_tags_service.rb create mode 100644 app/services/projects/hashed_storage/base_repository_service.rb create mode 100644 app/services/projects/hashed_storage/migration_service.rb delete mode 100644 app/services/projects/hashed_storage_migration_service.rb create mode 100644 app/services/projects/protect_default_branch_service.rb create mode 100644 app/services/task_list_toggle_service.rb create mode 100644 app/uploaders/external_diff_uploader.rb create mode 100644 app/views/admin/application_settings/_localization.html.haml create mode 100644 app/views/admin/users/_user_detail.html.haml create mode 100644 app/views/clusters/clusters/_form.html.haml delete mode 100644 app/views/clusters/clusters/_integration_form.html.haml delete mode 100644 app/views/clusters/clusters/gcp/_show.html.haml delete mode 100644 app/views/clusters/clusters/user/_show.html.haml create mode 100644 app/views/clusters/platforms/kubernetes/_form.html.haml create mode 100644 app/views/layouts/_init_client_detection_flags.html.haml create mode 100644 app/views/projects/badges/badge_flat-square.svg.erb create mode 100644 app/views/projects/issues/_merge_requests_status.html.haml create mode 100644 app/views/projects/serverless/functions/show.html.haml create mode 100644 app/views/shared/empty_states/_profile_tabs.html.haml delete mode 100644 app/views/shared/icons/_express.svg delete mode 100644 app/views/shared/icons/_rails.svg delete mode 100644 app/views/shared/icons/_spring.svg delete mode 100644 app/views/shared/members/_access_request_buttons.html.haml create mode 100644 app/views/shared/milestones/_search_form.html.haml rename app/views/{projects/buttons/_notifications.html.haml => shared/notifications/_new_button.html.haml} (75%) create mode 100644 app/workers/cleanup_container_repository_worker.rb create mode 100644 app/workers/cluster_upgrade_app_worker.rb create mode 100644 app/workers/hashed_storage/migrator_worker.rb delete mode 100644 app/workers/storage_migrator_worker.rb create mode 100644 config/initializers/kaminari_active_record_relation_methods_with_limit.rb delete mode 100644 config/initializers/kubeclient.rb create mode 100644 config/initializers/sprockets_base_file_digest_key.rb create mode 100644 config/initializers/tracing.rb create mode 100644 config/jsdocs.config.js create mode 100644 db/migrate/20181027114222_add_first_day_of_week_to_user_preferences.rb create mode 100644 db/migrate/20181028120717_add_first_day_of_week_to_application_settings.rb create mode 100644 db/migrate/20190104182041_cleanup_legacy_artifact_migration.rb create mode 100644 db/migrate/20190108192941_remove_partial_index_from_ci_builds_artifacts_file.rb create mode 100644 db/migrate/20190109153125_add_merge_request_external_diffs.rb create mode 100644 db/migrate/20190114172110_add_domain_to_cluster.rb create mode 100644 db/migrate/20190115092821_add_columns_project_error_tracking_settings.rb create mode 100644 db/migrate/20190116234221_add_sorting_fields_to_user_preference.rb create mode 100644 db/migrate/20190130091630_add_local_cached_markdown_version.rb create mode 100644 db/post_migrate/20190102152410_delete_inconsistent_internal_id_records2.rb create mode 100644 db/post_migrate/20190115054215_migrate_delete_container_repository_worker.rb create mode 100644 db/post_migrate/20190124200344_migrate_storage_migrator_sidekiq_queue.rb create mode 100644 db/post_migrate/20190131122559_fix_null_type_labels.rb create mode 100644 db/post_migrate/20190204115450_migrate_auto_dev_ops_domain_to_cluster_domain.rb create mode 100644 doc/administration/invalidate_markdown_cache.md create mode 100644 doc/administration/merge_request_diffs.md create mode 100644 doc/api/container_registry.md create mode 100644 doc/api/group_labels.md create mode 100644 doc/api/import.md rename doc/ci/{ => review_apps}/img/view_on_env_blob.png (100%) rename doc/ci/{ => review_apps}/img/view_on_env_mr.png (100%) rename doc/ci/{ => review_apps}/img/view_on_mr_widget.png (100%) delete mode 100644 doc/ci/variables/img/variables.png create mode 100644 doc/development/go_guide/index.md create mode 100644 doc/development/import_export.md create mode 100644 doc/development/testing_guide/img/review_apps_cicd_architecture.png delete mode 100644 doc/gitlab-basics/img/create_new_project_button.png delete mode 100644 doc/gitlab-basics/img/create_new_project_info.png create mode 100644 doc/update/11.7-to-11.8.md create mode 100644 doc/user/admin_area/broadcast_messages.md create mode 100644 doc/user/admin_area/img/broadcast_messages.png create mode 100644 doc/user/project/clusters/serverless/img/app-domain.png delete mode 100644 doc/user/project/issues/img/import_csv_button.png create mode 100644 doc/user/project/merge_requests/img/allow_collaboration_after_save.png create mode 100644 doc/user/project/merge_requests/img/checkout_button.png create mode 100644 doc/user/project/merge_requests/img/squash_mr_message.png create mode 100644 doc/user/project/operations/index.md create mode 100644 lib/api/container_registry.rb create mode 100644 lib/api/entities/container_registry.rb create mode 100644 lib/api/group_labels.rb create mode 100644 lib/api/helpers/label_helpers.rb create mode 100644 lib/api/import_github.rb create mode 100644 lib/banzai/filter/footnote_filter.rb delete mode 100644 lib/banzai/filter/markdown_engines/redcarpet.rb delete mode 100644 lib/banzai/renderer/redcarpet/html.rb create mode 100644 lib/gitlab/access/branch_protection.rb create mode 100644 lib/gitlab/bitbucket_import/wiki_formatter.rb create mode 100644 lib/gitlab/ci/pipeline/chain/limit/activity.rb create mode 100644 lib/gitlab/ci/pipeline/chain/limit/size.rb create mode 100644 lib/gitlab/ci/pipeline/chain/remove_unwanted_chat_jobs.rb create mode 100644 lib/gitlab/ci/templates/Android-Fastlane.gitlab-ci.yml create mode 100644 lib/gitlab/content_disposition.rb create mode 100644 lib/gitlab/error_tracking/project.rb delete mode 100644 lib/gitlab/kubernetes/helm/upgrade_command.rb create mode 100644 lib/gitlab/loop_helpers.rb create mode 100644 lib/gitlab/patch/sprockets_base_file_digest_key.rb create mode 100644 lib/gitlab/tracing.rb create mode 100644 lib/gitlab/tracing/common.rb create mode 100644 lib/gitlab/tracing/factory.rb create mode 100644 lib/gitlab/tracing/grpc_interceptor.rb create mode 100644 lib/gitlab/tracing/jaeger_factory.rb create mode 100644 lib/gitlab/tracing/rack_middleware.rb create mode 100644 lib/gitlab/tracing/rails/action_view_subscriber.rb create mode 100644 lib/gitlab/tracing/rails/active_record_subscriber.rb create mode 100644 lib/gitlab/tracing/rails/rails_common.rb create mode 100644 lib/gitlab/tracing/sidekiq/client_middleware.rb create mode 100644 lib/gitlab/tracing/sidekiq/server_middleware.rb create mode 100644 lib/gitlab/tracing/sidekiq/sidekiq_common.rb create mode 100644 locale/hi_IN/gitlab.po create mode 100644 locale/hr_HR/gitlab.po create mode 100644 locale/pa_IN/gitlab.po create mode 100644 locale/sv_SE/gitlab.po create mode 100644 locale/sw_KE/gitlab.po create mode 100644 qa/qa/page/admin/settings/component/account_and_limit.rb create mode 100644 qa/qa/page/admin/settings/general.rb create mode 100644 qa/qa/page/component/lazy_loader.rb create mode 100644 qa/qa/page/project/branches/show.rb create mode 100644 qa/qa/page/project/sub_menus/ci_cd.rb create mode 100644 qa/qa/page/project/sub_menus/common.rb create mode 100644 qa/qa/page/project/sub_menus/issues.rb create mode 100644 qa/qa/page/project/sub_menus/operations.rb create mode 100644 qa/qa/page/project/sub_menus/repository.rb create mode 100644 qa/qa/page/project/sub_menus/settings.rb create mode 100644 qa/qa/scenario/test/integration/oauth.rb create mode 100644 qa/qa/specs/features/browser_ui/1_manage/login/login_via_oauth_spec.rb create mode 100644 qa/qa/specs/features/browser_ui/3_create/repository/add_list_delete_branches_spec.rb create mode 100644 qa/qa/specs/features/browser_ui/3_create/repository/push_over_http_file_size_spec.rb create mode 100644 qa/qa/tools/delete_subgroups.rb create mode 100644 qa/qa/vendor/github/page/base.rb create mode 100644 qa/qa/vendor/github/page/login.rb create mode 100644 qa/spec/scenario/test/integration/oauth_spec.rb create mode 100644 qa/spec/spec_helper_spec.rb create mode 100755 scripts/clean-old-cached-assets create mode 100644 spec/factories/error_tracking/project.rb create mode 100644 spec/features/clusters/cluster_detail_page_spec.rb create mode 100644 spec/features/projects/releases/user_views_releases_spec.rb create mode 100644 spec/fixtures/api/schemas/error_tracking/list_projects.json create mode 100644 spec/fixtures/api/schemas/error_tracking/project.json create mode 100644 spec/fixtures/api/schemas/public_api/v4/group_labels.json create mode 100644 spec/fixtures/sentry/list_projects_sample_response.json create mode 100644 spec/frontend/vue_shared/components/__snapshots__/file_row_header_spec.js.snap create mode 100644 spec/frontend/vue_shared/components/file_row_header_spec.js create mode 100644 spec/javascripts/diffs/components/diff_stats_spec.js create mode 100644 spec/javascripts/diffs/components/settings_dropdown_spec.js create mode 100644 spec/javascripts/fixtures/sessions.rb create mode 100644 spec/javascripts/helpers/vue_test_utils_helper.js create mode 100644 spec/javascripts/helpers/vue_test_utils_helper_spec.js create mode 100644 spec/javascripts/lib/utils/grammar_spec.js create mode 100644 spec/javascripts/lib/utils/icon_utils_spec.js create mode 100644 spec/javascripts/monitoring/charts/area_spec.js delete mode 100644 spec/javascripts/monitoring/graph/axis_spec.js delete mode 100644 spec/javascripts/monitoring/graph/deployment_spec.js delete mode 100644 spec/javascripts/monitoring/graph/flag_spec.js delete mode 100644 spec/javascripts/monitoring/graph/legend_spec.js delete mode 100644 spec/javascripts/monitoring/graph/track_info_spec.js delete mode 100644 spec/javascripts/monitoring/graph/track_line_spec.js delete mode 100644 spec/javascripts/monitoring/graph_path_spec.js delete mode 100644 spec/javascripts/monitoring/graph_spec.js delete mode 100644 spec/javascripts/monitoring/utils/multiple_time_series_spec.js create mode 100644 spec/javascripts/notes/components/discussion_jump_to_next_button_spec.js create mode 100644 spec/javascripts/notes/components/discussion_reply_placeholder_spec.js create mode 100644 spec/javascripts/notes/components/discussion_resolve_button_spec.js create mode 100644 spec/javascripts/notes/components/note_actions/reply_button_spec.js create mode 100644 spec/javascripts/pages/sessions/new/preserve_url_fragment_spec.js create mode 100644 spec/javascripts/serverless/components/environment_row_spec.js create mode 100644 spec/javascripts/serverless/components/function_row_spec.js create mode 100644 spec/javascripts/serverless/components/functions_spec.js create mode 100644 spec/javascripts/serverless/components/url_spec.js create mode 100644 spec/javascripts/serverless/mock_data.js create mode 100644 spec/javascripts/serverless/stores/serverless_store_spec.js create mode 100644 spec/javascripts/task_list_spec.js create mode 100644 spec/javascripts/vue_mr_widget/components/states/commit_edit_spec.js create mode 100644 spec/javascripts/vue_mr_widget/components/states/mr_widget_commit_message_dropdown_spec.js create mode 100644 spec/javascripts/vue_mr_widget/components/states/mr_widget_commits_header_spec.js create mode 100644 spec/javascripts/vue_mr_widget/components/states/mr_widget_squash_before_merge_spec.js rename spec/javascripts/{ide => vue_shared}/components/file_finder/index_spec.js (58%) rename spec/javascripts/{ide => vue_shared}/components/file_finder/item_spec.js (95%) create mode 100644 spec/lib/banzai/filter/footnote_filter_spec.rb create mode 100644 spec/lib/gitlab/access/branch_protection_spec.rb create mode 100644 spec/lib/gitlab/bitbucket_import/wiki_formatter_spec.rb delete mode 100644 spec/lib/gitlab/kubernetes/helm/upgrade_command_spec.rb create mode 100644 spec/lib/gitlab/loop_helpers_spec.rb create mode 100644 spec/lib/gitlab/tracing/factory_spec.rb create mode 100644 spec/lib/gitlab/tracing/grpc_interceptor_spec.rb create mode 100644 spec/lib/gitlab/tracing/jaeger_factory_spec.rb create mode 100644 spec/lib/gitlab/tracing/rack_middleware_spec.rb create mode 100644 spec/lib/gitlab/tracing/rails/action_view_subscriber_spec.rb create mode 100644 spec/lib/gitlab/tracing/rails/active_record_subscriber_spec.rb create mode 100644 spec/lib/gitlab/tracing/sidekiq/client_middleware_spec.rb create mode 100644 spec/lib/gitlab/tracing/sidekiq/server_middleware_spec.rb create mode 100644 spec/migrations/cleanup_legacy_artifact_migration_spec.rb create mode 100644 spec/migrations/fix_null_type_labels_spec.rb create mode 100644 spec/migrations/migrate_auto_dev_ops_domain_to_cluster_domain_spec.rb create mode 100644 spec/migrations/migrate_storage_migrator_sidekiq_queue_spec.rb create mode 100644 spec/models/application_record_spec.rb create mode 100644 spec/policies/board_policy_spec.rb create mode 100644 spec/requests/api/container_registry_spec.rb create mode 100644 spec/requests/api/group_labels_spec.rb create mode 100644 spec/requests/api/import_github_spec.rb create mode 100644 spec/requests/user_activity_spec.rb create mode 100644 spec/serializers/merge_request_widget_commit_entity_spec.rb create mode 100644 spec/services/ci/destroy_expired_job_artifacts_service_spec.rb create mode 100644 spec/services/clusters/applications/upgrade_service_spec.rb create mode 100644 spec/services/error_tracking/list_projects_service_spec.rb create mode 100644 spec/services/projects/container_repository/cleanup_tags_service_spec.rb rename spec/services/projects/{hashed_storage_migration_service_spec.rb => hashed_storage/migration_service_spec.rb} (97%) create mode 100644 spec/services/projects/protect_default_branch_service_spec.rb create mode 100644 spec/services/task_list_toggle_service_spec.rb create mode 100644 spec/support/helpers/features/responsive_table_helpers.rb create mode 100644 spec/support/migrations_helpers/cluster_helpers.rb create mode 100644 spec/support/shared_examples/models/cluster_application_initial_status.rb create mode 100644 spec/support/shared_examples/models/cluster_application_version_shared_examples.rb create mode 100644 spec/uploaders/external_diff_uploader_spec.rb create mode 100644 spec/views/projects/issues/_merge_requests_status.html.haml_spec.rb create mode 100644 spec/views/projects/issues/show.html.haml_spec.rb create mode 100644 spec/workers/cleanup_container_repository_worker_spec.rb rename spec/workers/{storage_migrator_worker_spec.rb => hashed_storage/migrator_worker_spec.rb} (86%) create mode 100644 vendor/project_templates/gitbook.tar.gz create mode 100644 vendor/project_templates/hexo.tar.gz create mode 100644 vendor/project_templates/hugo.tar.gz create mode 100644 vendor/project_templates/jekyll.tar.gz create mode 100644 vendor/project_templates/plainhtml.tar.gz diff --git a/.babelrc.js b/.babelrc.js index bfcc7d9663..1b05a67354 100644 --- a/.babelrc.js +++ b/.babelrc.js @@ -18,6 +18,7 @@ const plugins = [ '@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 diff --git a/.gitignore b/.gitignore index 65f61e1fad..0696dd217a 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 45de5ce61c..4e8453726a 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 @@ -386,20 +386,27 @@ 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:v4" + paths: + - vendor/ruby/ + - .yarn-cache/ + # We have disabled caching of sprockets for now, as it fails to pick up changes in SCSS: + # https://gitlab.com/gitlab-org/gitlab-ce/issues/57431 + # - 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 @@ -408,6 +415,7 @@ compile-assets: paths: - node_modules - public/assets + <<: *assets-compile-cache setup-test-env: <<: *dedicated-runner @@ -427,15 +435,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 @@ -445,6 +445,17 @@ setup-test-env: refs: - master - /(^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 @@ -499,6 +510,22 @@ rspec-mysql: <<: *rspec-metadata-mysql parallel: 50 +.rspec-quarantine: &rspec-quarantine + 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: @@ -527,7 +554,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 @@ -608,8 +635,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: @@ -623,18 +651,19 @@ 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 @@ -788,6 +817,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 @@ -802,11 +832,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 @@ -854,6 +879,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: [] @@ -863,6 +903,7 @@ pages: - karma - gitlab:assets:compile - lint:javascript:report + - jsdoc script: - mv public/ .public/ - mkdir public/ @@ -872,6 +913,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 @@ -918,6 +960,23 @@ no_ee_check: - //@gitlab-org/gitlab-ce # GitLab Review apps +review-build-cng: + <<: *review-only + 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-deploy: <<: *review-base retry: 2 @@ -932,15 +991,14 @@ 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=$( + +- [ ] 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/Feature proposal.md b/.gitlab/issue_templates/Feature proposal.md index 639a236631..1bb8d33ff6 100644 --- a/.gitlab/issue_templates/Feature proposal.md +++ b/.gitlab/issue_templates/Feature proposal.md @@ -4,7 +4,30 @@ ### Target audience - + ### Further details @@ -12,12 +35,12 @@ ### Proposal - + ### What does success look like, and how can we measure that? - + ### 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 0000000000..ae469d3b12 --- /dev/null +++ b/.gitlab/issue_templates/Security Release.md @@ -0,0 +1,69 @@ + + +## 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}
+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 08651195d9..aaa1614539 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 diff --git a/.gitlab/merge_request_templates/Security Release.md b/.gitlab/merge_request_templates/Security Release.md new file mode 100644 index 0000000000..246f2dae00 --- /dev/null +++ b/.gitlab/merge_request_templates/Security Release.md @@ -0,0 +1,31 @@ + +## Related issues + + + +## 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 e8e550fdbd..bcff67ded8 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -143,6 +143,7 @@ Naming/FileName: - XMPP - XSRF - XSS + - GRPC # GitLab ################################################################### diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml index 847a0f74aa..77ad4753c8 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: @@ -443,11 +432,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 +670,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/CHANGELOG.md b/CHANGELOG.md index 8890a82932..feda5e0835 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,253 @@ 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 ) +- 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 +/-/. +- 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) @@ -16,19 +263,15 @@ entry. - Changed external wiki query method to prevent attribute caching. !24907 -## 11.7.4 (2019-02-04) - -### Security (1 change) - -- Use sanitized user status message for user popover. - - -## 11.7.3 (2019-01-30) - -- No changes. - ## 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 @@ -56,14 +299,6 @@ entry. - Notify only users who can access the project on project move. - Alias GitHub and BitBucket OAuth2 callback URLs. -### Fixed (1 change) - -- Fix uninitialized constant with GitLab Pages. - - -## 11.7.1 (2019-01-28) - -- Unreleased due to quality assurance failure. ## 11.7.0 (2019-01-22) @@ -251,6 +486,28 @@ entry. - Update url placeholder for the sentry configuration page. !24338 +## 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) @@ -573,6 +830,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/GITALY_SERVER_VERSION b/GITALY_SERVER_VERSION index 6b89d58f86..3989355915 100644 --- a/GITALY_SERVER_VERSION +++ b/GITALY_SERVER_VERSION @@ -1 +1 @@ -1.12.2 +1.20.0 diff --git a/GITLAB_PAGES_VERSION b/GITLAB_PAGES_VERSION index 3a3cd8cc8b..bc80560fad 100644 --- a/GITLAB_PAGES_VERSION +++ b/GITLAB_PAGES_VERSION @@ -1 +1 @@ -1.3.1 +1.5.0 diff --git a/GITLAB_WORKHORSE_VERSION b/GITLAB_WORKHORSE_VERSION index 8b22a322d0..56b6be4ebb 100644 --- a/GITLAB_WORKHORSE_VERSION +++ b/GITLAB_WORKHORSE_VERSION @@ -1 +1 @@ -8.0.2 +8.3.1 diff --git a/Gemfile b/Gemfile index f59e61208a..a3b01c275c 100644 --- a/Gemfile +++ b/Gemfile @@ -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' @@ -113,10 +113,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' @@ -126,9 +125,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.5' +gem 'nokogiri', '~> 1.10.1' gem 'escape_utils', '~> 1.1' # Calendar rendering @@ -161,12 +160,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' @@ -188,7 +187,7 @@ gem 're2', '~> 1.1.1' gem 'version_sorter', '~> 2.1.0' # Export Ruby Regex to Javascript -gem 'js_regex', '~> 2.2.1' +gem 'js_regex', '~> 3.1' # User agent parsing gem 'device_detector' @@ -225,7 +224,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' @@ -305,6 +304,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 @@ -417,7 +422,7 @@ group :ed25519 do end # Gitaly GRPC client -gem 'gitaly-proto', '~> 1.5.0', require: 'gitaly' +gem 'gitaly-proto', '~> 1.10.0', require: 'gitaly' gem 'grpc', '~> 1.15.0' gem 'google-protobuf', '~> 3.6' diff --git a/Gemfile.lock b/Gemfile.lock index 77b4360cf4..0b2bd2c96b 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -113,6 +113,7 @@ GEM 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) @@ -143,7 +144,7 @@ GEM 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) @@ -258,6 +259,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 +278,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.10.0) grpc (~> 1.0) github-markup (1.7.0) gitlab-default_value_for (3.1.1) @@ -282,7 +286,7 @@ 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) @@ -389,13 +393,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 @@ -419,7 +428,7 @@ GEM kgio (2.10.0) 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) @@ -462,9 +471,9 @@ GEM mimemagic (0.3.2) mini_magick (4.8.0) mini_mime (1.0.1) - mini_portile2 (2.3.0) + mini_portile2 (2.4.0) minitest (5.11.3) - msgpack (1.2.4) + msgpack (1.2.6) multi_json (1.13.1) multi_xml (0.6.0) multipart-post (2.0.0) @@ -477,8 +486,8 @@ 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) @@ -544,6 +553,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 +586,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) @@ -606,6 +617,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,7 +630,7 @@ 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 @@ -664,16 +676,15 @@ GEM 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 +704,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 +787,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 +826,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) @@ -868,6 +879,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 +887,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) @@ -974,7 +985,7 @@ DEPENDENCIES connection_pool (~> 2.0) creole (~> 0.5.0) database_cleaner (~> 1.7.0) - deckar01-task_list (= 2.0.0) + deckar01-task_list (= 2.2.0) device_detector devise (~> 4.4) devise-two-factor (~> 3.0.0) @@ -1003,12 +1014,13 @@ DEPENDENCIES 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.10.0) github-markup (~> 1.7.0) gitlab-default_value_for (~> 3.1.1) gitlab-markup (~> 1.6.5) @@ -1037,14 +1049,15 @@ DEPENDENCIES 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 (~> 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) @@ -1059,7 +1072,7 @@ DEPENDENCIES nakayoshi_fork (~> 0.0.4) net-ldap net-ssh (~> 5.0) - nokogiri (~> 1.8.5) + nokogiri (~> 1.10.1) oauth2 (~> 1.4) octokit (~> 4.9) omniauth (~> 1.8) @@ -1077,6 +1090,7 @@ DEPENDENCIES 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,7 +1098,7 @@ 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.5.1) @@ -1107,7 +1121,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) @@ -1128,7 +1141,6 @@ DEPENDENCIES ruby-progressbar ruby_parser (~> 3.8) rubyzip (~> 1.2.2) - rufus-scheduler (~> 3.4) rugged (~> 0.27) sanitize (~> 4.6) sass (~> 3.5) @@ -1142,7 +1154,7 @@ 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) @@ -1157,7 +1169,7 @@ 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) diff --git a/PROCESS.md b/PROCESS.md index f2eed5544f..7fdac09880 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 diff --git a/VERSION b/VERSION index 64e4bdff1c..897063bb32 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -11.7.5 +11.8.0 diff --git a/app/assets/javascripts/api.js b/app/assets/javascripts/api.js index d1396b6c4b..85eb08cc97 100644 --- a/app/assets/javascripts/api.js +++ b/app/assets/javascripts/api.js @@ -5,6 +5,7 @@ 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', @@ -40,6 +41,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); diff --git a/app/assets/javascripts/awards_handler.js b/app/assets/javascripts/awards_handler.js index cace8bb9db..73ce3e760a 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 = ` - diff --git a/app/assets/javascripts/badges/components/badge_list_row.vue b/app/assets/javascripts/badges/components/badge_list_row.vue index 9051be1e10..cad5611c8c 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)" > @@ -65,7 +65,7 @@ export default { type="button" data-toggle="modal" data-target="#delete-badge-modal" - @click="updateBadgeInModal(badge);" + @click="updateBadgeInModal(badge)" > diff --git a/app/assets/javascripts/behaviors/gl_emoji.js b/app/assets/javascripts/behaviors/gl_emoji.js index 56293d5f96..d1d7565818 100644 --- a/app/assets/javascripts/behaviors/gl_emoji.js +++ b/app/assets/javascripts/behaviors/gl_emoji.js @@ -1,11 +1,10 @@ -import installCustomElements from 'document-register-element'; +import 'document-register-element'; import isEmojiUnicodeSupported from '../emoji/support'; -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; @@ -43,9 +42,11 @@ export default function installGlEmojiElement() { }); } } - }; - - document.registerElement('gl-emoji', { - prototype: GlEmojiElementProto, - }); + } +} + +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 fe02096d90..9482a9f166 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 `
\n${lines.join('\n')}\n
\n`; - }, - 'dt, dd, summary, details'(el, text) { - const tag = el.nodeName.toLowerCase(); - return `<${tag}>${text}\n`; - }, - 'sup, sub, kbd, q, samp, var, ruby, rt, rp, abbr'(el, text) { - const tag = el.nodeName.toLowerCase(); - return `<${tag}>${text}`; - }, - }, - 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,22 @@ export class CopyAsGFM { return codeElement; } - static nodeToGFM(node, respectWhitespaceParam = false) { - if (node.nodeType === Node.COMMENT_NODE) { - return ''; - } + 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); - 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; + const res = markdownSerializer.default.serialize(doc); + 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 0000000000..47e5fc65c4 --- /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 0000000000..b537954c1c --- /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 0000000000..a760ee80dd --- /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 0000000000..ce425e80cd --- /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 0000000000..ebed8698e2 --- /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 ``; + }, + }; + } +} 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 0000000000..44b35c9773 --- /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 0000000000..5c23d6a5ce --- /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 0000000000..e582fb18f1 --- /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 0000000000..c2951a40a4 --- /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 0000000000..b0bc8f7964 --- /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 0000000000..3b0792e1af --- /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 0000000000..1e0c05eff0 --- /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 0000000000..a4451d8ce8 --- /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('
'); + state.text(node.textContent, false); + state.write('
'); + 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 0000000000..6aa1aca29d --- /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('
\n'); + state.wrapBlock(' ', null, node, () => state.renderContent(node)); + state.flushClose(1); + state.ensureNewLine(); + state.write('
'); + 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 0000000000..89057ec644 --- /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('
'); + state.text(node.textContent, false); + state.write('
'); + 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 0000000000..1c40dbb816 --- /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('
\n'); + state.renderContent(node); + state.flushClose(1); + state.ensureNewLine(); + state.write('
'); + 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 0000000000..88b16fd85d --- /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 0000000000..a7cc3e828f --- /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 0000000000..59e5d8ab3e --- /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 0000000000..fec8608cf5 --- /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 0000000000..695c7160bd --- /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 0000000000..c225a5ed87 --- /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 0000000000..4237637ed9 --- /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 0000000000..4c1542d14e --- /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 0000000000..25c4976a1b --- /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 0000000000..dec3207b1b --- /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 0000000000..5d6bbeca83 --- /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 0000000000..2e36e316d7 --- /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(''); + state.text(node.textContent, false); + state.write(''); + 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 0000000000..a7fcb9227c --- /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 0000000000..403556dc0c --- /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 0000000000..c63bfe10e3 --- /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 0000000000..4cb94bf088 --- /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 0000000000..e7eee63640 --- /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 0000000000..20c7fa8a9a --- /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 0000000000..5852502773 --- /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 0000000000..ab33bc2150 --- /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 0000000000..d0ee7333d5 --- /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 0000000000..84838c1499 --- /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 0000000000..516f983397 --- /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/schema.js b/app/assets/javascripts/behaviors/markdown/schema.js new file mode 100644 index 0000000000..163182ab77 --- /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 0000000000..70dbd8bd20 --- /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 35f1bb6b08..7adccbb062 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 2918e1486a..680f203140 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); + const blockquoteEl = document.createElement('blockquote'); + blockquoteEl.appendChild(el); + CopyAsGFM.nodeToGFM(blockquoteEl) + .then(text => { + if (text.trim() === '') { + return false; + } - if (selected.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'); - const quote = _.map(selected.split('\n'), val => `${`> ${val}`.trim()}\n`); + // Trigger autosize + const event = document.createEvent('Event'); + event.initEvent('autosize:update', true, false); + $replyField.get(0).dispatchEvent(event); - // 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'); + // Focus the input field + $replyField.focus(); - // Trigger autosize - const event = document.createEvent('Event'); - event.initEvent('autosize:update', true, false); - $replyField.get(0).dispatchEvent(event); - - // Focus the input field - $replyField.focus(); + return false; + }) + .catch(() => {}); return false; } diff --git a/app/assets/javascripts/boards/components/board_card.vue b/app/assets/javascripts/boards/components/board_card.vue index 30fbdb9e97..f569322ab7 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)" >
-
+
An error occurred. Please try again.
diff --git a/app/assets/javascripts/boards/components/issue_card_inner.vue b/app/assets/javascripts/boards/components/issue_card_inner.vue index 0f581c3d37..90ab3a7634 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 }} diff --git a/app/assets/javascripts/boards/components/modal/empty_state.vue b/app/assets/javascripts/boards/components/modal/empty_state.vue index defd857b92..2a0008467c 100644 --- a/app/assets/javascripts/boards/components/modal/empty_state.vue +++ b/app/assets/javascripts/boards/components/modal/empty_state.vue @@ -58,7 +58,7 @@ export default { v-if="activeTab === 'selected'" class="btn btn-default" type="button" - @click="changeTab('all');" + @click="changeTab('all')" > Open issues diff --git a/app/assets/javascripts/boards/components/modal/footer.vue b/app/assets/javascripts/boards/components/modal/footer.vue index b1bc7d8708..d4afd9d59d 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 { to list
- diff --git a/app/assets/javascripts/boards/components/modal/header.vue b/app/assets/javascripts/boards/components/modal/header.vue index d0e285a149..1f0961e02d 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)" > diff --git a/app/assets/javascripts/boards/components/modal/list.vue b/app/assets/javascripts/boards/components/modal/list.vue index 878bb002c6..e9ed2de859 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 {
{{ list.title }} diff --git a/app/assets/javascripts/boards/components/modal/tabs.vue b/app/assets/javascripts/boards/components/modal/tabs.vue index 7b800a6ab9..2d2920e312 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 {