From dd13d6ff10073d2a30bab29fff1e8b1c4998014e Mon Sep 17 00:00:00 2001
From: Pirate Praveen
Date: Wed, 9 May 2018 12:01:36 +0530
Subject: [PATCH] New upstream version 10.7.3+dfsg
---
.babelrc | 26 +-
.codeclimate.yml | 6 -
.eslintignore | 5 +-
.eslintrc | 28 +-
.flayignore | 1 +
.gitignore | 5 +
.gitlab-ci.yml | 133 +-
.../Database Changes.md | 11 +-
.../merge_request_templates/Documentation.md | 27 +-
.prettierignore | 5 +
.prettierrc | 13 +
.rubocop.yml | 72 +
.scss-lint.yml | 2 +
CHANGELOG.md | 323 +-
CONTRIBUTING.md | 18 +-
GITALY_SERVER_VERSION | 2 +-
GITLAB_PAGES_VERSION | 2 +-
GITLAB_SHELL_VERSION | 2 +-
GITLAB_WORKHORSE_VERSION | 2 +-
Gemfile | 90 +-
Gemfile.lock | 249 +-
Gemfile.rails5 | 7 +
Gemfile.rails5.lock | 1223 ++
PROCESS.md | 5 +-
Procfile | 1 -
VERSION | 2 +-
.../canary/favicon_status_canceled.ico | Bin 0 -> 4286 bytes
.../canary/favicon_status_created.ico | Bin 0 -> 4286 bytes
.../canary/favicon_status_failed.ico | Bin 0 -> 4286 bytes
.../canary/favicon_status_manual.ico | Bin 0 -> 4286 bytes
.../canary/favicon_status_not_found.ico | Bin 0 -> 4286 bytes
.../canary/favicon_status_pending.ico | Bin 0 -> 4286 bytes
.../canary/favicon_status_running.ico | Bin 0 -> 4286 bytes
.../canary/favicon_status_skipped.ico | Bin 0 -> 4286 bytes
.../canary/favicon_status_success.ico | Bin 0 -> 4286 bytes
.../canary/favicon_status_warning.ico | Bin 0 -> 4286 bytes
app/assets/images/favicon-yellow.ico | Bin 0 -> 5430 bytes
app/assets/images/icons.json | 1 -
app/assets/images/icons.svg | 1 -
.../images/illustrations/cluster_popover.svg | 1 -
.../images/illustrations/clusters_empty.svg | 1 -
.../illustrations/convdev/convdev_no_data.svg | 1 -
.../convdev/convdev_no_index.svg | 1 -
.../convdev/convdev_overview.svg | 1 -
.../illustrations/convdev/i2p_step_1.svg | 1 -
.../illustrations/convdev/i2p_step_10.svg | 1 -
.../illustrations/convdev/i2p_step_2.svg | 1 -
.../illustrations/convdev/i2p_step_3.svg | 1 -
.../illustrations/convdev/i2p_step_4.svg | 1 -
.../illustrations/convdev/i2p_step_5.svg | 1 -
.../illustrations/convdev/i2p_step_6.svg | 1 -
.../illustrations/convdev/i2p_step_7.svg | 1 -
.../illustrations/convdev/i2p_step_8.svg | 1 -
.../illustrations/convdev/i2p_step_9.svg | 1 -
app/assets/images/illustrations/epics.svg | 1 -
.../images/illustrations/gitlab_logo.svg | 1 -
.../image_comment_light_cursor.svg | 1 -
.../image_comment_light_cursor@2x.svg | 1 -
app/assets/images/illustrations/issues.svg | 1 -
.../illustrations/job_not_triggered.svg | 1 -
app/assets/images/illustrations/labels.svg | 1 -
.../images/illustrations/logos/go_logo.svg | 1 -
.../illustrations/logos/mattermost_logo.svg | 1 -
.../images/illustrations/manual_action.svg | 1 -
.../merge_request_changes_empty.svg | 1 -
.../images/illustrations/merge_requests.svg | 1 -
.../monitoring/getting_started.svg | 1 -
.../illustrations/monitoring/loading.svg | 1 -
.../monitoring/unable_to_connect.svg | 1 -
...lti-editor_all_changes_committed_empty.svg | 1 -
.../multi-editor_no_changes_empty.svg | 1 -
.../multi-editor_no_staged_files_empty.svg | 1 -
.../illustrations/multi_file_editor_empty.svg | 1 -
.../images/illustrations/no_commits.svg | 1 -
.../illustrations/pending_job_empty.svg | 1 -
.../images/illustrations/pipelines_empty.svg | 1 -
.../images/illustrations/pipelines_failed.svg | 1 -
.../illustrations/pipelines_pending.svg | 1 -
.../images/illustrations/priority_labels.svg | 1 -
.../illustrations/service_desk_callout.svg | 1 -
.../illustrations/service_desk_empty.svg | 1 -
.../images/illustrations/slack_logo.svg | 1 -
.../images/illustrations/todos_all_done.svg | 1 -
.../images/illustrations/todos_empty.svg | 1 -
.../illustrations/welcome/add_new_group.svg | 1 -
.../illustrations/welcome/add_new_project.svg | 1 -
.../illustrations/welcome/add_new_user.svg | 1 -
.../welcome/configure_server.svg | 1 -
.../images/illustrations/welcome/ee_trial.svg | 1 -
.../images/illustrations/welcome/globe.svg | 1 -
.../illustrations/welcome/lightbulb.svg | 1 -
.../wiki-fro-logged-out-users.svg | 1 -
.../images/illustrations/wiki_login_empty.svg | 1 -
.../illustrations/wiki_logout_empty.svg | 1 -
app/assets/javascripts/activities.js | 1 +
.../javascripts/ajax_loading_spinner.js | 2 +
app/assets/javascripts/api.js | 147 +-
app/assets/javascripts/awards_handler.js | 17 +-
.../javascripts/badges/components/badge.vue | 121 +
.../badges/components/badge_form.vue | 219 +
.../badges/components/badge_list.vue | 57 +
.../badges/components/badge_list_row.vue | 89 +
.../badges/components/badge_settings.vue | 70 +
app/assets/javascripts/badges/constants.js | 2 +
app/assets/javascripts/badges/empty_badge.js | 7 +
.../javascripts/badges/store/actions.js | 167 +
app/assets/javascripts/badges/store/index.js | 13 +
.../badges/store/mutation_types.js | 21 +
.../javascripts/badges/store/mutations.js | 158 +
app/assets/javascripts/badges/store/state.js | 13 +
.../behaviors/copy_to_clipboard.js | 1 +
.../javascripts/behaviors/details_behavior.js | 1 +
app/assets/javascripts/behaviors/index.js | 3 +-
.../behaviors/{ => markdown}/copy_as_gfm.js | 5 +-
.../{ => behaviors/markdown}/render_gfm.js | 3 +-
.../{ => behaviors/markdown}/render_math.js | 7 +-
.../markdown}/render_mermaid.js | 6 +-
.../javascripts/behaviors/quick_submit.js | 3 +-
.../javascripts/behaviors/requires_input.js | 1 +
.../javascripts/behaviors/toggler_behavior.js | 4 +-
.../javascripts/blob/blob_file_dropzone.js | 2 +
.../javascripts/blob/blob_fork_suggestion.js | 2 +
.../blob/file_template_mediator.js | 2 +
.../blob/file_template_selector.js | 2 +
.../javascripts/blob/template_selector.js | 4 +-
app/assets/javascripts/blob/viewer/index.js | 1 +
.../javascripts/blob_edit/blob_bundle.js | 2 +
app/assets/javascripts/blob_edit/edit_blob.js | 1 +
.../javascripts/boards/components/board.js | 2 +
.../boards/components/board_delete.js | 1 +
.../boards/components/board_new_issue.vue | 1 +
.../boards/components/board_sidebar.js | 9 +-
.../boards/components/issue_card_inner.js | 18 +-
.../boards/components/new_list_dropdown.js | 5 +-
.../boards/components/project_select.vue | 2 +
.../boards/components/sidebar/remove_issue.js | 6 +-
.../boards/filtered_search_boards.js | 1 +
app/assets/javascripts/boards/index.js | 1 +
.../boards/mixins/sortable_default_options.js | 1 +
app/assets/javascripts/boards/models/issue.js | 6 +-
app/assets/javascripts/boards/models/list.js | 2 +
.../javascripts/boards/stores/boards_store.js | 2 +
.../branches/branches_delete_modal.js | 2 +
app/assets/javascripts/breadcrumb.js | 2 +
app/assets/javascripts/build_artifacts.js | 2 +
app/assets/javascripts/build_variables.js | 4 +-
.../ci_variable_list/ci_variable_list.js | 4 +-
.../native_form_variable_list.js | 1 +
app/assets/javascripts/commit/image_file.js | 2 +
.../javascripts/commit_merge_requests.js | 1 +
app/assets/javascripts/commits.js | 1 +
app/assets/javascripts/compare.js | 2 +
.../javascripts/compare_autocomplete.js | 2 +
.../javascripts/confirm_danger_modal.js | 57 +-
app/assets/javascripts/contextual_sidebar.js | 1 +
app/assets/javascripts/create_label.js | 2 +
.../cycle_analytics/cycle_analytics_bundle.js | 1 +
app/assets/javascripts/diff.js | 1 +
.../components/comment_resolve_btn.js | 1 +
.../components/diff_note_avatars.js | 1 +
.../components/jump_to_discussion.js | 1 +
.../diff_notes/components/resolve_btn.js | 1 +
.../diff_notes/diff_notes_bundle.js | 1 +
.../diff_notes/models/discussion.js | 1 +
app/assets/javascripts/dispatcher.js | 14 +-
app/assets/javascripts/dropzone_input.js | 1 +
app/assets/javascripts/due_date_select.js | 1 +
.../components/environment_stop.vue | 2 +
app/assets/javascripts/experimental_flags.js | 1 +
.../feature_highlight/feature_highlight.js | 1 +
.../feature_highlight_helper.js | 1 +
app/assets/javascripts/filterable_list.js | 1 +
.../filtered_search_dropdown_manager.js | 18 +-
.../filtered_search_manager.js | 3 +-
app/assets/javascripts/gfm_auto_complete.js | 23 +-
app/assets/javascripts/gl_dropdown.js | 6 +-
app/assets/javascripts/gl_field_error.js | 2 +
app/assets/javascripts/gl_field_errors.js | 1 +
app/assets/javascripts/gl_form.js | 7 +-
app/assets/javascripts/gpg_badges.js | 1 +
app/assets/javascripts/group.js | 2 +
app/assets/javascripts/group_avatar.js | 2 +
.../javascripts/group_label_subscription.js | 1 +
.../javascripts/groups/components/app.vue | 89 +-
.../groups/groups_filterable_list.js | 1 +
.../javascripts/groups/transfer_dropdown.js | 2 +
app/assets/javascripts/groups_select.js | 1 +
app/assets/javascripts/header.js | 1 +
app/assets/javascripts/help/help.js | 3 +
app/assets/javascripts/how_to_merge.js | 2 +
.../ide/components/changed_file_icon.vue | 31 +
.../ide/components/commit_sidebar/actions.vue | 65 +
.../ide/components/commit_sidebar/list.vue | 66 +
.../commit_sidebar/list_collapsed.vue | 35 +
.../components/commit_sidebar/list_item.vue | 58 +
.../components/commit_sidebar/radio_group.vue | 94 +
.../ide/components/editor_mode_dropdown.vue | 130 +
app/assets/javascripts/ide/components/ide.vue | 108 +
.../ide/components/ide_context_bar.vue | 84 +
.../ide/components/ide_external_links.vue | 43 +
.../ide/components/ide_file_buttons.vue | 84 +
.../components/ide_project_branches_tree.vue | 47 +
.../ide/components/ide_project_tree.vue | 65 +
.../ide/components/ide_repo_tree.vue | 41 +
.../ide/components/ide_side_bar.vue | 51 +
.../ide/components/ide_status_bar.vue | 60 +
.../ide/components/mr_file_icon.vue | 23 +
.../ide/components/new_dropdown/index.vue | 111 +
.../ide/components/new_dropdown/modal.vue | 99 +
.../ide/components/new_dropdown/upload.vue | 75 +
.../ide/components/repo_commit_section.vue | 172 +
.../ide/components/repo_editor.vue | 219 +
.../javascripts/ide/components/repo_file.vue | 127 +
.../ide/components/repo_file_status_icon.vue | 39 +
.../ide/components/repo_loading_file.vue | 42 +
.../javascripts/ide/components/repo_tab.vue | 104 +
.../javascripts/ide/components/repo_tabs.vue | 82 +
.../ide/components/resizable_panel.vue | 85 +
app/assets/javascripts/ide/eventhub.js | 3 +
app/assets/javascripts/ide/ide_router.js | 173 +
app/assets/javascripts/ide/index.js | 33 +
.../javascripts/ide/lib/common/disposable.js | 14 +
.../javascripts/ide/lib/common/model.js | 94 +
.../ide/lib/common/model_manager.js | 48 +
.../ide/lib/decorations/controller.js | 45 +
.../javascripts/ide/lib/diff/controller.js | 72 +
app/assets/javascripts/ide/lib/diff/diff.js | 30 +
.../javascripts/ide/lib/diff/diff_worker.js | 10 +
app/assets/javascripts/ide/lib/editor.js | 192 +
.../javascripts/ide/lib/editor_options.js | 16 +
.../javascripts/ide/lib/themes/gl_theme.js | 14 +
app/assets/javascripts/ide/monaco_loader.js | 16 +
app/assets/javascripts/ide/services/index.js | 78 +
app/assets/javascripts/ide/stores/actions.js | 118 +
.../javascripts/ide/stores/actions/file.js | 187 +
.../ide/stores/actions/merge_request.js | 84 +
.../javascripts/ide/stores/actions/project.js | 49 +
.../javascripts/ide/stores/actions/tree.js | 95 +
app/assets/javascripts/ide/stores/getters.js | 37 +
app/assets/javascripts/ide/stores/index.js | 19 +
.../ide/stores/modules/commit/actions.js | 200 +
.../ide/stores/modules/commit/constants.js | 3 +
.../ide/stores/modules/commit/getters.js | 24 +
.../ide/stores/modules/commit/index.js | 12 +
.../stores/modules/commit/mutation_types.js | 4 +
.../ide/stores/modules/commit/mutations.js | 24 +
.../ide/stores/modules/commit/state.js | 6 +
.../javascripts/ide/stores/mutation_types.js | 55 +
.../javascripts/ide/stores/mutations.js | 103 +
.../ide/stores/mutations/branch.js | 26 +
.../javascripts/ide/stores/mutations/file.js | 147 +
.../ide/stores/mutations/merge_request.js | 33 +
.../ide/stores/mutations/project.js | 24 +
.../javascripts/ide/stores/mutations/tree.js | 34 +
app/assets/javascripts/ide/stores/state.js | 20 +
app/assets/javascripts/ide/stores/utils.js | 134 +
.../stores/workers/files_decorator_worker.js | 90 +
.../javascripts/image_diff/image_diff.js | 1 +
app/assets/javascripts/importer_status.js | 1 +
.../javascripts/init_changes_dropdown.js | 1 +
app/assets/javascripts/init_labels.js | 1 +
.../integrations/integration_settings_form.js | 1 +
.../issuable/auto_width_dropdown_select.js | 2 +
.../issuable_bulk_update_actions.js | 2 +
.../issuable_bulk_update_sidebar.js | 1 +
app/assets/javascripts/issuable_context.js | 1 +
app/assets/javascripts/issuable_form.js | 1 +
app/assets/javascripts/issuable_index.js | 1 +
app/assets/javascripts/issue.js | 2 +
.../issue_show/components/description.vue | 1 +
.../fields/description_template.vue | 1 +
app/assets/javascripts/issue_status_select.js | 2 +
app/assets/javascripts/job.js | 1 +
.../jobs/components/sidebar_detail_row.vue | 24 +
.../jobs/components/sidebar_details_block.vue | 27 +
.../javascripts/jobs/job_details_bundle.js | 1 +
app/assets/javascripts/label_manager.js | 2 +
app/assets/javascripts/labels.js | 2 +
app/assets/javascripts/labels_select.js | 2 +
app/assets/javascripts/layout_nav.js | 1 +
.../lib/utils/bootstrap_linked_tabs.js | 2 +
.../javascripts/lib/utils/common_utils.js | 5 +-
app/assets/javascripts/lib/utils/csrf.js | 2 +
.../javascripts/lib/utils/datetime_utility.js | 1 +
app/assets/javascripts/lib/utils/dom_utils.js | 7 +-
.../javascripts/lib/utils/text_markdown.js | 135 +-
.../javascripts/lib/utils/text_utility.js | 34 +-
.../javascripts/lib/utils/url_utility.js | 10 +-
app/assets/javascripts/line_highlighter.js | 2 +
app/assets/javascripts/logo.js | 2 +
app/assets/javascripts/main.js | 14 +-
.../javascripts/member_expiration_date.js | 1 +
app/assets/javascripts/members.js | 2 +
.../merge_conflicts/merge_conflict_store.js | 1 +
.../merge_conflicts/merge_conflicts_bundle.js | 1 +
app/assets/javascripts/merge_request.js | 2 +
app/assets/javascripts/merge_request_tabs.js | 53 +-
app/assets/javascripts/milestone.js | 1 +
app/assets/javascripts/milestone_select.js | 2 +
.../mini_pipeline_graph_dropdown.js | 2 +
.../monitoring/components/dashboard.vue | 288 +-
.../monitoring/components/empty_state.vue | 159 +-
.../monitoring/components/graph.vue | 442 +-
.../monitoring/components/graph/axis.vue | 142 +
.../components/graph/deployment.vue | 48 +-
.../monitoring/components/graph/flag.vue | 246 +-
.../monitoring/components/graph/legend.vue | 258 +-
.../monitoring/components/graph/path.vue | 60 +-
.../components/graph/track_info.vue | 29 +
.../components/graph/track_line.vue | 36 +
.../monitoring/components/graph_group.vue | 24 +-
.../monitoring/stores/monitoring_store.js | 2 +-
.../monitoring/utils/multiple_time_series.js | 82 +-
app/assets/javascripts/mr_notes/index.js | 14 +-
app/assets/javascripts/namespace_select.js | 2 +
.../javascripts/network/branch_graph.js | 1 +
app/assets/javascripts/new_branch_form.js | 2 +
app/assets/javascripts/notes.js | 745 +-
.../notes/components/comment_form.vue | 578 +-
.../notes/components/diff_file_header.vue | 34 +-
.../notes/components/diff_with_note.vue | 95 +-
.../notes/components/discussion_counter.vue | 114 +-
.../components/discussion_locked_widget.vue | 18 +-
.../notes/components/note_actions.vue | 217 +-
.../notes/components/note_attachment.vue | 16 +-
.../notes/components/note_awards_list.vue | 354 +-
.../notes/components/note_body.vue | 136 +-
.../notes/components/note_edited_text.vue | 50 +-
.../notes/components/note_form.vue | 228 +-
.../notes/components/note_header.vue | 110 +-
.../components/note_signed_out_widget.vue | 24 +-
.../notes/components/noteable_discussion.vue | 380 +-
.../notes/components/noteable_note.vue | 262 +-
.../notes/components/notes_app.vue | 288 +-
app/assets/javascripts/notes/constants.js | 7 +
app/assets/javascripts/notes/index.js | 73 +-
.../javascripts/notes/mixins/autosave.js | 7 +-
.../javascripts/notes/mixins/noteable.js | 9 +-
.../javascripts/notes/mixins/resolvable.js | 11 +-
.../notes/services/notes_service.js | 4 +-
.../javascripts/notes/stores/actions.js | 254 +-
.../javascripts/notes/stores/getters.js | 34 +-
.../javascripts/notes/stores/mutations.js | 28 +-
app/assets/javascripts/notes/stores/utils.js | 13 +-
.../javascripts/notifications_dropdown.js | 1 +
app/assets/javascripts/notifications_form.js | 1 +
app/assets/javascripts/pager.js | 1 +
.../admin/abuse_reports/abuse_reports.js | 1 +
app/assets/javascripts/pages/admin/admin.js | 1 +
.../pages/admin/application_settings/index.js | 6 +
.../broadcast_messages/broadcast_message.js | 1 +
.../index/components/delete_project_modal.vue | 8 +-
.../pages/admin/projects/index/index.js | 1 +
.../users/components/delete_user_modal.vue | 8 +-
.../javascripts/pages/admin/users/index.js | 1 +
.../pages/dashboard/todos/index/todos.js | 2 +
.../javascripts/pages/groups/edit/index.js | 2 +
.../javascripts/pages/groups/issues/index.js | 1 +
.../pages/groups/merge_requests/index.js | 1 +
.../pages/groups/settings/badges/index.js | 10 +
.../javascripts/pages/help/index/index.js | 1 +
.../components/delete_milestone_modal.vue | 8 +-
.../javascripts/pages/profiles/index.js | 1 +
.../pages/profiles/two_factor_auths/index.js | 1 +
.../pages/projects/blob/show/index.js | 22 +
.../pages/projects/branches/new/index.js | 1 +
.../{ => projects}/ci/lints/ci_lint_editor.js | 0
.../{ => projects}/ci/lints/new/index.js | 0
.../{ => projects}/ci/lints/show/index.js | 0
.../pages/projects/commit/pipelines/index.js | 1 +
.../pages/projects/commit/show/index.js | 2 +
.../javascripts/pages/projects/edit/index.js | 2 +
.../pages/projects/find_file/show/index.js | 1 +
.../pages/projects/graphs/charts/index.js | 1 +
.../pages/projects/graphs/show/index.js | 1 +
.../graphs/show/stat_graph_contributors.js | 1 +
.../show/stat_graph_contributors_graph.js | 2 +
.../javascripts/pages/projects/issues/form.js | 2 +
.../merge_requests/init_merge_request.js | 1 +
.../pages/projects/network/network.js | 1 +
.../pages/projects/network/show/index.js | 1 +
.../components/target_branch_dropdown.js | 2 +
.../shared/components/timezone_dropdown.js | 2 +
.../pipeline_schedules/shared/init_form.js | 1 +
.../pages/projects/pipelines/charts/index.js | 1 +
.../pages/projects/pipelines/new/index.js | 1 +
.../javascripts/pages/projects/project.js | 1 +
.../pages/projects/releases/edit/index.js | 1 +
.../projects/settings/badges/index/index.js | 10 +
.../repository/create_deploy_token/index.js | 3 +
.../projects/settings/repository/form.js | 19 +
.../settings/repository/show/index.js | 18 +-
.../pages/projects/shared/project_avatar.js | 2 +
.../pages/projects/shared/project_new.js | 1 +
.../pages/projects/snippets/edit/index.js | 1 +
.../pages/projects/snippets/new/index.js | 1 +
.../pages/projects/tags/new/index.js | 1 +
.../pages/projects/tree/show/index.js | 1 +
.../javascripts/pages/projects/wikis/index.js | 1 +
.../javascripts/pages/search/show/search.js | 1 +
.../javascripts/pages/sessions/new/index.js | 1 +
.../pages/sessions/new/oauth_remember_me.js | 2 +
.../pages/sessions/new/username_validator.js | 1 +
.../pages/shared/mount_badge_settings.js | 24 +
app/assets/javascripts/pages/snippets/form.js | 1 +
.../pages/users/activity_calendar.js | 1 +
app/assets/javascripts/pages/users/index.js | 1 +
.../javascripts/pages/users/user_tabs.js | 1 +
app/assets/javascripts/performance_bar.js | 63 -
.../components/detailed_metric.vue | 93 +
.../components/performance_bar_app.vue | 191 +
.../components/request_selector.vue | 52 +
.../components/simple_metric.vue | 30 +
.../components/upstream_performance_bar.vue | 20 +
.../javascripts/performance_bar/index.js | 37 +
.../services/performance_bar_service.js | 41 +
.../stores/performance_bar_store.js | 39 +
.../components/graph/action_component.vue | 98 +-
.../graph/dropdown_job_component.vue | 1 +
.../components/graph/graph_component.vue | 94 +-
.../components/graph/job_component.vue | 179 +-
.../graph/stage_column_component.vue | 90 +-
.../pipelines/components/nav_controls.vue | 27 +-
.../pipelines/components/pipelines.vue | 21 +
.../pipelines/components/pipelines_table.vue | 8 +-
.../pipelines/components/stage.vue | 1 +
.../javascripts/pipelines/mixins/pipelines.js | 6 +-
.../pipelines/pipeline_details_bundle.js | 23 +
.../pipelines/pipeline_details_mediator.js | 7 +-
app/assets/javascripts/preview_markdown.js | 9 +-
.../components/delete_account_modal.vue | 8 +-
.../account/components/update_username.vue | 121 +
.../javascripts/profile/account/index.js | 15 +
app/assets/javascripts/profile/gl_crop.js | 1 +
app/assets/javascripts/profile/profile.js | 43 +-
app/assets/javascripts/project_edit.js | 2 +
app/assets/javascripts/project_find_file.js | 1 +
app/assets/javascripts/project_fork.js | 2 +
.../javascripts/project_label_subscription.js | 1 +
app/assets/javascripts/project_select.js | 2 +
.../project_select_combo_button.js | 1 +
app/assets/javascripts/project_visibility.js | 2 +
.../projects/project_import_gitlab_project.js | 1 +
.../javascripts/projects/project_new.js | 1 +
.../javascripts/projects_dropdown/index.js | 1 +
.../prometheus_metrics/prometheus_metrics.js | 1 +
.../protected_branch_create.js | 1 +
.../protected_branch_edit_list.js | 1 +
.../protected_tags/protected_tag_create.js | 1 +
.../protected_tags/protected_tag_edit_list.js | 1 +
app/assets/javascripts/ref_select_dropdown.js | 2 +
app/assets/javascripts/right_sidebar.js | 1 +
app/assets/javascripts/search_autocomplete.js | 10 +-
app/assets/javascripts/settings_panels.js | 2 +
.../javascripts/shared/milestones/form.js | 1 +
app/assets/javascripts/shared/sessions/u2f.js | 1 +
app/assets/javascripts/shortcuts.js | 1 +
app/assets/javascripts/shortcuts_issuable.js | 3 +-
.../components/assignees/assignee_title.js | 59 -
.../components/assignees/assignee_title.vue | 64 +
.../assignees/sidebar_assignees.vue | 2 +-
.../confidential_issue_sidebar.vue | 101 +-
.../components/confidential/edit_form.vue | 53 +-
.../confidential/edit_form_buttons.vue | 21 +-
.../sidebar/components/lock/edit_form.vue | 66 +-
.../components/lock/edit_form_buttons.vue | 23 +-
.../components/lock/lock_issue_sidebar.vue | 120 +-
.../time_tracking/collapsed_state.js | 96 -
.../time_tracking/collapsed_state.vue | 102 +
...comparison_pane.js => comparison_pane.vue} | 76 +-
.../time_tracking/sidebar_time_tracking.js | 1 +
.../components/time_tracking/time_tracker.vue | 8 +-
.../sidebar/lib/sidebar_move_issue.js | 1 +
.../javascripts/sidebar/mount_sidebar.js | 1 +
app/assets/javascripts/single_file_diff.js | 1 +
app/assets/javascripts/smart_interval.js | 2 +
.../javascripts/snippet/snippet_bundle.js | 2 +
app/assets/javascripts/star.js | 1 +
app/assets/javascripts/subscription_select.js | 2 +
app/assets/javascripts/syntax_highlight.js | 2 +
app/assets/javascripts/task_list.js | 1 +
.../templates/issuable_template_selector.js | 1 +
.../templates/issuable_template_selectors.js | 2 +
app/assets/javascripts/terminal/terminal.js | 2 +
app/assets/javascripts/tree.js | 2 +
app/assets/javascripts/u2f/authenticate.js | 1 +
app/assets/javascripts/u2f/register.js | 1 +
app/assets/javascripts/ui_development_kit.js | 1 +
app/assets/javascripts/user_callout.js | 1 +
app/assets/javascripts/users_select.js | 2 +
.../components/deployment.vue | 144 +
...idget_memory_usage.js => memory_usage.vue} | 105 +-
.../components/mr_widget_deployment.js | 113 -
.../components/mr_widget_header.vue | 97 +-
.../source_branch_removal_status.vue | 34 +
.../states/mr_widget_nothing_to_merge.js | 44 -
.../states/mr_widget_ready_to_merge.js | 4 +-
.../states/mr_widget_sha_mismatch.js | 18 -
.../mr_widget_unresolved_discussions.js | 27 -
.../components/states/mr_widget_wip.js | 1 +
.../components/states/nothing_to_merge.vue | 47 +
.../components/states/sha_mismatch.vue | 25 +
.../states/unresolved_discussions.vue | 33 +
.../vue_merge_request_widget/dependencies.js | 12 +-
.../mr_widget_options.js | 27 +-
.../stores/mr_widget_store.js | 4 +
.../stores/state_maps.js | 3 +-
.../content_viewer/content_viewer.vue | 58 +
.../content_viewer/lib/viewer_utils.js | 32 +
.../viewers/download_viewer.vue | 52 +
.../content_viewer/viewers/image_viewer.vue | 68 +
.../viewers/markdown_viewer.vue | 90 +
.../{modal.vue => deprecated_modal.vue} | 2 +-
.../vue_shared/components/file_icon.vue | 3 +-
.../vue_shared/components/gl_modal.vue | 79 +-
.../vue_shared/components/identicon.vue | 2 +-
.../vue_shared/components/markdown/field.vue | 1 +
.../vue_shared/components/markdown/header.vue | 1 +
.../{memory_graph.js => memory_graph.vue} | 38 +-
.../vue_shared/components/navigation_tabs.vue | 2 +
.../vue_shared/components/recaptcha_modal.vue | 8 +-
.../components/sidebar/labels_select/base.vue | 24 +
.../labels_select/dropdown_create_label.vue | 11 +-
.../sidebar/labels_select/dropdown_footer.vue | 16 +-
.../components/skeleton_loading_container.vue | 2 +-
.../vue_shared/directives/popover.js | 2 +
.../vue_shared/directives/tooltip.js | 2 +
app/assets/javascripts/zen_mode.js | 1 +
.../stylesheets/framework/animations.scss | 80 +-
app/assets/stylesheets/framework/buttons.scss | 4 +
app/assets/stylesheets/framework/common.scss | 4 +
.../framework/contextual_sidebar.scss | 26 +-
.../stylesheets/framework/dropdowns.scss | 33 +-
.../stylesheets/framework/gitlab_theme.scss | 113 +-
app/assets/stylesheets/framework/header.scss | 107 +-
app/assets/stylesheets/framework/images.scss | 41 +-
app/assets/stylesheets/framework/lists.scss | 13 +-
.../framework/responsive_tables.scss | 2 +-
app/assets/stylesheets/framework/sidebar.scss | 2 +-
.../stylesheets/framework/typography.scss | 5 +
.../stylesheets/framework/variables.scss | 72 +-
app/assets/stylesheets/pages/boards.scss | 47 +-
app/assets/stylesheets/pages/branches.scss | 21 +-
app/assets/stylesheets/pages/builds.scss | 2 +-
app/assets/stylesheets/pages/commits.scss | 69 +-
app/assets/stylesheets/pages/diff.scss | 5 +
.../stylesheets/pages/environments.scss | 46 +-
app/assets/stylesheets/pages/events.scss | 9 +-
app/assets/stylesheets/pages/issuable.scss | 44 +-
app/assets/stylesheets/pages/labels.scss | 8 +-
app/assets/stylesheets/pages/lint.scss | 21 -
.../stylesheets/pages/merge_requests.scss | 52 +
app/assets/stylesheets/pages/notes.scss | 8 +-
app/assets/stylesheets/pages/pages.scss | 60 +
app/assets/stylesheets/pages/pipelines.scss | 18 +-
app/assets/stylesheets/pages/profile.scss | 7 +-
app/assets/stylesheets/pages/projects.scss | 80 +-
app/assets/stylesheets/pages/repo.scss | 468 +-
app/assets/stylesheets/pages/repo.scss.orig | 786 +
app/assets/stylesheets/pages/search.scss | 2 +-
app/assets/stylesheets/pages/settings.scss | 20 +
app/assets/stylesheets/performance_bar.scss | 43 +-
.../admin/appearances_controller.rb | 18 +-
.../admin/application_controller.rb | 14 -
.../admin/application_settings_controller.rb | 23 +-
app/controllers/admin/groups_controller.rb | 2 +-
app/controllers/admin/users_controller.rb | 2 +-
app/controllers/application_controller.rb | 4 -
app/controllers/boards/issues_controller.rb | 3 +-
app/controllers/ci/lints_controller.rb | 15 -
.../concerns/authenticates_with_two_factor.rb | 2 +-
.../concerns/checks_collaboration.rb | 21 +
app/controllers/concerns/group_tree.rb | 2 +-
app/controllers/concerns/issuable_actions.rb | 6 +-
app/controllers/concerns/notes_actions.rb | 6 +-
app/controllers/concerns/renders_notes.rb | 2 +-
app/controllers/concerns/send_file_upload.rb | 17 +
app/controllers/concerns/uploads_actions.rb | 32 +-
app/controllers/dashboard_controller.rb | 19 +
.../groups/group_members_controller.rb | 2 +-
.../groups/milestones_controller.rb | 2 +-
.../groups/settings/badges_controller.rb | 13 +
.../groups/variables_controller.rb | 2 +-
app/controllers/groups_controller.rb | 4 +-
app/controllers/ide_controller.rb | 6 +
app/controllers/jwt_controller.rb | 3 +-
.../omniauth_callbacks_controller.rb | 12 +
app/controllers/profiles_controller.rb | 24 +-
.../projects/application_controller.rb | 14 +-
.../projects/artifacts_controller.rb | 12 +-
.../projects/branches_controller.rb | 10 +-
.../projects/ci/lints_controller.rb | 27 +
.../projects/deploy_tokens_controller.rb | 10 +
.../projects/discussions_controller.rb | 12 +-
.../projects/git_http_client_controller.rb | 1 +
.../projects/git_http_controller.rb | 2 +-
app/controllers/projects/issues_controller.rb | 2 +-
app/controllers/projects/jobs_controller.rb | 40 +-
app/controllers/projects/labels_controller.rb | 3 +-
.../projects/lfs_api_controller.rb | 2 +-
.../projects/lfs_storage_controller.rb | 66 +-
.../merge_requests/creations_controller.rb | 2 +-
.../projects/milestones_controller.rb | 6 +-
app/controllers/projects/notes_controller.rb | 2 +-
app/controllers/projects/pages_controller.rb | 22 +
.../projects/pipeline_schedules_controller.rb | 2 +-
.../projects/pipelines_settings_controller.rb | 28 -
.../projects/project_members_controller.rb | 2 +-
.../projects/protected_branches_controller.rb | 8 +-
.../projects/protected_refs_controller.rb | 14 +-
.../projects/protected_tags_controller.rb | 8 +-
app/controllers/projects/raw_controller.rb | 3 +-
app/controllers/projects/refs_controller.rb | 2 +-
.../projects/repositories_controller.rb | 23 +-
.../projects/services_controller.rb | 2 +
.../projects/settings/badges_controller.rb | 13 +
.../projects/settings/ci_cd_controller.rb | 72 +-
.../settings/repository_controller.rb | 34 +-
.../projects/variables_controller.rb | 2 +-
app/controllers/projects_controller.rb | 2 +-
app/controllers/root_controller.rb | 4 +
app/finders/admin/projects_finder.rb | 2 +-
app/finders/issuable_finder.rb | 13 +-
app/finders/labels_finder.rb | 35 +-
.../merge_request_target_project_finder.rb | 1 +
app/finders/projects_finder.rb | 2 +-
app/finders/todos_finder.rb | 2 +-
app/helpers/appearances_helper.rb | 16 +-
app/helpers/application_helper.rb | 93 +-
app/helpers/application_settings_helper.rb | 6 +-
app/helpers/avatars_helper.rb | 74 +
app/helpers/blob_helper.rb | 19 +-
app/helpers/boards_helper.rb | 6 +-
app/helpers/commits_helper.rb | 29 +-
app/helpers/compare_helper.rb | 2 +-
app/helpers/deploy_tokens_helper.rb | 12 +
app/helpers/emails_helper.rb | 4 +-
app/helpers/groups_helper.rb | 2 +-
app/helpers/import_helper.rb | 13 +-
app/helpers/issuables_helper.rb | 31 +-
app/helpers/issues_helper.rb | 15 +-
app/helpers/javascript_helper.rb | 5 -
app/helpers/labels_helper.rb | 43 +-
app/helpers/markup_helper.rb | 2 +-
app/helpers/merge_requests_helper.rb | 12 +
app/helpers/namespaces_helper.rb | 2 +-
app/helpers/notes_helper.rb | 22 +-
app/helpers/page_layout_helper.rb | 5 +-
app/helpers/preferences_helper.rb | 14 +-
app/helpers/projects_helper.rb | 18 +
app/helpers/tree_helper.rb | 2 +-
app/helpers/workhorse_helper.rb | 4 +-
app/mailers/emails/merge_requests.rb | 9 +
app/mailers/notify.rb | 1 +
app/models/ability.rb | 4 -
app/models/appearance.rb | 4 +-
app/models/ci/artifact_blob.rb | 7 +-
app/models/ci/build.rb | 245 +-
app/models/ci/build_metadata.rb | 35 +
app/models/ci/group_variable.rb | 2 +
app/models/ci/job_artifact.rb | 22 +-
app/models/ci/pipeline.rb | 37 +-
app/models/ci/pipeline_schedule_variable.rb | 2 +
app/models/ci/runner.rb | 18 +-
app/models/ci/variable.rb | 2 +
app/models/clusters/cluster.rb | 4 +
.../clusters/concerns/application_status.rb | 2 +
app/models/clusters/platforms/kubernetes.rb | 24 +-
app/models/commit.rb | 12 +-
app/models/commit_status.rb | 2 +-
app/models/concerns/atomic_internal_id.rb | 46 +
app/models/concerns/avatarable.rb | 8 +-
app/models/concerns/awardable.rb | 14 +-
.../concerns/chronic_duration_attribute.rb | 39 +
app/models/concerns/issuable.rb | 2 +-
app/models/concerns/milestoneish.rb | 4 +-
...nternal_id.rb => nonatomic_internal_id.rb} | 2 +-
app/models/concerns/presentable.rb | 8 +
app/models/concerns/protected_ref.rb | 2 +-
app/models/cycle_analytics/summary.rb | 0
app/models/deploy_key.rb | 4 +
app/models/deploy_token.rb | 61 +
app/models/deployment.rb | 2 +-
app/models/environment.rb | 9 +-
app/models/event.rb | 10 +-
app/models/group.rb | 12 +-
app/models/internal_id.rb | 141 +
app/models/issue.rb | 24 +-
app/models/lfs_object.rb | 17 +
app/models/member.rb | 2 +-
app/models/merge_request.rb | 36 +-
app/models/merge_request_diff_commit.rb | 2 +-
app/models/milestone.rb | 8 +-
app/models/namespace.rb | 4 +
app/models/note.rb | 11 +-
app/models/notification_recipient.rb | 18 +-
app/models/notification_setting.rb | 7 +-
app/models/pages_domain.rb | 10 +-
app/models/project.rb | 155 +-
app/models/project_auto_devops.rb | 11 +-
app/models/project_deploy_token.rb | 8 +
.../project_services/gemnasium_service.rb | 2 +-
app/models/project_services/jira_service.rb | 19 +-
.../project_services/kubernetes_service.rb | 24 +-
.../pipelines_email_service.rb | 4 -
app/models/project_wiki.rb | 2 +-
app/models/protected_branch.rb | 9 +
app/models/redirect_route.rb | 28 -
app/models/repository.rb | 9 +-
app/models/route.rb | 26 +-
app/models/service.rb | 29 +-
app/models/todo.rb | 2 +-
app/models/upload.rb | 19 +-
app/models/user.rb | 48 +-
app/policies/ci/build_policy.rb | 4 +-
app/policies/ci/pipeline_schedule_policy.rb | 14 +-
app/policies/deploy_token_policy.rb | 11 +
app/policies/group_policy.rb | 8 +-
app/policies/issuable_policy.rb | 16 -
app/policies/issue_policy.rb | 2 -
app/policies/merge_request_policy.rb | 1 -
app/policies/note_policy.rb | 11 +-
app/policies/personal_snippet_policy.rb | 2 +
app/policies/project_policy.rb | 133 +-
app/policies/project_policy/class_methods.rb | 19 +
app/policies/protected_branch_policy.rb | 9 +
app/presenters/ci/build_metadata_presenter.rb | 18 +
app/presenters/ci/build_presenter.rb | 16 +
app/presenters/merge_request_presenter.rb | 11 +-
app/presenters/project_presenter.rb | 17 +-
app/serializers/build_details_entity.rb | 2 +
app/serializers/build_metadata_entity.rb | 6 +
app/serializers/discussion_entity.rb | 6 +-
app/serializers/issue_entity.rb | 4 +
app/serializers/note_entity.rb | 36 +-
app/serializers/note_serializer.rb | 3 -
app/serializers/project_note_entity.rb | 25 +
app/serializers/project_note_serializer.rb | 3 +
app/serializers/status_entity.rb | 12 +-
...ntainer_registry_authentication_service.rb | 22 +-
app/services/boards/issues/list_service.rb | 5 +
app/services/boards/list_service.rb | 6 +-
app/services/boards/lists/create_service.rb | 8 +-
app/services/ci/create_pipeline_service.rb | 3 +-
.../ci/create_pipeline_stages_service.rb | 20 -
.../ci/fetch_kubernetes_token_service.rb | 2 +-
app/services/ci/pipeline_trigger_service.rb | 12 +-
.../check_installation_progress_service.rb | 2 +-
.../clusters/applications/install_service.rb | 2 +-
app/services/deploy_tokens/create_service.rb | 7 +
app/services/events/render_service.rb | 12 +-
app/services/files/create_service.rb | 8 +-
app/services/files/multi_service.rb | 26 +-
app/services/issuable/destroy_service.rb | 1 +
app/services/issuable_base_service.rb | 5 +-
app/services/issues/close_service.rb | 1 +
app/services/issues/update_service.rb | 2 +-
app/services/lfs/file_modification_handler.rb | 42 -
app/services/lfs/file_transformer.rb | 66 +
app/services/merge_requests/create_service.rb | 4 +-
.../merge_request_diff_cache_service.rb | 11 +-
.../merge_requests/refresh_service.rb | 8 +-
app/services/notes/post_process_service.rb | 4 +-
app/services/notes/render_service.rb | 13 +-
app/services/notification_service.rb | 10 +
app/services/projects/autocomplete_service.rb | 3 +-
.../projects/base_move_relations_service.rb | 22 +
.../projects/create_from_template_service.rb | 3 +-
app/services/projects/create_service.rb | 25 +-
app/services/projects/destroy_service.rb | 28 +-
.../gitlab_projects_import_service.rb | 26 +-
.../projects/import_export/export_service.rb | 39 +-
app/services/projects/import_service.rb | 8 +-
app/services/projects/move_access_service.rb | 25 +
.../move_deploy_keys_projects_service.rb | 31 +
app/services/projects/move_forks_service.rb | 42 +
.../move_lfs_objects_projects_service.rb | 29 +
.../move_notification_settings_service.rb | 38 +
.../move_project_authorizations_service.rb | 40 +
.../move_project_group_links_service.rb | 40 +
.../projects/move_project_members_service.rb | 40 +
.../move_users_star_projects_service.rb | 20 +
.../projects/overwrite_project_service.rb | 69 +
app/services/projects/transfer_service.rb | 2 +
.../update_pages_configuration_service.rb | 6 +-
app/services/projects/update_pages_service.rb | 18 +-
app/services/projects/update_service.rb | 10 +
.../protected_branches/create_service.rb | 17 +-
.../protected_branches/destroy_service.rb | 9 +
.../protected_branches/update_service.rb | 2 +-
.../protected_tags/destroy_service.rb | 7 +
.../quick_actions/interpret_service.rb | 5 +-
.../repository_archive_clean_up_service.rb | 5 +-
app/services/system_note_service.rb | 4 +-
app/uploaders/attachment_uploader.rb | 6 +-
app/uploaders/avatar_uploader.rb | 8 +-
app/uploaders/file_mover.rb | 9 +-
app/uploaders/file_uploader.rb | 56 +-
app/uploaders/gitlab_uploader.rb | 14 +-
app/uploaders/job_artifact_uploader.rb | 13 +-
app/uploaders/legacy_artifact_uploader.rb | 5 +
app/uploaders/lfs_object_uploader.rb | 6 +-
app/uploaders/namespace_file_uploader.rb | 11 +-
app/uploaders/object_storage.rb | 434 +
app/uploaders/personal_file_uploader.rb | 17 +-
app/uploaders/records_uploads.rb | 3 +-
.../certificate_fingerprint_validator.rb | 9 +
app/validators/certificate_validator.rb | 2 -
app/validators/importable_url_validator.rb | 6 +-
app/validators/top_level_group_validator.rb | 7 +
.../application_settings/_abuse.html.haml | 12 +
.../_account_and_limit.html.haml | 39 +
.../_background_jobs.html.haml | 30 +
.../application_settings/_ci_cd.html.haml | 47 +
.../application_settings/_email.html.haml | 26 +
.../application_settings/_form.html.haml | 873 -
.../application_settings/_gitaly.html.haml | 27 +
.../application_settings/_help_page.html.haml | 22 +
.../application_settings/_influx.html.haml | 68 +
.../application_settings/_ip_limits.html.haml | 54 +
.../application_settings/_koding.html.haml | 24 +
.../application_settings/_logging.html.haml | 36 +
.../application_settings/_outbound.html.haml | 12 +
.../application_settings/_pages.html.haml | 22 +
.../_performance.html.haml | 19 +
.../_performance_bar.html.haml | 16 +
.../application_settings/_plantuml.html.haml | 20 +
.../_prometheus.html.haml | 28 +
.../application_settings/_realtime.html.haml | 19 +
.../application_settings/_registry.html.haml | 10 +
.../_repository_check.html.haml | 62 +
.../_repository_storage.html.haml | 58 +
.../application_settings/_signin.html.haml | 60 +
.../application_settings/_signup.html.haml | 58 +
.../application_settings/_spam.html.haml | 65 +
.../application_settings/_terminal.html.haml | 13 +
.../application_settings/_usage.html.haml | 37 +
.../_visibility_and_access.html.haml | 67 +
.../admin/application_settings/show.html.haml | 305 +-
app/views/admin/projects/show.html.haml | 12 +-
app/views/admin/runners/show.html.haml | 4 +
app/views/award_emoji/_awards_block.html.haml | 4 +-
app/views/ci/lints/show.html.haml | 36 +-
app/views/ci/status/_badge.html.haml | 4 +-
.../ci/status/_dropdown_graph_badge.html.haml | 7 +-
.../ci/variables/_variable_row.html.haml | 4 +-
app/views/dashboard/issues.html.haml | 12 +-
app/views/dashboard/merge_requests.html.haml | 12 +-
.../discussions/_diff_with_notes.html.haml | 34 +-
app/views/discussions/_discussion.html.haml | 2 +-
.../rejection.text.haml | 3 +-
.../groups/settings/badges/index.html.haml | 4 +
app/views/groups/show.html.haml | 2 +-
app/views/ide/index.html.haml | 12 +
app/views/import/github/new.html.haml | 3 -
.../import/gitlab_projects/new.html.haml | 6 +-
app/views/layouts/_mailer.html.haml | 10 +-
app/views/layouts/_page.html.haml | 1 +
app/views/layouts/devise.html.haml | 4 +-
app/views/layouts/devise_empty.html.haml | 2 +-
app/views/layouts/header/_new_dropdown.haml | 4 +-
.../header/_read_only_banner.html.haml | 7 +
.../layouts/nav/sidebar/_group.html.haml | 8 +-
.../layouts/nav/sidebar/_project.html.haml | 25 +-
.../push_to_merge_request_email.html.haml | 26 +
.../push_to_merge_request_email.text.haml | 13 +
app/views/peek/_bar.html.haml | 12 +
app/views/peek/views/_gc.html.haml | 7 +
app/views/peek/views/_gitaly.html.haml | 7 -
app/views/peek/views/_host.html.haml | 2 -
app/views/peek/views/_mysql2.html.haml | 4 -
app/views/peek/views/_pg.html.haml | 4 -
app/views/peek/views/_rblineprof.html.haml | 7 -
app/views/peek/views/_redis.html.haml | 7 +
app/views/peek/views/_sidekiq.html.haml | 7 +
app/views/peek/views/_sql.html.haml | 13 -
app/views/profiles/accounts/show.html.haml | 16 +-
.../personal_access_tokens/index.html.haml | 7 +-
app/views/projects/_export.html.haml | 4 +-
app/views/projects/_home_panel.html.haml | 11 +-
app/views/projects/_last_push.html.haml | 7 +-
.../projects/_new_project_fields.html.haml | 4 +-
app/views/projects/blob/_header.html.haml | 1 +
app/views/projects/branches/_branch.html.haml | 143 +-
.../projects/buttons/_download.html.haml | 9 +-
.../projects/buttons/_dropdown.html.haml | 22 +-
.../{ => projects}/ci/lints/_create.html.haml | 0
app/views/projects/ci/lints/show.html.haml | 27 +
.../projects/clusters/_empty_state.html.haml | 5 +-
app/views/projects/clusters/show.html.haml | 4 +-
.../projects/clusters/user/_header.html.haml | 2 +-
.../projects/commit/_commit_box.html.haml | 15 +-
app/views/projects/commit/show.html.haml | 2 +-
.../projects/commits/_commit.atom.builder | 2 +-
app/views/projects/commits/_commit.html.haml | 15 +-
.../projects/deploy_keys/_index.html.haml | 2 +-
.../projects/deploy_tokens/_form.html.haml | 29 +
.../projects/deploy_tokens/_index.html.haml | 18 +
.../deploy_tokens/_new_deploy_token.html.haml | 14 +
.../deploy_tokens/_revoke_modal.html.haml | 17 +
.../projects/deploy_tokens/_table.html.haml | 31 +
app/views/projects/diffs/_stats.html.haml | 4 +-
app/views/projects/edit.html.haml | 19 +-
app/views/projects/empty.html.haml | 16 +-
.../projects/environments/metrics.html.haml | 1 +
.../projects/issues/_discussion.html.haml | 1 +
app/views/projects/issues/_issue.html.haml | 8 +-
app/views/projects/issues/_nav_btns.html.haml | 13 +-
.../projects/issues/_new_branch.html.haml | 8 +-
app/views/projects/issues/show.html.haml | 13 +-
.../projects/jobs/_empty_state.html.haml | 5 +-
.../projects/jobs/_empty_states.html.haml | 9 +
app/views/projects/jobs/_sidebar.html.haml | 10 +-
app/views/projects/jobs/show.html.haml | 27 +-
.../merge_requests/_merge_request.html.haml | 8 +-
.../creations/_new_compare.html.haml | 2 +-
.../projects/merge_requests/index.html.haml | 2 +-
.../projects/merge_requests/show.html.haml | 1 +
app/views/projects/new.html.haml | 8 -
app/views/projects/no_repo.html.haml | 6 +-
app/views/projects/notes/_actions.html.haml | 2 +-
.../projects/pages/_https_only.html.haml | 10 +
app/views/projects/pages/_list.html.haml | 37 +-
app/views/projects/pages/show.html.haml | 6 +-
.../projects/pages_domains/edit.html.haml | 2 +-
.../projects/pages_domains/new.html.haml | 4 +-
.../projects/pages_domains/show.html.haml | 56 +-
app/views/projects/pipelines/index.html.haml | 2 +-
.../shared/_branches_list.html.haml | 4 +-
.../shared/_index.html.haml | 2 +-
.../protected_tags/shared/_index.html.haml | 2 +-
.../shared/_tags_list.html.haml | 4 +-
.../registry/repositories/index.html.haml | 4 +
app/views/projects/runners/_form.html.haml | 6 +
app/views/projects/runners/show.html.haml | 3 +
app/views/projects/services/_form.html.haml | 5 -
.../projects/settings/badges/index.html.haml | 4 +
.../ci_cd}/_badge.html.haml | 0
.../ci_cd/_form.html.haml} | 14 +-
.../projects/settings/ci_cd/show.html.haml | 13 +-
.../settings/repository/show.html.haml | 1 +
app/views/projects/show.html.haml | 4 +-
app/views/projects/tags/_tag.html.haml | 6 +-
app/views/projects/tags/show.html.haml | 2 +-
.../projects/tree/_tree_header.html.haml | 31 +-
app/views/shared/_import_form.html.haml | 3 -
.../shared/_issuable_meta_data.html.haml | 8 +-
app/views/shared/_label.html.haml | 26 +-
app/views/shared/_service_settings.html.haml | 2 +-
.../shared/badges/_badge_settings.html.haml | 4 +
app/views/shared/boards/_show.html.haml | 2 +-
.../shared/boards/components/_board.html.haml | 2 +-
.../boards/components/_sidebar.html.haml | 2 +-
.../components/sidebar/_assignee.html.haml | 3 +-
.../components/sidebar/_due_date.html.haml | 3 +-
.../components/sidebar/_labels.html.haml | 3 +-
.../components/sidebar/_milestone.html.haml | 3 +-
.../dashboard/_no_filter_selected.html.haml | 8 +
app/views/shared/issuable/_filter.html.haml | 9 +-
.../issuable/_label_page_create.html.haml | 3 +-
.../issuable/_label_page_default.html.haml | 7 +-
app/views/shared/issuable/_nav.html.haml | 11 +-
app/views/shared/issuable/_sidebar.html.haml | 4 +-
.../shared/milestones/_milestone.html.haml | 20 +-
.../shared/milestones/_sidebar.html.haml | 2 +-
app/views/shared/milestones/_top.html.haml | 5 +-
app/views/shared/notes/_note.html.haml | 2 +-
app/workers/all_queues.yml | 4 +
app/workers/concerns/object_storage_queue.rb | 8 +
app/workers/git_garbage_collect_worker.rb | 9 +-
app/workers/new_note_worker.rb | 2 +-
.../object_storage/background_move_worker.rb | 29 +
.../object_storage/migrate_uploads_worker.rb | 214 +
app/workers/object_storage_upload_worker.rb | 21 +
app/workers/project_export_worker.rb | 13 +-
app/workers/repository_fork_worker.rb | 43 +-
bin/rails | 15 +-
bin/rake | 13 +-
bin/rspec | 6 +
bin/setup | 50 +-
bin/update | 29 +
.../39118-dynamic-pipeline-variables-fe.yml | 6 -
...-cluster-js-not-running-on-update-page.yml | 5 -
.../bvl-external-policy-classification.yml | 5 -
config.ru | 4 +-
config/application.rb | 14 +-
config/boot.rb | 11 +-
config/environment.rb | 8 +-
config/environments/production.rb | 6 +-
config/environments/test.rb | 8 +-
config/gitlab.yml.example | 95 +-
config/initializers/1_settings.rb | 39 +-
config/initializers/6_validations.rb | 6 +-
.../{fast_gettext.rb => 9_fast_gettext.rb} | 0
.../active_record_array_type_casting.rb | 31 +-
config/initializers/active_record_locking.rb | 108 +-
.../application_controller_renderer.rb | 12 +
config/initializers/ar5_batching.rb | 66 +-
config/initializers/ar5_pg_10_support.rb | 5 +-
.../initializers/ar_native_database_types.rb | 11 +
.../artifacts_direct_upload_support.rb | 7 +
config/initializers/backtrace_silencers.rb | 9 +-
config/initializers/carrierwave.rb | 12 -
config/initializers/devise.rb | 46 +-
config/initializers/doorkeeper.rb | 2 +-
.../fog_google_https_private_urls.rb | 20 +
config/initializers/new_framework_defaults.rb | 29 +
config/initializers/omniauth.rb | 1 +
config/initializers/peek.rb | 4 +-
config/initializers/sidekiq.rb | 9 +-
config/karma.config.js | 10 +-
config/prometheus/additional_metrics.yml | 34 +-
config/routes.rb | 5 +-
config/routes/ci.rb | 2 +-
config/routes/git_http.rb | 2 +-
config/routes/group.rb | 5 +-
config/routes/project.rb | 27 +-
config/routes/repository.rb | 7 +-
config/routes/user.rb | 4 +-
config/sidekiq_queues.yml | 2 +
config/spring.rb | 6 +
config/svg.config.js | 48 -
config/webpack.config.js | 100 +-
db/fixtures/development/10_merge_requests.rb | 8 +-
.../development/22_labeled_issues_seed.rb | 103 +
...1322_migrate_process_commit_worker_jobs.rb | 2 +-
...0141214_remove_dot_git_from_group_names.rb | 2 +-
...226122833_remove_dot_git_from_usernames.rb | 4 +-
...ect_foreign_keys_with_cascading_deletes.rb | 8 +-
...1163708_add_artifacts_store_to_ci_build.rb | 10 +
...2400_add_stage_id_foreign_key_to_builds.rb | 12 +-
...04829_add_foreign_key_to_merge_requests.rb | 12 +-
...825015534_add_file_store_to_lfs_objects.rb | 31 +
...0918072949_add_file_store_job_artifacts.rb | 10 +
...71214144320_add_store_column_to_uploads.rb | 12 +
...220145_add_pages_https_only_to_projects.rb | 9 +
...ange_default_value_for_pages_https_only.rb | 13 +
.../20180209165249_add_closed_by_to_issues.rb | 20 +
...53455_add_maximum_timeout_to_ci_runners.rb | 9 +
...1010859_create_ci_builds_metadata_table.rb | 20 +
...0180305095250_create_internal_ids_table.rb | 15 +
...le_commits_count_for_merge_request_diff.rb | 30 +
.../20180319190020_create_deploy_tokens.rb | 19 +
..._merge_request_to_notification_settings.rb | 9 +
...27101207_remove_index_from_events_table.rb | 18 +
...0405142733_create_project_deploy_tokens.rb | 16 +
...dd_index_to_ci_job_artifacts_file_store.rb | 15 +
...12101928_schedule_build_stage_migration.rb | 25 +-
...27_build_user_interacted_projects_table.rb | 10 +-
...0_remove_permanent_from_redirect_routes.rb | 37 +
...64012_add_path_index_to_redirect_routes.rb | 38 +
...1928_reschedule_builds_stages_migration.rb | 33 +
db/schema.rb | 59 +-
doc/README.md | 179 +-
doc/administration/auth/jwt.md | 72 +
.../img/circuitbreaker_config.png | Bin 335073 -> 99523 bytes
.../img/repository_storages_admin_ui.png | Bin 17760 -> 70416 bytes
doc/administration/incoming_email.md | 1 +
doc/administration/index.md | 9 +-
doc/administration/issue_closing_pattern.md | 4 +-
doc/administration/job_artifacts.md | 123 +-
doc/administration/job_traces.md | 42 +
doc/administration/logs.md | 30 +
.../performance/img/performance_bar.png | Bin 170256 -> 344274 bytes
.../img/performance_bar_gitaly_calls.png | Bin 0 -> 278693 bytes
.../monitoring/performance/performance_bar.md | 12 +-
.../monitoring/prometheus/index.md | 9 +-
doc/administration/pages/index.md | 36 +-
doc/administration/plugins.md | 77 +-
doc/administration/raketasks/check.md | 8 +-
doc/administration/raketasks/maintenance.md | 28 +
.../raketasks/uploads/migrate.md | 74 +
doc/administration/uploads.md | 210 +
doc/api/commits.md | 76 +-
doc/api/events.md | 4 +
doc/api/features.md | 8 +
doc/api/group_badges.md | 5 +-
doc/api/issues.md | 48 +
doc/api/jobs.md | 14 +-
doc/api/notification_settings.md | 4 +
doc/api/project_badges.md | 5 +-
doc/api/project_import_export.md | 24 +-
doc/api/projects.md | 55 +
doc/api/repositories.md | 2 +-
doc/api/runners.md | 7 +-
doc/api/search.md | 26 +-
doc/ci/caching/img/clear_runners_cache.png | Bin 0 -> 16029 bytes
doc/ci/caching/index.md | 18 +-
doc/ci/docker/using_docker_build.md | 91 +-
doc/ci/docker/using_docker_images.md | 63 +-
doc/ci/environments.md | 15 +-
doc/ci/examples/README.md | 27 +-
doc/ci/examples/browser_performance.md | 93 +-
doc/ci/examples/code_climate.md | 13 +-
doc/ci/examples/container_scanning.md | 59 +
doc/ci/examples/dast.md | 25 +-
doc/ci/examples/deployment/README.md | 2 +-
.../img/aws_config_window.png | Bin 0 -> 22046 bytes
.../img/gitlab_config.png | Bin 0 -> 27620 bytes
.../img/test_pipeline_pass.png | Bin 0 -> 18789 bytes
.../index.md | 526 +
.../laravel_with_gitlab_and_envoy/index.md | 2 +-
doc/ci/examples/sast_docker.md | 56 +-
doc/ci/img/job_failure_reason.png | Bin 0 -> 5346 bytes
doc/ci/pipelines.md | 24 +-
doc/ci/quick_start/README.md | 9 +-
doc/ci/runners/README.md | 64 +-
doc/ci/variables/README.md | 105 +-
doc/ci/yaml/README.md | 901 +-
doc/development/changelog.md | 1 +
doc/development/doc_styleguide.md | 370 +-
doc/development/ee_features.md | 304 +-
doc/development/emails.md | 10 +-
doc/development/fe_guide/index.md | 4 +-
doc/development/fe_guide/performance.md | 120 +-
doc/development/fe_guide/style_guide_js.md | 51 +
doc/development/fe_guide/vue.md | 12 +-
doc/development/i18n/externalization.md | 2 +-
doc/development/i18n/proofreader.md | 4 +
doc/development/migration_style_guide.md | 21 +-
.../new_fe_guide/development/performance.md | 15 +-
.../new_fe_guide/development/security.md | 13 +-
doc/development/new_fe_guide/index.md | 2 +-
doc/development/new_fe_guide/principles.md | 34 +-
doc/development/new_fe_guide/style/html.md | 52 +-
doc/development/new_fe_guide/style/index.md | 8 +-
.../new_fe_guide/style/javascript.md | 194 +-
.../new_fe_guide/style/prettier.md | 45 +
.../testing_guide/end_to_end_tests.md | 2 +-
doc/development/writing_documentation.md | 275 +-
doc/downgrade_ee_to_ce/README.md | 2 +-
doc/img/devops_lifecycle.png | Bin 0 -> 65043 bytes
doc/install/README.md | 2 +-
doc/install/installation.md | 15 +-
doc/install/kubernetes/index.md | 2 +-
doc/install/openshift_and_gitlab/index.md | 11 +-
doc/integration/google.md | 2 +-
doc/integration/omniauth.md | 1 +
doc/integration/saml.md | 6 +-
doc/integration/slash_commands.md | 3 +-
doc/policy/maintenance.md | 2 +-
doc/raketasks/README.md | 1 +
doc/topics/autodevops/index.md | 61 +-
doc/update/10.5-to-10.6.md | 16 +-
doc/update/10.6-to-10.7.md | 361 +
doc/user/admin_area/settings/email.md | 5 +
.../visibility_and_access_controls.md | 12 +-
doc/user/discussions/index.md | 5 +
doc/user/gitlab_com/index.md | 342 +
doc/user/group/index.md | 11 +-
doc/user/permissions.md | 3 +-
doc/user/profile/preferences.md | 4 +-
doc/user/project/badges.md | 73 +
doc/user/project/clusters/index.md | 4 +-
doc/user/project/container_registry.md | 11 +-
.../deploy_tokens/img/deploy_tokens.png | Bin 0 -> 75650 bytes
doc/user/project/deploy_tokens/index.md | 76 +
.../project/img/project_overview_badges.png | Bin 0 -> 40188 bytes
doc/user/project/index.md | 22 +-
.../img/jira_workflow_screenshot.png | Bin 66685 -> 0 bytes
doc/user/project/integrations/jira.md | 15 +-
.../prometheus_library/kubernetes.md | 15 +-
doc/user/project/issue_board.md | 5 +-
.../project/issues/issues_functionalities.md | 10 +-
doc/user/project/labels.md | 7 +-
.../members/share_project_with_groups.md | 24 +-
.../img/remove_source_branch_status.png | Bin 0 -> 32649 bytes
doc/user/project/merge_requests/index.md | 28 +-
doc/user/project/pipelines/schedules.md | 2 +-
doc/user/project/pipelines/settings.md | 11 +-
.../repository/img/jupyter_notebook.png | Bin 0 -> 63326 bytes
doc/user/project/repository/index.md | 23 +-
doc/user/project/settings/import_export.md | 2 +-
doc/user/project/settings/index.md | 17 +-
.../project/web_ide/img/commit_changes.png | Bin 0 -> 672321 bytes
.../project/web_ide/img/enable_web_ide.png | Bin 0 -> 11364 bytes
doc/user/project/web_ide/img/open_web_ide.png | Bin 0 -> 28574 bytes
doc/user/project/web_ide/index.md | 33 +
doc/workflow/lfs/lfs_administration.md | 123 +-
doc/workflow/notifications.md | 3 +-
doc/workflow/todos.md | 3 +-
features/groups.feature | 73 -
features/project/active_tab.feature | 138 -
features/project/fork.feature | 49 -
features/project/graph.feature | 33 -
features/project/issues/issues.feature | 180 -
features/project/issues/labels.feature | 48 -
features/project/issues/milestones.feature | 1 +
features/project/redirects.feature | 38 -
features/steps/groups.rb | 147 -
features/steps/project/active_tab.rb | 127 -
features/steps/project/fork.rb | 85 -
features/steps/project/graph.rb | 50 -
features/steps/project/issues/issues.rb | 181 -
features/steps/project/issues/labels.rb | 101 -
features/steps/project/project.rb | 2 +-
features/steps/project/redirects.rb | 67 -
features/steps/shared/builds.rb | 2 +-
features/steps/shared/issuable.rb | 23 -
features/steps/shared/markdown.rb | 37 -
features/steps/shared/note.rb | 22 -
features/steps/shared/paths.rb | 31 -
features/steps/shared/project.rb | 4 -
features/steps/shared/user.rb | 4 -
lib/api/api.rb | 9 +
lib/api/badges.rb | 1 +
lib/api/commits.rb | 14 +
lib/api/deploy_keys.rb | 23 +-
lib/api/entities.rb | 5 +-
lib/api/features.rb | 7 +
lib/api/helpers.rb | 59 +-
lib/api/helpers/internal_helpers.rb | 14 +-
lib/api/helpers/project_snapshots_helpers.rb | 25 +
lib/api/helpers/projects_helpers.rb | 38 +
lib/api/internal.rb | 3 +-
lib/api/issues.rb | 2 +-
lib/api/job_artifacts.rb | 4 +-
lib/api/jobs.rb | 2 +-
lib/api/merge_requests.rb | 2 +-
lib/api/project_export.rb | 26 +-
lib/api/project_import.rb | 16 +-
lib/api/project_snapshots.rb | 19 +
lib/api/projects.rb | 40 +-
lib/api/protected_branches.rb | 11 +-
lib/api/repositories.rb | 6 +-
lib/api/runner.rb | 41 +-
lib/api/runners.rb | 1 +
lib/api/search.rb | 4 +-
lib/api/services.rb | 2 +-
lib/api/v3/builds.rb | 6 +-
lib/api/v3/merge_requests.rb | 2 +-
lib/api/v3/projects.rb | 6 +-
lib/api/v3/repositories.rb | 2 +-
lib/backup/artifacts.rb | 4 -
lib/backup/builds.rb | 4 -
lib/backup/files.rb | 18 +-
lib/backup/helper.rb | 17 +
lib/backup/lfs.rb | 4 -
lib/backup/pages.rb | 4 -
lib/backup/registry.rb | 4 -
lib/backup/repository.rb | 30 +-
lib/backup/uploads.rb | 4 -
lib/banzai/commit_renderer.rb | 2 +-
lib/banzai/cross_project_reference.rb | 4 +-
.../filter/abstract_reference_filter.rb | 54 +-
.../filter/commit_range_reference_filter.rb | 4 +-
lib/banzai/filter/commit_reference_filter.rb | 2 +
lib/banzai/filter/commit_trailers_filter.rb | 151 +
lib/banzai/filter/emoji_filter.rb | 2 +-
lib/banzai/filter/gollum_tags_filter.rb | 2 +-
lib/banzai/filter/inline_diff_filter.rb | 2 +-
lib/banzai/filter/issuable_state_filter.rb | 13 +-
lib/banzai/filter/label_reference_filter.rb | 53 +-
.../filter/merge_request_reference_filter.rb | 39 +
.../filter/milestone_reference_filter.rb | 8 +-
lib/banzai/filter/redactor_filter.rb | 6 +-
lib/banzai/filter/relative_link_filter.rb | 2 +-
lib/banzai/filter/snippet_reference_filter.rb | 2 +
lib/banzai/issuable_extractor.rb | 14 +-
lib/banzai/object_renderer.rb | 32 +-
.../pipeline/commit_description_pipeline.rb | 11 +
lib/banzai/pipeline/gfm_pipeline.rb | 4 +-
lib/banzai/redactor.rb | 20 +-
lib/banzai/reference_extractor.rb | 4 +-
lib/banzai/reference_parser/base_parser.rb | 16 +-
.../reference_parser/commit_range_parser.rb | 2 +
lib/banzai/reference_parser/issue_parser.rb | 39 +-
lib/banzai/reference_parser/user_parser.rb | 3 +-
lib/banzai/render_context.rb | 32 +
lib/constraints/group_url_constrainer.rb | 12 +-
lib/constraints/project_url_constrainer.rb | 20 +-
lib/constraints/user_url_constrainer.rb | 12 +-
lib/container_registry/client.rb | 5 +-
lib/declarative_policy.rb | 4 +-
lib/declarative_policy/delegate_dsl.rb | 16 +
lib/declarative_policy/dsl.rb | 103 -
lib/declarative_policy/policy_dsl.rb | 44 +
lib/declarative_policy/preferred_scope.rb | 2 +-
lib/declarative_policy/rule_dsl.rb | 45 +
lib/forever.rb | 13 +
.../post_deployment_migration_generator.rb | 2 +-
lib/gitlab.rb | 1 +
lib/gitlab/auth.rb | 22 +-
lib/gitlab/auth/ldap/access.rb | 2 +
lib/gitlab/auth/ldap/adapter.rb | 43 +-
lib/gitlab/auth/ldap/ldap_connection_error.rb | 7 +
lib/gitlab/auth/o_auth/user.rb | 3 +
lib/gitlab/auth/result.rb | 2 +-
lib/gitlab/auth/saml/config.rb | 2 +-
.../add_merge_request_diff_commits_count.rb | 2 +-
...rialize_merge_request_diffs_and_commits.rb | 2 +-
lib/gitlab/bare_repository_import/importer.rb | 2 +-
lib/gitlab/base_doorkeeper_controller.rb | 8 +
lib/gitlab/bitbucket_import/importer.rb | 2 +-
lib/gitlab/checks/lfs_integrity.rb | 3 +-
lib/gitlab/checks/project_moved.rb | 20 +-
lib/gitlab/ci/build/policy/kubernetes.rb | 2 +-
lib/gitlab/ci/build/policy/refs.rb | 2 +-
lib/gitlab/ci/build/policy/specification.rb | 2 +-
lib/gitlab/ci/build/policy/variables.rb | 24 +
lib/gitlab/ci/build/step.rb | 4 +-
lib/gitlab/ci/config.rb | 3 +-
lib/gitlab/ci/config/entry/policy.rb | 20 +-
lib/gitlab/ci/pipeline/chain/command.rb | 2 +-
lib/gitlab/ci/pipeline/chain/create.rb | 15 +-
lib/gitlab/ci/pipeline/chain/populate.rb | 45 +
.../ci/pipeline/chain/validate/config.rb | 6 +-
.../ci/pipeline/expression/lexeme/string.rb | 2 +-
.../ci/pipeline/expression/lexeme/variable.rb | 2 +-
.../ci/pipeline/expression/statement.rb | 17 +-
lib/gitlab/ci/pipeline/seed/base.rb | 21 +
lib/gitlab/ci/pipeline/seed/build.rb | 48 +
lib/gitlab/ci/pipeline/seed/stage.rb | 47 +
lib/gitlab/ci/stage/seed.rb | 62 -
lib/gitlab/ci/status/build/cancelable.rb | 4 +
lib/gitlab/ci/status/build/canceled.rb | 21 +
lib/gitlab/ci/status/build/common.rb | 8 +
lib/gitlab/ci/status/build/created.rb | 22 +
lib/gitlab/ci/status/build/erased.rb | 21 +
lib/gitlab/ci/status/build/factory.rb | 12 +-
lib/gitlab/ci/status/build/failed.rb | 40 +
lib/gitlab/ci/status/build/failed_allowed.rb | 12 +-
lib/gitlab/ci/status/build/manual.rb | 22 +
lib/gitlab/ci/status/build/pending.rb | 22 +
lib/gitlab/ci/status/build/play.rb | 4 +
lib/gitlab/ci/status/build/retried.rb | 17 +
lib/gitlab/ci/status/build/retryable.rb | 4 +
lib/gitlab/ci/status/build/skipped.rb | 21 +
lib/gitlab/ci/status/build/stop.rb | 4 +
lib/gitlab/ci/status/core.rb | 18 +
lib/gitlab/ci/trace/http_io.rb | 197 +
lib/gitlab/ci/trace/stream.rb | 6 +-
lib/gitlab/ci/variables/collection.rb | 44 +
lib/gitlab/ci/variables/collection/item.rb | 47 +
lib/gitlab/ci/yaml_processor.rb | 44 +-
lib/gitlab/database/migration_helpers.rb | 105 +-
.../v1/migration_classes.rb | 2 +-
lib/gitlab/database/sha_attribute.rb | 51 +-
lib/gitlab/diff/file.rb | 39 +-
.../file_collection/merge_request_diff.rb | 14 +-
lib/gitlab/ee_compat_check.rb | 146 +-
.../handler/create_merge_request_handler.rb | 3 +-
lib/gitlab/etag_caching/middleware.rb | 2 +-
lib/gitlab/exclusive_lease.rb | 10 +
lib/gitlab/git/commit.rb | 3 +-
lib/gitlab/git/conflict/resolver.rb | 2 +-
lib/gitlab/git/gitlab_projects.rb | 69 +-
lib/gitlab/git/gitmodules_parser.rb | 4 +-
lib/gitlab/git/hook.rb | 4 +-
lib/gitlab/git/{env.rb => hook_env.rb} | 26 +-
lib/gitlab/git/lfs_pointer_file.rb | 9 +-
lib/gitlab/git/repository.rb | 253 +-
lib/gitlab/git/storage/checker.rb | 2 +-
lib/gitlab/git/storage/circuit_breaker.rb | 2 +-
lib/gitlab/git/wiki.rb | 3 -
lib/gitlab/git_access.rb | 47 +-
lib/gitlab/gitaly_client.rb | 31 +
lib/gitlab/gitaly_client/remote_service.rb | 11 +
.../gitaly_client/repository_service.rb | 27 +
lib/gitlab/gitaly_client/storage_settings.rb | 35 +
lib/gitlab/gitaly_client/util.rb | 8 +-
lib/gitlab/gitaly_client/wiki_service.rb | 2 +-
lib/gitlab/github_import/client.rb | 5 +-
.../importer/repository_importer.rb | 11 +-
lib/gitlab/gitlab_import/client.rb | 2 +-
lib/gitlab/health_checks/fs_shards_check.rb | 2 +-
lib/gitlab/health_checks/metric.rb | 2 +-
lib/gitlab/health_checks/result.rb | 2 +-
lib/gitlab/http.rb | 2 +
.../base_after_export_strategy.rb | 83 +
.../download_notification_strategy.rb | 17 +
.../web_upload_strategy.rb | 61 +
.../after_export_strategy_builder.rb | 24 +
lib/gitlab/import_export/import_export.yml | 5 +-
lib/gitlab/import_export/importer.rb | 49 +-
lib/gitlab/import_export/lfs_restorer.rb | 43 +
lib/gitlab/import_export/lfs_saver.rb | 55 +
.../import_export/project_tree_restorer.rb | 25 +-
.../import_export/project_tree_saver.rb | 7 +-
lib/gitlab/import_export/relation_factory.rb | 11 +-
lib/gitlab/import_export/shared.rb | 14 +-
.../import_export/statistics_restorer.rb | 17 +
lib/gitlab/kubernetes/namespace.rb | 2 +-
lib/gitlab/legacy_github_import/client.rb | 2 +-
lib/gitlab/legacy_github_import/importer.rb | 2 +-
lib/gitlab/metrics/methods.rb | 2 +-
.../metrics/sidekiq_metrics_exporter.rb | 10 +-
lib/gitlab/middleware/multipart.rb | 2 +-
lib/gitlab/middleware/read_only.rb | 2 +-
lib/gitlab/middleware/release_env.rb | 2 +-
lib/gitlab/omniauth_initializer.rb | 75 +
lib/gitlab/performance_bar.rb | 1 +
lib/gitlab/profiler.rb | 12 +-
lib/gitlab/project_search_results.rb | 2 +-
.../queries/query_additional_metrics.rb | 2 +-
lib/gitlab/proxy_http_connection_adapter.rb | 12 +-
lib/gitlab/repo_path.rb | 4 +-
lib/gitlab/setup_helper.rb | 2 +-
lib/gitlab/shell.rb | 42 +-
lib/gitlab/sidekiq_logging/json_formatter.rb | 21 +
.../sidekiq_logging/structured_logger.rb | 96 +
lib/gitlab/slash_commands/command.rb | 1 +
lib/gitlab/slash_commands/issue_move.rb | 45 +
.../slash_commands/presenters/issue_move.rb | 53 +
lib/gitlab/slash_commands/result.rb | 2 +-
lib/gitlab/task_helpers.rb | 4 +-
lib/gitlab/url_blocker.rb | 92 +-
lib/gitlab/usage_data.rb | 7 +
lib/gitlab/user_access.rb | 10 +-
lib/gitlab/utils.rb | 5 +
lib/gitlab/verify/job_artifacts.rb | 27 +
lib/gitlab/verify/lfs_objects.rb | 2 +-
lib/gitlab/verify/uploads.rb | 2 +-
lib/gitlab/workhorse.rb | 59 +-
lib/google_api/auth.rb | 2 +-
lib/haml_lint/inline_javascript.rb | 2 +-
lib/mattermost/session.rb | 6 +
lib/mattermost/team.rb | 5 +-
lib/omni_auth/strategies/jwt.rb | 62 +
lib/peek/views/gitaly.rb | 20 +-
lib/peek/views/host.rb | 9 +
lib/system_check/orphans/namespace_check.rb | 4 +-
lib/system_check/orphans/repository_check.rb | 8 +-
lib/tasks/gitlab/artifacts/check.rake | 8 +
lib/tasks/gitlab/artifacts/migrate.rake | 25 +
lib/tasks/gitlab/check.rake | 8 +-
lib/tasks/gitlab/cleanup.rake | 4 +-
lib/tasks/gitlab/exclusive_lease.rake | 9 +
lib/tasks/gitlab/info.rake | 2 +-
lib/tasks/gitlab/lfs/migrate.rake | 22 +
lib/tasks/gitlab/shell.rake | 2 +-
lib/tasks/gitlab/two_factor.rake | 2 +-
lib/tasks/gitlab/uploads/migrate.rake | 34 +
lib/tasks/migrate/setup_postgresql.rake | 4 +-
lib/tasks/test.rake | 5 -
lib/uploaded_file.rb | 40 +-
locale/bg/gitlab.po | 1053 +-
locale/de/gitlab.po | 1055 +-
locale/eo/gitlab.po | 1053 +-
locale/es/gitlab.po | 1059 +-
locale/fil_PH/gitlab.po | 1047 +-
locale/fr/gitlab.po | 1077 +-
locale/gitlab.pot | 353 +-
locale/id_ID/gitlab.po | 1042 +-
locale/it/gitlab.po | 1059 +-
locale/ja/gitlab.po | 1048 +-
locale/ko/gitlab.po | 1048 +-
locale/nl_NL/gitlab.po | 1049 +-
locale/pl_PL/gitlab.po | 1057 +-
locale/pt_BR/gitlab.po | 1625 +-
locale/ru/gitlab.po | 1367 +-
locale/tr_TR/gitlab.po | 1047 +-
locale/uk/gitlab.po | 1217 +-
locale/zh_CN/gitlab.po | 2154 ++-
locale/zh_HK/gitlab.po | 1050 +-
locale/zh_TW/gitlab.po | 1150 +-
package.json | 10 +-
public/robots.txt | 1 +
qa/README.md | 2 +-
qa/qa.rb | 9 +-
qa/qa/factory/settings/hashed_storage.rb | 8 +-
qa/qa/page/README.md | 2 +-
qa/qa/page/admin/settings.rb | 26 -
qa/qa/page/admin/settings/main.rb | 21 +
.../page/admin/settings/repository_storage.rb | 23 +
qa/qa/page/merge_request/show.rb | 17 +-
qa/qa/page/project/settings/ci_cd.rb | 2 +-
qa/qa/page/project/settings/common.rb | 20 +-
qa/qa/page/settings/common.rb | 25 +
qa/qa/scenario/bootable.rb | 2 +-
qa/qa/scenario/test/instance.rb | 8 +-
qa/qa/scenario/test/integration/mattermost.rb | 4 +-
qa/qa/specs/runner.rb | 6 +-
qa/spec/page/validator_spec.rb | 2 +-
qa/spec/scenario/test/instance_spec.rb | 4 +-
.../cop/rspec/factories_in_migration_specs.rb | 40 +
rubocop/rubocop.rb | 2 +
rubocop/spec_helpers.rb | 13 +-
scripts/codequality | 19 -
scripts/frontend/frontend_script_utils.js | 24 +
scripts/frontend/prettier.js | 117 +
scripts/lint-doc.sh | 34 +-
scripts/trigger-build-docs | 19 +-
scripts/trigger-build-omnibus | 3 +-
.../application_settings_controller_spec.rb | 5 +-
.../concerns/checks_collaboration_spec.rb | 55 +
.../concerns/send_file_upload_spec.rb | 89 +
spec/controllers/dashboard_controller_spec.rb | 2 +
.../omniauth_callbacks_controller_spec.rb | 140 +-
spec/controllers/profiles_controller_spec.rb | 29 +
.../projects/artifacts_controller_spec.rb | 14 +
.../projects/branches_controller_spec.rb | 18 +-
.../projects/ci/lints_controller_spec.rb | 123 +
.../projects/discussions_controller_spec.rb | 47 +
.../projects/issues_controller_spec.rb | 20 +-
.../projects/jobs_controller_spec.rb | 82 +-
.../projects/milestones_controller_spec.rb | 13 +-
.../projects/pages_controller_spec.rb | 37 +
.../projects/pages_domains_controller_spec.rb | 4 +-
.../pipeline_schedules_controller_spec.rb | 18 +-
.../pipelines_settings_controller_spec.rb | 57 +-
.../protected_branches_controller_spec.rb | 97 +
.../projects/raw_controller_spec.rb | 56 +-
.../projects/repositories_controller_spec.rb | 43 +-
.../settings/ci_cd_controller_spec.rb | 127 +-
spec/controllers/root_controller_spec.rb | 24 +
spec/factories/appearances.rb | 17 +-
spec/factories/award_emoji.rb | 4 +
spec/factories/ci/builds.rb | 5 +
spec/factories/ci/job_artifacts.rb | 10 +
spec/factories/deploy_tokens.rb | 14 +
spec/factories/internal_ids.rb | 7 +
spec/factories/lfs_objects.rb | 4 +
spec/factories/pages_domains.rb | 68 +-
spec/factories/project_deploy_tokens.rb | 6 +
spec/factories/projects.rb | 7 +
spec/factories/redirect_routes.rb | 9 -
spec/factories/uploads.rb | 5 +
spec/factories/users_star_projects.rb | 6 +
.../admin/admin_broadcast_messages_spec.rb | 2 +-
...admin_disables_git_access_protocol_spec.rb | 15 +-
spec/features/admin/admin_settings_spec.rb | 264 +-
spec/features/atom/dashboard_issues_spec.rb | 17 +-
spec/features/boards/boards_spec.rb | 2 +-
spec/features/boards/new_issue_spec.rb | 7 +
spec/features/boards/sidebar_spec.rb | 4 +-
.../features/boards/sub_group_project_spec.rb | 2 +-
spec/features/dashboard/issues_filter_spec.rb | 36 +-
spec/features/dashboard/issues_spec.rb | 9 -
.../features/dashboard/merge_requests_spec.rb | 14 +-
spec/features/groups/activity_spec.rb | 25 +-
spec/features/groups/group_settings_spec.rb | 21 +
spec/features/groups/issues_spec.rb | 20 +-
spec/features/groups/merge_requests_spec.rb | 16 +-
.../groups/settings/group_badges_spec.rb | 124 +
spec/features/groups/show_spec.rb | 38 +-
.../user_browse_projects_group_page_spec.rb | 29 +
spec/features/ide_spec.rb | 25 +
.../issuables/discussion_lock_spec.rb | 2 +-
.../filtered_search/filter_issues_spec.rb | 9 -
spec/features/issues/form_spec.rb | 4 +-
spec/features/issues/issue_sidebar_spec.rb | 54 +-
.../issues/user_uses_slash_commands_spec.rb | 26 +-
spec/features/labels_hierarchy_spec.rb | 319 +
spec/features/markdown/copy_as_gfm_spec.rb | 2 +-
.../merge_request/user_awards_emoji_spec.rb | 8 +
.../merge_request/user_cherry_picks_spec.rb | 8 +
...diff_notes_and_discussions_resolve_spec.rb | 12 +-
.../user_scrolls_to_note_on_load_spec.rb | 33 +-
.../user_sees_deployment_widget_spec.rb | 2 +-
.../user_sees_merge_widget_spec.rb | 26 +-
.../user_sees_mini_pipeline_graph_spec.rb | 9 +-
.../user_uses_slash_commands_spec.rb | 22 +-
spec/features/milestone_spec.rb | 11 +
spec/features/profile_spec.rb | 8 +-
spec/features/profiles/account_spec.rb | 16 +-
spec/features/projects/actve_tabs_spec.rb | 137 +
...ser_interacts_with_awards_in_issue_spec.rb | 70 +-
spec/features/projects/badges/list_spec.rb | 2 +-
.../features/projects/blobs/blob_show_spec.rb | 25 +
...er_creates_new_blob_in_new_project_spec.rb | 52 +
spec/features/projects/branches_spec.rb | 22 +-
.../ci/lint_spec.rb} | 10 +-
.../projects/commit/cherry_pick_spec.rb | 11 +
.../commit/user_reverts_commit_spec.rb | 17 +
spec/features/projects/fork_spec.rb | 104 +
spec/features/projects/graph_spec.rb | 75 +
.../projects/hook_logs/user_reads_log_spec.rb | 21 +
.../import_export/import_file_spec.rb | 1 +
.../import_export/test_project_export.tar.gz | Bin 343092 -> 341299 bytes
.../issues/user_comments_on_issue_spec.rb | 73 +
.../issues/user_creates_issue_spec.rb | 87 +
.../projects/issues/user_edits_issue_spec.rb | 25 +
.../projects/issues/user_sorts_issues_spec.rb | 39 +
.../issues/user_toggles_subscription_spec.rb | 28 +
.../projects/issues/user_views_issue_spec.rb | 32 +
.../projects/issues/user_views_issues_spec.rb | 128 +-
.../projects/jobs/user_browses_job_spec.rb | 35 +-
.../projects/jobs/user_browses_jobs_spec.rb | 11 +
spec/features/projects/jobs_spec.rb | 68 +-
.../labels/user_creates_labels_spec.rb | 88 +
.../projects/labels/user_edits_labels_spec.rb | 25 +
.../labels/user_removes_labels_spec.rb | 52 +
.../projects/labels/user_views_labels_spec.rb | 23 +
.../projects/merge_request_button_spec.rb | 12 +
.../user_reverts_merge_request_spec.rb | 8 +
.../user_views_open_merge_requests_spec.rb | 12 +
.../milestones/milestones_sorting_spec.rb | 1 -
spec/features/projects/pages_spec.rb | 91 +-
.../projects/pipeline_schedules_spec.rb | 4 +-
.../projects/pipelines/pipeline_spec.rb | 16 +
.../projects/pipelines/pipelines_spec.rb | 25 +-
spec/features/projects/redirects_spec.rb | 74 +
.../projects/settings/project_badges_spec.rb | 125 +
.../settings/repository_settings_spec.rb | 27 +
.../user_sees_collaboration_links_spec.rb | 87 +
.../projects/tree/create_directory_spec.rb | 53 +
.../projects/tree/create_file_spec.rb | 43 +
spec/features/projects/tree/tree_show_spec.rb | 14 +
.../projects/tree/upload_file_spec.rb | 51 +
.../projects/user_edits_files_spec.rb | 23 +
.../projects/user_views_empty_project_spec.rb | 43 +
spec/features/protected_branches_spec.rb | 5 +-
spec/features/protected_tags_spec.rb | 5 +-
spec/features/read_only_spec.rb | 25 +
.../user_uses_header_search_field_spec.rb | 127 +-
.../user_can_display_performance_bar_spec.rb | 10 +-
spec/features/user_sorts_things_spec.rb | 57 +
spec/finders/labels_finder_spec.rb | 34 +-
...erge_request_target_project_finder_spec.rb | 6 +
spec/fixtures/api/schemas/issue.json | 2 +
.../public_api/v4/project/export_status.json | 11 +-
spec/fixtures/big-image.png | Bin 0 -> 324444 bytes
spec/fixtures/exported-project.gz | Bin 0 -> 2306 bytes
spec/fixtures/trace/sample_trace | 4380 +++--
spec/helpers/application_helper_spec.rb | 139 -
spec/helpers/avatars_helper_spec.rb | 139 +-
spec/helpers/blob_helper_spec.rb | 25 +
spec/helpers/import_helper_spec.rb | 33 +-
spec/helpers/issuables_helper_spec.rb | 29 +-
spec/helpers/issues_helper_spec.rb | 45 +-
spec/helpers/labels_helper_spec.rb | 72 +
spec/helpers/page_layout_helper_spec.rb | 5 +
spec/helpers/preferences_helper_spec.rb | 4 +-
spec/helpers/tree_helper_spec.rb | 10 +
spec/initializers/6_validations_spec.rb | 14 +-
.../artifacts_direct_upload_support_spec.rb | 71 +
.../fog_google_https_private_urls_spec.rb | 24 +
spec/initializers/settings_spec.rb | 2 +-
spec/javascripts/activities_spec.js | 1 +
spec/javascripts/ajax_loading_spinner_spec.js | 5 +-
spec/javascripts/api_spec.js | 183 +-
spec/javascripts/autosave_spec.js | 1 +
spec/javascripts/awards_handler_spec.js | 1 +
.../badges/components/badge_form_spec.js | 171 +
.../badges/components/badge_list_row_spec.js | 97 +
.../badges/components/badge_list_spec.js | 88 +
.../badges/components/badge_settings_spec.js | 109 +
.../badges/components/badge_spec.js | 147 +
spec/javascripts/badges/dummy_badge.js | 23 +
spec/javascripts/badges/store/actions_spec.js | 607 +
.../badges/store/mutations_spec.js | 418 +
spec/javascripts/behaviors/autosize_spec.js | 1 +
.../javascripts/behaviors/copy_as_gfm_spec.js | 2 +-
.../behaviors/quick_submit_spec.js | 1 +
.../behaviors/requires_input_spec.js | 1 +
.../blob/blob_file_dropzone_spec.js | 3 +-
spec/javascripts/blob/viewer/index_spec.js | 2 +
spec/javascripts/boards/issue_card_spec.js | 2 +
spec/javascripts/boards/mock_data.js | 49 +-
spec/javascripts/bootstrap_jquery_spec.js | 1 +
.../ci_variable_list/ci_variable_list_spec.js | 1 +
.../native_form_variable_list_spec.js | 3 +-
spec/javascripts/commits_spec.js | 1 +
spec/javascripts/create_item_dropdown_spec.js | 1 +
spec/javascripts/droplab/constants_spec.js | 16 +-
.../feature_highlight_helper_spec.js | 1 +
.../feature_highlight_spec.js | 1 +
.../filtered_search_dropdown_manager_spec.js | 3 +-
.../fixtures/gl_dropdown.html.haml | 3 +-
spec/javascripts/fixtures/one_white_pixel.png | Bin 0 -> 68 bytes
spec/javascripts/fixtures/projects.rb | 2 -
spec/javascripts/gfm_auto_complete_spec.js | 11 +-
spec/javascripts/gl_dropdown_spec.js | 26 +
spec/javascripts/gl_field_errors_spec.js | 1 +
spec/javascripts/gl_form_spec.js | 1 +
.../javascripts/groups/components/app_spec.js | 1 +
spec/javascripts/header_spec.js | 1 +
.../helpers/vue_component_helper.js | 3 +
.../helpers/vue_mount_component_helper.js | 6 +
.../javascripts/helpers/vuex_action_helper.js | 70 +-
.../ide/components/changed_file_icon_spec.js | 46 +
.../components/commit_sidebar/actions_spec.js | 35 +
.../commit_sidebar/list_collapsed_spec.js | 28 +
.../commit_sidebar/list_item_spec.js | 95 +
.../components/commit_sidebar/list_spec.js | 53 +
.../commit_sidebar/radio_group_spec.js | 130 +
.../ide/components/ide_context_bar_spec.js | 37 +
.../ide/components/ide_external_links_spec.js | 43 +
.../ide/components/ide_file_buttons_spec.js | 61 +
.../ide/components/ide_project_tree_spec.js | 39 +
.../ide/components/ide_repo_tree_spec.js | 43 +
.../ide/components/ide_side_bar_spec.js | 42 +
spec/javascripts/ide/components/ide_spec.js | 41 +
.../ide/components/new_dropdown/index_spec.js | 84 +
.../ide/components/new_dropdown/modal_spec.js | 82 +
.../components/new_dropdown/upload_spec.js | 87 +
.../components/repo_commit_section_spec.js | 173 +
.../ide/components/repo_editor_spec.js | 284 +
.../ide/components/repo_file_spec.js | 80 +
.../ide/components/repo_loading_file_spec.js | 63 +
.../ide/components/repo_tab_spec.js | 165 +
.../ide/components/repo_tabs_spec.js | 85 +
spec/javascripts/ide/helpers.js | 22 +
.../ide/lib/common/disposable_spec.js | 44 +
.../ide/lib/common/model_manager_spec.js | 132 +
spec/javascripts/ide/lib/common/model_spec.js | 123 +
.../ide/lib/decorations/controller_spec.js | 120 +
.../ide/lib/diff/controller_spec.js | 196 +
spec/javascripts/ide/lib/diff/diff_spec.js | 80 +
.../ide/lib/editor_options_spec.js | 11 +
spec/javascripts/ide/lib/editor_spec.js | 271 +
spec/javascripts/ide/monaco_loader_spec.js | 15 +
.../ide/stores/actions/file_spec.js | 573 +
.../ide/stores/actions/merge_request_spec.js | 110 +
.../ide/stores/actions/tree_spec.js | 166 +
spec/javascripts/ide/stores/actions_spec.js | 306 +
spec/javascripts/ide/stores/getters_spec.js | 75 +
.../ide/stores/modules/commit/actions_spec.js | 508 +
.../ide/stores/modules/commit/getters_spec.js | 128 +
.../stores/modules/commit/mutations_spec.js | 42 +
.../ide/stores/mutations/branch_spec.js | 18 +
.../ide/stores/mutations/file_spec.js | 272 +
.../stores/mutations/merge_request_spec.js | 65 +
.../ide/stores/mutations/tree_spec.js | 79 +
spec/javascripts/ide/stores/mutations_spec.js | 79 +
spec/javascripts/ide/stores/utils_spec.js | 66 +
.../integration_settings_form_spec.js | 1 +
spec/javascripts/issuable_spec.js | 1 +
.../javascripts/issuable_time_tracker_spec.js | 1 +
.../issue_show/components/app_spec.js | 3 +-
.../issue_show/components/description_spec.js | 1 +
spec/javascripts/issue_spec.js | 2 +
spec/javascripts/job_spec.js | 1 +
spec/javascripts/jobs/mock_data.js | 4 +
.../jobs/sidebar_detail_row_spec.js | 21 +
.../jobs/sidebar_details_block_spec.js | 6 +
spec/javascripts/labels_issue_sidebar_spec.js | 2 +
spec/javascripts/labels_select_spec.js | 1 +
.../lib/utils/text_markdown_spec.js | 10 +-
.../lib/utils/text_utility_spec.js | 14 +-
spec/javascripts/line_highlighter_spec.js | 1 +
spec/javascripts/matchers.js | 35 +
spec/javascripts/merge_request_notes_spec.js | 4 +-
spec/javascripts/merge_request_spec.js | 6 +-
spec/javascripts/merge_request_tabs_spec.js | 2 +
.../mini_pipeline_graph_dropdown_spec.js | 1 +
spec/javascripts/monitoring/dashboard_spec.js | 1 +
.../monitoring/dashboard_state_spec.js | 46 +-
.../javascripts/monitoring/graph/axis_spec.js | 65 +
.../monitoring/graph/legend_spec.js | 108 +-
.../monitoring/graph/track_info_spec.js | 44 +
.../monitoring/graph/track_line_spec.js | 52 +
spec/javascripts/monitoring/graph_spec.js | 25 +-
spec/javascripts/monitoring/mock_data.js | 14732 +++++++---------
spec/javascripts/namespace_select_spec.js | 1 +
spec/javascripts/new_branch_spec.js | 1 +
.../notes/components/comment_form_spec.js | 1 +
.../notes/components/diff_file_header_spec.js | 2 +-
.../notes/components/diff_with_note_spec.js | 2 +-
.../notes/components/note_actions_spec.js | 4 +-
.../notes/components/note_app_spec.js | 3 +-
.../notes/components/note_awards_list_spec.js | 34 +-
.../notes/components/note_body_spec.js | 1 +
.../components/noteable_discussion_spec.js | 2 +-
.../notes/components/noteable_note_spec.js | 1 +
spec/javascripts/notes/mock_data.js | 881 +-
spec/javascripts/notes/stores/actions_spec.js | 199 +-
spec/javascripts/notes_spec.js | 314 +-
spec/javascripts/oauth_remember_me_spec.js | 1 +
.../admin/abuse_reports/abuse_reports_spec.js | 1 +
.../components/promote_label_modal_spec.js | 2 +-
.../promote_milestone_modal_spec.js | 2 +-
.../components/detailed_metric_spec.js | 80 +
.../components/performance_bar_app_spec.js | 88 +
.../components/request_selector_spec.js | 47 +
.../components/simple_metric_spec.js | 47 +
.../pipelines/graph/action_component_spec.js | 25 +-
.../pipelines/graph/job_component_spec.js | 2 +
spec/javascripts/pipelines/graph/mock_data.js | 467 +-
.../pipelines/nav_controls_spec.js | 37 +-
spec/javascripts/pipelines/pipelines_spec.js | 14 +-
.../components/update_username_spec.js | 172 +
.../project_select_combo_button_spec.js | 1 +
spec/javascripts/projects/project_new_spec.js | 1 +
.../registry/stores/actions_spec.js | 87 +-
spec/javascripts/right_sidebar_spec.js | 1 +
spec/javascripts/search_autocomplete_spec.js | 217 +-
spec/javascripts/search_spec.js | 1 +
spec/javascripts/shortcuts_issuable_spec.js | 3 +-
spec/javascripts/shortcuts_spec.js | 1 +
.../sidebar/assignee_title_spec.js | 2 +-
.../confidential_issue_sidebar_spec.js | 18 +
.../sidebar/lock/lock_issue_sidebar_spec.js | 18 +
spec/javascripts/sidebar/mock_data.js | 59 +-
.../sidebar/sidebar_move_issue_spec.js | 1 +
spec/javascripts/smart_interval_spec.js | 1 +
spec/javascripts/syntax_highlight_spec.js | 1 +
spec/javascripts/test_bundle.js | 30 +-
spec/javascripts/test_constants.js | 4 +
spec/javascripts/todos_spec.js | 1 +
spec/javascripts/toggle_buttons_spec.js | 1 +
spec/javascripts/u2f/authenticate_spec.js | 1 +
spec/javascripts/u2f/register_spec.js | 1 +
spec/javascripts/version_check_image_spec.js | 1 +
.../components/deployment_spec.js | 172 +
.../components/mr_widget_deployment_spec.js | 179 -
.../components/mr_widget_header_spec.js | 244 +-
.../components/mr_widget_memory_usage_spec.js | 106 +-
.../states/mr_widget_conflicts_spec.js | 6 +-
.../states/mr_widget_nothing_to_merge_spec.js | 6 +-
.../states/mr_widget_pipeline_blocked_spec.js | 5 +-
.../states/mr_widget_ready_to_merge_spec.js | 12 +-
.../states/mr_widget_sha_mismatch_spec.js | 33 +-
.../mr_widget_unresolved_discussions_spec.js | 8 +-
spec/javascripts/vue_mr_widget/mock_data.js | 393 +-
.../vue_mr_widget/mr_widget_options_spec.js | 140 +-
.../content_viewer/content_viewer_spec.js | 70 +
...modal_spec.js => deprecated_modal_spec.js} | 7 +-
.../vue_shared/components/gl_modal_spec.js | 1 +
.../components/markdown/field_spec.js | 1 +
.../components/markdown/toolbar_spec.js | 2 +-
.../components/memory_graph_spec.js | 26 +-
.../vue_shared/components/mock_data.js | 2 -
.../sidebar/labels_select/base_spec.js | 30 +-
.../labels_select/dropdown_button_spec.js | 4 +-
.../dropdown_create_label_spec.js | 20 +-
.../labels_select/dropdown_footer_spec.js | 36 +-
.../labels_select/dropdown_header_spec.js | 2 +-
.../dropdown_hidden_input_spec.js | 4 +-
.../dropdown_search_input_spec.js | 2 +-
.../labels_select/dropdown_title_spec.js | 2 +-
.../dropdown_value_collapsed_spec.js | 4 +-
.../labels_select/dropdown_value_spec.js | 4 +-
.../sidebar/labels_select/mock_data.js | 1 +
.../skeleton_loading_container_spec.js | 4 +-
.../vue_shared/directives/tooltip_spec.js | 1 +
spec/javascripts/zen_mode_spec.js | 1 +
spec/lib/api/helpers_spec.rb | 42 +
spec/lib/backup/files_spec.rb | 66 +
spec/lib/backup/manager_spec.rb | 4 +
spec/lib/backup/repository_spec.rb | 15 +-
spec/lib/banzai/commit_renderer_spec.rb | 5 +-
.../banzai/cross_project_reference_spec.rb | 10 +
.../commit_range_reference_filter_spec.rb | 16 +
.../filter/commit_reference_filter_spec.rb | 47 +
.../filter/commit_trailers_filter_spec.rb | 191 +
.../filter/issuable_state_filter_spec.rb | 8 +
.../filter/label_reference_filter_spec.rb | 22 +
.../merge_request_reference_filter_spec.rb | 35 +
.../filter/milestone_reference_filter_spec.rb | 12 +-
.../filter/relative_link_filter_spec.rb | 17 +
.../filter/snippet_reference_filter_spec.rb | 6 +
spec/lib/banzai/issuable_extractor_spec.rb | 2 +-
spec/lib/banzai/object_renderer_spec.rb | 9 +-
spec/lib/banzai/redactor_spec.rb | 4 +-
.../reference_parser/base_parser_spec.rb | 18 +-
.../reference_parser/commit_parser_spec.rb | 2 +-
.../commit_range_parser_spec.rb | 16 +-
.../external_issue_parser_spec.rb | 2 +-
.../reference_parser/issue_parser_spec.rb | 25 +-
.../reference_parser/label_parser_spec.rb | 2 +-
.../merge_request_parser_spec.rb | 30 +-
.../reference_parser/milestone_parser_spec.rb | 2 +-
.../reference_parser/snippet_parser_spec.rb | 2 +-
.../reference_parser/user_parser_spec.rb | 2 +-
spec/lib/banzai/render_context_spec.rb | 37 +
.../constraints/group_url_constrainer_spec.rb | 2 +-
.../project_url_constrainer_spec.rb | 2 +-
.../constraints/user_url_constrainer_spec.rb | 2 +-
spec/lib/forever_spec.rb | 21 +
spec/lib/gitlab/asciidoc_spec.rb | 2 +-
spec/lib/gitlab/auth/ldap/access_spec.rb | 22 +-
spec/lib/gitlab/auth/ldap/adapter_spec.rb | 30 +-
spec/lib/gitlab/auth/o_auth/user_spec.rb | 66 +-
spec/lib/gitlab/auth_spec.rb | 122 +-
...d_merge_request_diff_commits_count_spec.rb | 12 +
.../bare_repository_import/repository_spec.rb | 4 +-
.../gitlab/bitbucket_import/importer_spec.rb | 2 +-
spec/lib/gitlab/checks/project_moved_spec.rb | 43 +-
.../gitlab/ci/build/policy/variables_spec.rb | 72 +
spec/lib/gitlab/ci/build/step_spec.rb | 12 +-
.../lib/gitlab/ci/config/entry/policy_spec.rb | 33 +
.../gitlab/ci/pipeline/chain/create_spec.rb | 35 +-
.../gitlab/ci/pipeline/chain/populate_spec.rb | 158 +
.../ci/pipeline/chain/validate/config_spec.rb | 22 -
.../pipeline/expression/lexeme/string_spec.rb | 16 +
.../ci/pipeline/expression/statement_spec.rb | 91 +-
.../lib/gitlab/ci/pipeline/seed/build_spec.rb | 232 +
.../lib/gitlab/ci/pipeline/seed/stage_spec.rb | 123 +
spec/lib/gitlab/ci/stage/seed_spec.rb | 83 -
.../lib/gitlab/ci/status/build/action_spec.rb | 10 +
.../gitlab/ci/status/build/cancelable_spec.rb | 22 +
.../gitlab/ci/status/build/canceled_spec.rb | 33 +
.../lib/gitlab/ci/status/build/common_spec.rb | 6 +
.../gitlab/ci/status/build/created_spec.rb | 33 +
.../lib/gitlab/ci/status/build/erased_spec.rb | 33 +
.../gitlab/ci/status/build/factory_spec.rb | 62 +-
.../ci/status/build/failed_allowed_spec.rb | 23 +
.../lib/gitlab/ci/status/build/failed_spec.rb | 83 +
.../lib/gitlab/ci/status/build/manual_spec.rb | 34 +
.../gitlab/ci/status/build/pending_spec.rb | 33 +
spec/lib/gitlab/ci/status/build/play_spec.rb | 26 +-
.../gitlab/ci/status/build/retried_spec.rb | 96 +
.../gitlab/ci/status/build/retryable_spec.rb | 22 +
.../gitlab/ci/status/build/skipped_spec.rb | 33 +
spec/lib/gitlab/ci/status/build/stop_spec.rb | 24 +
.../gitlab/ci/status/success_warning_spec.rb | 4 +-
spec/lib/gitlab/ci/trace/http_io_spec.rb | 315 +
.../ci/variables/collection/item_spec.rb | 83 +
.../gitlab/ci/variables/collection_spec.rb | 114 +
spec/lib/gitlab/ci/yaml_processor_spec.rb | 686 +-
.../gitlab/database/migration_helpers_spec.rb | 137 +-
.../lib/gitlab/database/sha_attribute_spec.rb | 8 +-
.../merge_request_diff_spec.rb | 2 +-
spec/lib/gitlab/diff/file_spec.rb | 12 +
spec/lib/gitlab/exclusive_lease_spec.rb | 12 +
spec/lib/gitlab/git/gitlab_projects_spec.rb | 26 +-
spec/lib/gitlab/git/gitmodules_parser_spec.rb | 3 +-
.../git/{env_spec.rb => hook_env_spec.rb} | 71 +-
spec/lib/gitlab/git/repository_spec.rb | 200 +-
spec/lib/gitlab/git/rev_list_spec.rb | 13 +-
spec/lib/gitlab/git_access_spec.rb | 159 +-
.../gitaly_client/remote_service_spec.rb | 10 +
.../gitaly_client/repository_service_spec.rb | 32 +
spec/lib/gitlab/gitaly_client/util_spec.rb | 11 +-
.../importer/repository_importer_spec.rb | 8 +-
.../health_checks/fs_shards_check_spec.rb | 6 +-
spec/lib/gitlab/http_spec.rb | 6 +-
.../base_after_export_strategy_spec.rb | 104 +
.../web_upload_strategy_spec.rb | 36 +
.../after_export_strategy_builder_spec.rb | 29 +
spec/lib/gitlab/import_export/all_models.yml | 7 +
.../lib/gitlab/import_export/importer_spec.rb | 104 +
.../gitlab/import_export/lfs_restorer_spec.rb | 75 +
.../gitlab/import_export/lfs_saver_spec.rb | 62 +
spec/lib/gitlab/import_export/project.json | 92 +-
.../project_tree_restorer_spec.rb | 34 +-
.../import_export/project_tree_saver_spec.rb | 17 +-
.../import_export/safe_model_attributes.yml | 4 +
spec/lib/gitlab/kubernetes/namespace_spec.rb | 2 +-
.../metrics/sidekiq_metrics_exporter_spec.rb | 4 +-
spec/lib/gitlab/omniauth_initializer_spec.rb | 65 +
spec/lib/gitlab/performance_bar_spec.rb | 6 +
spec/lib/gitlab/profiler_spec.rb | 28 +-
.../lib/gitlab/project_search_results_spec.rb | 22 +-
spec/lib/gitlab/repo_path_spec.rb | 4 +-
spec/lib/gitlab/shell_spec.rb | 34 +-
.../sidekiq_logging/json_formatter_spec.rb | 31 +
.../sidekiq_logging/structured_logger_spec.rb | 101 +
.../lib/gitlab/slash_commands/command_spec.rb | 5 +
.../gitlab/slash_commands/issue_move_spec.rb | 117 +
.../presenters/issue_move_spec.rb | 26 +
spec/lib/gitlab/url_blocker_spec.rb | 12 +-
spec/lib/gitlab/usage_data_spec.rb | 23 +
spec/lib/gitlab/user_access_spec.rb | 12 +
spec/lib/gitlab/verify/job_artifacts_spec.rb | 35 +
spec/lib/gitlab/verify/lfs_objects_spec.rb | 16 +
spec/lib/gitlab/verify/uploads_spec.rb | 16 +
spec/lib/gitlab/workhorse_spec.rb | 36 +-
spec/lib/mattermost/team_spec.rb | 104 +
spec/lib/omni_auth/strategies/jwt_spec.rb | 87 +
spec/lib/uploaded_file_spec.rb | 116 +
spec/mailers/notify_spec.rb | 42 +
.../email_rejection_mailer_preview.rb | 5 +
spec/mailers/previews/notify_preview.rb | 85 +-
.../repository_check_mailer_preview.rb | 5 +
.../add_foreign_keys_to_todos_spec.rb | 6 +-
...ad_pipeline_for_each_merge_request_spec.rb | 18 +-
...lculate_conv_dev_index_percentages_spec.rb | 2 +-
...espaceless_pending_delete_projects_spec.rb | 10 +-
..._namespace_pending_delete_projects_spec.rb | 8 +-
.../issues_moved_to_id_foreign_key_spec.rb | 6 +-
spec/migrations/migrate_old_artifacts_spec.rb | 20 +-
...migrate_process_commit_worker_jobs_spec.rb | 4 +-
...tivities_to_users_last_activity_on_spec.rb | 4 +-
.../migrate_user_project_view_spec.rb | 2 +-
.../move_personal_snippets_files_spec.rb | 16 +-
.../remove_dot_git_from_usernames_spec.rb | 8 +-
.../remove_duplicate_mr_events_spec.rb | 18 +-
.../remove_empty_fork_networks_spec.rb | 4 +
.../remove_project_labels_group_id_spec.rb | 6 +-
.../remove_soft_removed_objects_spec.rb | 8 +-
...rename_more_reserved_project_names_spec.rb | 2 +-
.../rename_reserved_project_names_spec.rb | 2 +-
...ename_users_with_renamed_namespace_spec.rb | 12 +-
...eschedule_builds_stages_migration_spec.rb} | 8 +-
...mmits_count_for_merge_request_diff_spec.rb | 37 +
...eate_gpg_key_subkeys_from_gpg_keys_spec.rb | 4 +-
...e_request_metrics_with_events_data_spec.rb | 2 +-
...oups_into_regular_groups_for_mysql_spec.rb | 8 +-
.../update_retried_for_ci_build_spec.rb | 6 +-
spec/models/ability_spec.rb | 56 -
spec/models/ci/artifact_blob_spec.rb | 13 +
spec/models/ci/build_metadata_spec.rb | 61 +
spec/models/ci/build_spec.rb | 346 +-
spec/models/ci/job_artifact_spec.rb | 83 +
spec/models/ci/pipeline_spec.rb | 377 +-
.../models/clusters/applications/helm_spec.rb | 12 +
.../clusters/applications/ingress_spec.rb | 12 +
.../clusters/applications/prometheus_spec.rb | 12 +
.../clusters/applications/runner_spec.rb | 12 +
spec/models/clusters/cluster_spec.rb | 36 +
.../clusters/platforms/kubernetes_spec.rb | 2 +-
spec/models/commit_status_spec.rb | 4 +-
spec/models/concerns/avatarable_spec.rb | 16 +-
spec/models/concerns/awardable_spec.rb | 25 +
.../chronic_duration_attribute_spec.rb | 129 +
spec/models/concerns/issuable_spec.rb | 10 +-
spec/models/deploy_key_spec.rb | 21 +
spec/models/deploy_token_spec.rb | 145 +
spec/models/environment_spec.rb | 30 +-
spec/models/group_spec.rb | 2 +-
spec/models/internal_id_spec.rb | 139 +
spec/models/issue_spec.rb | 8 +-
spec/models/lfs_object_spec.rb | 122 +
spec/models/merge_request_diff_commit_spec.rb | 6 +-
spec/models/merge_request_spec.rb | 15 +-
spec/models/namespace_spec.rb | 2 +-
spec/models/note_spec.rb | 17 +
spec/models/pages_domain_spec.rb | 156 +-
spec/models/project_auto_devops_spec.rb | 8 +-
spec/models/project_deploy_token_spec.rb | 14 +
.../kubernetes_service_spec.rb | 2 +-
spec/models/project_spec.rb | 184 +-
spec/models/project_wiki_spec.rb | 14 +-
spec/models/repository_spec.rb | 32 +-
spec/models/route_spec.rb | 159 +-
spec/models/service_spec.rb | 15 +
spec/models/user_spec.rb | 83 +-
spec/policies/deploy_token_policy_spec.rb | 45 +
spec/policies/group_policy_spec.rb | 27 +-
spec/policies/note_policy_spec.rb | 4 -
spec/policies/personal_snippet_policy_spec.rb | 11 +
spec/policies/project_policy_spec.rb | 103 +-
spec/policies/protected_branch_policy_spec.rb | 22 +
spec/presenters/ci/build_presenter_spec.rb | 95 +-
spec/presenters/project_presenter_spec.rb | 11 +
spec/requests/api/boards_spec.rb | 31 +
spec/requests/api/commits_spec.rb | 29 +
spec/requests/api/deploy_keys_spec.rb | 4 +
spec/requests/api/features_spec.rb | 43 +-
spec/requests/api/internal_spec.rb | 53 +-
spec/requests/api/issues_spec.rb | 24 +
spec/requests/api/jobs_spec.rb | 84 +-
spec/requests/api/merge_requests_spec.rb | 4 +-
spec/requests/api/pages_domains_spec.rb | 14 +-
spec/requests/api/pipeline_schedules_spec.rb | 23 +-
spec/requests/api/project_export_spec.rb | 90 +-
spec/requests/api/project_import_spec.rb | 68 +-
spec/requests/api/project_snapshots_spec.rb | 51 +
spec/requests/api/projects_spec.rb | 56 +-
spec/requests/api/protected_branches_spec.rb | 34 +-
spec/requests/api/repositories_spec.rb | 15 +
spec/requests/api/runner_spec.rb | 254 +-
spec/requests/api/runners_spec.rb | 5 +-
spec/requests/api/search_spec.rb | 48 +-
spec/requests/api/templates_spec.rb | 2 +-
spec/requests/api/v3/builds_spec.rb | 32 +-
spec/requests/api/v3/merge_requests_spec.rb | 4 +-
spec/requests/api/v3/templates_spec.rb | 2 +-
spec/requests/git_http_spec.rb | 28 +-
spec/requests/lfs_http_spec.rb | 213 +-
spec/requests/openid_connect_spec.rb | 9 +
.../projects/cycle_analytics_events_spec.rb | 10 +-
spec/routing/project_routing_spec.rb | 30 +-
spec/routing/routing_spec.rb | 4 +-
.../factories_in_migration_specs_spec.rb | 48 +
spec/serializers/build_serializer_spec.rb | 22 +-
spec/serializers/discussion_entity_spec.rb | 2 +-
spec/serializers/job_entity_spec.rb | 26 +-
spec/serializers/note_entity_spec.rb | 50 +-
spec/serializers/pipeline_entity_spec.rb | 2 +-
spec/serializers/pipeline_serializer_spec.rb | 1 +
spec/serializers/project_note_entity_spec.rb | 29 +
spec/serializers/stage_entity_spec.rb | 2 +-
spec/serializers/status_entity_spec.rb | 7 +-
...er_registry_authentication_service_spec.rb | 136 +
.../boards/issues/list_service_spec.rb | 25 +-
.../ci/process_pipeline_service_spec.rb | 2 +
spec/services/ci/retry_build_service_spec.rb | 4 +-
.../ci/retry_pipeline_service_spec.rb | 2 +
.../applications/install_service_spec.rb | 2 +-
.../deploy_tokens/create_service_spec.rb | 45 +
spec/services/events/render_service_spec.rb | 6 +-
spec/services/files/create_service_spec.rb | 4 +-
spec/services/files/multi_service_spec.rb | 72 +-
spec/services/groups/transfer_service_spec.rb | 42 +-
.../services/issuable/destroy_service_spec.rb | 14 +-
spec/services/issues/close_service_spec.rb | 4 +
spec/services/issues/move_service_spec.rb | 2 +-
spec/services/issues/update_service_spec.rb | 6 +-
spec/services/lfs/file_transformer_spec.rb | 97 +
.../conflicts/list_service_spec.rb | 16 +
.../merge_requests/create_service_spec.rb | 24 +-
.../merge_request_diff_cache_service_spec.rb | 36 +-
.../merge_requests/refresh_service_spec.rb | 21 +
spec/services/notes/render_service_spec.rb | 25 +-
spec/services/notification_service_spec.rb | 51 +-
.../create_from_template_service_spec.rb | 22 +-
spec/services/projects/create_service_spec.rb | 31 +-
.../services/projects/destroy_service_spec.rb | 28 +
spec/services/projects/fork_service_spec.rb | 4 +-
.../gitlab_projects_import_service_spec.rb | 40 +-
.../import_export/export_service_spec.rb | 128 +
spec/services/projects/import_service_spec.rb | 4 +-
.../projects/move_access_service_spec.rb | 114 +
.../move_deploy_keys_projects_service_spec.rb | 58 +
.../projects/move_forks_service_spec.rb | 96 +
.../move_lfs_objects_projects_service_spec.rb | 55 +
...move_notification_settings_service_spec.rb | 56 +
...ove_project_authorizations_service_spec.rb | 56 +
.../move_project_group_links_service_spec.rb | 65 +
.../move_project_members_service_spec.rb | 65 +
.../move_users_star_projects_service_spec.rb | 42 +
.../overwrite_project_service_spec.rb | 198 +
.../projects/transfer_service_spec.rb | 10 +-
.../projects/update_pages_service_spec.rb | 130 +-
spec/services/projects/update_service_spec.rb | 25 +-
.../protected_branches/create_service_spec.rb | 13 +
.../destroy_service_spec.rb | 30 +
.../protected_branches/update_service_spec.rb | 11 +
.../protected_tags/destroy_service_spec.rb | 17 +
...epository_archive_clean_up_service_spec.rb | 72 +-
spec/services/system_note_service_spec.rb | 2 +-
spec/spec_helper.rb | 24 +-
spec/support/commit_trailers_spec_helper.rb | 41 +
spec/support/cookie_helper.rb | 13 +
.../discussion_comments_shared_example.rb | 19 +-
...issuable_slash_commands_shared_examples.rb | 28 +-
spec/support/filter_spec_helper.rb | 5 +
spec/support/filtered_search_helpers.rb | 23 +
spec/support/gitaly.rb | 6 +-
spec/support/helpers/expect_offense.rb | 20 +
.../support/helpers/features/notes_helpers.rb | 27 +
.../helpers/features/sorting_helpers.rb | 26 +
spec/support/http_io/http_io_helpers.rb | 65 +
...issuables_list_metadata_shared_examples.rb | 8 +-
...uables_requiring_filter_shared_examples.rb | 15 +
spec/support/ldap_helpers.rb | 5 +
spec/support/login_helpers.rb | 4 +
spec/support/matchers/have_emoji.rb | 5 +
spec/support/matchers/issuable_matchers.rb | 11 +
spec/support/quick_actions_helpers.rb | 10 -
spec/support/reference_parser_helpers.rb | 34 +
.../controllers/variables_shared_examples.rb | 10 +-
.../models/atomic_internal_id_spec.rb | 40 +
.../serializers/note_entity_examples.rb | 42 +
.../object_storage_shared_examples.rb | 138 +
spec/support/sorting_helper.rb | 18 -
spec/support/stored_repositories.rb | 2 +-
spec/support/stub_configuration.rb | 12 +-
spec/support/stub_object_storage.rb | 48 +
spec/support/test_env.rb | 3 +-
.../tasks/gitlab/artifacts/check_rake_spec.rb | 34 +
.../gitlab/artifacts/migrate_rake_spec.rb | 118 +
spec/tasks/gitlab/backup_rake_spec.rb | 15 +-
spec/tasks/gitlab/cleanup_rake_spec.rb | 7 +-
spec/tasks/gitlab/git_rake_spec.rb | 7 +-
spec/tasks/gitlab/gitaly_rake_spec.rb | 10 +-
spec/tasks/gitlab/lfs/migrate_rake_spec.rb | 37 +
spec/tasks/gitlab/shell_rake_spec.rb | 2 +-
.../tasks/gitlab/uploads/migrate_rake_spec.rb | 143 +
spec/uploaders/attachment_uploader_spec.rb | 22 +
spec/uploaders/avatar_uploader_spec.rb | 27 +-
spec/uploaders/file_mover_spec.rb | 6 +
spec/uploaders/file_uploader_spec.rb | 71 +-
spec/uploaders/gitlab_uploader_spec.rb | 4 +-
spec/uploaders/job_artifact_uploader_spec.rb | 35 +-
.../legacy_artifact_uploader_spec.rb | 14 +-
spec/uploaders/lfs_object_uploader_spec.rb | 52 +
.../uploaders/namespace_file_uploader_spec.rb | 22 +
spec/uploaders/object_storage_spec.rb | 660 +
spec/uploaders/personal_file_uploader_spec.rb | 22 +
.../background_move_worker_spec.rb | 146 +
.../migrate_uploads_worker_spec.rb | 119 +
.../buttons/_dropdown.html.haml_spec.rb | 3 +-
.../ci/lints/show.html.haml_spec.rb | 34 +-
.../commit/_commit_box.html.haml_spec.rb | 8 +-
.../projects/diffs/_stats.html.haml_spec.rb | 56 +
.../projects/jobs/show.html.haml_spec.rb | 20 +-
.../merge_requests/_commits.html.haml_spec.rb | 2 +-
.../projects/services/_form.haml_spec.rb | 46 +
.../ci_cd/_form.html.haml_spec.rb} | 2 +-
.../object_storage_upload_worker_spec.rb | 108 +
spec/workers/project_export_worker_spec.rb | 28 +
spec/workers/repository_fork_worker_spec.rb | 111 +-
vendor/assets/javascripts/peek.js | 70 -
vendor/gitignore/Android.gitignore | 2 +
vendor/gitignore/Elixir.gitignore | 1 +
vendor/gitignore/Global/JetBrains.gitignore | 15 +-
vendor/gitignore/Global/Windows.gitignore | 1 +
vendor/gitignore/Godot.gitignore | 8 +
vendor/gitignore/Joomla.gitignore | 1 -
vendor/gitignore/KiCad.gitignore | 5 +
vendor/gitignore/Leiningen.gitignore | 1 +
vendor/gitignore/Node.gitignore | 2 +-
vendor/gitignore/Python.gitignore | 3 +-
vendor/gitignore/Rails.gitignore | 1 +
vendor/gitignore/Rust.gitignore | 2 +-
vendor/gitignore/TeX.gitignore | 2 +
vendor/gitignore/Unity.gitignore | 2 +-
vendor/gitignore/VisualStudio.gitignore | 8 +
.../gitlab-ci-yml/Auto-DevOps.gitlab-ci.yml | 58 +-
vendor/gitlab-ci-yml/Laravel.gitlab-ci.yml | 2 +-
.../gitlab-ci-yml/Pages/Gatsby.gitlab-ci.yml | 17 +
vendor/gitlab-ci-yml/Pages/Hugo.gitlab-ci.yml | 2 +-
vendor/gitlab-ci-yml/Python.gitlab-ci.yml | 23 +-
vendor/licenses.csv | 129 +-
yarn.lock | 14 +-
2200 files changed, 89163 insertions(+), 28549 deletions(-)
create mode 100644 .prettierignore
create mode 100644 .prettierrc
create mode 100644 Gemfile.rails5
create mode 100644 Gemfile.rails5.lock
create mode 100644 app/assets/images/ci_favicons/canary/favicon_status_canceled.ico
create mode 100644 app/assets/images/ci_favicons/canary/favicon_status_created.ico
create mode 100644 app/assets/images/ci_favicons/canary/favicon_status_failed.ico
create mode 100644 app/assets/images/ci_favicons/canary/favicon_status_manual.ico
create mode 100644 app/assets/images/ci_favicons/canary/favicon_status_not_found.ico
create mode 100644 app/assets/images/ci_favicons/canary/favicon_status_pending.ico
create mode 100644 app/assets/images/ci_favicons/canary/favicon_status_running.ico
create mode 100644 app/assets/images/ci_favicons/canary/favicon_status_skipped.ico
create mode 100644 app/assets/images/ci_favicons/canary/favicon_status_success.ico
create mode 100644 app/assets/images/ci_favicons/canary/favicon_status_warning.ico
create mode 100644 app/assets/images/favicon-yellow.ico
delete mode 100644 app/assets/images/icons.json
delete mode 100644 app/assets/images/icons.svg
delete mode 100644 app/assets/images/illustrations/cluster_popover.svg
delete mode 100644 app/assets/images/illustrations/clusters_empty.svg
delete mode 100644 app/assets/images/illustrations/convdev/convdev_no_data.svg
delete mode 100644 app/assets/images/illustrations/convdev/convdev_no_index.svg
delete mode 100644 app/assets/images/illustrations/convdev/convdev_overview.svg
delete mode 100644 app/assets/images/illustrations/convdev/i2p_step_1.svg
delete mode 100644 app/assets/images/illustrations/convdev/i2p_step_10.svg
delete mode 100644 app/assets/images/illustrations/convdev/i2p_step_2.svg
delete mode 100644 app/assets/images/illustrations/convdev/i2p_step_3.svg
delete mode 100644 app/assets/images/illustrations/convdev/i2p_step_4.svg
delete mode 100644 app/assets/images/illustrations/convdev/i2p_step_5.svg
delete mode 100644 app/assets/images/illustrations/convdev/i2p_step_6.svg
delete mode 100644 app/assets/images/illustrations/convdev/i2p_step_7.svg
delete mode 100644 app/assets/images/illustrations/convdev/i2p_step_8.svg
delete mode 100644 app/assets/images/illustrations/convdev/i2p_step_9.svg
delete mode 100644 app/assets/images/illustrations/epics.svg
delete mode 100644 app/assets/images/illustrations/gitlab_logo.svg
delete mode 100644 app/assets/images/illustrations/image_comment_light_cursor.svg
delete mode 100644 app/assets/images/illustrations/image_comment_light_cursor@2x.svg
delete mode 100644 app/assets/images/illustrations/issues.svg
delete mode 100644 app/assets/images/illustrations/job_not_triggered.svg
delete mode 100644 app/assets/images/illustrations/labels.svg
delete mode 100644 app/assets/images/illustrations/logos/go_logo.svg
delete mode 100644 app/assets/images/illustrations/logos/mattermost_logo.svg
delete mode 100644 app/assets/images/illustrations/manual_action.svg
delete mode 100644 app/assets/images/illustrations/merge_request_changes_empty.svg
delete mode 100644 app/assets/images/illustrations/merge_requests.svg
delete mode 100644 app/assets/images/illustrations/monitoring/getting_started.svg
delete mode 100644 app/assets/images/illustrations/monitoring/loading.svg
delete mode 100644 app/assets/images/illustrations/monitoring/unable_to_connect.svg
delete mode 100644 app/assets/images/illustrations/multi-editor_all_changes_committed_empty.svg
delete mode 100644 app/assets/images/illustrations/multi-editor_no_changes_empty.svg
delete mode 100644 app/assets/images/illustrations/multi-editor_no_staged_files_empty.svg
delete mode 100644 app/assets/images/illustrations/multi_file_editor_empty.svg
delete mode 100644 app/assets/images/illustrations/no_commits.svg
delete mode 100644 app/assets/images/illustrations/pending_job_empty.svg
delete mode 100644 app/assets/images/illustrations/pipelines_empty.svg
delete mode 100644 app/assets/images/illustrations/pipelines_failed.svg
delete mode 100644 app/assets/images/illustrations/pipelines_pending.svg
delete mode 100644 app/assets/images/illustrations/priority_labels.svg
delete mode 100644 app/assets/images/illustrations/service_desk_callout.svg
delete mode 100644 app/assets/images/illustrations/service_desk_empty.svg
delete mode 100644 app/assets/images/illustrations/slack_logo.svg
delete mode 100644 app/assets/images/illustrations/todos_all_done.svg
delete mode 100644 app/assets/images/illustrations/todos_empty.svg
delete mode 100644 app/assets/images/illustrations/welcome/add_new_group.svg
delete mode 100644 app/assets/images/illustrations/welcome/add_new_project.svg
delete mode 100644 app/assets/images/illustrations/welcome/add_new_user.svg
delete mode 100644 app/assets/images/illustrations/welcome/configure_server.svg
delete mode 100644 app/assets/images/illustrations/welcome/ee_trial.svg
delete mode 100644 app/assets/images/illustrations/welcome/globe.svg
delete mode 100644 app/assets/images/illustrations/welcome/lightbulb.svg
delete mode 100644 app/assets/images/illustrations/wiki-fro-logged-out-users.svg
delete mode 100644 app/assets/images/illustrations/wiki_login_empty.svg
delete mode 100644 app/assets/images/illustrations/wiki_logout_empty.svg
create mode 100644 app/assets/javascripts/badges/components/badge.vue
create mode 100644 app/assets/javascripts/badges/components/badge_form.vue
create mode 100644 app/assets/javascripts/badges/components/badge_list.vue
create mode 100644 app/assets/javascripts/badges/components/badge_list_row.vue
create mode 100644 app/assets/javascripts/badges/components/badge_settings.vue
create mode 100644 app/assets/javascripts/badges/constants.js
create mode 100644 app/assets/javascripts/badges/empty_badge.js
create mode 100644 app/assets/javascripts/badges/store/actions.js
create mode 100644 app/assets/javascripts/badges/store/index.js
create mode 100644 app/assets/javascripts/badges/store/mutation_types.js
create mode 100644 app/assets/javascripts/badges/store/mutations.js
create mode 100644 app/assets/javascripts/badges/store/state.js
rename app/assets/javascripts/behaviors/{ => markdown}/copy_as_gfm.js (99%)
rename app/assets/javascripts/{ => behaviors/markdown}/render_gfm.js (85%)
rename app/assets/javascripts/{ => behaviors/markdown}/render_math.js (85%)
rename app/assets/javascripts/{ => behaviors/markdown}/render_mermaid.js (94%)
create mode 100644 app/assets/javascripts/ide/components/changed_file_icon.vue
create mode 100644 app/assets/javascripts/ide/components/commit_sidebar/actions.vue
create mode 100644 app/assets/javascripts/ide/components/commit_sidebar/list.vue
create mode 100644 app/assets/javascripts/ide/components/commit_sidebar/list_collapsed.vue
create mode 100644 app/assets/javascripts/ide/components/commit_sidebar/list_item.vue
create mode 100644 app/assets/javascripts/ide/components/commit_sidebar/radio_group.vue
create mode 100644 app/assets/javascripts/ide/components/editor_mode_dropdown.vue
create mode 100644 app/assets/javascripts/ide/components/ide.vue
create mode 100644 app/assets/javascripts/ide/components/ide_context_bar.vue
create mode 100644 app/assets/javascripts/ide/components/ide_external_links.vue
create mode 100644 app/assets/javascripts/ide/components/ide_file_buttons.vue
create mode 100644 app/assets/javascripts/ide/components/ide_project_branches_tree.vue
create mode 100644 app/assets/javascripts/ide/components/ide_project_tree.vue
create mode 100644 app/assets/javascripts/ide/components/ide_repo_tree.vue
create mode 100644 app/assets/javascripts/ide/components/ide_side_bar.vue
create mode 100644 app/assets/javascripts/ide/components/ide_status_bar.vue
create mode 100644 app/assets/javascripts/ide/components/mr_file_icon.vue
create mode 100644 app/assets/javascripts/ide/components/new_dropdown/index.vue
create mode 100644 app/assets/javascripts/ide/components/new_dropdown/modal.vue
create mode 100644 app/assets/javascripts/ide/components/new_dropdown/upload.vue
create mode 100644 app/assets/javascripts/ide/components/repo_commit_section.vue
create mode 100644 app/assets/javascripts/ide/components/repo_editor.vue
create mode 100644 app/assets/javascripts/ide/components/repo_file.vue
create mode 100644 app/assets/javascripts/ide/components/repo_file_status_icon.vue
create mode 100644 app/assets/javascripts/ide/components/repo_loading_file.vue
create mode 100644 app/assets/javascripts/ide/components/repo_tab.vue
create mode 100644 app/assets/javascripts/ide/components/repo_tabs.vue
create mode 100644 app/assets/javascripts/ide/components/resizable_panel.vue
create mode 100644 app/assets/javascripts/ide/eventhub.js
create mode 100644 app/assets/javascripts/ide/ide_router.js
create mode 100644 app/assets/javascripts/ide/index.js
create mode 100644 app/assets/javascripts/ide/lib/common/disposable.js
create mode 100644 app/assets/javascripts/ide/lib/common/model.js
create mode 100644 app/assets/javascripts/ide/lib/common/model_manager.js
create mode 100644 app/assets/javascripts/ide/lib/decorations/controller.js
create mode 100644 app/assets/javascripts/ide/lib/diff/controller.js
create mode 100644 app/assets/javascripts/ide/lib/diff/diff.js
create mode 100644 app/assets/javascripts/ide/lib/diff/diff_worker.js
create mode 100644 app/assets/javascripts/ide/lib/editor.js
create mode 100644 app/assets/javascripts/ide/lib/editor_options.js
create mode 100644 app/assets/javascripts/ide/lib/themes/gl_theme.js
create mode 100644 app/assets/javascripts/ide/monaco_loader.js
create mode 100644 app/assets/javascripts/ide/services/index.js
create mode 100644 app/assets/javascripts/ide/stores/actions.js
create mode 100644 app/assets/javascripts/ide/stores/actions/file.js
create mode 100644 app/assets/javascripts/ide/stores/actions/merge_request.js
create mode 100644 app/assets/javascripts/ide/stores/actions/project.js
create mode 100644 app/assets/javascripts/ide/stores/actions/tree.js
create mode 100644 app/assets/javascripts/ide/stores/getters.js
create mode 100644 app/assets/javascripts/ide/stores/index.js
create mode 100644 app/assets/javascripts/ide/stores/modules/commit/actions.js
create mode 100644 app/assets/javascripts/ide/stores/modules/commit/constants.js
create mode 100644 app/assets/javascripts/ide/stores/modules/commit/getters.js
create mode 100644 app/assets/javascripts/ide/stores/modules/commit/index.js
create mode 100644 app/assets/javascripts/ide/stores/modules/commit/mutation_types.js
create mode 100644 app/assets/javascripts/ide/stores/modules/commit/mutations.js
create mode 100644 app/assets/javascripts/ide/stores/modules/commit/state.js
create mode 100644 app/assets/javascripts/ide/stores/mutation_types.js
create mode 100644 app/assets/javascripts/ide/stores/mutations.js
create mode 100644 app/assets/javascripts/ide/stores/mutations/branch.js
create mode 100644 app/assets/javascripts/ide/stores/mutations/file.js
create mode 100644 app/assets/javascripts/ide/stores/mutations/merge_request.js
create mode 100644 app/assets/javascripts/ide/stores/mutations/project.js
create mode 100644 app/assets/javascripts/ide/stores/mutations/tree.js
create mode 100644 app/assets/javascripts/ide/stores/state.js
create mode 100644 app/assets/javascripts/ide/stores/utils.js
create mode 100644 app/assets/javascripts/ide/stores/workers/files_decorator_worker.js
create mode 100644 app/assets/javascripts/monitoring/components/graph/axis.vue
create mode 100644 app/assets/javascripts/monitoring/components/graph/track_info.vue
create mode 100644 app/assets/javascripts/monitoring/components/graph/track_line.vue
create mode 100644 app/assets/javascripts/pages/admin/application_settings/index.js
create mode 100644 app/assets/javascripts/pages/groups/settings/badges/index.js
rename app/assets/javascripts/pages/{ => projects}/ci/lints/ci_lint_editor.js (100%)
rename app/assets/javascripts/pages/{ => projects}/ci/lints/new/index.js (100%)
rename app/assets/javascripts/pages/{ => projects}/ci/lints/show/index.js (100%)
create mode 100644 app/assets/javascripts/pages/projects/settings/badges/index/index.js
create mode 100644 app/assets/javascripts/pages/projects/settings/repository/create_deploy_token/index.js
create mode 100644 app/assets/javascripts/pages/projects/settings/repository/form.js
create mode 100644 app/assets/javascripts/pages/shared/mount_badge_settings.js
delete mode 100644 app/assets/javascripts/performance_bar.js
create mode 100644 app/assets/javascripts/performance_bar/components/detailed_metric.vue
create mode 100644 app/assets/javascripts/performance_bar/components/performance_bar_app.vue
create mode 100644 app/assets/javascripts/performance_bar/components/request_selector.vue
create mode 100644 app/assets/javascripts/performance_bar/components/simple_metric.vue
create mode 100644 app/assets/javascripts/performance_bar/components/upstream_performance_bar.vue
create mode 100644 app/assets/javascripts/performance_bar/index.js
create mode 100644 app/assets/javascripts/performance_bar/services/performance_bar_service.js
create mode 100644 app/assets/javascripts/performance_bar/stores/performance_bar_store.js
create mode 100644 app/assets/javascripts/profile/account/components/update_username.vue
delete mode 100644 app/assets/javascripts/sidebar/components/assignees/assignee_title.js
create mode 100644 app/assets/javascripts/sidebar/components/assignees/assignee_title.vue
delete mode 100644 app/assets/javascripts/sidebar/components/time_tracking/collapsed_state.js
create mode 100644 app/assets/javascripts/sidebar/components/time_tracking/collapsed_state.vue
rename app/assets/javascripts/sidebar/components/time_tracking/{comparison_pane.js => comparison_pane.vue} (53%)
create mode 100644 app/assets/javascripts/vue_merge_request_widget/components/deployment.vue
rename app/assets/javascripts/vue_merge_request_widget/components/{mr_widget_memory_usage.js => memory_usage.vue} (61%)
delete mode 100644 app/assets/javascripts/vue_merge_request_widget/components/mr_widget_deployment.js
create mode 100644 app/assets/javascripts/vue_merge_request_widget/components/source_branch_removal_status.vue
delete mode 100644 app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_nothing_to_merge.js
delete mode 100644 app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_sha_mismatch.js
delete mode 100644 app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_unresolved_discussions.js
create mode 100644 app/assets/javascripts/vue_merge_request_widget/components/states/nothing_to_merge.vue
create mode 100644 app/assets/javascripts/vue_merge_request_widget/components/states/sha_mismatch.vue
create mode 100644 app/assets/javascripts/vue_merge_request_widget/components/states/unresolved_discussions.vue
create mode 100644 app/assets/javascripts/vue_shared/components/content_viewer/content_viewer.vue
create mode 100644 app/assets/javascripts/vue_shared/components/content_viewer/lib/viewer_utils.js
create mode 100644 app/assets/javascripts/vue_shared/components/content_viewer/viewers/download_viewer.vue
create mode 100644 app/assets/javascripts/vue_shared/components/content_viewer/viewers/image_viewer.vue
create mode 100644 app/assets/javascripts/vue_shared/components/content_viewer/viewers/markdown_viewer.vue
rename app/assets/javascripts/vue_shared/components/{modal.vue => deprecated_modal.vue} (98%)
rename app/assets/javascripts/vue_shared/components/{memory_graph.js => memory_graph.vue} (87%)
delete mode 100644 app/assets/stylesheets/pages/lint.scss
create mode 100644 app/assets/stylesheets/pages/pages.scss
create mode 100644 app/assets/stylesheets/pages/repo.scss.orig
create mode 100644 app/controllers/concerns/checks_collaboration.rb
create mode 100644 app/controllers/concerns/send_file_upload.rb
create mode 100644 app/controllers/groups/settings/badges_controller.rb
create mode 100644 app/controllers/ide_controller.rb
create mode 100644 app/controllers/projects/ci/lints_controller.rb
create mode 100644 app/controllers/projects/deploy_tokens_controller.rb
create mode 100644 app/controllers/projects/settings/badges_controller.rb
create mode 100644 app/helpers/deploy_tokens_helper.rb
create mode 100644 app/models/ci/build_metadata.rb
create mode 100644 app/models/concerns/atomic_internal_id.rb
create mode 100644 app/models/concerns/chronic_duration_attribute.rb
rename app/models/concerns/{internal_id.rb => nonatomic_internal_id.rb} (94%)
delete mode 100644 app/models/cycle_analytics/summary.rb
create mode 100644 app/models/deploy_token.rb
create mode 100644 app/models/internal_id.rb
create mode 100644 app/models/project_deploy_token.rb
create mode 100644 app/policies/deploy_token_policy.rb
create mode 100644 app/policies/project_policy/class_methods.rb
create mode 100644 app/policies/protected_branch_policy.rb
create mode 100644 app/presenters/ci/build_metadata_presenter.rb
create mode 100644 app/serializers/build_metadata_entity.rb
delete mode 100644 app/serializers/note_serializer.rb
create mode 100644 app/serializers/project_note_entity.rb
create mode 100644 app/serializers/project_note_serializer.rb
delete mode 100644 app/services/ci/create_pipeline_stages_service.rb
create mode 100644 app/services/deploy_tokens/create_service.rb
delete mode 100644 app/services/lfs/file_modification_handler.rb
create mode 100644 app/services/lfs/file_transformer.rb
create mode 100644 app/services/projects/base_move_relations_service.rb
create mode 100644 app/services/projects/move_access_service.rb
create mode 100644 app/services/projects/move_deploy_keys_projects_service.rb
create mode 100644 app/services/projects/move_forks_service.rb
create mode 100644 app/services/projects/move_lfs_objects_projects_service.rb
create mode 100644 app/services/projects/move_notification_settings_service.rb
create mode 100644 app/services/projects/move_project_authorizations_service.rb
create mode 100644 app/services/projects/move_project_group_links_service.rb
create mode 100644 app/services/projects/move_project_members_service.rb
create mode 100644 app/services/projects/move_users_star_projects_service.rb
create mode 100644 app/services/projects/overwrite_project_service.rb
create mode 100644 app/services/protected_branches/destroy_service.rb
create mode 100644 app/services/protected_tags/destroy_service.rb
create mode 100644 app/uploaders/object_storage.rb
create mode 100644 app/validators/certificate_fingerprint_validator.rb
create mode 100644 app/validators/top_level_group_validator.rb
create mode 100644 app/views/admin/application_settings/_abuse.html.haml
create mode 100644 app/views/admin/application_settings/_account_and_limit.html.haml
create mode 100644 app/views/admin/application_settings/_background_jobs.html.haml
create mode 100644 app/views/admin/application_settings/_ci_cd.html.haml
create mode 100644 app/views/admin/application_settings/_email.html.haml
delete mode 100644 app/views/admin/application_settings/_form.html.haml
create mode 100644 app/views/admin/application_settings/_gitaly.html.haml
create mode 100644 app/views/admin/application_settings/_help_page.html.haml
create mode 100644 app/views/admin/application_settings/_influx.html.haml
create mode 100644 app/views/admin/application_settings/_ip_limits.html.haml
create mode 100644 app/views/admin/application_settings/_koding.html.haml
create mode 100644 app/views/admin/application_settings/_logging.html.haml
create mode 100644 app/views/admin/application_settings/_outbound.html.haml
create mode 100644 app/views/admin/application_settings/_pages.html.haml
create mode 100644 app/views/admin/application_settings/_performance.html.haml
create mode 100644 app/views/admin/application_settings/_performance_bar.html.haml
create mode 100644 app/views/admin/application_settings/_plantuml.html.haml
create mode 100644 app/views/admin/application_settings/_prometheus.html.haml
create mode 100644 app/views/admin/application_settings/_realtime.html.haml
create mode 100644 app/views/admin/application_settings/_registry.html.haml
create mode 100644 app/views/admin/application_settings/_repository_check.html.haml
create mode 100644 app/views/admin/application_settings/_repository_storage.html.haml
create mode 100644 app/views/admin/application_settings/_signin.html.haml
create mode 100644 app/views/admin/application_settings/_signup.html.haml
create mode 100644 app/views/admin/application_settings/_spam.html.haml
create mode 100644 app/views/admin/application_settings/_terminal.html.haml
create mode 100644 app/views/admin/application_settings/_usage.html.haml
create mode 100644 app/views/admin/application_settings/_visibility_and_access.html.haml
create mode 100644 app/views/groups/settings/badges/index.html.haml
create mode 100644 app/views/ide/index.html.haml
create mode 100644 app/views/layouts/header/_read_only_banner.html.haml
create mode 100644 app/views/notify/push_to_merge_request_email.html.haml
create mode 100644 app/views/notify/push_to_merge_request_email.text.haml
create mode 100644 app/views/peek/_bar.html.haml
create mode 100644 app/views/peek/views/_gc.html.haml
delete mode 100644 app/views/peek/views/_gitaly.html.haml
delete mode 100644 app/views/peek/views/_host.html.haml
delete mode 100644 app/views/peek/views/_mysql2.html.haml
delete mode 100644 app/views/peek/views/_pg.html.haml
delete mode 100644 app/views/peek/views/_rblineprof.html.haml
create mode 100644 app/views/peek/views/_redis.html.haml
create mode 100644 app/views/peek/views/_sidekiq.html.haml
delete mode 100644 app/views/peek/views/_sql.html.haml
rename app/views/{ => projects}/ci/lints/_create.html.haml (100%)
create mode 100644 app/views/projects/ci/lints/show.html.haml
create mode 100644 app/views/projects/deploy_tokens/_form.html.haml
create mode 100644 app/views/projects/deploy_tokens/_index.html.haml
create mode 100644 app/views/projects/deploy_tokens/_new_deploy_token.html.haml
create mode 100644 app/views/projects/deploy_tokens/_revoke_modal.html.haml
create mode 100644 app/views/projects/deploy_tokens/_table.html.haml
create mode 100644 app/views/projects/jobs/_empty_states.html.haml
create mode 100644 app/views/projects/pages/_https_only.html.haml
create mode 100644 app/views/projects/settings/badges/index.html.haml
rename app/views/projects/{pipelines_settings => settings/ci_cd}/_badge.html.haml (100%)
rename app/views/projects/{pipelines_settings/_show.html.haml => settings/ci_cd/_form.html.haml} (93%)
create mode 100644 app/views/shared/badges/_badge_settings.html.haml
create mode 100644 app/views/shared/dashboard/_no_filter_selected.html.haml
create mode 100644 app/workers/concerns/object_storage_queue.rb
create mode 100644 app/workers/object_storage/background_move_worker.rb
create mode 100644 app/workers/object_storage/migrate_uploads_worker.rb
create mode 100644 app/workers/object_storage_upload_worker.rb
create mode 100755 bin/update
delete mode 100644 changelogs/unreleased-ee/39118-dynamic-pipeline-variables-fe.yml
delete mode 100644 changelogs/unreleased-ee/4378-fix-cluster-js-not-running-on-update-page.yml
delete mode 100644 changelogs/unreleased-ee/bvl-external-policy-classification.yml
rename config/initializers/{fast_gettext.rb => 9_fast_gettext.rb} (100%)
create mode 100644 config/initializers/application_controller_renderer.rb
create mode 100644 config/initializers/ar_native_database_types.rb
create mode 100644 config/initializers/artifacts_direct_upload_support.rb
create mode 100644 config/initializers/fog_google_https_private_urls.rb
create mode 100644 config/initializers/new_framework_defaults.rb
create mode 100644 config/spring.rb
delete mode 100644 config/svg.config.js
create mode 100644 db/fixtures/development/22_labeled_issues_seed.rb
create mode 100644 db/migrate/20170601163708_add_artifacts_store_to_ci_build.rb
create mode 100644 db/migrate/20170825015534_add_file_store_to_lfs_objects.rb
create mode 100644 db/migrate/20170918072949_add_file_store_job_artifacts.rb
create mode 100644 db/migrate/20171214144320_add_store_column_to_uploads.rb
create mode 100644 db/migrate/20180102220145_add_pages_https_only_to_projects.rb
create mode 100644 db/migrate/20180109183319_change_default_value_for_pages_https_only.rb
create mode 100644 db/migrate/20180209165249_add_closed_by_to_issues.rb
create mode 100644 db/migrate/20180219153455_add_maximum_timeout_to_ci_runners.rb
create mode 100644 db/migrate/20180301010859_create_ci_builds_metadata_table.rb
create mode 100644 db/migrate/20180305095250_create_internal_ids_table.rb
create mode 100644 db/migrate/20180309121820_reschedule_commits_count_for_merge_request_diff.rb
create mode 100644 db/migrate/20180319190020_create_deploy_tokens.rb
create mode 100644 db/migrate/20180323150945_add_push_to_merge_request_to_notification_settings.rb
create mode 100644 db/migrate/20180327101207_remove_index_from_events_table.rb
create mode 100644 db/migrate/20180405142733_create_project_deploy_tokens.rb
create mode 100644 db/migrate/20180418053107_add_index_to_ci_job_artifacts_file_store.rb
create mode 100644 db/post_migrate/20180305100050_remove_permanent_from_redirect_routes.rb
create mode 100644 db/post_migrate/20180306164012_add_path_index_to_redirect_routes.rb
create mode 100644 db/post_migrate/20180405101928_reschedule_builds_stages_migration.rb
create mode 100644 doc/administration/auth/jwt.md
create mode 100644 doc/administration/job_traces.md
create mode 100644 doc/administration/monitoring/performance/img/performance_bar_gitaly_calls.png
create mode 100644 doc/administration/raketasks/uploads/migrate.md
create mode 100644 doc/administration/uploads.md
create mode 100644 doc/ci/caching/img/clear_runners_cache.png
create mode 100644 doc/ci/examples/container_scanning.md
create mode 100644 doc/ci/examples/devops_and_game_dev_with_gitlab_ci_cd/img/aws_config_window.png
create mode 100644 doc/ci/examples/devops_and_game_dev_with_gitlab_ci_cd/img/gitlab_config.png
create mode 100644 doc/ci/examples/devops_and_game_dev_with_gitlab_ci_cd/img/test_pipeline_pass.png
create mode 100644 doc/ci/examples/devops_and_game_dev_with_gitlab_ci_cd/index.md
create mode 100644 doc/ci/img/job_failure_reason.png
create mode 100644 doc/development/new_fe_guide/style/prettier.md
create mode 100644 doc/img/devops_lifecycle.png
create mode 100644 doc/update/10.6-to-10.7.md
create mode 100644 doc/user/admin_area/settings/email.md
create mode 100644 doc/user/gitlab_com/index.md
create mode 100644 doc/user/project/badges.md
create mode 100644 doc/user/project/deploy_tokens/img/deploy_tokens.png
create mode 100644 doc/user/project/deploy_tokens/index.md
create mode 100644 doc/user/project/img/project_overview_badges.png
delete mode 100644 doc/user/project/integrations/img/jira_workflow_screenshot.png
create mode 100644 doc/user/project/merge_requests/img/remove_source_branch_status.png
create mode 100644 doc/user/project/repository/img/jupyter_notebook.png
create mode 100644 doc/user/project/web_ide/img/commit_changes.png
create mode 100644 doc/user/project/web_ide/img/enable_web_ide.png
create mode 100644 doc/user/project/web_ide/img/open_web_ide.png
create mode 100644 doc/user/project/web_ide/index.md
delete mode 100644 features/groups.feature
delete mode 100644 features/project/active_tab.feature
delete mode 100644 features/project/fork.feature
delete mode 100644 features/project/graph.feature
delete mode 100644 features/project/issues/issues.feature
delete mode 100644 features/project/issues/labels.feature
delete mode 100644 features/project/redirects.feature
delete mode 100644 features/steps/groups.rb
delete mode 100644 features/steps/project/active_tab.rb
delete mode 100644 features/steps/project/fork.rb
delete mode 100644 features/steps/project/graph.rb
delete mode 100644 features/steps/project/issues/labels.rb
delete mode 100644 features/steps/project/redirects.rb
create mode 100644 lib/api/helpers/project_snapshots_helpers.rb
create mode 100644 lib/api/helpers/projects_helpers.rb
create mode 100644 lib/api/project_snapshots.rb
create mode 100644 lib/backup/helper.rb
create mode 100644 lib/banzai/filter/commit_trailers_filter.rb
create mode 100644 lib/banzai/pipeline/commit_description_pipeline.rb
create mode 100644 lib/banzai/render_context.rb
create mode 100644 lib/declarative_policy/delegate_dsl.rb
delete mode 100644 lib/declarative_policy/dsl.rb
create mode 100644 lib/declarative_policy/policy_dsl.rb
create mode 100644 lib/declarative_policy/rule_dsl.rb
create mode 100644 lib/forever.rb
create mode 100644 lib/gitlab/auth/ldap/ldap_connection_error.rb
create mode 100644 lib/gitlab/base_doorkeeper_controller.rb
create mode 100644 lib/gitlab/ci/build/policy/variables.rb
create mode 100644 lib/gitlab/ci/pipeline/chain/populate.rb
create mode 100644 lib/gitlab/ci/pipeline/seed/base.rb
create mode 100644 lib/gitlab/ci/pipeline/seed/build.rb
create mode 100644 lib/gitlab/ci/pipeline/seed/stage.rb
delete mode 100644 lib/gitlab/ci/stage/seed.rb
create mode 100644 lib/gitlab/ci/status/build/canceled.rb
create mode 100644 lib/gitlab/ci/status/build/created.rb
create mode 100644 lib/gitlab/ci/status/build/erased.rb
create mode 100644 lib/gitlab/ci/status/build/failed.rb
create mode 100644 lib/gitlab/ci/status/build/manual.rb
create mode 100644 lib/gitlab/ci/status/build/pending.rb
create mode 100644 lib/gitlab/ci/status/build/retried.rb
create mode 100644 lib/gitlab/ci/status/build/skipped.rb
create mode 100644 lib/gitlab/ci/trace/http_io.rb
create mode 100644 lib/gitlab/ci/variables/collection.rb
create mode 100644 lib/gitlab/ci/variables/collection/item.rb
rename lib/gitlab/git/{env.rb => hook_env.rb} (64%)
create mode 100644 lib/gitlab/gitaly_client/storage_settings.rb
create mode 100644 lib/gitlab/import_export/after_export_strategies/base_after_export_strategy.rb
create mode 100644 lib/gitlab/import_export/after_export_strategies/download_notification_strategy.rb
create mode 100644 lib/gitlab/import_export/after_export_strategies/web_upload_strategy.rb
create mode 100644 lib/gitlab/import_export/after_export_strategy_builder.rb
create mode 100644 lib/gitlab/import_export/lfs_restorer.rb
create mode 100644 lib/gitlab/import_export/lfs_saver.rb
create mode 100644 lib/gitlab/import_export/statistics_restorer.rb
create mode 100644 lib/gitlab/omniauth_initializer.rb
create mode 100644 lib/gitlab/sidekiq_logging/json_formatter.rb
create mode 100644 lib/gitlab/sidekiq_logging/structured_logger.rb
create mode 100644 lib/gitlab/slash_commands/issue_move.rb
create mode 100644 lib/gitlab/slash_commands/presenters/issue_move.rb
create mode 100644 lib/gitlab/verify/job_artifacts.rb
create mode 100644 lib/omni_auth/strategies/jwt.rb
create mode 100644 lib/peek/views/host.rb
create mode 100644 lib/tasks/gitlab/artifacts/check.rake
create mode 100644 lib/tasks/gitlab/artifacts/migrate.rake
create mode 100644 lib/tasks/gitlab/exclusive_lease.rake
create mode 100644 lib/tasks/gitlab/lfs/migrate.rake
create mode 100644 lib/tasks/gitlab/uploads/migrate.rake
delete mode 100644 qa/qa/page/admin/settings.rb
create mode 100644 qa/qa/page/admin/settings/main.rb
create mode 100644 qa/qa/page/admin/settings/repository_storage.rb
create mode 100644 qa/qa/page/settings/common.rb
create mode 100644 rubocop/cop/rspec/factories_in_migration_specs.rb
delete mode 100755 scripts/codequality
create mode 100644 scripts/frontend/frontend_script_utils.js
create mode 100644 scripts/frontend/prettier.js
create mode 100644 spec/controllers/concerns/checks_collaboration_spec.rb
create mode 100644 spec/controllers/concerns/send_file_upload_spec.rb
create mode 100644 spec/controllers/projects/ci/lints_controller_spec.rb
create mode 100644 spec/factories/deploy_tokens.rb
create mode 100644 spec/factories/internal_ids.rb
create mode 100644 spec/factories/project_deploy_tokens.rb
create mode 100644 spec/factories/users_star_projects.rb
create mode 100644 spec/features/groups/settings/group_badges_spec.rb
create mode 100644 spec/features/groups/user_browse_projects_group_page_spec.rb
create mode 100644 spec/features/ide_spec.rb
create mode 100644 spec/features/labels_hierarchy_spec.rb
create mode 100644 spec/features/projects/actve_tabs_spec.rb
create mode 100644 spec/features/projects/blobs/user_creates_new_blob_in_new_project_spec.rb
rename spec/features/{ci_lint_spec.rb => projects/ci/lint_spec.rb} (91%)
create mode 100644 spec/features/projects/graph_spec.rb
create mode 100644 spec/features/projects/hook_logs/user_reads_log_spec.rb
create mode 100644 spec/features/projects/issues/user_comments_on_issue_spec.rb
create mode 100644 spec/features/projects/issues/user_creates_issue_spec.rb
create mode 100644 spec/features/projects/issues/user_edits_issue_spec.rb
create mode 100644 spec/features/projects/issues/user_sorts_issues_spec.rb
create mode 100644 spec/features/projects/issues/user_toggles_subscription_spec.rb
create mode 100644 spec/features/projects/issues/user_views_issue_spec.rb
create mode 100644 spec/features/projects/labels/user_creates_labels_spec.rb
create mode 100644 spec/features/projects/labels/user_edits_labels_spec.rb
create mode 100644 spec/features/projects/labels/user_removes_labels_spec.rb
create mode 100644 spec/features/projects/labels/user_views_labels_spec.rb
create mode 100644 spec/features/projects/redirects_spec.rb
create mode 100644 spec/features/projects/settings/project_badges_spec.rb
create mode 100644 spec/features/projects/show/user_sees_collaboration_links_spec.rb
create mode 100644 spec/features/projects/tree/create_directory_spec.rb
create mode 100644 spec/features/projects/tree/create_file_spec.rb
create mode 100644 spec/features/projects/tree/upload_file_spec.rb
create mode 100644 spec/features/projects/user_views_empty_project_spec.rb
create mode 100644 spec/features/read_only_spec.rb
create mode 100644 spec/features/user_sorts_things_spec.rb
create mode 100644 spec/fixtures/big-image.png
create mode 100644 spec/fixtures/exported-project.gz
create mode 100644 spec/initializers/artifacts_direct_upload_support_spec.rb
create mode 100644 spec/initializers/fog_google_https_private_urls_spec.rb
create mode 100644 spec/javascripts/badges/components/badge_form_spec.js
create mode 100644 spec/javascripts/badges/components/badge_list_row_spec.js
create mode 100644 spec/javascripts/badges/components/badge_list_spec.js
create mode 100644 spec/javascripts/badges/components/badge_settings_spec.js
create mode 100644 spec/javascripts/badges/components/badge_spec.js
create mode 100644 spec/javascripts/badges/dummy_badge.js
create mode 100644 spec/javascripts/badges/store/actions_spec.js
create mode 100644 spec/javascripts/badges/store/mutations_spec.js
create mode 100644 spec/javascripts/fixtures/one_white_pixel.png
create mode 100644 spec/javascripts/helpers/vue_component_helper.js
create mode 100644 spec/javascripts/ide/components/changed_file_icon_spec.js
create mode 100644 spec/javascripts/ide/components/commit_sidebar/actions_spec.js
create mode 100644 spec/javascripts/ide/components/commit_sidebar/list_collapsed_spec.js
create mode 100644 spec/javascripts/ide/components/commit_sidebar/list_item_spec.js
create mode 100644 spec/javascripts/ide/components/commit_sidebar/list_spec.js
create mode 100644 spec/javascripts/ide/components/commit_sidebar/radio_group_spec.js
create mode 100644 spec/javascripts/ide/components/ide_context_bar_spec.js
create mode 100644 spec/javascripts/ide/components/ide_external_links_spec.js
create mode 100644 spec/javascripts/ide/components/ide_file_buttons_spec.js
create mode 100644 spec/javascripts/ide/components/ide_project_tree_spec.js
create mode 100644 spec/javascripts/ide/components/ide_repo_tree_spec.js
create mode 100644 spec/javascripts/ide/components/ide_side_bar_spec.js
create mode 100644 spec/javascripts/ide/components/ide_spec.js
create mode 100644 spec/javascripts/ide/components/new_dropdown/index_spec.js
create mode 100644 spec/javascripts/ide/components/new_dropdown/modal_spec.js
create mode 100644 spec/javascripts/ide/components/new_dropdown/upload_spec.js
create mode 100644 spec/javascripts/ide/components/repo_commit_section_spec.js
create mode 100644 spec/javascripts/ide/components/repo_editor_spec.js
create mode 100644 spec/javascripts/ide/components/repo_file_spec.js
create mode 100644 spec/javascripts/ide/components/repo_loading_file_spec.js
create mode 100644 spec/javascripts/ide/components/repo_tab_spec.js
create mode 100644 spec/javascripts/ide/components/repo_tabs_spec.js
create mode 100644 spec/javascripts/ide/helpers.js
create mode 100644 spec/javascripts/ide/lib/common/disposable_spec.js
create mode 100644 spec/javascripts/ide/lib/common/model_manager_spec.js
create mode 100644 spec/javascripts/ide/lib/common/model_spec.js
create mode 100644 spec/javascripts/ide/lib/decorations/controller_spec.js
create mode 100644 spec/javascripts/ide/lib/diff/controller_spec.js
create mode 100644 spec/javascripts/ide/lib/diff/diff_spec.js
create mode 100644 spec/javascripts/ide/lib/editor_options_spec.js
create mode 100644 spec/javascripts/ide/lib/editor_spec.js
create mode 100644 spec/javascripts/ide/monaco_loader_spec.js
create mode 100644 spec/javascripts/ide/stores/actions/file_spec.js
create mode 100644 spec/javascripts/ide/stores/actions/merge_request_spec.js
create mode 100644 spec/javascripts/ide/stores/actions/tree_spec.js
create mode 100644 spec/javascripts/ide/stores/actions_spec.js
create mode 100644 spec/javascripts/ide/stores/getters_spec.js
create mode 100644 spec/javascripts/ide/stores/modules/commit/actions_spec.js
create mode 100644 spec/javascripts/ide/stores/modules/commit/getters_spec.js
create mode 100644 spec/javascripts/ide/stores/modules/commit/mutations_spec.js
create mode 100644 spec/javascripts/ide/stores/mutations/branch_spec.js
create mode 100644 spec/javascripts/ide/stores/mutations/file_spec.js
create mode 100644 spec/javascripts/ide/stores/mutations/merge_request_spec.js
create mode 100644 spec/javascripts/ide/stores/mutations/tree_spec.js
create mode 100644 spec/javascripts/ide/stores/mutations_spec.js
create mode 100644 spec/javascripts/ide/stores/utils_spec.js
create mode 100644 spec/javascripts/matchers.js
create mode 100644 spec/javascripts/monitoring/graph/axis_spec.js
create mode 100644 spec/javascripts/monitoring/graph/track_info_spec.js
create mode 100644 spec/javascripts/monitoring/graph/track_line_spec.js
create mode 100644 spec/javascripts/performance_bar/components/detailed_metric_spec.js
create mode 100644 spec/javascripts/performance_bar/components/performance_bar_app_spec.js
create mode 100644 spec/javascripts/performance_bar/components/request_selector_spec.js
create mode 100644 spec/javascripts/performance_bar/components/simple_metric_spec.js
create mode 100644 spec/javascripts/profile/account/components/update_username_spec.js
create mode 100644 spec/javascripts/test_constants.js
create mode 100644 spec/javascripts/vue_mr_widget/components/deployment_spec.js
delete mode 100644 spec/javascripts/vue_mr_widget/components/mr_widget_deployment_spec.js
create mode 100644 spec/javascripts/vue_shared/components/content_viewer/content_viewer_spec.js
rename spec/javascripts/vue_shared/components/{modal_spec.js => deprecated_modal_spec.js} (90%)
create mode 100644 spec/lib/backup/files_spec.rb
create mode 100644 spec/lib/banzai/filter/commit_trailers_filter_spec.rb
create mode 100644 spec/lib/banzai/render_context_spec.rb
create mode 100644 spec/lib/forever_spec.rb
create mode 100644 spec/lib/gitlab/ci/build/policy/variables_spec.rb
create mode 100644 spec/lib/gitlab/ci/pipeline/chain/populate_spec.rb
create mode 100644 spec/lib/gitlab/ci/pipeline/seed/build_spec.rb
create mode 100644 spec/lib/gitlab/ci/pipeline/seed/stage_spec.rb
delete mode 100644 spec/lib/gitlab/ci/stage/seed_spec.rb
create mode 100644 spec/lib/gitlab/ci/status/build/canceled_spec.rb
create mode 100644 spec/lib/gitlab/ci/status/build/created_spec.rb
create mode 100644 spec/lib/gitlab/ci/status/build/erased_spec.rb
create mode 100644 spec/lib/gitlab/ci/status/build/failed_spec.rb
create mode 100644 spec/lib/gitlab/ci/status/build/manual_spec.rb
create mode 100644 spec/lib/gitlab/ci/status/build/pending_spec.rb
create mode 100644 spec/lib/gitlab/ci/status/build/retried_spec.rb
create mode 100644 spec/lib/gitlab/ci/status/build/skipped_spec.rb
create mode 100644 spec/lib/gitlab/ci/trace/http_io_spec.rb
create mode 100644 spec/lib/gitlab/ci/variables/collection/item_spec.rb
create mode 100644 spec/lib/gitlab/ci/variables/collection_spec.rb
rename spec/lib/gitlab/git/{env_spec.rb => hook_env_spec.rb} (54%)
create mode 100644 spec/lib/gitlab/import_export/after_export_strategies/base_after_export_strategy_spec.rb
create mode 100644 spec/lib/gitlab/import_export/after_export_strategies/web_upload_strategy_spec.rb
create mode 100644 spec/lib/gitlab/import_export/after_export_strategy_builder_spec.rb
create mode 100644 spec/lib/gitlab/import_export/importer_spec.rb
create mode 100644 spec/lib/gitlab/import_export/lfs_restorer_spec.rb
create mode 100644 spec/lib/gitlab/import_export/lfs_saver_spec.rb
create mode 100644 spec/lib/gitlab/omniauth_initializer_spec.rb
create mode 100644 spec/lib/gitlab/sidekiq_logging/json_formatter_spec.rb
create mode 100644 spec/lib/gitlab/sidekiq_logging/structured_logger_spec.rb
create mode 100644 spec/lib/gitlab/slash_commands/issue_move_spec.rb
create mode 100644 spec/lib/gitlab/slash_commands/presenters/issue_move_spec.rb
create mode 100644 spec/lib/gitlab/verify/job_artifacts_spec.rb
create mode 100644 spec/lib/omni_auth/strategies/jwt_spec.rb
create mode 100644 spec/lib/uploaded_file_spec.rb
create mode 100644 spec/mailers/previews/email_rejection_mailer_preview.rb
create mode 100644 spec/mailers/previews/repository_check_mailer_preview.rb
rename spec/migrations/{schedule_build_stage_migration_spec.rb => reschedule_builds_stages_migration_spec.rb} (77%)
create mode 100644 spec/migrations/reschedule_commits_count_for_merge_request_diff_spec.rb
create mode 100644 spec/models/ci/build_metadata_spec.rb
create mode 100644 spec/models/concerns/chronic_duration_attribute_spec.rb
create mode 100644 spec/models/deploy_token_spec.rb
create mode 100644 spec/models/internal_id_spec.rb
create mode 100644 spec/models/lfs_object_spec.rb
create mode 100644 spec/models/project_deploy_token_spec.rb
create mode 100644 spec/policies/deploy_token_policy_spec.rb
create mode 100644 spec/policies/protected_branch_policy_spec.rb
create mode 100644 spec/requests/api/project_snapshots_spec.rb
create mode 100644 spec/rubocop/cop/rspec/factories_in_migration_specs_spec.rb
create mode 100644 spec/serializers/project_note_entity_spec.rb
create mode 100644 spec/services/deploy_tokens/create_service_spec.rb
create mode 100644 spec/services/lfs/file_transformer_spec.rb
create mode 100644 spec/services/projects/import_export/export_service_spec.rb
create mode 100644 spec/services/projects/move_access_service_spec.rb
create mode 100644 spec/services/projects/move_deploy_keys_projects_service_spec.rb
create mode 100644 spec/services/projects/move_forks_service_spec.rb
create mode 100644 spec/services/projects/move_lfs_objects_projects_service_spec.rb
create mode 100644 spec/services/projects/move_notification_settings_service_spec.rb
create mode 100644 spec/services/projects/move_project_authorizations_service_spec.rb
create mode 100644 spec/services/projects/move_project_group_links_service_spec.rb
create mode 100644 spec/services/projects/move_project_members_service_spec.rb
create mode 100644 spec/services/projects/move_users_star_projects_service_spec.rb
create mode 100644 spec/services/projects/overwrite_project_service_spec.rb
create mode 100644 spec/services/protected_branches/destroy_service_spec.rb
create mode 100644 spec/services/protected_tags/destroy_service_spec.rb
create mode 100644 spec/support/commit_trailers_spec_helper.rb
create mode 100644 spec/support/helpers/expect_offense.rb
create mode 100644 spec/support/helpers/features/notes_helpers.rb
create mode 100644 spec/support/helpers/features/sorting_helpers.rb
create mode 100644 spec/support/http_io/http_io_helpers.rb
create mode 100644 spec/support/issuables_requiring_filter_shared_examples.rb
create mode 100644 spec/support/matchers/have_emoji.rb
create mode 100644 spec/support/matchers/issuable_matchers.rb
delete mode 100644 spec/support/quick_actions_helpers.rb
create mode 100644 spec/support/shared_examples/models/atomic_internal_id_spec.rb
create mode 100644 spec/support/shared_examples/serializers/note_entity_examples.rb
create mode 100644 spec/support/shared_examples/uploaders/object_storage_shared_examples.rb
delete mode 100644 spec/support/sorting_helper.rb
create mode 100644 spec/support/stub_object_storage.rb
create mode 100644 spec/tasks/gitlab/artifacts/check_rake_spec.rb
create mode 100644 spec/tasks/gitlab/artifacts/migrate_rake_spec.rb
create mode 100644 spec/tasks/gitlab/lfs/migrate_rake_spec.rb
create mode 100644 spec/tasks/gitlab/uploads/migrate_rake_spec.rb
create mode 100644 spec/uploaders/object_storage_spec.rb
create mode 100644 spec/uploaders/workers/object_storage/background_move_worker_spec.rb
create mode 100644 spec/uploaders/workers/object_storage/migrate_uploads_worker_spec.rb
rename spec/views/{ => projects}/ci/lints/show.html.haml_spec.rb (83%)
create mode 100644 spec/views/projects/diffs/_stats.html.haml_spec.rb
create mode 100644 spec/views/projects/services/_form.haml_spec.rb
rename spec/views/projects/{pipelines_settings/_show.html.haml_spec.rb => settings/ci_cd/_form.html.haml_spec.rb} (97%)
create mode 100644 spec/workers/object_storage_upload_worker_spec.rb
create mode 100644 spec/workers/project_export_worker_spec.rb
delete mode 100644 vendor/assets/javascripts/peek.js
create mode 100644 vendor/gitignore/Godot.gitignore
create mode 100644 vendor/gitlab-ci-yml/Pages/Gatsby.gitlab-ci.yml
diff --git a/.babelrc b/.babelrc
index b93bef72de..8cf07b7342 100644
--- a/.babelrc
+++ b/.babelrc
@@ -1,20 +1,20 @@
{
- "presets": [
- ["latest", { "es2015": { "modules": false } }],
- "stage-2"
- ],
+ "presets": [["latest", { "es2015": { "modules": false } }], "stage-2"],
"env": {
"coverage": {
"plugins": [
- ["istanbul", {
- "exclude": [
- "spec/javascripts/**/*",
- "app/assets/javascripts/locale/**/app.js"
- ]
- }],
- ["transform-define", {
- "process.env.BABEL_ENV": "coverage"
- }]
+ [
+ "istanbul",
+ {
+ "exclude": ["spec/javascripts/**/*", "app/assets/javascripts/locale/**/app.js"]
+ }
+ ],
+ [
+ "transform-define",
+ {
+ "process.env.BABEL_ENV": "coverage"
+ }
+ ]
]
}
}
diff --git a/.codeclimate.yml b/.codeclimate.yml
index 216ecf43be..8699a903f2 100644
--- a/.codeclimate.yml
+++ b/.codeclimate.yml
@@ -10,12 +10,6 @@ engines:
- javascript
exclude_paths:
- "lib/api/v3/*"
- eslint:
- enabled: true
- channel: "eslint-4"
- rubocop:
- enabled: true
- channel: "gitlab-rubocop-0-52-1"
ratings:
paths:
- Gemfile.lock
diff --git a/.eslintignore b/.eslintignore
index 1623b99621..33a8186fad 100644
--- a/.eslintignore
+++ b/.eslintignore
@@ -1,11 +1,12 @@
+/app/assets/javascripts/locale/**/app.js
+/config/
/builds/
/coverage/
/coverage-javascript/
/node_modules/
/public/
+/scripts/
/tmp/
/vendor/
karma.config.js
webpack.config.js
-svg.config.js
-/app/assets/javascripts/locale/**/app.js
diff --git a/.eslintrc b/.eslintrc
index 8f9cdfb14a..3f187db0c0 100644
--- a/.eslintrc
+++ b/.eslintrc
@@ -1,6 +1,5 @@
{
"env": {
- "jquery": true,
"browser": true,
"es6": true
},
@@ -36,15 +35,22 @@
"import/no-commonjs": "error",
"no-multiple-empty-lines": ["error", { "max": 1 }],
"promise/catch-or-return": "error",
- "no-underscore-dangle": ["error", { "allow": ["__", "_links"]}],
- "vue/html-self-closing": ["error", {
- "html": {
- "void": "always",
- "normal": "never",
- "component": "always"
- },
- "svg": "always",
- "math": "always"
- }]
+ "no-underscore-dangle": ["error", { "allow": ["__", "_links"] }],
+ "no-mixed-operators": 0,
+ "space-before-function-paren": 0,
+ "curly": 0,
+ "arrow-parens": 0,
+ "vue/html-self-closing": [
+ "error",
+ {
+ "html": {
+ "void": "always",
+ "normal": "never",
+ "component": "always"
+ },
+ "svg": "always",
+ "math": "always"
+ }
+ ]
}
}
diff --git a/.flayignore b/.flayignore
index 87cb3507b0..3d69bb2c98 100644
--- a/.flayignore
+++ b/.flayignore
@@ -8,3 +8,4 @@ lib/gitlab/redis/*.rb
lib/gitlab/gitaly_client/operation_service.rb
lib/gitlab/background_migration/*
app/models/project_services/kubernetes_service.rb
+lib/gitlab/workhorse.rb
diff --git a/.gitignore b/.gitignore
index fa39ae01ff..e9ff0048c1 100644
--- a/.gitignore
+++ b/.gitignore
@@ -11,6 +11,7 @@
eslint-report.html
/.gitlab_shell_secret
.idea
+/.vscode/*
/.rbenv-version
.rbx/
/.ruby-gemset
@@ -22,6 +23,9 @@ eslint-report.html
/.yarn-cache
/.byebug_history
/Vagrantfile
+/app/assets/images/icons.json
+/app/assets/images/icons.svg
+/app/assets/images/illustrations/
/app/assets/javascripts/locale/**/app.js
/backups/*
/config/aws.yml
@@ -46,6 +50,7 @@ eslint-report.html
/db/data.yml
/doc/code/*
/dump.rdb
+/jsconfig.json
/log/*.log*
/node_modules/
/nohup.out
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index f3ebcb10fb..26e442ccea 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -78,6 +78,19 @@ stages:
- mysql:5.7
- redis:alpine
+.rails5-variables: &rails5-variables
+ script:
+ - export RAILS5=${RAILS5}
+ - export BUNDLE_GEMFILE=${BUNDLE_GEMFILE}
+
+.rails5: &rails5
+ allow_failure: true
+ only:
+ - /rails5/
+ variables:
+ BUNDLE_GEMFILE: "Gemfile.rails5"
+ RAILS5: "true"
+
# Skip all jobs except the ones that begin with 'docs/'.
# Used for commits including ONLY documentation changes.
# https://docs.gitlab.com/ce/development/writing_documentation.html#testing
@@ -118,6 +131,7 @@ stages:
<<: *dedicated-runner
<<: *except-docs-and-qa
<<: *pull-cache
+ <<: *rails5-variables
stage: test
script:
- JOB_NAME=( $CI_JOB_NAME )
@@ -148,14 +162,23 @@ stages:
<<: *rspec-metadata
<<: *use-pg
+.rspec-metadata-pg-rails5: &rspec-metadata-pg-rails5
+ <<: *rspec-metadata-pg
+ <<: *rails5
+
.rspec-metadata-mysql: &rspec-metadata-mysql
<<: *rspec-metadata
<<: *use-mysql
+.rspec-metadata-mysql-rails5: &rspec-metadata-mysql-rails5
+ <<: *rspec-metadata-mysql
+ <<: *rails5
+
.spinach-metadata: &spinach-metadata
<<: *dedicated-runner
<<: *except-docs-and-qa
<<: *pull-cache
+ <<: *rails5-variables
stage: test
script:
- JOB_NAME=( $CI_JOB_NAME )
@@ -179,10 +202,18 @@ stages:
<<: *spinach-metadata
<<: *use-pg
+.spinach-metadata-pg-rails5: &spinach-metadata-pg-rails5
+ <<: *spinach-metadata-pg
+ <<: *rails5
+
.spinach-metadata-mysql: &spinach-metadata-mysql
<<: *spinach-metadata
<<: *use-mysql
+.spinach-metadata-mysql-rails5: &spinach-metadata-mysql-rails5
+ <<: *spinach-metadata-mysql
+ <<: *rails5
+
.only-canonical-masters: &only-canonical-masters
only:
- master@gitlab-org/gitlab-ce
@@ -257,15 +288,25 @@ stages:
##
# Trigger a package build in omnibus-gitlab repository
#
-package-qa:
+package-and-qa:
<<: *dedicated-runner
image: ruby:2.4-alpine
before_script: []
stage: build
cache: {}
when: manual
+ variables:
+ GIT_STRATEGY: none
+ retry: 0
+ 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).
+ - apk add --update openssl
+ - wget https://gitlab.com/$CI_PROJECT_PATH/raw/$CI_COMMIT_SHA/scripts/trigger-build-omnibus
+ - chmod 755 trigger-build-omnibus
script:
- - scripts/trigger-build-omnibus
+ - ./trigger-build-omnibus
only:
- //@gitlab-org/gitlab-ce
- //@gitlab-org/gitlab-ee
@@ -458,6 +499,70 @@ spinach-pg 1 2: *spinach-metadata-pg
spinach-mysql 0 2: *spinach-metadata-mysql
spinach-mysql 1 2: *spinach-metadata-mysql
+rspec-pg-rails5 0 28: *rspec-metadata-pg-rails5
+rspec-pg-rails5 1 28: *rspec-metadata-pg-rails5
+rspec-pg-rails5 2 28: *rspec-metadata-pg-rails5
+rspec-pg-rails5 3 28: *rspec-metadata-pg-rails5
+rspec-pg-rails5 4 28: *rspec-metadata-pg-rails5
+rspec-pg-rails5 5 28: *rspec-metadata-pg-rails5
+rspec-pg-rails5 6 28: *rspec-metadata-pg-rails5
+rspec-pg-rails5 7 28: *rspec-metadata-pg-rails5
+rspec-pg-rails5 8 28: *rspec-metadata-pg-rails5
+rspec-pg-rails5 9 28: *rspec-metadata-pg-rails5
+rspec-pg-rails5 10 28: *rspec-metadata-pg-rails5
+rspec-pg-rails5 11 28: *rspec-metadata-pg-rails5
+rspec-pg-rails5 12 28: *rspec-metadata-pg-rails5
+rspec-pg-rails5 13 28: *rspec-metadata-pg-rails5
+rspec-pg-rails5 14 28: *rspec-metadata-pg-rails5
+rspec-pg-rails5 15 28: *rspec-metadata-pg-rails5
+rspec-pg-rails5 16 28: *rspec-metadata-pg-rails5
+rspec-pg-rails5 17 28: *rspec-metadata-pg-rails5
+rspec-pg-rails5 18 28: *rspec-metadata-pg-rails5
+rspec-pg-rails5 19 28: *rspec-metadata-pg-rails5
+rspec-pg-rails5 20 28: *rspec-metadata-pg-rails5
+rspec-pg-rails5 21 28: *rspec-metadata-pg-rails5
+rspec-pg-rails5 22 28: *rspec-metadata-pg-rails5
+rspec-pg-rails5 23 28: *rspec-metadata-pg-rails5
+rspec-pg-rails5 24 28: *rspec-metadata-pg-rails5
+rspec-pg-rails5 25 28: *rspec-metadata-pg-rails5
+rspec-pg-rails5 26 28: *rspec-metadata-pg-rails5
+rspec-pg-rails5 27 28: *rspec-metadata-pg-rails5
+
+rspec-mysql-rails5 0 28: *rspec-metadata-mysql-rails5
+rspec-mysql-rails5 1 28: *rspec-metadata-mysql-rails5
+rspec-mysql-rails5 2 28: *rspec-metadata-mysql-rails5
+rspec-mysql-rails5 3 28: *rspec-metadata-mysql-rails5
+rspec-mysql-rails5 4 28: *rspec-metadata-mysql-rails5
+rspec-mysql-rails5 5 28: *rspec-metadata-mysql-rails5
+rspec-mysql-rails5 6 28: *rspec-metadata-mysql-rails5
+rspec-mysql-rails5 7 28: *rspec-metadata-mysql-rails5
+rspec-mysql-rails5 8 28: *rspec-metadata-mysql-rails5
+rspec-mysql-rails5 9 28: *rspec-metadata-mysql-rails5
+rspec-mysql-rails5 10 28: *rspec-metadata-mysql-rails5
+rspec-mysql-rails5 11 28: *rspec-metadata-mysql-rails5
+rspec-mysql-rails5 12 28: *rspec-metadata-mysql-rails5
+rspec-mysql-rails5 13 28: *rspec-metadata-mysql-rails5
+rspec-mysql-rails5 14 28: *rspec-metadata-mysql-rails5
+rspec-mysql-rails5 15 28: *rspec-metadata-mysql-rails5
+rspec-mysql-rails5 16 28: *rspec-metadata-mysql-rails5
+rspec-mysql-rails5 17 28: *rspec-metadata-mysql-rails5
+rspec-mysql-rails5 18 28: *rspec-metadata-mysql-rails5
+rspec-mysql-rails5 19 28: *rspec-metadata-mysql-rails5
+rspec-mysql-rails5 20 28: *rspec-metadata-mysql-rails5
+rspec-mysql-rails5 21 28: *rspec-metadata-mysql-rails5
+rspec-mysql-rails5 22 28: *rspec-metadata-mysql-rails5
+rspec-mysql-rails5 23 28: *rspec-metadata-mysql-rails5
+rspec-mysql-rails5 24 28: *rspec-metadata-mysql-rails5
+rspec-mysql-rails5 25 28: *rspec-metadata-mysql-rails5
+rspec-mysql-rails5 26 28: *rspec-metadata-mysql-rails5
+rspec-mysql-rails5 27 28: *rspec-metadata-mysql-rails5
+
+spinach-pg-rails5 0 2: *spinach-metadata-pg-rails5
+spinach-pg-rails5 1 2: *spinach-metadata-pg-rails5
+
+spinach-mysql-rails5 0 2: *spinach-metadata-mysql-rails5
+spinach-mysql-rails5 1 2: *spinach-metadata-mysql-rails5
+
static-analysis:
<<: *dedicated-no-docs-no-db-pull-cache-job
dependencies:
@@ -544,7 +649,7 @@ migration:path-mysql:
.db-rollback: &db-rollback
<<: *dedicated-no-docs-pull-cache-job
script:
- - bundle exec rake db:rollback STEP=119
+ - bundle exec rake db:migrate VERSION=20170523121229
- bundle exec rake db:migrate
db:rollback-pg:
@@ -608,21 +713,23 @@ karma:
codequality:
<<: *dedicated-no-docs-no-db-pull-cache-job
- image: docker:latest
+ image: docker:stable
+ allow_failure: true
+ # gitlab-org runners set `privileged: false` but we need to have it set to true
+ # since we're using Docker in Docker
+ tags: []
before_script: []
services:
- docker:dind
variables:
SETUP_DB: "false"
DOCKER_DRIVER: overlay2
- CODECLIMATE_FORMAT: json
cache: {}
dependencies: []
script:
- - apk update && apk add jq
- - ./scripts/codequality analyze -f json > raw_codeclimate.json || true
- # The following line keeps only the fields used in the MR widget, reducing the JSON artifact size
- - jq -c 'map({check_name,description,fingerprint,location})' raw_codeclimate.json > codeclimate.json
+ # Extract "MAJOR.MINOR" from CI_SERVER_VERSION and generate "MAJOR-MINOR-stable" for Security Products
+ - export SP_VERSION=$(echo "$CI_SERVER_VERSION" | sed 's/^\([0-9]*\)\.\([0-9]*\).*/\1-\2-stable/')
+ - docker run --env SOURCE_CODE="$PWD" --volume "$PWD":/code --volume /var/run/docker.sock:/var/run/docker.sock "registry.gitlab.com/gitlab-org/security-products/codequality:$SP_VERSION" /code
artifacts:
paths: [codeclimate.json]
expire_in: 1 week
@@ -655,7 +762,13 @@ qa:selectors:
- bundle exec bin/qa Test::Sanity::Selectors
coverage:
- <<: *dedicated-no-docs-no-db-pull-cache-job
+ # Don't include dedicated-no-docs-no-db-pull-cache-job here since we need to
+ # download artifacts from all the rspec jobs instead of from setup-test-env only
+ <<: *dedicated-runner
+ <<: *except-docs-and-qa
+ <<: *pull-cache
+ variables:
+ SETUP_DB: "false"
stage: post-test
script:
- bundle exec scripts/merge-simplecov
diff --git a/.gitlab/merge_request_templates/Database Changes.md b/.gitlab/merge_request_templates/Database Changes.md
index 8302b3b30c..68bc0fd1c7 100644
--- a/.gitlab/merge_request_templates/Database Changes.md
+++ b/.gitlab/merge_request_templates/Database Changes.md
@@ -33,13 +33,16 @@ When removing columns, tables, indexes or other structures:
## General Checklist
-- [ ] [Changelog entry](https://docs.gitlab.com/ce/development/changelog.html) added, if necessary
-- [ ] [Documentation created/updated](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/doc/development/doc_styleguide.md)
+- [ ] [Changelog entry](https://docs.gitlab.com/ee/development/changelog.html) added, if necessary
+- [ ] [Documentation created/updated](https://docs.gitlab.com/ee/development/doc_styleguide.html)
- [ ] API support added
- [ ] Tests added for this feature/bug
- Review
- [ ] Has been reviewed by Backend
- [ ] Has been reviewed by Database
-- [ ] Conform by the [merge request performance guides](http://docs.gitlab.com/ce/development/merge_request_performance_guidelines.html)
-- [ ] Conform by the [style guides](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/CONTRIBUTING.md#style-guides)
+- [ ] Conform by the [merge request performance guides](https://docs.gitlab.com/ee/development/merge_request_performance_guidelines.html)
+- [ ] Conform by the [style guides](https://gitlab.com/gitlab-org/gitlab-ee/blob/master/CONTRIBUTING.md#style-guides)
- [ ] [Squashed related commits together](https://git-scm.com/book/en/Git-Tools-Rewriting-History#Squashing-Commits)
+- [ ] Internationalization required/considered
+- [ ] If paid feature, have we considered GitLab.com plan and how it works for groups and is there a design for promoting it to users who aren't on the correct plan
+- [ ] End-to-end tests pass (`package-qa` manual pipeline job)
diff --git a/.gitlab/merge_request_templates/Documentation.md b/.gitlab/merge_request_templates/Documentation.md
index 102eb7e795..da38a703c3 100644
--- a/.gitlab/merge_request_templates/Documentation.md
+++ b/.gitlab/merge_request_templates/Documentation.md
@@ -1,16 +1,29 @@
-See the general Documentation guidelines http://docs.gitlab.com/ce/development/doc_styleguide.html
+
## What does this MR do?
-(briefly describe what this MR is about)
+
+
+## Related issues
+
+
+
+Closes
## Moving docs to a new location?
-See the guidelines: http://docs.gitlab.com/ce/development/doc_styleguide.html#changing-document-location
+Read the guidelines:
+https://docs.gitlab.com/ce/development/writing_documentation.html#changing-document-location
-- [ ] Make sure the old link is not removed and has its contents replaced with a link to the new location.
+- [ ] Make sure the old link is not removed and has its contents replaced with
+ a link to the new location.
- [ ] Make sure internal links pointing to the document in question are not broken.
-- [ ] Search and replace any links referring to old docs in GitLab Rails app, specifically under the `app/views/` directory.
-- [ ] Make sure to add [`redirect_from`](https://docs.gitlab.com/ee/development/doc_styleguide.html#redirections-for-pages-with-disqus-comments) to the new document if there are any Disqus comments on the old document thread.
-- [ ] If working on CE, submit an MR to EE with the changes as well.
+- [ ] Search and replace any links referring to old docs in GitLab Rails app,
+ specifically under the `app/views/` and `ee/app/views` (for GitLab EE) directories.
+- [ ] Make sure to add [`redirect_from`](https://docs.gitlab.com/ce/development/writing_documentation.html#redirections-for-pages-with-disqus-comments)
+ to the new document if there are any Disqus comments on the old document thread.
+- [ ] If working on CE and the `ee-compat-check` jobs fails, submit an MR to EE
+ with the changes as well (https://docs.gitlab.com/ce/development/writing_documentation.html#cherry-picking-from-ce-to-ee).
- [ ] Ping one of the technical writers for review.
+
+/label ~Documentation
diff --git a/.prettierignore b/.prettierignore
new file mode 100644
index 0000000000..b674ccd50c
--- /dev/null
+++ b/.prettierignore
@@ -0,0 +1,5 @@
+/app/assets/javascripts/locale/**/app.js
+/node_modules/
+/public/
+/vendor/
+/tmp/
diff --git a/.prettierrc b/.prettierrc
new file mode 100644
index 0000000000..3384551aea
--- /dev/null
+++ b/.prettierrc
@@ -0,0 +1,13 @@
+{
+ "printWidth": 100,
+ "singleQuote": true,
+ "trailingComma": "es5",
+ "overrides": [
+ {
+ "files": ["**/app/**/*", "**/spec/**/*"],
+ "options": {
+ "trailingComma": "all"
+ }
+ }
+ ]
+}
diff --git a/.rubocop.yml b/.rubocop.yml
index 90dac88453..0582bfe8d7 100644
--- a/.rubocop.yml
+++ b/.rubocop.yml
@@ -31,6 +31,78 @@ Style/MutableConstant:
- 'ee/db/post_migrate/**/*'
- 'ee/db/geo/migrate/**/*'
+Naming/FileName:
+ ExpectMatchingDefinition: true
+ Exclude:
+ - 'spec/**/*'
+ - 'features/**/*'
+ - 'ee/spec/**/*'
+ - 'qa/spec/**/*'
+ - 'qa/qa/specs/**/*'
+ - 'qa/bin/*'
+ - 'config/**/*'
+ - 'lib/generators/**/*'
+ - 'ee/lib/generators/**/*'
+ IgnoreExecutableScripts: true
+ AllowedAcronyms:
+ - EE
+ - JSON
+ - LDAP
+ - IO
+ - HMAC
+ - QA
+ - ENV
+ - STL
+ - PDF
+ - SVG
+ - CTE
+ - DN
+ - RSA
+ - CI
+ - CD
+ - OAuth
+ # default ones:
+ - CLI
+ - DSL
+ - ACL
+ - API
+ - ASCII
+ - CPU
+ - CSS
+ - DNS
+ - EOF
+ - GUID
+ - HTML
+ - HTTP
+ - HTTPS
+ - ID
+ - IP
+ - JSON
+ - LHS
+ - QPS
+ - RAM
+ - RHS
+ - RPC
+ - SLA
+ - SMTP
+ - SQL
+ - SSH
+ - TCP
+ - TLS
+ - TTL
+ - UDP
+ - UI
+ - UID
+ - UUID
+ - URI
+ - URL
+ - UTF8
+ - VM
+ - XML
+ - XMPP
+ - XSRF
+ - XSS
+
# Gitlab ###################################################################
Gitlab/ModuleWithInstanceVariables:
diff --git a/.scss-lint.yml b/.scss-lint.yml
index dcd4cac780..180d377d6f 100644
--- a/.scss-lint.yml
+++ b/.scss-lint.yml
@@ -59,6 +59,8 @@ linters:
# Reports when you define the same property twice in a single rule set.
DuplicateProperty:
enabled: true
+ ignore_consecutive:
+ - cursor
# Separate rule, function, and mixin declarations with empty lines.
EmptyLineBetweenBlocks:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index fcc4225afd..6371b38775 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -2,29 +2,261 @@
documentation](doc/development/changelog.md) for instructions on adding your own
entry.
-## 10.6.5 (2018-04-24)
+## 10.7.3 (2018-05-02)
-### Security (1 change)
+### Fixed (8 changes)
+- Fixed wrong avatar URL when the avatar is on object storage. !18092
+- Fix errors on pushing to an empty repository. !18462
+- Update doorkeeper to 4.3.2 to fix GitLab OAuth authentication. !18543
+- Ports omniauth-jwt gem onto GitLab OmniAuth Strategies suite. !18580
+- Fix redirection error for applications using OpenID. !18599
+- Fix commit trailer rendering when Gravatar is disabled.
+- Fix file_store for artifacts and lfs when saving.
+- Fix users not seeing labels from private groups when being a member of a child project.
+
+
+## 10.7.2 (2018-04-25)
+
+### Security (2 changes)
+
+- Serve archive requests with the correct file in all cases.
- Sanitizes user name to avoid XSS attacks.
-## 10.6.4 (2018-04-09)
+## 10.7.1 (2018-04-23)
-### Fixed (8 changes, 1 of them is from the community)
+### Fixed (11 changes)
+- [API] Fix URLs in the `Link` header for `GET /projects/:id/repository/contributors` when no value is passed for `order_by` or `sort`. !18393
+- Fix a case with secret variables being empty sometimes. !18400
+- Fix `Trace::HttpIO` can not render multi-byte chars. !18417
+- Fix specifying a non-default ref when requesting an archive using the legacy URL. !18468
+- Respect visibility options and description when importing project from template. !18473
+- Removes 'No Job log' message from build trace. !18523
+- Align action icons in pipeline graph.
+- Fix direct_upload when records with null file_store are used.
+- Removed alert box in IDE when redirecting to new merge request.
+- Fixed IDE not loading for sub groups.
+- Fixed IDE not showing loading state when tree is loading.
+
+### Performance (4 changes)
+
+- Validate project path prior to hitting the database. !18322
+- Add index to file_store on ci_job_artifacts. !18444
+- Fix N+1 queries when loading participants for a commit note.
+- Support Markdown rendering using multiple projects.
+
+### Added (1 change)
+
+- Add an API endpoint to download git repository snapshots. !18173
+
+
+## 10.7.0 (2018-04-22)
+
+### Security (6 changes, 2 of them are from the community)
+
+- Fixed some SSRF vulnerabilities in services, hooks and integrations. !2337
+- Update ruby-saml to 1.7.2 and omniauth-saml to 1.10.0. !17734 (Takuya Noguchi)
+- Update rack-protection to 2.0.1. !17835 (Takuya Noguchi)
+- Adds confidential notes channel for Slack/Mattermost.
+- Fix XSS on diff view stored on filenames.
+- Fix GitLab Auth0 integration signing in the wrong user.
+
+### Fixed (65 changes, 20 of them are from the community)
+
+- File uploads in remote storage now support project renaming. !4597
+- Fixed bug in dropdown selector when selecting the same selection again. !14631 (bitsapien)
+- Fixed group deletion linked to Mattermost. !16209 (Julien Millau)
+- Create commit API and Web IDE obey LFS filters. !16718
+- Set breadcrumb for admin/runners/show. !17431 (Takuya Noguchi)
+- Enable restore rake task to handle nested storage directories. !17516 (Balasankar C)
+- Fix hover style of dropdown items in the right sidebar. !17519
+- Improve empty state for canceled job. !17646
+- Fix generated URL when listing repoitories for import. !17692
+- Use singular in the diff stats if only one line has been changed. !17697 (Jan Beckmann)
+- Long instance urls do not overflow anymore during project creation. !17717
+- Fix importing multiple assignees from GitLab export. !17718
- Correct copy text for the promote milestone and label modals. !17726
+- Fix search results stripping last endline when parsing the results. !17777 (Jasper Maes)
+- Add read-only banner to all pages. !17798
+- Fix viewing diffs on old merge requests. !17805
+- Fix forking to subgroup via API when namespace is given by name. !17815 (Jan Beckmann)
+- Fix UI breakdown for Create merge request button. !17821 (Takuya Noguchi)
+- Unify format for nested non-task lists. !17823 (Takuya Noguchi)
+- UX re-design branch items with flexbox. !17832 (Takuya Noguchi)
+- Use porcelain commit lookup method on CI::CreatePipelineService. !17911
+- Update dashboard milestones breadcrumb link. !17933 (George Tsiolis)
+- Deleting a MR you are assigned to should decrements counter. !17951 (m b)
+- Update no repository placeholder. !17964 (George Tsiolis)
+- Drop JSON response in Project Milestone along with avoiding error. !17977 (Takuya Noguchi)
+- Fix personal access token clipboard button style. !17978 (Fabian Schneider)
- Avoid validation errors when running the Pages domain verification service. !17992
+- Project creation will now raise an error if a service template is invalid. !18013
+- Add better LDAP connection handling. !18039
- Fix autolinking URLs containing ampersands. !18045
- Fix exceptions raised when migrating pipeline stages in the background. !18076
+- Always display Labels section in issuable sidebar, even when the project has no labels. !18081 (Branka Martinovic)
+- Fixed gitlab:uploads:migrate task ignoring some uploads. !18082
+- Fixed gitlab:uploads:migrate task failing for Groups' avatar. !18088
+- Increase dropdown width in pipeline graph & center action icon. !18089
+- Fix `JobsController#raw` endpoint can not read traces in database. !18101
+- Fix `gitlab-rake gitlab:two_factor:disable_for_all_users`. !18154
+- Adjust 404's for LegacyDiffNote discussion rendering. !18201
- Work around Prometheus Helm chart name changes to fix integration. !18206 (joshlambert)
-- Don't show Jump to Discussion button on Issues.
-- Fix listing commit branch/tags that contain special characters.
+- Prioritize weight over title when sorting charts. !18233
+- Verify that deploy token has valid access when pulling container registry image. !18260
+- Stop redirecting the page in pipeline main actions.
+- Fixed IDE button opening the wrong URL in tree list.
+- Ensure hooks run when a deploy key without a user pushes.
- Fix 404 in group boards when moving issue between lists.
+- Display state indicator for issuable references in non-project scope (e.g. when referencing issuables from group scope).
+- Add missing port to artifact links.
+- Fix data race between ObjectStorage background_upload and Pages publishing.
+- Fixes unresolved discussions rendering the error state instead of the diff.
+- Don't show Jump to Discussion button on Issues.
+- Fix bug rendering group icons when forking.
+- Automatically cleanup stale worktrees and lock files upon a push.
+- Use the GitLab version as part of the appearances cache key.
+- Fix Firefox stealing formatting characters on issue notes.
+- Include matching branches and tags in protected branches / tags count. (Jan Beckmann)
+- Fix 500 error when a merge request from a fork has conflicts and has not yet been updated.
+- Test if remote repository exists when importing wikis.
+- Hide emoji popup after multiple spaces. (Jan Beckmann)
+- Fix relative uri when "#" is in branch name. (Jan)
+- Escape Markdown characters properly when using autocomplete.
+- Ignore project internal references in group context.
+- Fix finding wiki file when Gitaly is enabled.
+- Fix listing commit branch/tags that contain special characters.
+- Ensure internal users (ghost, support bot) get assigned a namespace.
+- Fix links to subdirectories of a directory with a plus character in its path.
-### Performance (1 change)
+### Deprecated (1 change)
+- Remove support for legacy tar.gz pages artifacts. !18090
+
+### Changed (22 changes, 2 of them are from the community)
+
+- Add yellow favicon when `CANARY=true` to differientate canary environment. !12477
+- Use human readable value build_timeout in Project. !17386
+- Improved visual styles and consistency for commit hash and possible actions across commit lists. !17406
+- Don't create permanent redirect routes. !17521
+- Add empty repo check before running AutoDevOps pipeline. !17605
+- Update wording to specify create/manage project vs group labels in labels dropdown. !17640
+- Add tooltips to icons in lists of issues and merge requests. !17700
+- Change avatar error message to include allowed file formats. !17747 (Fabian Schneider)
+- Polish design for verifying domains. !17767
+- Move email footer info to a single line. !17916
+- Add average and maximum summary statistics to the prometheus dashboard. !17921
+- Add additional cluster usage metrics to usage ping. !17922
+- Move 'Registry' after 'CI/CD' in project navigation sidebar. !18018 (Elias Werberich)
+- Redesign application settings to match project settings. !18019
+- Allow HTTP(s) when git request is made by GitLab CI. !18021
+- Added hover background color to IDE file list rows.
+- Make project avatar in IDE consistent with the rest of GitLab.
+- Show issues of subgroups in group-level issue board.
+- Repository checksum calculation is handled by Gitaly when feature is enabled.
+- Allow viewing timings for AJAX requests in the performance bar.
+- Fixes remove source branch checkbox being visible when user cannot remove the branch.
+- Make /-/ delimiter optional for search endpoints.
+
+### Performance (24 changes, 11 of them are from the community)
+
+- Move AssigneeTitle vue component. !17397 (George Tsiolis)
+- Move TimeTrackingCollapsedState vue component. !17399 (George Tsiolis)
+- Move MemoryGraph and MemoryUsage vue components. !17533 (George Tsiolis)
+- Move UnresolvedDiscussions vue component. !17538 (George Tsiolis)
+- Move NothingToMerge vue component. !17544 (George Tsiolis)
+- Move ShaMismatch vue component. !17546 (George Tsiolis)
+- Stop caching highlighted diffs in Redis unnecessarily. !17746
+- Add i18n and update specs for ShaMismatch vue component. !17870 (George Tsiolis)
+- Update spec import path for vue mount component helper. !17880 (George Tsiolis)
+- Move TimeTrackingComparisonPane vue component. !17931 (George Tsiolis)
+- Improves the performance of projects list page. !17934
+- Remove N+1 query for Noteable association. !17956
+- Improve performance of loading issues with lots of references to merge requests. !17986
+- Reuse root_ref_hash for performance on Branches. !17998 (Takuya Noguchi)
+- Update asciidoctor-plantuml to 0.0.8. !18022 (Takuya Noguchi)
+- Cache personal projects count. !18197
+- Reduce complexity of issuable finder query. !18219
+- Reduce number of queries when viewing a merge request.
- Free open file descriptors and libgit2 buffers in UpdatePagesService.
+- Memoize Git::Repository#has_visible_content?.
+- Require at least one filter when listing issues or merge requests on dashboard page.
+- lazy load diffs on merge request discussions.
+- Bulk deleting refs is handled by Gitaly by default.
+- ListCommitsByOid is executed by Gitaly by default.
+
+### Added (38 changes, 7 of them are from the community)
+
+- Add HTTPS-only pages. !16273 (rfwatson)
+- adds closed by informations in issue api. !17042 (haseebeqx)
+- Projects and groups badges settings UI. !17114
+- Add per-runner configured job timeout. !17221
+- Add alternate archive route for simplified packaging. !17225
+- Add support for pipeline variables expressions in only/except. !17316
+- Add object storage support for LFS objects, CI artifacts, and uploads. !17358
+- Added confirmation modal for changing username. !17405
+- Implement foreground verification of CI artifacts. !17578
+- Extend API for exporting a project with direct upload URL. !17686
+- Move ci/lint under project's namespace. !17729
+- Add Total CPU/Memory consumption metrics for Kubernetes. !17731
+- Adds the option to the project export API to override the project description and display GitLab export description once imported. !17744
+- Port direct upload of LFS artifacts from EE. !17752
+- Adds support for OmniAuth JWT provider. !17774
+- Display error message on job's tooltip if this one fails. !17782
+- Add 'Assigned Issues' and 'Assigned Merge Requests' as dashboard view choices for users. !17860 (Elias Werberich)
+- Extend API for importing a project export with overwrite support. !17883
+- Create Deploy Tokens to allow permanent access to repository and registry. !17894
+- Detect commit message trailers and link users properly to their accounts on Gitlab. !17919 (cousine)
+- Adds cancel btn to new pages domain page. !18026 (Jacopo Beschi @jacopo-beschi)
+- API: Add parameter merge_method to projects. !18031 (Jan Beckmann)
+- Introduce simpler env vars for auto devops REPLICAS and CANARY_REPLICAS #41436. !18036
+- Allow overriding params on project import through API. !18086
+- Support LFS objects when importing/exporting GitLab project archives. !18115
+- Store sha256 checksum of artifact metadata. !18149
+- Limit the number of failed logins when using LDAP for authentication. !43525
+- Allow assigning and filtering issuables by ancestor group labels.
+- Include subgroup issues when searching for group issues using the API.
+- Allow to store uploads by default on Object Storage.
+- Add slash command for moving issues. (Adam Pahlevi)
+- Render MR commit SHA instead "diffs" when viable.
+- Send @mention notifications even if a user has explicitly unsubscribed from item.
+- Add support for Sidekiq JSON logging.
+- Add Gitaly call details to performance bar.
+- Add support for patch link extension for commit links on GitLab Flavored Markdown.
+- Allow feature gates to be removed through the API.
+- Allow merge requests related to a commit to be found via API.
+
+### Other (27 changes, 11 of them are from the community)
+
+- Send notification emails when push to a merge request. !7610 (YarNayar)
+- Rename modal.vue to deprecated_modal.vue. !17438
+- Atomic generation of internal ids for issues. !17580
+- Use object ID to prevent duplicate keys Vue warning on Issue Boards page during development. !17682
+- Update foreman from 0.78.0 to 0.84.0. !17690 (Takuya Noguchi)
+- Add realtime pipeline status for adding/viewing files. !17705
+- Update documentation to reflect current minimum required versions of node and yarn. !17706
+- Update knapsack to 1.16.0. !17735 (Takuya Noguchi)
+- Update CI services documnetation. !17749
+- Added i18n support for the prometheus memory widget. !17753
+- Use specific names for filtered CI variable controller parameters. !17796
+- Apply NestingDepth (level 5) (framework/dropdowns.scss). !17820 (Takuya Noguchi)
+- Clean up selectors in framework/header.scss. !17822 (Takuya Noguchi)
+- Bump `state_machines-activerecord` to 0.5.1. !17924 (blackst0ne)
+- Increase the memory limits used in the unicorn killer. !17948
+- Replace the spinach test with an rspec analog. !17950 (blackst0ne)
+- Remove unused index from events table. !18014
+- Make all workhorse gitaly calls opt-out, take 2. !18043
+- Update brakeman 3.6.1 to 4.2.1. !18122 (Takuya Noguchi)
+- Replace the `project/issues/labels.feature` spinach test with an rspec analog. !18126 (blackst0ne)
+- Bump html-pipeline to 2.7.1. !18132 (@blackst0ne)
+- Remove test_ci rake task. !18139 (Takuya Noguchi)
+- Add documentation for Pipelines failure reasons. !18352
+- Improve JIRA event descriptions.
+- Add query counts to profiler output.
+- Move Sidekiq exporter logs to log/sidekiq_exporter.log.
+- Upgrade Gitaly to upgrade its charlock_holmes.
## 10.6.3 (2018-04-03)
@@ -224,7 +456,6 @@ entry.
- Enable privileged mode for GitLab Runner. !17528
- Expose GITLAB_FEATURES as CI/CD variable (fixes #40994).
- Upgrade GitLab Workhorse to 4.0.0.
-- Allow CI/CD Jobs being grouped on version strings.
- Add discussions API for Issues and Snippets.
- Add one group board to Libre.
- Add support for filtering by source and target branch to merge requests API.
@@ -251,6 +482,57 @@ entry.
- Use host URL to build JIRA remote link icon.
+## 10.5.7 (2018-04-03)
+
+### Security (2 changes)
+
+- Fix XSS on diff view stored on filenames.
+- Adds confidential notes channel for Slack/Mattermost.
+
+
+## 10.5.6 (2018-03-16)
+
+### Security (2 changes)
+
+- Fixed some SSRF vulnerabilities in services, hooks and integrations. !2337
+- Fix GitLab Auth0 integration signing in the wrong user.
+
+
+## 10.5.5 (2018-03-15)
+
+### Fixed (3 changes)
+
+- Fix missing uploads after group transfer. !17658
+- Fix code and wiki search results when filename is non-ASCII.
+- Remove double caching of Repository#empty?.
+
+### Performance (2 changes)
+
+- Adding missing indexes on taggings table.
+- Add index on section_name_id on ci_build_trace_sections table.
+
+
+## 10.5.4 (2018-03-08)
+
+### Fixed (11 changes)
+
+- Encode branch name as binary before creating a RPC request to copy attributes. !17291
+- Restart Unicorn and Sidekiq when GRPC throws 14:Endpoint read failed. !17293
+- Ensure group issues and merge requests pages show results from subgroups when there are no results from the current group. !17312
+- Prevent trace artifact migration to incur data loss. !17313
+- Return a 404 instead of 403 if the repository does not exist on disk. !17341
+- Allow Prometheus application to be installed from Cluster applications. !17372
+- Fixes Prometheus admin configuration page. !17377
+- Fix code and wiki search results pages when non-ASCII text is displayed. !17413
+- Fix pages flaky failure by reloading stale object. !17522
+- Fixed issue edit shortcut not opening edit form.
+- Revert Project.public_or_visible_to_user changes and only apply to snippets.
+
+### Performance (1 change)
+
+- Don't use ProjectsFinder in TodosFinder.
+
+
## 10.5.3 (2018-03-01)
### Security (1 change)
@@ -475,6 +757,22 @@ entry.
- Adds empty state illustration for pending job.
+## 10.4.7 (2018-04-03)
+
+### Security (2 changes)
+
+- Fix XSS on diff view stored on filenames.
+- Adds confidential notes channel for Slack/Mattermost.
+
+
+## 10.4.6 (2018-03-16)
+
+### Security (2 changes)
+
+- Fixed some SSRF vulnerabilities in services, hooks and integrations. !2337
+- Fix GitLab Auth0 integration signing in the wrong user.
+
+
## 10.4.5 (2018-03-01)
### Security (1 change)
@@ -706,6 +1004,15 @@ entry.
- Use a background migration for issues.closed_at.
+## 10.3.9 (2018-03-16)
+
+### Security (3 changes)
+
+- Fixed some SSRF vulnerabilities in services, hooks and integrations. !2337
+- Update nokogiri to 1.8.2. !16807
+- Fix GitLab Auth0 integration signing in the wrong user.
+
+
## 10.3.8 (2018-03-01)
### Security (1 change)
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 76ee6265c5..9c8fdc1275 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -26,7 +26,7 @@ _This notice should stay as the first item in the CONTRIBUTING.md file._
- [Type labels (~"feature proposal", ~bug, ~customer, etc.)](#type-labels-feature-proposal-bug-customer-etc)
- [Subject labels (~wiki, ~"container registry", ~ldap, ~api, etc.)](#subject-labels-wiki-container-registry-ldap-api-etc)
- [Team labels (~"CI/CD", ~Discussion, ~Edge, ~Platform, etc.)](#team-labels-cicd-discussion-edge-platform-etc)
- - [Priority labels (~Deliverable and ~Stretch)](#priority-labels-deliverable-and-stretch)
+ - [Priority labels (~Deliverable, ~Stretch, ~"Next Patch Release")](#priority-labels-deliverable-stretch-next-patch-release)
- [Label for community contributors (~"Accepting Merge Requests")](#label-for-community-contributors-accepting-merge-requests)
- [Implement design & UI elements](#implement-design-ui-elements)
- [Issue tracker](#issue-tracker)
@@ -98,8 +98,8 @@ coach is going to finish the merge request we assign the
## Helping others
-Please help other GitLab users when you can. The channels people will reach out
-on can be found on the [getting help page][getting-help].
+Please help other GitLab users when you can.
+The methods people will use to seek help can be found on the [getting help page][getting-help].
Sign up for the mailing list, answer GitLab questions on StackOverflow or
respond in the IRC channel. You can also sign up on [CodeTriage][codetriage] to help with
@@ -126,7 +126,7 @@ Most issues will have labels for at least one of the following:
- Type: ~"feature proposal", ~bug, ~customer, etc.
- Subject: ~wiki, ~"container registry", ~ldap, ~api, ~frontend, etc.
- Team: ~"CI/CD", ~Discussion, ~Edge, ~Platform, etc.
-- Priority: ~Deliverable, ~Stretch
+- Priority: ~Deliverable, ~Stretch, ~"Next Patch Release"
All labels, their meaning and priority are defined on the
[labels page][labels-page].
@@ -185,7 +185,7 @@ indicate if an issue needs backend work, frontend work, or both.
Team labels are always capitalized so that they show up as the first label for
any issue.
-### Priority labels (~Deliverable and ~Stretch)
+### Priority labels (~Deliverable, ~Stretch, ~"Next Patch Release")
Priority labels help us clearly communicate expectations of the work for the
release. There are two levels of priority labels:
@@ -195,6 +195,13 @@ release. There are two levels of priority labels:
- ~Stretch: Issues that are a stretch goal for delivering in the current
milestone. If these issues are not done in the current release, they will
strongly be considered for the next release.
+- ~"Next Patch Release": Issues to put in the next patch release. Work on these
+ first, and add the "Pick Into X" label to the merge request, along with the
+ appropriate milestone.
+
+Each issue scheduled for the current milestone should be labeled ~Deliverable
+or ~"Stretch". Any open issue for a previous milestone should be labeled
+~"Next Patch Release", or otherwise rescheduled to a different milestone.
### Severity labels (~S1, ~S2, etc.)
@@ -686,3 +693,4 @@ available at [http://contributor-covenant.org/version/1/1/0/](http://contributor
[^1]: Please note that specs other than JavaScript specs are considered backend
code.
+
\ No newline at end of file
diff --git a/GITALY_SERVER_VERSION b/GITALY_SERVER_VERSION
index 8f63f4f9a1..483b771941 100644
--- a/GITALY_SERVER_VERSION
+++ b/GITALY_SERVER_VERSION
@@ -1 +1 @@
-0.91.0
+0.96.1
diff --git a/GITLAB_PAGES_VERSION b/GITLAB_PAGES_VERSION
index 39e898a4f9..6f4eebdf6f 100644
--- a/GITLAB_PAGES_VERSION
+++ b/GITLAB_PAGES_VERSION
@@ -1 +1 @@
-0.7.1
+0.8.1
diff --git a/GITLAB_SHELL_VERSION b/GITLAB_SHELL_VERSION
index 1aa5e414fd..a8a1887568 100644
--- a/GITLAB_SHELL_VERSION
+++ b/GITLAB_SHELL_VERSION
@@ -1 +1 @@
-6.0.4
+7.1.2
diff --git a/GITLAB_WORKHORSE_VERSION b/GITLAB_WORKHORSE_VERSION
index fcdb2e109f..ee74734aa2 100644
--- a/GITLAB_WORKHORSE_VERSION
+++ b/GITLAB_WORKHORSE_VERSION
@@ -1 +1 @@
-4.0.0
+4.1.0
diff --git a/Gemfile b/Gemfile
index ac06a938d0..e61dfd8e47 100644
--- a/Gemfile
+++ b/Gemfile
@@ -1,6 +1,18 @@
+# --- Special code for migrating to Rails 5.0 ---
+def rails5?
+ %w[1 true].include?(ENV["RAILS5"])
+end
+
+gem_versions = {}
+gem_versions['activerecord_sane_schema_dumper'] = rails5? ? '1.0' : '0.2'
+gem_versions['default_value_for'] = rails5? ? '~> 3.0.5' : '~> 3.0.0'
+gem_versions['rails'] = rails5? ? '5.0.6' : '4.2.10'
+gem_versions['rails-i18n'] = rails5? ? '~> 5.1' : '~> 4.0.9'
+# --- The end of special code for migrating to Rails 5.0 ---
+
source 'https://rubygems.org'
-gem 'rails', '4.2.10'
+gem 'rails', gem_versions['rails']
gem 'rails-deprecated_sanitizer', '~> 1.0.3'
# Responders respond_to and respond_with
@@ -9,34 +21,34 @@ gem 'responders', '~> 2.0'
gem 'sprockets', '~> 3.7.0'
# Default values for AR models
-gem 'default_value_for', '~> 3.0.0'
+gem 'default_value_for', gem_versions['default_value_for']
# Supported DBs
gem 'mysql2', '~> 0.4.10', group: :mysql
gem 'pg', '~> 0.18.2', group: :postgres
-gem 'rugged', '~> 0.26.0'
+gem 'rugged', '~> 0.27'
gem 'grape-route-helpers', '~> 2.1.0'
gem 'faraday', '~> 0.12'
# Authentication libraries
gem 'devise', '~> 4.2'
-gem 'doorkeeper', '~> 4.2.0'
-gem 'doorkeeper-openid_connect', '~> 1.2.0'
-gem 'omniauth', '~> 1.4.2'
+gem 'doorkeeper', '~> 4.3'
+gem 'doorkeeper-openid_connect', '~> 1.3'
+gem 'omniauth', '~> 1.8'
gem 'omniauth-auth0', '~> 2.0.0'
gem 'omniauth-azure-oauth2', '~> 0.0.9'
gem 'omniauth-cas3', '~> 1.1.4'
gem 'omniauth-facebook', '~> 4.0.0'
gem 'omniauth-github', '~> 1.1.1'
gem 'omniauth-gitlab', '~> 1.0.2'
-gem 'omniauth-google-oauth2', '~> 0.5.2'
+gem 'omniauth-google-oauth2', '~> 0.5.3'
gem 'omniauth-kerberos', '~> 0.3.0', group: :kerberos
gem 'omniauth-oauth2-generic', '~> 0.2.2'
-gem 'omniauth-saml', '~> 1.7.0'
+gem 'omniauth-saml', '~> 1.10'
gem 'omniauth-shibboleth', '~> 1.2.0'
-gem 'omniauth-twitter', '~> 1.2.0'
+gem 'omniauth-twitter', '~> 1.4'
gem 'omniauth_crowd', '~> 2.2.0'
gem 'omniauth-authentiq', '~> 0.3.1'
gem 'rack-oauth2', '~> 1.2.1'
@@ -49,7 +61,7 @@ gem 'akismet', '~> 2.0'
# Two-factor authentication
gem 'devise-two-factor', '~> 3.0.0'
gem 'rqrcode-rails3', '~> 0.1.7'
-gem 'attr_encrypted', '~> 3.0.0'
+gem 'attr_encrypted', '~> 3.1.0'
gem 'u2f', '~> 0.2.1'
# GitLab Pages
@@ -104,16 +116,16 @@ gem 'carrierwave', '~> 1.2'
gem 'dropzonejs-rails', '~> 0.7.1'
# for backups
-gem 'fog-aws', '~> 1.4'
+gem 'fog-aws', '~> 2.0.1'
gem 'fog-core', '~> 1.44'
-gem 'fog-google', '~> 0.5'
+gem 'fog-google', '~> 1.3.3'
gem 'fog-local', '~> 0.3'
gem 'fog-openstack', '~> 0.1'
gem 'fog-rackspace', '~> 0.1.1'
gem 'fog-aliyun', '~> 0.2.0'
# for Google storage
-gem 'google-api-client', '~> 0.13.6'
+gem 'google-api-client', '~> 0.19.8'
# for aws storage
gem 'unf', '~> 0.1.4'
@@ -122,7 +134,7 @@ gem 'unf', '~> 0.1.4'
gem 'seed-fu', '~> 2.3.7'
# Markdown and HTML processing
-gem 'html-pipeline', '~> 1.11.0'
+gem 'html-pipeline', '~> 2.7.1'
gem 'deckar01-task_list', '2.0.0'
gem 'gitlab-markup', '~> 1.6.2'
gem 'redcarpet', '~> 3.4'
@@ -132,8 +144,8 @@ gem 'rdoc', '~> 4.2'
gem 'org-ruby', '~> 0.9.12'
gem 'creole', '~> 0.5.0'
gem 'wikicloth', '0.8.1'
-gem 'asciidoctor', '~> 1.5.2'
-gem 'asciidoctor-plantuml', '0.0.7'
+gem 'asciidoctor', '~> 1.5.6'
+gem 'asciidoctor-plantuml', '0.0.8'
gem 'rouge', '~> 2.0'
gem 'truncato', '~> 0.7.9'
gem 'bootstrap_form', '~> 2.7.0'
@@ -149,10 +161,10 @@ group :unicorn do
end
# State machine
-gem 'state_machines-activerecord', '~> 0.4.0'
+gem 'state_machines-activerecord', '~> 0.5.1'
# Issue tags
-gem 'acts-as-taggable-on', '~> 4.0'
+gem 'acts-as-taggable-on', '~> 5.0'
# Background jobs
gem 'sidekiq', '~> 5.0'
@@ -208,7 +220,7 @@ gem 'asana', '~> 0.6.0'
gem 'ruby-fogbugz', '~> 0.2.1'
# Kubernetes integration
-gem 'kubeclient', '~> 2.2.0'
+gem 'kubeclient', '~> 3.0'
# d3
gem 'd3_rails', '~> 3.5.0'
@@ -221,7 +233,7 @@ gem 'babosa', '~> 1.0.2'
gem 'loofah', '~> 2.2'
# Working with license
-gem 'licensee', '~> 8.7.0'
+gem 'licensee', '~> 8.9'
# Protect against bruteforcing
gem 'rack-attack', '~> 4.4.1'
@@ -235,9 +247,6 @@ gem 'mousetrap-rails', '~> 1.4.6'
# Detect and convert string character encoding
gem 'charlock_holmes', '~> 0.7.5'
-# Faster JSON
-gem 'oj', '~> 2.17.4'
-
# Faster blank
gem 'fast_blank'
@@ -257,22 +266,21 @@ gem 'font-awesome-rails', '~> 4.7'
gem 'gemojione', '~> 3.3'
gem 'gon', '~> 6.1.0'
gem 'jquery-atwho-rails', '~> 1.3.2'
-gem 'jquery-rails', '~> 4.3.1'
gem 'request_store', '~> 1.3'
gem 'select2-rails', '~> 3.5.9'
gem 'virtus', '~> 1.0.1'
gem 'base32', '~> 0.3.0'
# Sentry integration
-gem 'sentry-raven', '~> 2.5.3'
+gem 'sentry-raven', '~> 2.7'
gem 'premailer-rails', '~> 1.9.7'
# I18n
gem 'ruby_parser', '~> 3.8', require: false
-gem 'rails-i18n', '~> 4.0.9'
+gem 'rails-i18n', gem_versions['rails-i18n']
gem 'gettext_i18n_rails', '~> 1.8.0'
-gem 'gettext_i18n_rails_js', '~> 1.2.0'
+gem 'gettext_i18n_rails_js', '~> 1.3'
gem 'gettext', '~> 3.2.2', require: false, group: :development
gem 'batch-loader', '~> 1.2.1'
@@ -280,7 +288,6 @@ gem 'batch-loader', '~> 1.2.1'
# Perf bar
gem 'peek', '~> 1.0.1'
gem 'peek-gc', '~> 0.0.2'
-gem 'peek-host', '~> 1.0.0'
gem 'peek-mysql2', '~> 1.1.0', group: :mysql
gem 'peek-performance_bar', '~> 1.3.0'
gem 'peek-pg', '~> 1.3.0', group: :postgres
@@ -300,8 +307,8 @@ group :metrics do
end
group :development do
- gem 'foreman', '~> 0.78.0'
- gem 'brakeman', '~> 3.6.0', require: false
+ gem 'foreman', '~> 0.84.0'
+ gem 'brakeman', '~> 4.2', require: false
gem 'letter_opener_web', '~> 1.3.0'
gem 'rblineprof', '~> 0.3.6', platform: :mri, require: false
@@ -360,13 +367,15 @@ group :development, :test do
gem 'benchmark-ips', '~> 2.3.0', require: false
gem 'license_finder', '~> 3.1', require: false
- gem 'knapsack', '~> 1.11.0'
+ gem 'knapsack', '~> 1.16'
- gem 'activerecord_sane_schema_dumper', '0.2'
+ gem 'activerecord_sane_schema_dumper', gem_versions['activerecord_sane_schema_dumper']
gem 'stackprof', '~> 0.2.10', require: false
gem 'simple_po_parser', '~> 1.1.2', require: false
+
+ gem 'timecop', '~> 0.8.0'
end
group :test do
@@ -374,21 +383,20 @@ group :test do
gem 'email_spec', '~> 1.6.0'
gem 'json-schema', '~> 2.8.0'
gem 'webmock', '~> 2.3.2'
- gem 'test_after_commit', '~> 1.1'
+ gem 'test_after_commit', '~> 1.1' unless rails5? # Remove this gem when migrated to rails 5.0. It's been integrated to rails 5.0.
gem 'sham_rack', '~> 1.3.6'
- gem 'timecop', '~> 0.8.0'
gem 'concurrent-ruby', '~> 1.0.5'
gem 'test-prof', '~> 0.2.5'
end
-gem 'octokit', '~> 4.6.2'
+gem 'octokit', '~> 4.8'
gem 'mail_room', '~> 0.9.1'
gem 'email_reply_trimmer', '~> 0.1'
gem 'html2text'
-gem 'ruby-prof', '~> 0.16.2'
+gem 'ruby-prof', '~> 0.17.0'
# OAuth
gem 'oauth2', '~> 1.4'
@@ -401,7 +409,7 @@ gem 'vmstat', '~> 2.3.0'
gem 'sys-filesystem', '~> 1.1.6'
# SSH host key support
-gem 'net-ssh', '~> 4.1.0'
+gem 'net-ssh', '~> 4.2.0'
gem 'sshkey', '~> 1.9.0'
# Required for ED25519 SSH host key support
@@ -412,7 +420,7 @@ group :ed25519 do
end
# Gitaly GRPC client
-gem 'gitaly-proto', '~> 0.88.0', require: 'gitaly'
+gem 'gitaly-proto', '~> 0.96.0', require: 'gitaly'
gem 'grpc', '~> 1.10.0'
# Locked until https://github.com/google/protobuf/issues/4210 is closed
@@ -421,9 +429,9 @@ gem 'google-protobuf', '= 3.5.1'
gem 'toml-rb', '~> 1.0.0', require: false
# Feature toggles
-gem 'flipper', '~> 0.11.0'
-gem 'flipper-active_record', '~> 0.11.0'
-gem 'flipper-active_support_cache_store', '~> 0.11.0'
+gem 'flipper', '~> 0.13.0'
+gem 'flipper-active_record', '~> 0.13.0'
+gem 'flipper-active_support_cache_store', '~> 0.13.0'
# Structured logging
gem 'lograge', '~> 0.5'
diff --git a/Gemfile.lock b/Gemfile.lock
index 41e6f2cc52..31b0dc9c0e 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -40,13 +40,14 @@ GEM
minitest (~> 5.1)
thread_safe (~> 0.3, >= 0.3.4)
tzinfo (~> 1.1)
- acts-as-taggable-on (4.0.0)
- activerecord (>= 4.0)
+ acts-as-taggable-on (5.0.0)
+ activerecord (>= 4.2.8)
adamantium (0.2.0)
ice_nine (~> 0.11.0)
memoizable (~> 0.4.0)
addressable (2.5.2)
public_suffix (>= 2.0.2, < 4.0)
+ aes_key_wrap (1.0.1)
akismet (2.0.0)
allocations (1.0.5)
arel (6.0.4)
@@ -55,17 +56,17 @@ GEM
faraday_middleware (~> 0.9)
faraday_middleware-multi_json (~> 0.0)
oauth2 (~> 1.0)
- asciidoctor (1.5.3)
- asciidoctor-plantuml (0.0.7)
+ asciidoctor (1.5.6.2)
+ asciidoctor-plantuml (0.0.8)
asciidoctor (~> 1.5)
asset_sync (2.2.0)
activemodel (>= 4.1.0)
fog-core
mime-types (>= 2.99)
unf
- ast (2.3.0)
+ ast (2.4.0)
atomic (1.1.99)
- attr_encrypted (3.0.3)
+ attr_encrypted (3.1.0)
encryptor (~> 3.0.0)
attr_required (1.0.0)
autoprefixer-rails (6.2.3)
@@ -86,7 +87,7 @@ GEM
coderay (>= 1.0.0)
erubis (>= 2.6.6)
rack (>= 0.9.0)
- bindata (2.4.1)
+ bindata (2.4.3)
binding_of_caller (0.7.2)
debug_inspector (>= 0.0.1)
blankslate (2.1.2.4)
@@ -94,7 +95,7 @@ GEM
autoprefixer-rails (>= 5.2.1)
sass (>= 3.3.4)
bootstrap_form (2.7.0)
- brakeman (3.6.1)
+ brakeman (4.2.1)
browser (2.2.0)
builder (3.2.3)
bullet (5.5.1)
@@ -119,7 +120,7 @@ GEM
activesupport (>= 4.0.0)
mime-types (>= 1.16)
cause (0.1)
- charlock_holmes (0.7.5)
+ charlock_holmes (0.7.6)
childprocess (0.7.0)
ffi (~> 1.0, >= 1.0.11)
chronic (0.10.2)
@@ -175,12 +176,12 @@ GEM
diff-lcs (1.3)
diffy (3.1.0)
docile (1.1.5)
- domain_name (0.5.20161021)
+ domain_name (0.5.20170404)
unf (>= 0.0.5, < 1.0.0)
- doorkeeper (4.2.6)
+ doorkeeper (4.3.2)
railties (>= 4.2)
- doorkeeper-openid_connect (1.2.0)
- doorkeeper (~> 4.0)
+ doorkeeper-openid_connect (1.3.0)
+ doorkeeper (~> 4.3)
json-jwt (~> 1.6)
dropzonejs-rails (0.7.2)
rails (> 3.1)
@@ -195,7 +196,7 @@ GEM
et-orbi (1.0.3)
tzinfo
eventmachine (1.0.8)
- excon (0.57.1)
+ excon (0.60.0)
execjs (2.6.0)
expression_parser (0.9.0)
factory_bot (4.8.2)
@@ -211,7 +212,7 @@ GEM
faraday_middleware
multi_json
fast_blank (1.0.0)
- fast_gettext (1.4.0)
+ fast_gettext (1.6.0)
ffaker (2.4.0)
ffi (1.9.18)
flay (2.10.0)
@@ -219,13 +220,13 @@ GEM
path_expander (~> 1.0)
ruby_parser (~> 3.0)
sexp_processor (~> 4.0)
- flipper (0.11.0)
- flipper-active_record (0.11.0)
+ flipper (0.13.0)
+ flipper-active_record (0.13.0)
activerecord (>= 3.2, < 6)
- flipper (~> 0.11.0)
- flipper-active_support_cache_store (0.11.0)
+ flipper (~> 0.13.0)
+ flipper-active_support_cache_store (0.13.0)
activesupport (>= 3.2, < 6)
- flipper (~> 0.11.0)
+ flipper (~> 0.13.0)
flowdock (0.7.1)
httparty (~> 0.7)
multi_json
@@ -234,19 +235,20 @@ GEM
fog-json (~> 1.0)
ipaddress (~> 0.8)
xml-simple (~> 1.1)
- fog-aws (1.4.0)
+ fog-aws (2.0.1)
fog-core (~> 1.38)
fog-json (~> 1.0)
fog-xml (~> 0.1)
ipaddress (~> 0.8)
- fog-core (1.44.3)
+ fog-core (1.45.0)
builder
- excon (~> 0.49)
+ excon (~> 0.58)
formatador (~> 0.2)
- fog-google (0.5.3)
+ fog-google (1.3.3)
fog-core
fog-json
fog-xml
+ google-api-client (~> 0.19.1)
fog-json (1.0.2)
fog-core (~> 1.0)
multi_json (~> 1.10)
@@ -266,7 +268,7 @@ GEM
nokogiri (>= 1.5.11, < 2.0.0)
font-awesome-rails (4.7.0.1)
railties (>= 3.2, < 5.1)
- foreman (0.78.0)
+ foreman (0.84.0)
thor (~> 0.19.1)
formatador (0.2.5)
fuubar (2.2.0)
@@ -277,20 +279,20 @@ GEM
gemojione (3.3.0)
json
get_process_mem (0.2.0)
- gettext (3.2.2)
+ gettext (3.2.9)
locale (>= 2.0.5)
text (>= 1.3.0)
gettext_i18n_rails (1.8.0)
fast_gettext (>= 0.9.0)
- gettext_i18n_rails_js (1.2.0)
+ gettext_i18n_rails_js (1.3.0)
gettext (>= 3.0.2)
gettext_i18n_rails (>= 0.7.1)
po_to_json (>= 1.0.0)
rails (>= 3.2.0)
gherkin-ruby (0.3.2)
- gitaly-proto (0.88.0)
+ gitaly-proto (0.96.0)
google-protobuf (~> 3.1)
- grpc (~> 1.0)
+ grpc (~> 1.10)
github-linguist (5.3.3)
charlock_holmes (~> 0.7.5)
escape_utils (~> 1.1.0)
@@ -336,9 +338,9 @@ GEM
json
multi_json
request_store (>= 1.0)
- google-api-client (0.13.6)
+ google-api-client (0.19.8)
addressable (~> 2.5, >= 2.5.1)
- googleauth (~> 0.5)
+ googleauth (>= 0.5, < 0.7.0)
httpclient (>= 2.8.1, < 3.0)
mime-types (~> 3.0)
representable (~> 3.0)
@@ -356,7 +358,7 @@ GEM
signet (~> 0.7)
gpgme (2.0.13)
mini_portile2 (~> 2.1)
- grape (1.0.0)
+ grape (1.0.2)
activesupport
builder
mustermann-grape (~> 1.0.0)
@@ -389,7 +391,7 @@ GEM
thor
tilt
hashdiff (0.3.4)
- hashie (3.5.6)
+ hashie (3.5.7)
hashie-forbidden_attributes (0.1.1)
hashie (>= 3.0)
health_check (2.6.0)
@@ -397,26 +399,26 @@ GEM
hipchat (1.5.2)
httparty
mimemagic
- html-pipeline (1.11.0)
+ html-pipeline (2.7.1)
activesupport (>= 2)
- nokogiri (~> 1.4)
+ nokogiri (>= 1.4)
html2text (0.2.0)
nokogiri (~> 1.6)
htmlentities (4.3.4)
- http (0.9.8)
+ http (2.2.2)
addressable (~> 2.3)
http-cookie (~> 1.0)
http-form_data (~> 1.0.1)
http_parser.rb (~> 0.6.0)
http-cookie (1.0.3)
domain_name (~> 0.5)
- http-form_data (1.0.1)
+ http-form_data (1.0.3)
http_parser.rb (0.6.0)
httparty (0.13.7)
json (~> 1.8)
multi_xml (>= 0.5.2)
- httpclient (2.8.2)
- i18n (0.9.1)
+ httpclient (2.8.3)
+ i18n (0.9.5)
concurrent-ruby (~> 1.0)
ice_nine (0.11.2)
influxdb (0.2.3)
@@ -428,15 +430,11 @@ GEM
multipart-post
oauth (~> 0.5, >= 0.5.0)
jquery-atwho-rails (1.3.2)
- jquery-rails (4.3.1)
- rails-dom-testing (>= 1, < 3)
- railties (>= 4.2.0)
- thor (>= 0.14, < 2.0)
json (1.8.6)
- json-jwt (1.7.2)
+ json-jwt (1.9.2)
activesupport
+ aes_key_wrap
bindata
- multi_json (>= 1.3)
securecompare
url_safe_base64
json-schema (2.8.0)
@@ -455,13 +453,13 @@ GEM
kaminari-core (= 1.0.1)
kaminari-core (1.0.1)
kgio (2.10.0)
- knapsack (1.11.0)
+ knapsack (1.16.0)
rake
timecop (>= 0.1.0)
- kubeclient (2.2.0)
- http (= 0.9.8)
- recursive-open-struct (= 1.0.0)
- rest-client
+ kubeclient (3.0.0)
+ http (~> 2.2.2)
+ recursive-open-struct (~> 1.0.4)
+ rest-client (~> 2.0)
launchy (2.4.3)
addressable (~> 2.3)
letter_opener (1.4.1)
@@ -478,7 +476,7 @@ GEM
toml (= 0.1.2)
with_env (> 1.0)
xml-simple
- licensee (8.7.0)
+ licensee (8.9.2)
rugged (~> 0.24)
little-plugger (1.1.4)
locale (2.1.2)
@@ -503,36 +501,35 @@ GEM
mime-types-data (~> 3.2015)
mime-types-data (3.2016.0521)
mimemagic (0.3.0)
- mini_mime (0.1.4)
+ mini_mime (1.0.0)
mini_portile2 (2.3.0)
minitest (5.7.0)
mousetrap-rails (1.4.6)
multi_json (1.13.1)
multi_xml (0.6.0)
multipart-post (2.0.0)
- mustermann (1.0.0)
+ mustermann (1.0.2)
mustermann-grape (1.0.0)
mustermann (~> 1.0.0)
mysql2 (0.4.10)
net-ldap (0.16.0)
- net-ssh (4.1.0)
+ net-ssh (4.2.0)
netrc (0.11.0)
nokogiri (1.8.2)
mini_portile2 (~> 2.3.0)
numerizer (0.1.1)
- oauth (0.5.1)
+ oauth (0.5.4)
oauth2 (1.4.0)
faraday (>= 0.8, < 0.13)
jwt (~> 1.0)
multi_json (~> 1.3)
multi_xml (~> 0.5)
rack (>= 1.2, < 3)
- octokit (4.6.2)
+ octokit (4.8.0)
sawyer (~> 0.8.0, >= 0.5.3)
- oj (2.17.5)
- omniauth (1.4.2)
- hashie (>= 1.2, < 4)
- rack (>= 1.0, < 3)
+ omniauth (1.8.1)
+ hashie (>= 3.4.6, < 3.6.0)
+ rack (>= 1.6.2, < 3)
omniauth-auth0 (2.0.0)
omniauth-oauth2 (~> 1.4)
omniauth-authentiq (0.3.1)
@@ -553,11 +550,10 @@ GEM
omniauth-gitlab (1.0.2)
omniauth (~> 1.0)
omniauth-oauth2 (~> 1.0)
- omniauth-google-oauth2 (0.5.2)
- jwt (~> 1.5)
- multi_json (~> 1.3)
+ omniauth-google-oauth2 (0.5.3)
+ jwt (>= 1.5)
omniauth (>= 1.1.1)
- omniauth-oauth2 (>= 1.3.1)
+ omniauth-oauth2 (>= 1.5)
omniauth-kerberos (0.3.0)
omniauth-multipassword
timfel-krb5-auth (~> 0.8)
@@ -566,19 +562,19 @@ GEM
omniauth-oauth (1.1.0)
oauth
omniauth (~> 1.0)
- omniauth-oauth2 (1.4.0)
- oauth2 (~> 1.0)
+ omniauth-oauth2 (1.5.0)
+ oauth2 (~> 1.1)
omniauth (~> 1.2)
omniauth-oauth2-generic (0.2.2)
omniauth-oauth2 (~> 1.0)
- omniauth-saml (1.7.0)
- omniauth (~> 1.3)
- ruby-saml (~> 1.4)
+ omniauth-saml (1.10.0)
+ omniauth (~> 1.3, >= 1.3.2)
+ ruby-saml (~> 1.7)
omniauth-shibboleth (1.2.1)
omniauth (>= 1.0.0)
- omniauth-twitter (1.2.1)
- json (~> 1.3)
+ omniauth-twitter (1.4.0)
omniauth-oauth (~> 1.1)
+ rack
omniauth_crowd (2.2.3)
activesupport
nokogiri (>= 1.4.4)
@@ -588,8 +584,8 @@ GEM
orm_adapter (0.5.0)
os (0.9.6)
parallel (1.12.1)
- parser (2.4.0.2)
- ast (~> 2.3)
+ parser (2.5.0.5)
+ ast (~> 2.4.0)
parslet (1.5.0)
blankslate (~> 2.0)
path_expander (1.0.2)
@@ -599,8 +595,6 @@ GEM
railties (>= 4.0.0)
peek-gc (0.0.2)
peek
- peek-host (1.0.0)
- peek
peek-mysql2 (1.1.0)
atomic (>= 1.0.0)
mysql2
@@ -652,7 +646,7 @@ GEM
pry (>= 0.9.10)
public_suffix (3.0.2)
pyu-ruby-sasl (0.0.3.3)
- rack (1.6.8)
+ rack (1.6.9)
rack-accept (0.4.5)
rack (>= 0.4)
rack-attack (4.4.1)
@@ -664,7 +658,7 @@ GEM
httpclient (>= 2.4)
multi_json (>= 1.3.6)
rack (>= 1.1)
- rack-protection (1.5.3)
+ rack-protection (2.0.1)
rack
rack-proxy (0.6.0)
rack
@@ -683,8 +677,8 @@ GEM
sprockets-rails
rails-deprecated_sanitizer (1.0.3)
activesupport (>= 4.2.0.alpha)
- rails-dom-testing (1.0.8)
- activesupport (>= 4.2.0.beta, < 5.0)
+ rails-dom-testing (1.0.9)
+ activesupport (>= 4.2.0, < 5.0)
nokogiri (~> 1.6)
rails-deprecated_sanitizer (>= 1.0.1)
rails-html-sanitizer (1.0.4)
@@ -715,7 +709,7 @@ GEM
re2 (1.1.1)
recaptcha (3.0.0)
json
- recursive-open-struct (1.0.0)
+ recursive-open-struct (1.0.5)
redcarpet (3.4.0)
redis (3.3.5)
redis-actionpack (5.0.2)
@@ -743,7 +737,7 @@ GEM
request_store (1.3.1)
responders (2.3.0)
railties (>= 4.2.0, < 5.1)
- rest-client (2.0.0)
+ rest-client (2.0.2)
http-cookie (>= 1.0.2, < 2.0)
mime-types (>= 1.16, < 4.0)
netrc (~> 0.8)
@@ -805,9 +799,9 @@ GEM
i18n
ruby-fogbugz (0.2.1)
crack (~> 0.4)
- ruby-prof (0.16.2)
+ ruby-prof (0.17.0)
ruby-progressbar (1.9.0)
- ruby-saml (1.4.1)
+ ruby-saml (1.7.2)
nokogiri (>= 1.5.10)
ruby_parser (3.9.0)
sexp_processor (~> 4.1)
@@ -816,7 +810,7 @@ GEM
rubyzip (1.2.1)
rufus-scheduler (3.4.0)
et-orbi (~> 1.0)
- rugged (0.26.0)
+ rugged (0.27.0)
safe_yaml (1.0.4)
sanitize (2.1.0)
nokogiri (>= 1.4.4)
@@ -846,7 +840,7 @@ GEM
selenium-webdriver (3.5.0)
childprocess (~> 0.5)
rubyzip (~> 1.0)
- sentry-raven (2.5.3)
+ sentry-raven (2.7.2)
faraday (>= 0.7.6, < 1.0)
settingslogic (2.0.9)
sexp_processor (4.9.0)
@@ -903,13 +897,13 @@ GEM
sqlite3 (1.3.13)
sshkey (1.9.0)
stackprof (0.2.10)
- state_machines (0.4.0)
- state_machines-activemodel (0.4.0)
- activemodel (>= 4.1, < 5.1)
- state_machines (>= 0.4.0)
- state_machines-activerecord (0.4.0)
- activerecord (>= 4.1, < 5.1)
- state_machines-activemodel (>= 0.3.0)
+ state_machines (0.5.0)
+ state_machines-activemodel (0.5.1)
+ activemodel (>= 4.1, < 6.0)
+ state_machines (>= 0.5.0)
+ state_machines-activerecord (0.5.1)
+ activerecord (>= 4.1, < 6.0)
+ state_machines-activemodel (>= 0.5.0)
stringex (2.7.1)
sys-filesystem (1.1.6)
ffi
@@ -935,7 +929,7 @@ GEM
truncato (0.7.10)
htmlentities (~> 4.3.1)
nokogiri (~> 1.8.0, >= 1.7.0)
- tzinfo (1.2.4)
+ tzinfo (1.2.5)
thread_safe (~> 0.1)
u2f (0.2.1)
uber (0.1.0)
@@ -944,7 +938,7 @@ GEM
json (>= 1.8.0)
unf (0.1.4)
unf_ext
- unf_ext (0.0.7.4)
+ unf_ext (0.0.7.5)
unicode-display_width (1.3.0)
unicorn (5.1.0)
kgio (~> 2.6)
@@ -953,13 +947,13 @@ GEM
get_process_mem (~> 0)
unicorn (>= 4, < 6)
uniform_notifier (1.10.0)
- unparser (0.2.6)
+ unparser (0.2.7)
abstract_type (~> 0.0.7)
adamantium (~> 0.2.0)
concord (~> 0.1.5)
diff-lcs (~> 1.3)
equalizer (~> 0.0.9)
- parser (>= 2.3.1.2, < 2.5)
+ parser (>= 2.3.1.2, < 2.6)
procto (~> 0.0.2)
url_safe_base64 (0.2.2)
validates_hostname (1.0.6)
@@ -996,15 +990,15 @@ DEPENDENCIES
RedCloth (~> 4.3.2)
ace-rails-ap (~> 4.1.0)
activerecord_sane_schema_dumper (= 0.2)
- acts-as-taggable-on (~> 4.0)
+ acts-as-taggable-on (~> 5.0)
addressable (~> 2.5.2)
akismet (~> 2.0)
allocations (~> 1.0)
asana (~> 0.6.0)
- asciidoctor (~> 1.5.2)
- asciidoctor-plantuml (= 0.0.7)
+ asciidoctor (~> 1.5.6)
+ asciidoctor-plantuml (= 0.0.8)
asset_sync (~> 2.2.0)
- attr_encrypted (~> 3.0.0)
+ attr_encrypted (~> 3.1.0)
awesome_print (~> 1.2.0)
babosa (~> 1.0.2)
base32 (~> 0.3.0)
@@ -1015,7 +1009,7 @@ DEPENDENCIES
binding_of_caller (~> 0.7.2)
bootstrap-sass (~> 3.3.0)
bootstrap_form (~> 2.7.0)
- brakeman (~> 3.6.0)
+ brakeman (~> 4.2)
browser (~> 2.2)
bullet (~> 5.5.0)
bundler-audit (~> 0.5.0)
@@ -1036,8 +1030,8 @@ DEPENDENCIES
devise (~> 4.2)
devise-two-factor (~> 3.0.0)
diffy (~> 3.1.0)
- doorkeeper (~> 4.2.0)
- doorkeeper-openid_connect (~> 1.2.0)
+ doorkeeper (~> 4.3)
+ doorkeeper-openid_connect (~> 1.3)
dropzonejs-rails (~> 0.7.1)
email_reply_trimmer (~> 0.1)
email_spec (~> 1.6.0)
@@ -1046,25 +1040,25 @@ DEPENDENCIES
fast_blank
ffaker (~> 2.4)
flay (~> 2.10.0)
- flipper (~> 0.11.0)
- flipper-active_record (~> 0.11.0)
- flipper-active_support_cache_store (~> 0.11.0)
+ flipper (~> 0.13.0)
+ flipper-active_record (~> 0.13.0)
+ flipper-active_support_cache_store (~> 0.13.0)
fog-aliyun (~> 0.2.0)
- fog-aws (~> 1.4)
+ fog-aws (~> 2.0.1)
fog-core (~> 1.44)
- fog-google (~> 0.5)
+ fog-google (~> 1.3.3)
fog-local (~> 0.3)
fog-openstack (~> 0.1)
fog-rackspace (~> 0.1.1)
font-awesome-rails (~> 4.7)
- foreman (~> 0.78.0)
+ foreman (~> 0.84.0)
fuubar (~> 2.2.0)
gemnasium-gitlab-service (~> 0.2)
gemojione (~> 3.3)
gettext (~> 3.2.2)
gettext_i18n_rails (~> 1.8.0)
- gettext_i18n_rails_js (~> 1.2.0)
- gitaly-proto (~> 0.88.0)
+ gettext_i18n_rails_js (~> 1.3)
+ gitaly-proto (~> 0.96.0)
github-linguist (~> 5.3.3)
gitlab-flowdock-git-hook (~> 1.0.1)
gitlab-markup (~> 1.6.2)
@@ -1073,7 +1067,7 @@ DEPENDENCIES
gollum-lib (~> 4.2)
gollum-rugged_adapter (~> 0.4.4)
gon (~> 6.1.0)
- google-api-client (~> 0.13.6)
+ google-api-client (~> 0.19.8)
google-protobuf (= 3.5.1)
gpgme
grape (~> 1.0)
@@ -1086,21 +1080,20 @@ DEPENDENCIES
hashie-forbidden_attributes
health_check (~> 2.6.0)
hipchat (~> 1.5.0)
- html-pipeline (~> 1.11.0)
+ html-pipeline (~> 2.7.1)
html2text
httparty (~> 0.13.3)
influxdb (~> 0.2)
jira-ruby (~> 1.4)
jquery-atwho-rails (~> 1.3.2)
- jquery-rails (~> 4.3.1)
json-schema (~> 2.8.0)
jwt (~> 1.5.6)
kaminari (~> 1.0)
- knapsack (~> 1.11.0)
- kubeclient (~> 2.2.0)
+ knapsack (~> 1.16)
+ kubeclient (~> 3.0)
letter_opener_web (~> 1.3.0)
license_finder (~> 3.1)
- licensee (~> 8.7.0)
+ licensee (~> 8.9)
lograge (~> 0.5)
loofah (~> 2.2)
mail_room (~> 0.9.1)
@@ -1109,12 +1102,11 @@ DEPENDENCIES
mousetrap-rails (~> 1.4.6)
mysql2 (~> 0.4.10)
net-ldap
- net-ssh (~> 4.1.0)
+ net-ssh (~> 4.2.0)
nokogiri (~> 1.8.2)
oauth2 (~> 1.4)
- octokit (~> 4.6.2)
- oj (~> 2.17.4)
- omniauth (~> 1.4.2)
+ octokit (~> 4.8)
+ omniauth (~> 1.8)
omniauth-auth0 (~> 2.0.0)
omniauth-authentiq (~> 0.3.1)
omniauth-azure-oauth2 (~> 0.0.9)
@@ -1122,17 +1114,16 @@ DEPENDENCIES
omniauth-facebook (~> 4.0.0)
omniauth-github (~> 1.1.1)
omniauth-gitlab (~> 1.0.2)
- omniauth-google-oauth2 (~> 0.5.2)
+ omniauth-google-oauth2 (~> 0.5.3)
omniauth-kerberos (~> 0.3.0)
omniauth-oauth2-generic (~> 0.2.2)
- omniauth-saml (~> 1.7.0)
+ omniauth-saml (~> 1.10)
omniauth-shibboleth (~> 1.2.0)
- omniauth-twitter (~> 1.2.0)
+ omniauth-twitter (~> 1.4)
omniauth_crowd (~> 2.2.0)
org-ruby (~> 0.9.12)
peek (~> 1.0.1)
peek-gc (~> 0.0.2)
- peek-host (~> 1.0.0)
peek-mysql2 (~> 1.1.0)
peek-performance_bar (~> 1.3.0)
peek-pg (~> 1.3.0)
@@ -1175,17 +1166,17 @@ DEPENDENCIES
rubocop (~> 0.52.1)
rubocop-rspec (~> 1.22.1)
ruby-fogbugz (~> 0.2.1)
- ruby-prof (~> 0.16.2)
+ ruby-prof (~> 0.17.0)
ruby_parser (~> 3.8)
rufus-scheduler (~> 3.4)
- rugged (~> 0.26.0)
+ rugged (~> 0.27)
sanitize (~> 2.0)
sass-rails (~> 5.0.6)
scss_lint (~> 0.56.0)
seed-fu (~> 2.3.7)
select2-rails (~> 3.5.9)
selenium-webdriver (~> 3.5)
- sentry-raven (~> 2.5.3)
+ sentry-raven (~> 2.7)
settingslogic (~> 2.0.9)
sham_rack (~> 1.3.6)
shoulda-matchers (~> 3.1.2)
@@ -1203,7 +1194,7 @@ DEPENDENCIES
sprockets (~> 3.7.0)
sshkey (~> 1.9.0)
stackprof (~> 0.2.10)
- state_machines-activerecord (~> 0.4.0)
+ state_machines-activerecord (~> 0.5.1)
sys-filesystem (~> 1.1.6)
test-prof (~> 0.2.5)
test_after_commit (~> 1.1)
diff --git a/Gemfile.rails5 b/Gemfile.rails5
new file mode 100644
index 0000000000..2b526b19ba
--- /dev/null
+++ b/Gemfile.rails5
@@ -0,0 +1,7 @@
+# BUNDLE_GEMFILE=Gemfile.rails5 bundle install
+
+ENV["RAILS5"] = "true"
+
+gemfile = File.expand_path("../Gemfile", __FILE__)
+
+eval(File.read(gemfile), nil, gemfile)
diff --git a/Gemfile.rails5.lock b/Gemfile.rails5.lock
new file mode 100644
index 0000000000..18bbad88ec
--- /dev/null
+++ b/Gemfile.rails5.lock
@@ -0,0 +1,1223 @@
+GEM
+ remote: https://rubygems.org/
+ specs:
+ RedCloth (4.3.2)
+ abstract_type (0.0.7)
+ ace-rails-ap (4.1.4)
+ actioncable (5.0.6)
+ actionpack (= 5.0.6)
+ nio4r (>= 1.2, < 3.0)
+ websocket-driver (~> 0.6.1)
+ actionmailer (5.0.6)
+ actionpack (= 5.0.6)
+ actionview (= 5.0.6)
+ activejob (= 5.0.6)
+ mail (~> 2.5, >= 2.5.4)
+ rails-dom-testing (~> 2.0)
+ actionpack (5.0.6)
+ actionview (= 5.0.6)
+ activesupport (= 5.0.6)
+ rack (~> 2.0)
+ rack-test (~> 0.6.3)
+ rails-dom-testing (~> 2.0)
+ rails-html-sanitizer (~> 1.0, >= 1.0.2)
+ actionview (5.0.6)
+ activesupport (= 5.0.6)
+ builder (~> 3.1)
+ erubis (~> 2.7.0)
+ rails-dom-testing (~> 2.0)
+ rails-html-sanitizer (~> 1.0, >= 1.0.3)
+ activejob (5.0.6)
+ activesupport (= 5.0.6)
+ globalid (>= 0.3.6)
+ activemodel (5.0.6)
+ activesupport (= 5.0.6)
+ activerecord (5.0.6)
+ activemodel (= 5.0.6)
+ activesupport (= 5.0.6)
+ arel (~> 7.0)
+ activerecord_sane_schema_dumper (1.0)
+ rails (>= 5, < 6)
+ activesupport (5.0.6)
+ concurrent-ruby (~> 1.0, >= 1.0.2)
+ i18n (~> 0.7)
+ minitest (~> 5.1)
+ tzinfo (~> 1.1)
+ acts-as-taggable-on (5.0.0)
+ activerecord (>= 4.2.8)
+ adamantium (0.2.0)
+ ice_nine (~> 0.11.0)
+ memoizable (~> 0.4.0)
+ addressable (2.5.2)
+ public_suffix (>= 2.0.2, < 4.0)
+ aes_key_wrap (1.0.1)
+ akismet (2.0.0)
+ allocations (1.0.5)
+ arel (7.1.4)
+ asana (0.6.3)
+ faraday (~> 0.9)
+ faraday_middleware (~> 0.9)
+ faraday_middleware-multi_json (~> 0.0)
+ oauth2 (~> 1.0)
+ asciidoctor (1.5.6.1)
+ asciidoctor-plantuml (0.0.8)
+ asciidoctor (~> 1.5)
+ asset_sync (2.2.0)
+ activemodel (>= 4.1.0)
+ fog-core
+ mime-types (>= 2.99)
+ unf
+ ast (2.4.0)
+ atomic (1.1.100)
+ attr_encrypted (3.0.3)
+ encryptor (~> 3.0.0)
+ attr_required (1.0.1)
+ autoprefixer-rails (8.1.0.1)
+ execjs
+ awesome_print (1.2.0)
+ axiom-types (0.1.1)
+ descendants_tracker (~> 0.0.4)
+ ice_nine (~> 0.11.0)
+ thread_safe (~> 0.3, >= 0.3.1)
+ babosa (1.0.2)
+ base32 (0.3.2)
+ batch-loader (1.2.1)
+ bcrypt (3.1.11)
+ bcrypt_pbkdf (1.0.0)
+ benchmark-ips (2.3.0)
+ better_errors (2.1.1)
+ coderay (>= 1.0.0)
+ erubis (>= 2.6.6)
+ rack (>= 0.9.0)
+ bindata (2.4.3)
+ binding_of_caller (0.7.3)
+ debug_inspector (>= 0.0.1)
+ blankslate (2.1.2.4)
+ bootstrap-sass (3.3.7)
+ autoprefixer-rails (>= 5.2.1)
+ sass (>= 3.3.4)
+ bootstrap_form (2.7.0)
+ brakeman (4.2.1)
+ browser (2.5.3)
+ builder (3.2.3)
+ bullet (5.5.1)
+ activesupport (>= 3.0.0)
+ uniform_notifier (~> 1.10.0)
+ bundler-audit (0.5.0)
+ bundler (~> 1.2)
+ thor (~> 0.18)
+ byebug (9.0.6)
+ capybara (2.18.0)
+ addressable
+ mini_mime (>= 0.1.3)
+ nokogiri (>= 1.3.3)
+ rack (>= 1.0.0)
+ rack-test (>= 0.5.4)
+ xpath (>= 2.0, < 4.0)
+ capybara-screenshot (1.0.18)
+ capybara (>= 1.0, < 3)
+ launchy
+ carrierwave (1.2.2)
+ activemodel (>= 4.0.0)
+ activesupport (>= 4.0.0)
+ mime-types (>= 1.16)
+ charlock_holmes (0.7.5)
+ childprocess (0.9.0)
+ ffi (~> 1.0, >= 1.0.11)
+ chronic (0.10.2)
+ chronic_duration (0.10.6)
+ numerizer (~> 0.1.1)
+ chunky_png (1.3.10)
+ citrus (3.0.2)
+ coderay (1.1.2)
+ coercible (1.0.0)
+ descendants_tracker (~> 0.0.1)
+ colorize (0.8.1)
+ commonmarker (0.17.9)
+ ruby-enum (~> 0.5)
+ concord (0.1.5)
+ adamantium (~> 0.2.0)
+ equalizer (~> 0.0.9)
+ concurrent-ruby (1.0.5)
+ concurrent-ruby-ext (1.0.5)
+ concurrent-ruby (= 1.0.5)
+ connection_pool (2.2.1)
+ crack (0.4.3)
+ safe_yaml (~> 1.0.0)
+ crass (1.0.3)
+ creole (0.5.0)
+ css_parser (1.6.0)
+ addressable
+ d3_rails (3.5.17)
+ railties (>= 3.1.0)
+ daemons (1.2.6)
+ database_cleaner (1.5.3)
+ debug_inspector (0.0.3)
+ debugger-ruby_core_source (1.3.8)
+ deckar01-task_list (2.0.0)
+ html-pipeline
+ declarative (0.0.10)
+ declarative-option (0.1.0)
+ default_value_for (3.0.5)
+ activerecord (>= 3.2.0, < 5.2)
+ descendants_tracker (0.0.4)
+ thread_safe (~> 0.3, >= 0.3.1)
+ devise (4.4.1)
+ bcrypt (~> 3.0)
+ orm_adapter (~> 0.1)
+ railties (>= 4.1.0, < 5.2)
+ responders
+ warden (~> 1.2.3)
+ devise-two-factor (3.0.2)
+ activesupport (< 5.2)
+ attr_encrypted (>= 1.3, < 4, != 2)
+ devise (~> 4.0)
+ railties (< 5.2)
+ rotp (~> 2.0)
+ diff-lcs (1.3)
+ diffy (3.1.0)
+ docile (1.1.5)
+ domain_name (0.5.20170404)
+ unf (>= 0.0.5, < 1.0.0)
+ doorkeeper (4.3.1)
+ railties (>= 4.2)
+ doorkeeper-openid_connect (1.3.0)
+ doorkeeper (~> 4.3)
+ json-jwt (~> 1.6)
+ dropzonejs-rails (0.7.4)
+ rails (> 3.1)
+ email_reply_trimmer (0.1.10)
+ email_spec (1.6.0)
+ launchy (~> 2.1)
+ mail (~> 2.2)
+ encryptor (3.0.0)
+ equalizer (0.0.11)
+ erubis (2.7.0)
+ escape_utils (1.1.1)
+ et-orbi (1.0.9)
+ tzinfo
+ eventmachine (1.2.5)
+ excon (0.60.0)
+ execjs (2.7.0)
+ expression_parser (0.9.0)
+ factory_bot (4.8.2)
+ activesupport (>= 3.0.0)
+ factory_bot_rails (4.8.2)
+ factory_bot (~> 4.8.2)
+ railties (>= 3.0.0)
+ faraday (0.12.2)
+ multipart-post (>= 1.2, < 3)
+ faraday_middleware (0.12.2)
+ faraday (>= 0.7.4, < 1.0)
+ faraday_middleware-multi_json (0.0.6)
+ faraday_middleware
+ multi_json
+ fast_blank (1.0.0)
+ fast_gettext (1.6.0)
+ ffaker (2.8.1)
+ ffi (1.9.23)
+ flay (2.10.0)
+ erubis (~> 2.7.0)
+ path_expander (~> 1.0)
+ ruby_parser (~> 3.0)
+ sexp_processor (~> 4.0)
+ flipper (0.13.0)
+ flipper-active_record (0.13.0)
+ activerecord (>= 3.2, < 6)
+ flipper (~> 0.13.0)
+ flipper-active_support_cache_store (0.13.0)
+ activesupport (>= 3.2, < 6)
+ flipper (~> 0.13.0)
+ flowdock (0.7.1)
+ httparty (~> 0.7)
+ multi_json
+ fog-aliyun (0.2.0)
+ fog-core (~> 1.27)
+ fog-json (~> 1.0)
+ ipaddress (~> 0.8)
+ xml-simple (~> 1.1)
+ fog-aws (2.0.1)
+ fog-core (~> 1.38)
+ fog-json (~> 1.0)
+ fog-xml (~> 0.1)
+ ipaddress (~> 0.8)
+ fog-core (1.45.0)
+ builder
+ excon (~> 0.58)
+ formatador (~> 0.2)
+ fog-google (1.3.3)
+ fog-core
+ fog-json
+ fog-xml
+ google-api-client (~> 0.19.1)
+ fog-json (1.0.2)
+ fog-core (~> 1.0)
+ multi_json (~> 1.10)
+ fog-local (0.5.0)
+ fog-core (>= 1.27, < 3.0)
+ fog-openstack (0.1.24)
+ fog-core (~> 1.40)
+ fog-json (>= 1.0)
+ ipaddress (>= 0.8)
+ fog-rackspace (0.1.5)
+ fog-core (>= 1.35)
+ fog-json (>= 1.0)
+ fog-xml (>= 0.1)
+ ipaddress (>= 0.8)
+ fog-xml (0.1.3)
+ fog-core
+ nokogiri (>= 1.5.11, < 2.0.0)
+ font-awesome-rails (4.7.0.3)
+ railties (>= 3.2, < 5.2)
+ foreman (0.84.0)
+ thor (~> 0.19.1)
+ formatador (0.2.5)
+ fuubar (2.2.0)
+ rspec-core (~> 3.0)
+ ruby-progressbar (~> 1.4)
+ gemnasium-gitlab-service (0.2.6)
+ rugged (~> 0.21)
+ gemojione (3.3.0)
+ json
+ get_process_mem (0.2.1)
+ gettext (3.2.9)
+ locale (>= 2.0.5)
+ text (>= 1.3.0)
+ gettext_i18n_rails (1.8.0)
+ fast_gettext (>= 0.9.0)
+ gettext_i18n_rails_js (1.3.0)
+ gettext (>= 3.0.2)
+ gettext_i18n_rails (>= 0.7.1)
+ po_to_json (>= 1.0.0)
+ rails (>= 3.2.0)
+ gherkin-ruby (0.3.2)
+ gitaly-proto (0.94.0)
+ google-protobuf (~> 3.1)
+ grpc (~> 1.0)
+ github-linguist (5.3.3)
+ charlock_holmes (~> 0.7.5)
+ escape_utils (~> 1.1.0)
+ mime-types (>= 1.19)
+ rugged (>= 0.25.1)
+ github-markup (1.7.0)
+ gitlab-flowdock-git-hook (1.0.1)
+ flowdock (~> 0.7)
+ gitlab-grit (>= 2.4.1)
+ multi_json
+ gitlab-grit (2.8.2)
+ charlock_holmes (~> 0.6)
+ diff-lcs (~> 1.1)
+ mime-types (>= 1.16)
+ posix-spawn (~> 0.3)
+ gitlab-markup (1.6.3)
+ gitlab-styles (2.3.2)
+ rubocop (~> 0.51)
+ rubocop-gitlab-security (~> 0.1.0)
+ rubocop-rspec (~> 1.19)
+ gitlab_omniauth-ldap (2.0.4)
+ net-ldap (~> 0.16)
+ omniauth (~> 1.3)
+ pyu-ruby-sasl (>= 0.0.3.3, < 0.1)
+ rubyntlm (~> 0.5)
+ globalid (0.4.1)
+ activesupport (>= 4.2.0)
+ gollum-grit_adapter (1.0.1)
+ gitlab-grit (~> 2.7, >= 2.7.1)
+ gollum-lib (4.2.7)
+ gemojione (~> 3.2)
+ github-markup (~> 1.6)
+ gollum-grit_adapter (~> 1.0)
+ nokogiri (>= 1.6.1, < 2.0)
+ rouge (~> 2.1)
+ sanitize (~> 2.1)
+ stringex (~> 2.6)
+ gollum-rugged_adapter (0.4.4)
+ mime-types (>= 1.15)
+ rugged (~> 0.25)
+ gon (6.1.0)
+ actionpack (>= 3.0)
+ json
+ multi_json
+ request_store (>= 1.0)
+ google-api-client (0.19.8)
+ addressable (~> 2.5, >= 2.5.1)
+ googleauth (>= 0.5, < 0.7.0)
+ httpclient (>= 2.8.1, < 3.0)
+ mime-types (~> 3.0)
+ representable (~> 3.0)
+ retriable (>= 2.0, < 4.0)
+ google-protobuf (3.5.1)
+ googleapis-common-protos-types (1.0.1)
+ google-protobuf (~> 3.0)
+ googleauth (0.6.2)
+ faraday (~> 0.12)
+ jwt (>= 1.4, < 3.0)
+ logging (~> 2.0)
+ memoist (~> 0.12)
+ multi_json (~> 1.11)
+ os (~> 0.9)
+ signet (~> 0.7)
+ gpgme (2.0.16)
+ mini_portile2 (~> 2.3)
+ grape (1.0.2)
+ activesupport
+ builder
+ mustermann-grape (~> 1.0.0)
+ rack (>= 1.3.0)
+ rack-accept
+ virtus (>= 1.0.0)
+ grape-entity (0.6.1)
+ activesupport (>= 5.0.0)
+ multi_json (>= 1.3.2)
+ grape-route-helpers (2.1.0)
+ activesupport
+ grape (>= 0.16.0)
+ rake
+ grape_logging (1.7.0)
+ grape
+ grpc (1.10.0)
+ google-protobuf (~> 3.1)
+ googleapis-common-protos-types (~> 1.0.0)
+ googleauth (>= 0.5.1, < 0.7)
+ haml (4.0.7)
+ tilt
+ haml_lint (0.26.0)
+ haml (>= 4.0, < 5.1)
+ rainbow
+ rake (>= 10, < 13)
+ rubocop (>= 0.49.0)
+ sysexits (~> 1.1)
+ hamlit (2.6.2)
+ temple (~> 0.7.6)
+ thor
+ tilt
+ hashdiff (0.3.7)
+ hashie (3.5.7)
+ hashie-forbidden_attributes (0.1.1)
+ hashie (>= 3.0)
+ health_check (2.6.0)
+ rails (>= 4.0)
+ hipchat (1.5.4)
+ httparty
+ mimemagic
+ html-pipeline (2.7.1)
+ activesupport (>= 2)
+ nokogiri (>= 1.4)
+ html2text (0.2.1)
+ nokogiri (~> 1.6)
+ htmlentities (4.3.4)
+ http (2.2.2)
+ addressable (~> 2.3)
+ http-cookie (~> 1.0)
+ http-form_data (~> 1.0.1)
+ http_parser.rb (~> 0.6.0)
+ http-cookie (1.0.3)
+ domain_name (~> 0.5)
+ http-form_data (1.0.3)
+ http_parser.rb (0.6.0)
+ httparty (0.13.7)
+ json (~> 1.8)
+ multi_xml (>= 0.5.2)
+ httpclient (2.8.3)
+ i18n (0.9.5)
+ concurrent-ruby (~> 1.0)
+ ice_nine (0.11.2)
+ influxdb (0.5.3)
+ ipaddress (0.8.3)
+ jira-ruby (1.5.0)
+ activesupport
+ multipart-post
+ oauth (~> 0.5, >= 0.5.0)
+ jquery-atwho-rails (1.3.2)
+ json (1.8.6)
+ json-jwt (1.9.2)
+ activesupport
+ aes_key_wrap
+ bindata
+ securecompare
+ url_safe_base64
+ json-schema (2.8.0)
+ addressable (>= 2.4)
+ jwt (1.5.6)
+ kaminari (1.1.1)
+ activesupport (>= 4.1.0)
+ kaminari-actionview (= 1.1.1)
+ kaminari-activerecord (= 1.1.1)
+ kaminari-core (= 1.1.1)
+ kaminari-actionview (1.1.1)
+ actionview
+ kaminari-core (= 1.1.1)
+ kaminari-activerecord (1.1.1)
+ activerecord
+ kaminari-core (= 1.1.1)
+ kaminari-core (1.1.1)
+ kgio (2.11.2)
+ knapsack (1.16.0)
+ rake
+ kubeclient (3.0.0)
+ http (~> 2.2.2)
+ recursive-open-struct (~> 1.0.4)
+ rest-client (~> 2.0)
+ launchy (2.4.3)
+ addressable (~> 2.3)
+ letter_opener (1.6.0)
+ launchy (~> 2.2)
+ letter_opener_web (1.3.3)
+ actionmailer (>= 3.2)
+ letter_opener (~> 1.0)
+ railties (>= 3.2)
+ license_finder (3.1.1)
+ bundler
+ httparty
+ rubyzip
+ thor
+ toml (= 0.1.2)
+ with_env (> 1.0)
+ xml-simple
+ licensee (8.9.2)
+ rugged (~> 0.24)
+ little-plugger (1.1.4)
+ locale (2.1.2)
+ logging (2.2.2)
+ little-plugger (~> 1.1)
+ multi_json (~> 1.10)
+ lograge (0.9.0)
+ actionpack (>= 4)
+ activesupport (>= 4)
+ railties (>= 4)
+ request_store (~> 1.0)
+ loofah (2.2.2)
+ crass (~> 1.0.2)
+ nokogiri (>= 1.5.9)
+ mail (2.7.0)
+ mini_mime (>= 0.1.1)
+ mail_room (0.9.1)
+ memoist (0.16.0)
+ memoizable (0.4.2)
+ thread_safe (~> 0.3, >= 0.3.1)
+ method_source (0.9.0)
+ mime-types (3.1)
+ mime-types-data (~> 3.2015)
+ mime-types-data (3.2016.0521)
+ mimemagic (0.3.2)
+ mini_mime (1.0.0)
+ mini_portile2 (2.3.0)
+ minitest (5.7.0)
+ mousetrap-rails (1.4.6)
+ multi_json (1.13.1)
+ multi_xml (0.6.0)
+ multipart-post (2.0.0)
+ mustermann (1.0.2)
+ mustermann-grape (1.0.0)
+ mustermann (~> 1.0.0)
+ mysql2 (0.4.10)
+ net-ldap (0.16.1)
+ net-ssh (4.2.0)
+ netrc (0.11.0)
+ nio4r (2.2.0)
+ nokogiri (1.8.2)
+ mini_portile2 (~> 2.3.0)
+ numerizer (0.1.1)
+ oauth (0.5.4)
+ oauth2 (1.4.0)
+ faraday (>= 0.8, < 0.13)
+ jwt (~> 1.0)
+ multi_json (~> 1.3)
+ multi_xml (~> 0.5)
+ rack (>= 1.2, < 3)
+ octokit (4.8.0)
+ sawyer (~> 0.8.0, >= 0.5.3)
+ omniauth (1.8.1)
+ hashie (>= 3.4.6, < 3.6.0)
+ rack (>= 1.6.2, < 3)
+ omniauth-auth0 (2.0.0)
+ omniauth-oauth2 (~> 1.4)
+ omniauth-authentiq (0.3.1)
+ omniauth-oauth2 (~> 1.3, >= 1.3.1)
+ omniauth-azure-oauth2 (0.0.9)
+ jwt (~> 1.0)
+ omniauth (~> 1.0)
+ omniauth-oauth2 (~> 1.4)
+ omniauth-cas3 (1.1.4)
+ addressable (~> 2.3)
+ nokogiri (~> 1.7, >= 1.7.1)
+ omniauth (~> 1.2)
+ omniauth-facebook (4.0.0)
+ omniauth-oauth2 (~> 1.2)
+ omniauth-github (1.1.2)
+ omniauth (~> 1.0)
+ omniauth-oauth2 (~> 1.1)
+ omniauth-gitlab (1.0.3)
+ omniauth (~> 1.0)
+ omniauth-oauth2 (~> 1.0)
+ omniauth-google-oauth2 (0.5.3)
+ jwt (>= 1.5)
+ omniauth (>= 1.1.1)
+ omniauth-oauth2 (>= 1.5)
+ omniauth-jwt (0.0.2)
+ jwt
+ omniauth (~> 1.1)
+ omniauth-kerberos (0.3.0)
+ omniauth-multipassword
+ timfel-krb5-auth (~> 0.8)
+ omniauth-multipassword (0.4.2)
+ omniauth (~> 1.0)
+ omniauth-oauth (1.1.0)
+ oauth
+ omniauth (~> 1.0)
+ omniauth-oauth2 (1.5.0)
+ oauth2 (~> 1.1)
+ omniauth (~> 1.2)
+ omniauth-oauth2-generic (0.2.4)
+ omniauth-oauth2 (~> 1.0)
+ omniauth-saml (1.10.0)
+ omniauth (~> 1.3, >= 1.3.2)
+ ruby-saml (~> 1.7)
+ omniauth-shibboleth (1.2.1)
+ omniauth (>= 1.0.0)
+ omniauth-twitter (1.4.0)
+ omniauth-oauth (~> 1.1)
+ rack
+ omniauth_crowd (2.2.3)
+ activesupport
+ nokogiri (>= 1.4.4)
+ omniauth (~> 1.0)
+ org-ruby (0.9.12)
+ rubypants (~> 0.2)
+ orm_adapter (0.5.0)
+ os (0.9.6)
+ parallel (1.12.1)
+ parser (2.5.0.5)
+ ast (~> 2.4.0)
+ parslet (1.5.0)
+ blankslate (~> 2.0)
+ path_expander (1.0.2)
+ peek (1.0.1)
+ concurrent-ruby (>= 0.9.0)
+ concurrent-ruby-ext (>= 0.9.0)
+ railties (>= 4.0.0)
+ peek-gc (0.0.2)
+ peek
+ peek-mysql2 (1.1.0)
+ atomic (>= 1.0.0)
+ mysql2
+ peek
+ peek-performance_bar (1.3.1)
+ peek (>= 0.1.0)
+ peek-pg (1.3.0)
+ concurrent-ruby
+ concurrent-ruby-ext
+ peek
+ pg
+ peek-rblineprof (0.2.0)
+ peek
+ rblineprof
+ peek-redis (1.2.0)
+ atomic (>= 1.0.0)
+ peek
+ redis
+ peek-sidekiq (1.0.3)
+ atomic (>= 1.0.0)
+ peek
+ sidekiq
+ pg (0.18.4)
+ po_to_json (1.0.1)
+ json (>= 1.6.0)
+ posix-spawn (0.3.13)
+ powerpack (0.1.1)
+ premailer (1.11.1)
+ addressable
+ css_parser (>= 1.6.0)
+ htmlentities (>= 4.0.0)
+ premailer-rails (1.9.7)
+ actionmailer (>= 3, < 6)
+ premailer (~> 1.7, >= 1.7.9)
+ proc_to_ast (0.1.0)
+ coderay
+ parser
+ unparser
+ procto (0.0.3)
+ prometheus-client-mmap (0.9.1)
+ pry (0.11.3)
+ coderay (~> 1.1.0)
+ method_source (~> 0.9.0)
+ pry-byebug (3.4.3)
+ byebug (>= 9.0, < 9.1)
+ pry (~> 0.10)
+ pry-rails (0.3.6)
+ pry (>= 0.10.4)
+ public_suffix (3.0.2)
+ pyu-ruby-sasl (0.0.3.3)
+ rack (2.0.4)
+ rack-accept (0.4.5)
+ rack (>= 0.4)
+ rack-attack (4.4.1)
+ rack
+ rack-cors (1.0.2)
+ rack-oauth2 (1.2.3)
+ activesupport (>= 2.3)
+ attr_required (>= 0.0.5)
+ httpclient (>= 2.4)
+ multi_json (>= 1.3.6)
+ rack (>= 1.1)
+ rack-protection (2.0.1)
+ rack
+ rack-proxy (0.6.4)
+ rack
+ rack-test (0.6.3)
+ rack (>= 1.0)
+ rails (5.0.6)
+ actioncable (= 5.0.6)
+ actionmailer (= 5.0.6)
+ actionpack (= 5.0.6)
+ actionview (= 5.0.6)
+ activejob (= 5.0.6)
+ activemodel (= 5.0.6)
+ activerecord (= 5.0.6)
+ activesupport (= 5.0.6)
+ bundler (>= 1.3.0)
+ railties (= 5.0.6)
+ sprockets-rails (>= 2.0.0)
+ rails-deprecated_sanitizer (1.0.3)
+ activesupport (>= 4.2.0.alpha)
+ rails-dom-testing (2.0.3)
+ activesupport (>= 4.2.0)
+ nokogiri (>= 1.6)
+ rails-html-sanitizer (1.0.3)
+ loofah (~> 2.0)
+ rails-i18n (5.1.1)
+ i18n (>= 0.7, < 2)
+ railties (>= 5.0, < 6)
+ railties (5.0.6)
+ actionpack (= 5.0.6)
+ activesupport (= 5.0.6)
+ method_source
+ rake (>= 0.8.7)
+ thor (>= 0.18.1, < 2.0)
+ rainbow (2.2.2)
+ rake
+ raindrops (0.19.0)
+ rake (12.3.0)
+ rb-fsevent (0.10.3)
+ rb-inotify (0.9.10)
+ ffi (>= 0.5.0, < 2)
+ rblineprof (0.3.7)
+ debugger-ruby_core_source (~> 1.3)
+ rbnacl (4.0.2)
+ ffi
+ rbnacl-libsodium (1.0.16)
+ rbnacl (>= 3.0.1)
+ rdoc (4.3.0)
+ re2 (1.1.1)
+ recaptcha (3.4.0)
+ json
+ recursive-open-struct (1.0.5)
+ redcarpet (3.4.0)
+ redis (3.3.5)
+ redis-actionpack (5.0.2)
+ actionpack (>= 4.0, < 6)
+ redis-rack (>= 1, < 3)
+ redis-store (>= 1.1.0, < 2)
+ redis-activesupport (5.0.4)
+ activesupport (>= 3, < 6)
+ redis-store (>= 1.3, < 2)
+ redis-namespace (1.5.3)
+ redis (~> 3.0, >= 3.0.4)
+ redis-rack (2.0.4)
+ rack (>= 1.5, < 3)
+ redis-store (>= 1.2, < 2)
+ redis-rails (5.0.2)
+ redis-actionpack (>= 5.0, < 6)
+ redis-activesupport (>= 5.0, < 6)
+ redis-store (>= 1.2, < 2)
+ redis-store (1.4.1)
+ redis (>= 2.2, < 5)
+ representable (3.0.4)
+ declarative (< 0.1.0)
+ declarative-option (< 0.2.0)
+ uber (< 0.2.0)
+ request_store (1.4.0)
+ rack (>= 1.4)
+ responders (2.4.0)
+ actionpack (>= 4.2.0, < 5.3)
+ railties (>= 4.2.0, < 5.3)
+ rest-client (2.0.2)
+ http-cookie (>= 1.0.2, < 2.0)
+ mime-types (>= 1.16, < 4.0)
+ netrc (~> 0.8)
+ retriable (3.1.1)
+ rinku (2.0.4)
+ rotp (2.1.2)
+ rouge (2.2.1)
+ rqrcode (0.10.1)
+ chunky_png (~> 1.0)
+ rqrcode-rails3 (0.1.7)
+ rqrcode (>= 0.4.2)
+ rspec (3.6.0)
+ rspec-core (~> 3.6.0)
+ rspec-expectations (~> 3.6.0)
+ rspec-mocks (~> 3.6.0)
+ rspec-core (3.6.0)
+ rspec-support (~> 3.6.0)
+ rspec-expectations (3.6.0)
+ diff-lcs (>= 1.2.0, < 2.0)
+ rspec-support (~> 3.6.0)
+ rspec-mocks (3.6.0)
+ diff-lcs (>= 1.2.0, < 2.0)
+ rspec-support (~> 3.6.0)
+ rspec-parameterized (0.4.0)
+ binding_of_caller
+ parser
+ proc_to_ast
+ rspec (>= 2.13, < 4)
+ unparser
+ rspec-rails (3.6.1)
+ actionpack (>= 3.0)
+ activesupport (>= 3.0)
+ railties (>= 3.0)
+ rspec-core (~> 3.6.0)
+ rspec-expectations (~> 3.6.0)
+ rspec-mocks (~> 3.6.0)
+ rspec-support (~> 3.6.0)
+ rspec-retry (0.4.6)
+ rspec-core
+ rspec-set (0.1.3)
+ rspec-support (3.6.0)
+ rspec_profiling (0.0.5)
+ activerecord
+ pg
+ rails
+ sqlite3
+ rubocop (0.52.1)
+ parallel (~> 1.10)
+ parser (>= 2.4.0.2, < 3.0)
+ powerpack (~> 0.1)
+ rainbow (>= 2.2.2, < 4.0)
+ ruby-progressbar (~> 1.7)
+ unicode-display_width (~> 1.0, >= 1.0.1)
+ rubocop-gitlab-security (0.1.1)
+ rubocop (>= 0.51)
+ rubocop-rspec (1.22.2)
+ rubocop (>= 0.52.1)
+ ruby-enum (0.7.2)
+ i18n
+ ruby-fogbugz (0.2.1)
+ crack (~> 0.4)
+ ruby-prof (0.17.0)
+ ruby-progressbar (1.9.0)
+ ruby-saml (1.7.2)
+ nokogiri (>= 1.5.10)
+ ruby_parser (3.11.0)
+ sexp_processor (~> 4.9)
+ rubyntlm (0.6.2)
+ rubypants (0.7.0)
+ rubyzip (1.2.1)
+ rufus-scheduler (3.4.2)
+ et-orbi (~> 1.0)
+ rugged (0.27.0)
+ safe_yaml (1.0.4)
+ sanitize (2.1.0)
+ nokogiri (>= 1.4.4)
+ sass (3.5.5)
+ sass-listen (~> 4.0.0)
+ sass-listen (4.0.0)
+ rb-fsevent (~> 0.9, >= 0.9.4)
+ rb-inotify (~> 0.9, >= 0.9.7)
+ sass-rails (5.0.7)
+ railties (>= 4.0.0, < 6)
+ sass (~> 3.1)
+ sprockets (>= 2.8, < 4.0)
+ sprockets-rails (>= 2.0, < 4.0)
+ tilt (>= 1.1, < 3)
+ sawyer (0.8.1)
+ addressable (>= 2.3.5, < 2.6)
+ faraday (~> 0.8, < 1.0)
+ scss_lint (0.56.0)
+ rake (>= 0.9, < 13)
+ sass (~> 3.5.3)
+ securecompare (1.0.0)
+ seed-fu (2.3.7)
+ activerecord (>= 3.1)
+ activesupport (>= 3.1)
+ select2-rails (3.5.10)
+ thor (~> 0.14)
+ selenium-webdriver (3.11.0)
+ childprocess (~> 0.5)
+ rubyzip (~> 1.2)
+ sentry-raven (2.7.2)
+ faraday (>= 0.7.6, < 1.0)
+ settingslogic (2.0.9)
+ sexp_processor (4.10.1)
+ sham_rack (1.3.6)
+ rack
+ shoulda-matchers (3.1.2)
+ activesupport (>= 4.0.0)
+ sidekiq (5.1.1)
+ concurrent-ruby (~> 1.0)
+ connection_pool (~> 2.2, >= 2.2.0)
+ rack-protection (>= 1.5.0)
+ redis (>= 3.3.5, < 5)
+ sidekiq-cron (0.6.3)
+ rufus-scheduler (>= 3.3.0)
+ sidekiq (>= 4.2.1)
+ sidekiq-limit_fetch (3.4.0)
+ sidekiq (>= 4)
+ signet (0.8.1)
+ addressable (~> 2.3)
+ faraday (~> 0.9)
+ jwt (>= 1.5, < 3.0)
+ multi_json (~> 1.10)
+ simple_po_parser (1.1.3)
+ simplecov (0.14.1)
+ docile (~> 1.1.0)
+ json (>= 1.8, < 3)
+ simplecov-html (~> 0.10.0)
+ simplecov-html (0.10.2)
+ slack-notifier (1.5.1)
+ spinach (0.10.1)
+ colorize
+ gherkin-ruby (>= 0.3.2)
+ json
+ spinach-rails (0.2.1)
+ capybara (>= 2.0.0)
+ railties (>= 3)
+ spinach (>= 0.4)
+ spinach-rerun-reporter (0.0.2)
+ spinach (~> 0.8)
+ spring (2.0.2)
+ activesupport (>= 4.2)
+ spring-commands-rspec (1.0.4)
+ spring (>= 0.9.1)
+ spring-commands-spinach (1.1.0)
+ spring (>= 0.9.1)
+ sprockets (3.7.1)
+ concurrent-ruby (~> 1.0)
+ rack (> 1, < 3)
+ sprockets-rails (3.2.1)
+ actionpack (>= 4.0)
+ activesupport (>= 4.0)
+ sprockets (>= 3.0.0)
+ sqlite3 (1.3.13)
+ sshkey (1.9.0)
+ stackprof (0.2.11)
+ state_machines (0.5.0)
+ state_machines-activemodel (0.5.1)
+ activemodel (>= 4.1, < 6.0)
+ state_machines (>= 0.5.0)
+ state_machines-activerecord (0.5.1)
+ activerecord (>= 4.1, < 6.0)
+ state_machines-activemodel (>= 0.5.0)
+ stringex (2.8.4)
+ sys-filesystem (1.1.9)
+ ffi
+ sysexits (1.2.0)
+ temple (0.7.7)
+ test-prof (0.2.5)
+ text (1.3.1)
+ thin (1.7.2)
+ daemons (~> 1.0, >= 1.0.9)
+ eventmachine (~> 1.0, >= 1.0.4)
+ rack (>= 1, < 3)
+ thor (0.19.4)
+ thread_safe (0.3.6)
+ tilt (2.0.8)
+ timecop (0.8.1)
+ timfel-krb5-auth (0.8.3)
+ toml (0.1.2)
+ parslet (~> 1.5.0)
+ toml-rb (1.0.0)
+ citrus (~> 3.0, > 3.0)
+ truncato (0.7.10)
+ htmlentities (~> 4.3.1)
+ nokogiri (~> 1.8.0, >= 1.7.0)
+ tzinfo (1.2.5)
+ thread_safe (~> 0.1)
+ u2f (0.2.1)
+ uber (0.1.0)
+ uglifier (2.7.2)
+ execjs (>= 0.3.0)
+ json (>= 1.8.0)
+ unf (0.1.4)
+ unf_ext
+ unf_ext (0.0.7.5)
+ unicode-display_width (1.3.0)
+ unicorn (5.1.0)
+ kgio (~> 2.6)
+ raindrops (~> 0.7)
+ unicorn-worker-killer (0.4.4)
+ get_process_mem (~> 0)
+ unicorn (>= 4, < 6)
+ uniform_notifier (1.10.0)
+ unparser (0.2.7)
+ abstract_type (~> 0.0.7)
+ adamantium (~> 0.2.0)
+ concord (~> 0.1.5)
+ diff-lcs (~> 1.3)
+ equalizer (~> 0.0.9)
+ parser (>= 2.3.1.2, < 2.6)
+ procto (~> 0.0.2)
+ url_safe_base64 (0.2.2)
+ validates_hostname (1.0.8)
+ activerecord (>= 3.0)
+ activesupport (>= 3.0)
+ version_sorter (2.1.0)
+ virtus (1.0.5)
+ axiom-types (~> 0.1)
+ coercible (~> 1.0)
+ descendants_tracker (~> 0.0, >= 0.0.3)
+ equalizer (~> 0.0, >= 0.0.9)
+ vmstat (2.3.0)
+ warden (1.2.7)
+ rack (>= 1.0)
+ webmock (2.3.2)
+ addressable (>= 2.3.6)
+ crack (>= 0.3.2)
+ hashdiff
+ webpack-rails (0.9.11)
+ railties (>= 3.2.0)
+ websocket-driver (0.6.5)
+ websocket-extensions (>= 0.1.0)
+ websocket-extensions (0.1.3)
+ wikicloth (0.8.1)
+ builder
+ expression_parser
+ rinku
+ with_env (1.1.0)
+ xml-simple (1.1.5)
+ xpath (3.0.0)
+ nokogiri (~> 1.8)
+
+PLATFORMS
+ ruby
+
+DEPENDENCIES
+ RedCloth (~> 4.3.2)
+ ace-rails-ap (~> 4.1.0)
+ activerecord_sane_schema_dumper (= 1.0)
+ acts-as-taggable-on (~> 5.0)
+ addressable (~> 2.5.2)
+ akismet (~> 2.0)
+ allocations (~> 1.0)
+ asana (~> 0.6.0)
+ asciidoctor (~> 1.5.6)
+ asciidoctor-plantuml (= 0.0.8)
+ asset_sync (~> 2.2.0)
+ attr_encrypted (~> 3.0.0)
+ awesome_print (~> 1.2.0)
+ babosa (~> 1.0.2)
+ base32 (~> 0.3.0)
+ batch-loader (~> 1.2.1)
+ bcrypt_pbkdf (~> 1.0)
+ benchmark-ips (~> 2.3.0)
+ better_errors (~> 2.1.0)
+ binding_of_caller (~> 0.7.2)
+ bootstrap-sass (~> 3.3.0)
+ bootstrap_form (~> 2.7.0)
+ brakeman (~> 4.2)
+ browser (~> 2.2)
+ bullet (~> 5.5.0)
+ bundler-audit (~> 0.5.0)
+ capybara (~> 2.15)
+ capybara-screenshot (~> 1.0.0)
+ carrierwave (~> 1.2)
+ charlock_holmes (~> 0.7.5)
+ chronic (~> 0.10.2)
+ chronic_duration (~> 0.10.6)
+ commonmarker (~> 0.17)
+ concurrent-ruby (~> 1.0.5)
+ connection_pool (~> 2.0)
+ creole (~> 0.5.0)
+ d3_rails (~> 3.5.0)
+ database_cleaner (~> 1.5.0)
+ deckar01-task_list (= 2.0.0)
+ default_value_for (~> 3.0.5)
+ devise (~> 4.2)
+ devise-two-factor (~> 3.0.0)
+ diffy (~> 3.1.0)
+ doorkeeper (~> 4.3)
+ doorkeeper-openid_connect (~> 1.3)
+ dropzonejs-rails (~> 0.7.1)
+ email_reply_trimmer (~> 0.1)
+ email_spec (~> 1.6.0)
+ factory_bot_rails (~> 4.8.2)
+ faraday (~> 0.12)
+ fast_blank
+ ffaker (~> 2.4)
+ flay (~> 2.10.0)
+ flipper (~> 0.13.0)
+ flipper-active_record (~> 0.13.0)
+ flipper-active_support_cache_store (~> 0.13.0)
+ fog-aliyun (~> 0.2.0)
+ fog-aws (~> 2.0.1)
+ fog-core (~> 1.44)
+ fog-google (~> 1.3.3)
+ fog-local (~> 0.3)
+ fog-openstack (~> 0.1)
+ fog-rackspace (~> 0.1.1)
+ font-awesome-rails (~> 4.7)
+ foreman (~> 0.84.0)
+ fuubar (~> 2.2.0)
+ gemnasium-gitlab-service (~> 0.2)
+ gemojione (~> 3.3)
+ gettext (~> 3.2.2)
+ gettext_i18n_rails (~> 1.8.0)
+ gettext_i18n_rails_js (~> 1.3)
+ gitaly-proto (~> 0.94.0)
+ github-linguist (~> 5.3.3)
+ gitlab-flowdock-git-hook (~> 1.0.1)
+ gitlab-markup (~> 1.6.2)
+ gitlab-styles (~> 2.3)
+ gitlab_omniauth-ldap (~> 2.0.4)
+ gollum-lib (~> 4.2)
+ gollum-rugged_adapter (~> 0.4.4)
+ gon (~> 6.1.0)
+ google-api-client (~> 0.19.8)
+ google-protobuf (= 3.5.1)
+ gpgme
+ grape (~> 1.0)
+ grape-entity (~> 0.6.0)
+ grape-route-helpers (~> 2.1.0)
+ grape_logging (~> 1.7)
+ grpc (~> 1.10.0)
+ haml_lint (~> 0.26.0)
+ hamlit (~> 2.6.1)
+ hashie-forbidden_attributes
+ health_check (~> 2.6.0)
+ hipchat (~> 1.5.0)
+ html-pipeline (~> 2.7.1)
+ html2text
+ httparty (~> 0.13.3)
+ influxdb (~> 0.2)
+ jira-ruby (~> 1.4)
+ jquery-atwho-rails (~> 1.3.2)
+ json-schema (~> 2.8.0)
+ jwt (~> 1.5.6)
+ kaminari (~> 1.0)
+ knapsack (~> 1.16)
+ kubeclient (~> 3.0)
+ letter_opener_web (~> 1.3.0)
+ license_finder (~> 3.1)
+ licensee (~> 8.9)
+ lograge (~> 0.5)
+ loofah (~> 2.2)
+ mail_room (~> 0.9.1)
+ method_source (~> 0.8)
+ minitest (~> 5.7.0)
+ mousetrap-rails (~> 1.4.6)
+ mysql2 (~> 0.4.10)
+ net-ldap
+ net-ssh (~> 4.2.0)
+ nokogiri (~> 1.8.2)
+ oauth2 (~> 1.4)
+ octokit (~> 4.8)
+ omniauth (~> 1.8)
+ omniauth-auth0 (~> 2.0.0)
+ omniauth-authentiq (~> 0.3.1)
+ omniauth-azure-oauth2 (~> 0.0.9)
+ omniauth-cas3 (~> 1.1.4)
+ omniauth-facebook (~> 4.0.0)
+ omniauth-github (~> 1.1.1)
+ omniauth-gitlab (~> 1.0.2)
+ omniauth-google-oauth2 (~> 0.5.3)
+ omniauth-jwt (~> 0.0.2)
+ omniauth-kerberos (~> 0.3.0)
+ omniauth-oauth2-generic (~> 0.2.2)
+ omniauth-saml (~> 1.10)
+ omniauth-shibboleth (~> 1.2.0)
+ omniauth-twitter (~> 1.4)
+ omniauth_crowd (~> 2.2.0)
+ org-ruby (~> 0.9.12)
+ peek (~> 1.0.1)
+ peek-gc (~> 0.0.2)
+ peek-mysql2 (~> 1.1.0)
+ peek-performance_bar (~> 1.3.0)
+ peek-pg (~> 1.3.0)
+ peek-rblineprof (~> 0.2.0)
+ peek-redis (~> 1.2.0)
+ peek-sidekiq (~> 1.0.3)
+ pg (~> 0.18.2)
+ premailer-rails (~> 1.9.7)
+ prometheus-client-mmap (~> 0.9.1)
+ pry-byebug (~> 3.4.1)
+ pry-rails (~> 0.3.4)
+ rack-attack (~> 4.4.1)
+ rack-cors (~> 1.0.0)
+ rack-oauth2 (~> 1.2.1)
+ rack-proxy (~> 0.6.0)
+ rails (= 5.0.6)
+ rails-deprecated_sanitizer (~> 1.0.3)
+ rails-i18n (~> 5.1)
+ rainbow (~> 2.2)
+ raindrops (~> 0.18)
+ rblineprof (~> 0.3.6)
+ rbnacl (~> 4.0)
+ rbnacl-libsodium
+ rdoc (~> 4.2)
+ re2 (~> 1.1.1)
+ recaptcha (~> 3.0)
+ redcarpet (~> 3.4)
+ redis (~> 3.2)
+ redis-namespace (~> 1.5.2)
+ redis-rails (~> 5.0.2)
+ request_store (~> 1.3)
+ responders (~> 2.0)
+ rouge (~> 2.0)
+ rqrcode-rails3 (~> 0.1.7)
+ rspec-parameterized
+ rspec-rails (~> 3.6.0)
+ rspec-retry (~> 0.4.5)
+ rspec-set (~> 0.1.3)
+ rspec_profiling (~> 0.0.5)
+ rubocop (~> 0.52.1)
+ rubocop-rspec (~> 1.22.1)
+ ruby-fogbugz (~> 0.2.1)
+ ruby-prof (~> 0.17.0)
+ ruby_parser (~> 3.8)
+ rufus-scheduler (~> 3.4)
+ rugged (~> 0.27)
+ sanitize (~> 2.0)
+ sass-rails (~> 5.0.6)
+ scss_lint (~> 0.56.0)
+ seed-fu (~> 2.3.7)
+ select2-rails (~> 3.5.9)
+ selenium-webdriver (~> 3.5)
+ sentry-raven (~> 2.7)
+ settingslogic (~> 2.0.9)
+ sham_rack (~> 1.3.6)
+ shoulda-matchers (~> 3.1.2)
+ sidekiq (~> 5.0)
+ sidekiq-cron (~> 0.6.0)
+ sidekiq-limit_fetch (~> 3.4)
+ simple_po_parser (~> 1.1.2)
+ simplecov (~> 0.14.0)
+ slack-notifier (~> 1.5.1)
+ spinach-rails (~> 0.2.1)
+ spinach-rerun-reporter (~> 0.0.2)
+ spring (~> 2.0.0)
+ spring-commands-rspec (~> 1.0.4)
+ spring-commands-spinach (~> 1.1.0)
+ sprockets (~> 3.7.0)
+ sshkey (~> 1.9.0)
+ stackprof (~> 0.2.10)
+ state_machines-activerecord (~> 0.5.1)
+ sys-filesystem (~> 1.1.6)
+ test-prof (~> 0.2.5)
+ thin (~> 1.7.0)
+ timecop (~> 0.8.0)
+ toml-rb (~> 1.0.0)
+ truncato (~> 0.7.9)
+ u2f (~> 0.2.1)
+ uglifier (~> 2.7.2)
+ unf (~> 0.1.4)
+ unicorn (~> 5.1.0)
+ unicorn-worker-killer (~> 0.4.4)
+ validates_hostname (~> 1.0.6)
+ version_sorter (~> 2.1.0)
+ virtus (~> 1.0.1)
+ vmstat (~> 2.3.0)
+ webmock (~> 2.3.2)
+ webpack-rails (~> 0.9.10)
+ wikicloth (= 0.8.1)
+
+BUNDLED WITH
+ 1.16.1
diff --git a/PROCESS.md b/PROCESS.md
index 5ae191840f..f206506f7c 100644
--- a/PROCESS.md
+++ b/PROCESS.md
@@ -53,7 +53,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/jobs/merge-request-coach/.
+What you can expect from them is described at https://about.gitlab.com/roles/merge-request-coach/.
## Assigning issues
@@ -202,6 +202,9 @@ you can ask for an exception to be made.
Go to [Release tasks issue tracker](https://gitlab.com/gitlab-org/release/tasks/issues/new) and create an issue
using the `Exception-request` issue template.
+**Do not** set the relevant `Pick into X.Y` label (see above) before request an
+exception; this should be done after the exception is approved.
+
You can find who is who on the [team page](https://about.gitlab.com/team/).
Whether an exception is made is determined by weighing the benefit and urgency of the change
diff --git a/Procfile b/Procfile
index cad738d429..1776fd9794 100644
--- a/Procfile
+++ b/Procfile
@@ -4,4 +4,3 @@
#
web: RAILS_ENV=development bin/web start_foreground
worker: RAILS_ENV=development bin/background_jobs start_foreground
-# mail_room: bundle exec mail_room -q -c config/mail_room.yml
diff --git a/VERSION b/VERSION
index cac93e55f5..992a0120b2 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-10.6.5
+10.7.3
diff --git a/app/assets/images/ci_favicons/canary/favicon_status_canceled.ico b/app/assets/images/ci_favicons/canary/favicon_status_canceled.ico
new file mode 100644
index 0000000000000000000000000000000000000000..48b1095370d446df1f3107565b1c5e72c0128c7d
GIT binary patch
literal 4286
zcmb`Je@t6d6vrQ##y>GJ(Fmo`Qu@ju;IbISe}L%7Lgt_Rq5g%2Kb9B-GvfLK)++N4
zl`M);853LW{^<}q-Jr_ZO)dyzT^2mc1
zd(Zitd(Qn)LCE93k`e*`g|8kLgeL_-aItWgP{)FPrSRBJm!_tsUFGHFjZUYt&*gH>
zar>4iiZQN3T#s}A+Z7cR)}7|U9`g<`;~F!lva&MS+}uoFua~;JyQ!_MjT#ynB#iOA
z1lPS>Kd}>jV9ji+2e#|$>!s1rQHsT4WL6dz7s>5*6Z29}$G7#o2x6Jsi6ZEP$CdC!@MP{GAM-Jb4g+Dz#t>Zrk
z8wPM!^BI^k@?C@SIq{+-D{NkS*>IffXQE{Pd_m#&_V()dfj~g%-`vm2nKR3`Rta}C
z-V4_0Q~9OCMO3a*2iG^);15Ts?1e^pXY80f)9v8rgcLJ?*-m0-h0=ScMS2qbU)sT
z590|cJ^k-}HuFn9T%`j4&m4pORQ=4JZO`GBb0!VESy(&g{s7kQx*#QV>qgE8|I@Lt
z{=#>!DEz`h-;!9hmulc2<+~&DfV7k1A}eA5!$@u;K&a
zfLv(zgUON!?*-m0usQBSi2DYe*MBN`ROLI*r?Rnj+eZ-{A3h)s$OUX-PvTtQY~p^v
z9ff-mcQy7#`R?5$x+?JYA5yt$y|<6@aleT_aLxzsq{JQkqW7+*@YPsgPvTs_4>NJ?
zd6t~7du8zzf0fEK*3O{xr(^J*DcjzEJ1txF0k!?uf^tVW-s&gE!B5E1@g2XXgozv@PtaN>r&Y4(>4d2z9>E>(u
zi#^v*8g;Fn`CqhiGPSLqKYlXWV7tSa^e}GmhaCm}%eoxc+)Hm{qpQxbA6|M*&%Z1?
zIztuec&56jbM|jlzp(39iSLrUOghH#!mg==YQy5YvSu9L?z`Bta8}i|dVinYZf?3U
zt8acvwZZnzrJHBgZ+mCCx*)KTgObBHvi@zVwN>K2aZu$uyvxsP$Fga24x$BJQ%SxT
zAI)aIaZXc^c5x0Qi|@C)#<6U^i`~};tls&_Z04q$gLA-k&ZHaH_7e%UBn$Zz6CPvP
zMQcJHEh!?rgu31T9!4Fn!stFc93m5EByl0SnmSVpk)GBghqIQCoj;OLkYZTg)
KC`IWG#p!=)nEBZN
literal 0
HcmV?d00001
diff --git a/app/assets/images/ci_favicons/canary/favicon_status_created.ico b/app/assets/images/ci_favicons/canary/favicon_status_created.ico
new file mode 100644
index 0000000000000000000000000000000000000000..623c728faf6981b0b21af20b6b351ddd277fffb7
GIT binary patch
literal 4286
zcmb`JUrbwd6vr<0B>}8le;l9c^Ob%zW{Uy_o1SABl-R_@K$+%aR$5qx@M>G4ao0
z%zPNz+y*Q`na=rVL6mG{wzQ>X$e%!=g|+-!g)u1`(9+v`Jl{*NyS=^rL&lFBe!ain
z`JK->=l46mdj+A0|0*j5{1?7^QV^aN1i{L}L&8B8jLVJZ_PP;KvBTjw=WxtEc5Kc{zvtJ?R0=03cNKtE;QT=bVrm2k8f=k&sh3I=~!=A=4khGa&j^+A3oqr
zsvGVo9*?o6gcRmdnW*%Z&tCeoxSmpF=Vy9*?Wd(9FzCL44GOx~0zGJw3kl9KB(=
zCdOs<^#qwOZqn;N?c^Etqi(qS5MM4qU1%HbYR>Qa;r
zblsI1b8~ZAQ#3L%l9P|xR5#q!cwaETP2pE}lG*yB7*V)#-@Prf!LRC!Qb&)A2ECcF
z;9k@70p||2scov99RlBSo{rY^B*ZlKZ=ClI=7J459i_U{J9QR`M6@R5XV}Ggz?no{
zXln&Zr~|ySIQ9vCESB?q<6*vKANmqheR1OSChiB^QP_Lj)p%bxoKCv=ms8}NzprqW{>3&b!To0Gsi@~59kkExGUdL
zM}C>5qrV2}t*c>r^@lrT>DVC4WpPoUv&C~v_u&q2>X7@1oFKyY`gUaK#3;s4$+p4U;{jS0{
zH!QrQo-5=x??JS**_Y&d@$o|RwK{d(RLpxI8XEt8pq(q^xuQOB-q_&x6r!6=2X(-9
zE@hinj}r;CBnc%H6P{oxrZu66Lb3?dFYJh&dtM~6;DZ&1s-MNq!VPB>?=wgVONCt!
aYGpamU)xWi6N-drjlwC3Qk3pfoc;s0mi`_9
literal 0
HcmV?d00001
diff --git a/app/assets/images/ci_favicons/canary/favicon_status_failed.ico b/app/assets/images/ci_favicons/canary/favicon_status_failed.ico
new file mode 100644
index 0000000000000000000000000000000000000000..3073fe5a761ba1825bfbab4337a0eacf36b848c9
GIT binary patch
literal 4286
zcmb_eZ%kWN6n_MbA2Bh}2&M2|3vIH*eNYqQTK>eD7=m9^vP2UrvXH8Kp}Fo)Xa^w^|(X
zh{Y){N=|u|%|6K?_el=-Cz8Ws-fCRvV|q(1PWM0J4ma6~J(0J|r>XL*S!&!rPaoF%
zsd$%90ng%ahnYP;*k77@Vk_+6XLfj6pxgO|S2=Zdg;s-6G8!IVi1vOtOUxHhYk@qO
z@3_AGVQpZ(J_78jujeQfHbRYG8ydYw&y`LnlGAKW|E8ory~U|qW&q~}W~sHHtVPRL2bP;z?8Q}sb!iSK2|obFrM
zz)&ALjxTe4;KPRTb!@!D1|vVfjrTq50513-d$G)CV8aha
z1NDLV)0Yh2-leqJ`jn`(@)p+_xE(Q4$Jfdm{V_Jc4~Yh96mmHczSvGr*-k_}w)0`K
z{T?Q9?=07Sb51c-sm5FN0cLGJ=!H-x+4&cZ@a+fbP1|oukYk?3nDDvQ4~c9*twz7lQCV
zJZ-$ye89a3>QV-^8vO$IS;e<>lhyvS;#YC`+#6cM27WigC>f`sU0#Y9qyTJyAG8Da
zVsa+FK%-y4SLmC-w{_A-`DemP4EC?g??)Ieut7fs$n^dYmpgVkpoQ7gbBLLPo`t@N
zKF0lh{=UDt4Siv<9KL%Wo8jj+&rqi8Pv(QGv~8!H@E#^J20e?Po%L><-F`+1$DA86
z?_xDtJ@@*YweJeYJgcQt>r<@wJIf+kl?6j@<%mjQrz@ti{hes)_kJwxun=v2lKo
zsr(YR0e(O%jPgP22lNZ{EMTK|!|!Y8?EHr!O)7r=FY(y$gZQmK1|K%S4~PYHA}9BE
zED-J{>H}&N>LhA4`h~TC=bB>KA@5Of)%n?0%0PXyon-(wMc(ezG~cZg@eJJ$KMxT~UM$gZx9}KHHOtn{*_526D=Tyr_RatY*
z)!_&2O~fvGD!#R5>IE$?m1h=%
zKxX}5gw@4IQ`xWIQ`SrAEC!0H_U}7-UMlZ7Rqjr6&DcOHdlT)!Jz#oz67jX`L_#4&
zg$!C19%GbF%R(A?ISJG+tdWb&Oh{pb4^|{qKO+|-Hjty}XP^v5IW9pcKdAmId3k!pyqoZ@RT5X$7r<=v~
z8qf1~oGmzy;Qq(4v9YS%#wB}*mxma45Ch`k;+)0B#h};gp|Pz8X0+8rwlgy`g@J(qu-on6Z7eJ-Ky`IBpr0<(xsS0(cu^nFRwrQ_3V9`O8*=eZXd85u7j_CJ-Cl`?y4Yip34oXju@*BkZp^vHCmCU@j21C2rS
z+gXQ5XJ}|hW{W;bOG`z2kd~GP1qB6kKKI_t%#4Q)-A&BHNFez9IXKMM_S*@cd>04R
zzR6^Qg9i^Xtg^B)a5x-{JvKH*d1m{qt*v0ST17QBQ-7cy{udlC{!m~b!=U?-NuR90t^FzWW!@hyom!5#eaE;lTnwpZ?
zp%02X#UUvv3A($xVRUp9ii(Qd*vhz&4)toRky$0auETYezah97HlBT7*Cs?>wn5}K
z^UNOIE9qEYU#Fhp#**ekTvLCR4vG!E7sziD@uRvxqx)X4inwg<+uFt^{4N{pdnXs(
zJ(LYjr&DSU>gwtsH8mB=%gf!lz`G4uSy>Ph69dD;!!mjDhkV2M=Mp}D0V=fD9fAz|
z2aJ0s;u1E|w>D4}pJsY}eSI=}^dZ(|ettfa85|sBZ-esg(Vd|;3v2HVd&el=qfg__
zd>C;+)TMu)Vk3UU7Y`uV_zTA1FeJRSUv>|r&aAGkvfk_KU7|OO&W^dyqqFO-3l7=2
zDd!yq?Q_EBeT
z44ckR6jt8Fe4sc`E|m2k#iTX87xZQkHpab^;=YZJ=fCJYCE{zZd1BMq)n8g=_~Zk{
zfpS4MsV3=O(A}i|K(#=9l6p107tvUQye^jB{^KI9I48EjUg~fBPnh$LM;>t}{IE~w
zJn+R>P)*XkAV0j3Za?;*BYGGAo-tm;RLazQr_D)%H@kXvbo`wE7JJD@9%Gwe%30}!q`E!
zzQb$guZX%T{qMJ*CF_f)GMFbt8))yUFF9}f>Z+xL;D+rSM4Y@A@NZM8t%&M-M@4*%
zekobX3uKKsum#smI
z`{GOY0l0K)ak#WW<4q+a@E|JY&27LElovudk1KdU_}liKLB(!(kCaJP&)`3#Zdr!0hnQ&`|oK
znWm~LaZM27TU%R8<3oWwU@zF_>|XbQ=QXnb=*Gr|rf(=$R#s?naZz_11E^8<71_(V
z;Av0roW+rmkzIX*je6Xzp(c?dmXq1$;HItbRm_>6pVxJbGa&Q7TaMrWXOq{{nGN4`
zkzRZ6ubD9Th+VIt=HlxT`=DnBJ?;nQ2Qu-^P3n15ry4ui5fHvnV|p!-k8`kFthl2%
z*03Jmc!8cXU5k#HZb!)UXM~Rb>KFXY%}qVL&<_s}@8kgIaBFKz(>`8<54HH_i}aT1
zrn)KEw<1(_Wu4yqWm5RX`N`B!gR&0v?g`x0od1DTzPTxO-E>Qh2{y0&V9O?zTn*9T
z)(3(=F)^WupP88vXIl=Ajg1L=zAL0^r$?RQd%^rh$uDi8GV{-BP;y1zwk6o$m$Zba
zx!plMZqJS%`49?)1dDyr?CdP9uC9uE5VfdvUU5F-b$S$h(J}@w_69eK|SXdD8CH})V3-NJ%9K+hp?P?@x-PrS{jU+bK
zpa01{!GGxs2X%DW$<^adivb+u0^b>}hFS!h*M0_UwDKR-(M0~i)`UHe=f3oONU*Vf
z$dPZlMGVM8>RxDZksExo;_PO&$=#;&`Y%TtB)|MdIvZ;@ejQBWBL?IFdjX%QNt_Fu
zP23O20q!2$)u=xk*TJ2C>?-H{L&=r>%Z+pZ_nWDM_q=H(E$`qLema=Om$^Vq;#?pO
zE&1E#q|fj8Vh!!%FG^-=U*4uplr^nuvP&*3>#}7G=nr3hAnvH+zm3z0-$&`48v%O#
zrx`LeuaW7R`d=zD@!i-k`(>fkOIl*ApXxVS#=gra_0xS?^Pw|-7W_7mm-<{}nSVat
z>WU??1C^=vTJLQ4hMbes*SlgR*6EDDzYWy`!K8Vd(}LQ&TUsnVT|sSMIL$}R
z;JluFqQ1!D`#yE9!Q$;nw8`{ru#DJJeX!q_O!F{aV4W<>vpSRZz*yyfH=DWArsS0W
z?PR_)R#qE$L5^qY3v2rq)C1PjUP`P%B$brgW^;7v;J+G=&QKu{`-<&Rz3Af;#fA%ya%DY
zI!~1E#V50|PqnFRqg>ttwV>wT)zq4U^
literal 0
HcmV?d00001
diff --git a/app/assets/images/ci_favicons/canary/favicon_status_pending.ico b/app/assets/images/ci_favicons/canary/favicon_status_pending.ico
new file mode 100644
index 0000000000000000000000000000000000000000..ccd00606aeb39546a35b0fc902765d0a085f394d
GIT binary patch
literal 4286
zcmb_fYe*bd6dp;Sh0^3_C?$UiDJ_lbBWtV_
z+6Efp`iPIXYA_m_zEX@}RY<9iN*)>#MMXCnYYC06&(*mzr}vxP!P(hacQxK{ym#)o
z_k8Dd&)En<691QzBjB%ab)O)l3xeR{#J7YaoUpG9&fD#Atc~`V%GuH6a#n5fio+>h
z_H?h81yd@RKiSJVO%>ATsnulJZCuDRRkHUv=7Z#NkzS}|(tE#1^l6twr*BDgyhEZ_
zn;8R->mzbqF23lamv=)C*v#dghipe9V^>CHT4Q85M&^k=`9p#ZGWX4NaupqZRvq?M
zuts2?>Xv9jGK7uV?3*LXtY?htvHUDLn98LufnC^}Ah1Rg|6)i7_+clpNUb3=a_hqz
zlB^NCttI?`SRfy^8wcb#&ueLXVOx+
89sQUN(P%=e2&o8NW@+^w&R|
zoJUJUKTXK=czJVAT_GnCLz7oJov07es^}fuX&sApedn~S$m4z`7G{5ZQ&RR|tI<&2
zCa({P;5%#S-OQ^j2>gdnqosBDL-^o}VYrXlL-;2?B(pD~E%PV7gWM6EW$ch%By=kIJ?!S3QU
zu3?o9TwYf2do?+xdSWN|sMY8fdVH5pzV7T|vVzTRKh(5N_T~Utn-&%P(t+sw!+U(I
zmC?~(B~rOR+?DB#7Dm;>>W-={DYY8?0`FPHKiEVL*N<#Y#Z~6E4Fwzc_ND+me_@ea
zJP&qWeL^~*UnuX7_f6nC>*=%Hc9BJ3-#~BSxWEQg1!(^_qsqOy2hlcdTDSEI{Q^A;
zeG`35@pt#8zZD%iMLO89vWd;{bH1CUOiwTO!2<28GJc0!BZs)?S&Hqvcf)p9I};=9
zM$CO{5!kRl>)bsBKcny2)jgO5G}D)US}aVVNAh
z6>?r0SzpS-K
zUE2!$$MolozWKQi)H@M#Nxy9O%*OrwZ7CR@i@3*qYA(9HVT2WH&s=mT7$u|d{*zee
zwfk20Se^c^#XT~hJri$jagY9~m%-&W#k&W-*)#3P^z=o~Glw%vLNUlWGnw#jQ?0C={K-=)zN28~Z7na6HIG3cvv^SA
zbul@S^ZGNW?K}p|TzGd`&r9Unnm<-=DH!Qb5J&+@3YfRe@*N)>@fQ^8_u0n0ASV|lHMKw*Ib%g*lcoC~v^nVn&`mLZ3^b06nB
z_ndR@S&j?BzsN|A{&N=|=eQ?1j*COVF78DX>Sqs*?eqf;sljGr!mH-Ogi@0+vEO7&
zzH2rnuA7RI#<9Q6Y)txcq$F9h(_GRwWK7zJ`tO(u6JV(LCHLeHhroXIILx%41ly%N
z7_Cg>X$SClSf~yJd6!PMG1$9J=;~`!{G1Tg_Y56Ab+e*
z^#gd^k~yv=JF|iO@PA@qIq^yu<``hx#2C*L~C#la|l<-BMKDbtVAcfW}nc5|M`f$#TfwlI-ZEc`fi1UHY
zCfyH#@O2gN@~7W5uM^)nKkmb49e56AyUH=PNvd|RoZMPX_XFKg{`heu`at)ddGjFEE|1U*O8
zb4C8LrOUg9?n%00Fy0@aj-&DDiQxAhwGN!QMM7#sJ#yUqzw=Nz!Nc8u}ouGgqxz5Pmj@wuV9n(76eXMrDG2QhI!@^*pC
z-VGa!P5h`j2mDmrU$a-2QbWwQ)_u&*r*|Hn6RKHMH>r*>e|OyXH?yJ51<}>_?z52}
zdE5pehTqW#X<#aOP5m4q$kvh%lZ{`&!p$ZhUs27Xy;JR`y~kbQU6OrM%xl&pY}$Wl
z-fhNzF0Tb{6z+qe(zmy@!Mk5kgKE~6-;KnkC$^p+7V~$X7sY(b_t9kz#-{y~q#Uhh
zHjp1!EM#>~gk(*s7gVzt8*4ZDeUpy+KkLpH_^}s#*|c|UpqHiUs7cYHqd)-*%-T{4wiinhfB}G
zN97k`e^oc=a8J5Mep=2He{1t+3c?L0P!etKRG(Hqa>}pd+HNVWr#|g5dx@AQZ%627
zpAI$jc*Oe=+S<(VRQY_RZ=APZSR;Ao_IRQUHow2WHJSZ($vX6DSoX~gC6-!WSoW=T
zA01f(vug9j{SkUgrF^YMZ~8+#$6s5cH(!(MK)rST*3o#FVKOGf&@G99HpBWsAZvv=
zQR&wAr2KAAO!oLQ!nnV8cy`~sus$^B29K9VkiRwZ@z9)Jm!Kmo>-M62e7o-m{qT8V
zttNA@Z@al_W11{eub>0en8g+7pty8H335v4DS@igiV1jC~^TV=|{+5RV1Y
z#uzw4a(dl(FFqQ`eEFQz1_;I&@L^eht;oj$`Hsl2RB19zJ%P+sn?vUS^_){17xx2j
z@!;Wh!8-RCN-!*PL11OVK_|B<27Kcp9)*6eQc`uI7*Oz`9Hn|jvI`}`z;W?RjO%
Tg7t_XR#=4bEpdPYuu8#y89IH8
literal 0
HcmV?d00001
diff --git a/app/assets/images/ci_favicons/canary/favicon_status_skipped.ico b/app/assets/images/ci_favicons/canary/favicon_status_skipped.ico
new file mode 100644
index 0000000000000000000000000000000000000000..7e3be35cc3a5f869c574290f58ca1bbc6f4095ef
GIT binary patch
literal 4286
zcmb_eT})e59KQsOkC>Qfgi2Tc}Vmdt1zm<%m
zqyeP&eLkP@pmE8b)9HK-?N1;cxLmHx`1m-4LLr!*o`zsB2*bm}BJog0!1=7l<9X^J
z{Ggc8<{7f>^?Jpnr6tH@GPs>PwzjsIPbe=T&7lv6AJqr6(?!_fa2O;>$_3TfSzliV
z#HM^~Jcev2{Sb
z4(z$i_V#v;<&BMvy*;YQ=H}+!TKz#iinfGe&IQ_d40Tqgrl!>9ARdpCJy=*+V7%Gc
zS+-tTS;>*54eCj%A=1f0b8yq{f0=ZamzQ&FilPXkqoaF1q|<2_85!Bv2RfVR^FSf^
z{6%=>-9HzSgipR}jbeSE`vLKz`S2~B;(2~Rluq_XS347dibUb@C<(~bCr!W@cvCIuHot
z+)ukbcwY?3;G8g;2H83?E}48gpIMEA#56T
zKZs!^{-GX4&3AKOdp^OiDSo1(Uptu(l!roULGJ~l=mHUjQ?_`UB<7wk&8{S
zo4$%?;gb)P2dV|xq@JX6L1&Zh2fByoo}{~)`p}MV!=1k!BIf)98CRZP?0_=5-}rv4
zdFO+iyc2%qC*wKzaxSPR>0FQ>TJ)FQ4WHc!N$q{p&&!zVxvp27HFs`lV%J<)*Tt57
zp!vw@?--yDiKP~{@wF&$+@n1Eja&2l~{G!qp1T8YP#l}q5yWi%e
zwt2snKJA%4jen!WQ-4=km!GY$c_d{#^0%oe+Mt%#TBF?SvQF0A=8&YwktE{2#)VfA%a7ZbW@7rjdva4;N-R^vP#5dUH
z%;h$BRt-#zk#`Ewm1Sy9Mc&HBcT47$=yNhZ-(1-;wj%3Sw0h}>MoB&$HNT?OC&)Go
z&7*5-{(kE!Yq&?&H8xF-?I)|pGd2f(vJJF%T~AJH-}F)JaCzHK4XRJg6#Uy%X{)+%
z<~aYIV^h#mh^(Fr
zoddLURgbUS2jJ>K;>sY&J%LmTYg`FL7;!Mj?T`&;R1%Ts2P-wzAd(FU2lXhuXGCR4
dRW^>RXLNe7eh?z3Ws1NWM0Y6x33vc0_z#P^91;Kk
literal 0
HcmV?d00001
diff --git a/app/assets/images/ci_favicons/canary/favicon_status_success.ico b/app/assets/images/ci_favicons/canary/favicon_status_success.ico
new file mode 100644
index 0000000000000000000000000000000000000000..a1fb6e91d653f60418ab8d1c1925b7f99aa69c2f
GIT binary patch
literal 4286
zcmb_eYfKzf6dr=cpO~0v+!=P+Wy@^Zgqjdj@c~3*(qR3eW|u~yu~B1elQtT(WqEW_
z`BAY^Qe&XB$U=GT073d#jo2lISg2T9AT4G~d5RE%us|uWvva&>mZ3Adv&^e4}Wvym_UJsZkn!dhSj)SiDA??72k4zYm|2#sg8
z(7U&41HrCF?25l~ffxL0uwgv!Y%hG+_6$$rwX_u*2<~Ty-8fJZhM~onU7ifuK;rN)
zxyWv&89ZAjI^Pqtup+Hv955Hehf@!l2R!5ZIelPyX-rjpK;U87zo@zeS%EA2WYSG6&}yS4!K-}b?Q)?ILCu788CHo-HAIkYv=pF|sjH(W2gihHh%
zpAS=s*tzYmi8@i{KO(a6>>1db+FG}Qx+fQh6!>!N{Y`rKpeeGli2cWS8(?fdI-jCx1J)=!%aQPn74Q_x1%_CU
zAK0J$u&1_6)H!!=TH!ywxV@FoJ#lG+AB_!IC$Uzm;akqY+w4VtRm8sR2Xoajq|`Nu
z_}WiowO$dw`Q~?Fx*{>q
zhNHjkg3+eZ_oXBi#D|T
zA+hT2eQbiCP%;TR#}yKTGu(%_B{Feh^_);wJOya!=`i8Mp(p%h4
zc)2Y{c%?2US;7n*lU)3m*}1HWZK_y^h%MP5=H#qbtWkUFet_rePr|cxPDrlxkh8P^
zEXV&7iYb3L7Ega2?-&F%G8Rqr8SO*gYf{l{opFqtb&f7Y4ve`Y??6n>N{i!NxSKNf}=2ByrICS~Eq9d4SKMwiv73u77=ZklK`mf>$`B{3@D
zM`Gl+FrX-nqzfxnNnv3vSkhV`FqJkP1PP`oGW>Puym_DJ+?m(DdGp@P!*a-(^WMGZ
zp6{G>*-sNg4E4P$2QI^zB|rIv`1shnR+>7m0aX5Y6p4^&?Yi#Br$}Eg21%+|`I>
zl3|i_QUiu){C%3Y?>H_SY{1KeHBA`EYC`nb0C4gb;M554>P5iS1)1kaCqlYkNX^LE
z5kF!v*RgF!2jrd^U{i)6%`5|N|15k^C@1q$6H1=ghkE!K`<)?RD{2UvH2B*hu)hT|
z+@0pDN`^VCV
zI1gk)5$9pM8$oBB>_%r-j4a2-$hN>|X-4t$5ZTtf7{=~h4fyx9AI+@B#y`0Rymbj+
zX-0e|IY*R(_pGKMs~N|5P2VjutJ@nFca!Ub1#-9JrDwm1h8chQerlZ82Z54afMqJ;
z`XFjl8hlT;-0B{Zm3>{Z$k}o@mDPA&Ik&{Ah-(y|WixnZ8xFe9NAI|YBXIu|K~8H}
z*qmQWWz{-9*GY4IIYM=G69+ps1pXDeKdDHZD+}>+t)}=V_4uA{
zWx#z|Rs=T1ez<1~g}ouz{i}qpz&Dx--CF!ytGQp0uPrKmQ4d_6@8u;GSIGW{0-Ny*
zdqQ}+ZUaS~3S_h5L#|ngpZkT-9$!HArI{R8FQPq>WD{8b2hYyTAM+NR8N
zkPe^w1@|n<{j@}VOyqm`alVBQLlG2pZ9K*%{DRLGamaU-ajinKB
z&k{aT@8;M&gK{JxZr=0m2MO35f8Lp!$R+#(XRaf&K7#yqb03UwdCRzG#q(ar*i6OW
z$+xxmhx;^p9?yMIYe---KJ&h_lfnni1Mfwu^T57vzu=w~-y1*YJ%pNrP2_{A5J
zu{n0<=SvCrY94qm*e0Jz?zwz7xjt}>;yTH-n)^j&qXOz3GWDAeR9sa)--2weZ|+O9
z=iO^bd1w6mvr|d<>;s<%K9hVe_-@AIOOU&p6lD7qWzUy5s$%M8alibRt9#QByRdE5
z5L?{~RoYuuMUBd7+r%@i53s*|6S?QsDW(m$&&z-7F}3f`+J8RH_XS|Y&YFb@r}s{C
zTCQ2VVYHsdoF6YWYVq{X4)47~dA>14jYTV+<#Q+W`bO`h_lkDiqvx72rO>yS_WRpj
zKDqR0P5hkODz85@!ZI7PRo)0E*{GPhXQrb45R&>fPbJ-KVa#m(NV3(lwj2R|LjY8)R?5OwVZC`O!j2ZcS_t3Qpg(
z{B5eWRZw>KT@~L|zVL!}&dM|GK`6IsJW6%(DJ%MVofA~sX%A#u#UJbXIVbSi*=DV;@OcBop%oD<7&6VjnRP
jpHc2-%-O^apCpwEt{y2JL9kloAXYFJ=MX|z!xsJnN+79=
literal 0
HcmV?d00001
diff --git a/app/assets/images/favicon-yellow.ico b/app/assets/images/favicon-yellow.ico
new file mode 100644
index 0000000000000000000000000000000000000000..b650f277fb66d6193e27e1f2bfe59f751159270b
GIT binary patch
literal 5430
zcmb_geM}VT8GrRIB{5da#a7(eot^!faeIy0=I+uqHTp->f7)CvX^b_ExtJJeqvmSW
zhW%g>?@J3xv3K>WD6onWRspw&7A(259-_!e!6;oR7^MwRZuvM4cLv`+&&Pc#Tw?{U6^#nzqX;)X|51
zd`+}5%eu;>=lGfL*ed7QksjfSNL}Y=sJ(iea({ZL#ap3{KI}t`vv%Z;Bk$OEkz?sw
zht>Ug^
z=Y|%KbvyWw!vPqfCC+hCoDdqsTNv*QeJPI-F}A}aTCBPT+@FUPZk$JGS{Xxw*qyVj
zqLBaVV=Wfr*#q~J;@Q&sN<7X3IQZ~mnzOy4c=?9HH|)noD0k$)npt*VyZMbR)d}X<
z^^co+j16LP))juw?RFE!-#M&~lPT;RTd>4EU%x+CUjjbBjp}ftUuP7YX=le#&Ak`x#
zseWUbwQS`=z#uO6HK^M6(GQ$ReceB|?hksl8B#Dz@JrRIF=~5Y;GE@(c%y1($--vl|oSKXO33i)0@Z8mlF?VP-;y5(MeHHFZF|N{~H-!t*knlHA
za#TVdJvI)xpk2-f_9Kvgs-`G^S){@RamZ0Rl$(j~dHQW7kq?AsX&CdgE2!jQ+reQi
z7ugO#4udst2EUYZIb!Xlk&@@pNQM2*-rj{=Nq1PdERJD*hx-b2lswM9_b*MKeK(%R
zaUVjEg8>UMQCmrO^S6q66V7ugom4)XzjMW_A+a5JW-yP#T>^Pl(YBw!weQgMv5r2>
z(N4S*F9IH8Al4m{+HFOh@|~1QCza1q@X02jQTj}15ha-i@3vD-BckUZU=1KfjhDHarGB&La@m@~)|6+|{B}5J%T?(#+`FS%9FD&+2Ip(?DL34=mOWib
z`b=>bwO1;8Am7IjBQ!pp19HN?jJ{SkdnV_1;e_`LCco~7!g(poUyAQF>Y~AUa-M>-
z2G138%68=QByIKXu^;~YDGu-sh((Ts`G5vrFEug0sauO{zbvnMqtGyW74|6+2l}qF
z%30I2aqUb0lUAQA8A{N{al6jIv!KpLEm5ms_S&*7m79bRJZE@b)V_GhpNF$nrCay-
z{4MX?Nvm&pr#Dd_*8rXy{+#YvP<2o~NGmDk`e#&f4U`|A3e
zimp>TVD#&Sbw@S4n>8u#W_m5is`J~&~`681bk23z@P+PSM^u$7G@=_~sH
z?{`@x<&7y}m01d#*cc`nj<0_h-~+--{&c|(yZl!^wqtiM;HIpe|#?XqvGMC>>nSb>>SrC0(oP2ZKRk_H{*#>!`LF|E&pkZZPHdoywsvb9009nP>8KO}w!!m~aoUo_j5-
zp0Q*-cQd|!>-Dj2@!oAS@~Ca-OL|Xd3m$G(`;Dc|JFvsZpQ+9H2l9t10BZ^Sg7_&2u+d`mZ;dnHvo>$`K;h_`rq
z`%_`(;xl`DBSt>6w
literal 0
HcmV?d00001
diff --git a/app/assets/images/icons.json b/app/assets/images/icons.json
deleted file mode 100644
index 19843d24e2..0000000000
--- a/app/assets/images/icons.json
+++ /dev/null
@@ -1 +0,0 @@
-{"iconCount":191,"spriteSize":86607,"icons":["abuse","account","admin","angle-double-left","angle-double-right","angle-down","angle-left","angle-right","angle-up","appearance","applications","approval","arrow-down","arrow-right","assignee","bold","book","bookmark","branch","bullhorn","calendar","cancel","chart","chevron-down","chevron-left","chevron-right","chevron-up","clock","close","code","collapse","comment-dots","comment-next","comment","comments","commit","credit-card","cut","dashboard","disk","doc_code","doc_image","doc_text","double-headed-arrow","download","duplicate","earth","ellipsis_v","emoji_slightly_smiling_face","emoji_smile","emoji_smiley","epic","external-link","eye-slash","eye","file-addition","file-deletion","file-modified","filter","folder-o","folder-open","folder","fork","geo-nodes","git-merge","group","history","home","hook","hourglass","image-comment-dark","image-comment-light","import","issue-block","issue-child","issue-close","issue-duplicate","issue-external","issue-new","issue-open-m","issue-open","issue-parent","issues","italic","key-2","key","label","labels","leave","level-up","license","link","list-bulleted","list-numbered","location-dot","location","lock-open","lock","log","mail","menu","merge-request-close","messages","mobile-issue-close","monitor","more","notifications-off","notifications","overview","pencil-square","pencil","pipeline","play","plus-square-o","plus-square","plus","podcast","preferences","profile","project","push-rules","question-o","question","quote","redo","remove","repeat","retry","scale","screen-full","screen-normal","scroll_down","scroll_up","search","settings","shield","slight-frown","slight-smile","smile","smiley","snippet","soft-unwrap","soft-wrap","spam","spinner","staged","star-o","star","status_canceled_borderless","status_canceled","status_closed","status_created_borderless","status_created","status_failed_borderless","status_failed","status_manual_borderless","status_manual","status_notfound_borderless","status_notfound","status_open","status_pending_borderless","status_pending","status_running_borderless","status_running","status_skipped_borderless","status_skipped","status_success_borderless","status_success_solid","status_success","status_warning_borderless","status_warning","stop","task-done","template","terminal","thumb-down","thumb-up","thumbtack","timer","todo-add","todo-done","token","unapproval","unassignee","unlink","unstaged","user","users","volume-up","warning","work"]}
\ No newline at end of file
diff --git a/app/assets/images/icons.svg b/app/assets/images/icons.svg
deleted file mode 100644
index 6aec54d054..0000000000
--- a/app/assets/images/icons.svg
+++ /dev/null
@@ -1 +0,0 @@
-
\ No newline at end of file
diff --git a/app/assets/images/illustrations/cluster_popover.svg b/app/assets/images/illustrations/cluster_popover.svg
deleted file mode 100644
index 202231373f..0000000000
--- a/app/assets/images/illustrations/cluster_popover.svg
+++ /dev/null
@@ -1 +0,0 @@
-
\ No newline at end of file
diff --git a/app/assets/images/illustrations/clusters_empty.svg b/app/assets/images/illustrations/clusters_empty.svg
deleted file mode 100644
index 39627a1c31..0000000000
--- a/app/assets/images/illustrations/clusters_empty.svg
+++ /dev/null
@@ -1 +0,0 @@
-
\ No newline at end of file
diff --git a/app/assets/images/illustrations/convdev/convdev_no_data.svg b/app/assets/images/illustrations/convdev/convdev_no_data.svg
deleted file mode 100644
index b90eddcccf..0000000000
--- a/app/assets/images/illustrations/convdev/convdev_no_data.svg
+++ /dev/null
@@ -1 +0,0 @@
-
\ No newline at end of file
diff --git a/app/assets/images/illustrations/convdev/convdev_no_index.svg b/app/assets/images/illustrations/convdev/convdev_no_index.svg
deleted file mode 100644
index 4aaf505e0b..0000000000
--- a/app/assets/images/illustrations/convdev/convdev_no_index.svg
+++ /dev/null
@@ -1 +0,0 @@
-
\ No newline at end of file
diff --git a/app/assets/images/illustrations/convdev/convdev_overview.svg b/app/assets/images/illustrations/convdev/convdev_overview.svg
deleted file mode 100644
index a06d70812c..0000000000
--- a/app/assets/images/illustrations/convdev/convdev_overview.svg
+++ /dev/null
@@ -1 +0,0 @@
-
\ No newline at end of file
diff --git a/app/assets/images/illustrations/convdev/i2p_step_1.svg b/app/assets/images/illustrations/convdev/i2p_step_1.svg
deleted file mode 100644
index 67467b1513..0000000000
--- a/app/assets/images/illustrations/convdev/i2p_step_1.svg
+++ /dev/null
@@ -1 +0,0 @@
-
\ No newline at end of file
diff --git a/app/assets/images/illustrations/convdev/i2p_step_10.svg b/app/assets/images/illustrations/convdev/i2p_step_10.svg
deleted file mode 100644
index 588ecd8141..0000000000
--- a/app/assets/images/illustrations/convdev/i2p_step_10.svg
+++ /dev/null
@@ -1 +0,0 @@
-
\ No newline at end of file
diff --git a/app/assets/images/illustrations/convdev/i2p_step_2.svg b/app/assets/images/illustrations/convdev/i2p_step_2.svg
deleted file mode 100644
index 4280024c23..0000000000
--- a/app/assets/images/illustrations/convdev/i2p_step_2.svg
+++ /dev/null
@@ -1 +0,0 @@
-
\ No newline at end of file
diff --git a/app/assets/images/illustrations/convdev/i2p_step_3.svg b/app/assets/images/illustrations/convdev/i2p_step_3.svg
deleted file mode 100644
index 7690f91b42..0000000000
--- a/app/assets/images/illustrations/convdev/i2p_step_3.svg
+++ /dev/null
@@ -1 +0,0 @@
-
\ No newline at end of file
diff --git a/app/assets/images/illustrations/convdev/i2p_step_4.svg b/app/assets/images/illustrations/convdev/i2p_step_4.svg
deleted file mode 100644
index ba21b9e2c3..0000000000
--- a/app/assets/images/illustrations/convdev/i2p_step_4.svg
+++ /dev/null
@@ -1 +0,0 @@
-
\ No newline at end of file
diff --git a/app/assets/images/illustrations/convdev/i2p_step_5.svg b/app/assets/images/illustrations/convdev/i2p_step_5.svg
deleted file mode 100644
index 3c8f8422a9..0000000000
--- a/app/assets/images/illustrations/convdev/i2p_step_5.svg
+++ /dev/null
@@ -1 +0,0 @@
-
\ No newline at end of file
diff --git a/app/assets/images/illustrations/convdev/i2p_step_6.svg b/app/assets/images/illustrations/convdev/i2p_step_6.svg
deleted file mode 100644
index 933860798a..0000000000
--- a/app/assets/images/illustrations/convdev/i2p_step_6.svg
+++ /dev/null
@@ -1 +0,0 @@
-
\ No newline at end of file
diff --git a/app/assets/images/illustrations/convdev/i2p_step_7.svg b/app/assets/images/illustrations/convdev/i2p_step_7.svg
deleted file mode 100644
index d97c8f7c2d..0000000000
--- a/app/assets/images/illustrations/convdev/i2p_step_7.svg
+++ /dev/null
@@ -1 +0,0 @@
-
\ No newline at end of file
diff --git a/app/assets/images/illustrations/convdev/i2p_step_8.svg b/app/assets/images/illustrations/convdev/i2p_step_8.svg
deleted file mode 100644
index 919bbeff31..0000000000
--- a/app/assets/images/illustrations/convdev/i2p_step_8.svg
+++ /dev/null
@@ -1 +0,0 @@
-
\ No newline at end of file
diff --git a/app/assets/images/illustrations/convdev/i2p_step_9.svg b/app/assets/images/illustrations/convdev/i2p_step_9.svg
deleted file mode 100644
index 2d1b10d430..0000000000
--- a/app/assets/images/illustrations/convdev/i2p_step_9.svg
+++ /dev/null
@@ -1 +0,0 @@
-
\ No newline at end of file
diff --git a/app/assets/images/illustrations/epics.svg b/app/assets/images/illustrations/epics.svg
deleted file mode 100644
index 1a37e6bba5..0000000000
--- a/app/assets/images/illustrations/epics.svg
+++ /dev/null
@@ -1 +0,0 @@
-
\ No newline at end of file
diff --git a/app/assets/images/illustrations/gitlab_logo.svg b/app/assets/images/illustrations/gitlab_logo.svg
deleted file mode 100644
index 8dbd75a340..0000000000
--- a/app/assets/images/illustrations/gitlab_logo.svg
+++ /dev/null
@@ -1 +0,0 @@
-
\ No newline at end of file
diff --git a/app/assets/images/illustrations/image_comment_light_cursor.svg b/app/assets/images/illustrations/image_comment_light_cursor.svg
deleted file mode 100644
index ac712ea0c9..0000000000
--- a/app/assets/images/illustrations/image_comment_light_cursor.svg
+++ /dev/null
@@ -1 +0,0 @@
-
\ No newline at end of file
diff --git a/app/assets/images/illustrations/image_comment_light_cursor@2x.svg b/app/assets/images/illustrations/image_comment_light_cursor@2x.svg
deleted file mode 100644
index 02943acd9d..0000000000
--- a/app/assets/images/illustrations/image_comment_light_cursor@2x.svg
+++ /dev/null
@@ -1 +0,0 @@
-
\ No newline at end of file
diff --git a/app/assets/images/illustrations/issues.svg b/app/assets/images/illustrations/issues.svg
deleted file mode 100644
index c8e0504732..0000000000
--- a/app/assets/images/illustrations/issues.svg
+++ /dev/null
@@ -1 +0,0 @@
-
\ No newline at end of file
diff --git a/app/assets/images/illustrations/job_not_triggered.svg b/app/assets/images/illustrations/job_not_triggered.svg
deleted file mode 100644
index e13c1cb0a7..0000000000
--- a/app/assets/images/illustrations/job_not_triggered.svg
+++ /dev/null
@@ -1 +0,0 @@
-
\ No newline at end of file
diff --git a/app/assets/images/illustrations/labels.svg b/app/assets/images/illustrations/labels.svg
deleted file mode 100644
index 3a2d521323..0000000000
--- a/app/assets/images/illustrations/labels.svg
+++ /dev/null
@@ -1 +0,0 @@
-
\ No newline at end of file
diff --git a/app/assets/images/illustrations/logos/go_logo.svg b/app/assets/images/illustrations/logos/go_logo.svg
deleted file mode 100644
index 7fd4911800..0000000000
--- a/app/assets/images/illustrations/logos/go_logo.svg
+++ /dev/null
@@ -1 +0,0 @@
-
\ No newline at end of file
diff --git a/app/assets/images/illustrations/logos/mattermost_logo.svg b/app/assets/images/illustrations/logos/mattermost_logo.svg
deleted file mode 100644
index b577c0599a..0000000000
--- a/app/assets/images/illustrations/logos/mattermost_logo.svg
+++ /dev/null
@@ -1 +0,0 @@
-
\ No newline at end of file
diff --git a/app/assets/images/illustrations/manual_action.svg b/app/assets/images/illustrations/manual_action.svg
deleted file mode 100644
index 85735855b4..0000000000
--- a/app/assets/images/illustrations/manual_action.svg
+++ /dev/null
@@ -1 +0,0 @@
-
\ No newline at end of file
diff --git a/app/assets/images/illustrations/merge_request_changes_empty.svg b/app/assets/images/illustrations/merge_request_changes_empty.svg
deleted file mode 100644
index 40efeb2de5..0000000000
--- a/app/assets/images/illustrations/merge_request_changes_empty.svg
+++ /dev/null
@@ -1 +0,0 @@
-
\ No newline at end of file
diff --git a/app/assets/images/illustrations/merge_requests.svg b/app/assets/images/illustrations/merge_requests.svg
deleted file mode 100644
index b9b8f0058e..0000000000
--- a/app/assets/images/illustrations/merge_requests.svg
+++ /dev/null
@@ -1 +0,0 @@
-
\ No newline at end of file
diff --git a/app/assets/images/illustrations/monitoring/getting_started.svg b/app/assets/images/illustrations/monitoring/getting_started.svg
deleted file mode 100644
index ff783bdd38..0000000000
--- a/app/assets/images/illustrations/monitoring/getting_started.svg
+++ /dev/null
@@ -1 +0,0 @@
-
\ No newline at end of file
diff --git a/app/assets/images/illustrations/monitoring/loading.svg b/app/assets/images/illustrations/monitoring/loading.svg
deleted file mode 100644
index 1e196fc8ad..0000000000
--- a/app/assets/images/illustrations/monitoring/loading.svg
+++ /dev/null
@@ -1 +0,0 @@
-
\ No newline at end of file
diff --git a/app/assets/images/illustrations/monitoring/unable_to_connect.svg b/app/assets/images/illustrations/monitoring/unable_to_connect.svg
deleted file mode 100644
index 314c052f93..0000000000
--- a/app/assets/images/illustrations/monitoring/unable_to_connect.svg
+++ /dev/null
@@ -1 +0,0 @@
-
\ No newline at end of file
diff --git a/app/assets/images/illustrations/multi-editor_all_changes_committed_empty.svg b/app/assets/images/illustrations/multi-editor_all_changes_committed_empty.svg
deleted file mode 100644
index 06d73941c3..0000000000
--- a/app/assets/images/illustrations/multi-editor_all_changes_committed_empty.svg
+++ /dev/null
@@ -1 +0,0 @@
-
\ No newline at end of file
diff --git a/app/assets/images/illustrations/multi-editor_no_changes_empty.svg b/app/assets/images/illustrations/multi-editor_no_changes_empty.svg
deleted file mode 100644
index ebeea1f3dd..0000000000
--- a/app/assets/images/illustrations/multi-editor_no_changes_empty.svg
+++ /dev/null
@@ -1 +0,0 @@
-
\ No newline at end of file
diff --git a/app/assets/images/illustrations/multi-editor_no_staged_files_empty.svg b/app/assets/images/illustrations/multi-editor_no_staged_files_empty.svg
deleted file mode 100644
index 08321ef526..0000000000
--- a/app/assets/images/illustrations/multi-editor_no_staged_files_empty.svg
+++ /dev/null
@@ -1 +0,0 @@
-
\ No newline at end of file
diff --git a/app/assets/images/illustrations/multi_file_editor_empty.svg b/app/assets/images/illustrations/multi_file_editor_empty.svg
deleted file mode 100644
index bd376f0a05..0000000000
--- a/app/assets/images/illustrations/multi_file_editor_empty.svg
+++ /dev/null
@@ -1 +0,0 @@
-
\ No newline at end of file
diff --git a/app/assets/images/illustrations/no_commits.svg b/app/assets/images/illustrations/no_commits.svg
deleted file mode 100644
index 76fa25156d..0000000000
--- a/app/assets/images/illustrations/no_commits.svg
+++ /dev/null
@@ -1 +0,0 @@
-
\ No newline at end of file
diff --git a/app/assets/images/illustrations/pending_job_empty.svg b/app/assets/images/illustrations/pending_job_empty.svg
deleted file mode 100644
index 8de695afa1..0000000000
--- a/app/assets/images/illustrations/pending_job_empty.svg
+++ /dev/null
@@ -1 +0,0 @@
-
\ No newline at end of file
diff --git a/app/assets/images/illustrations/pipelines_empty.svg b/app/assets/images/illustrations/pipelines_empty.svg
deleted file mode 100644
index f3107c8f06..0000000000
--- a/app/assets/images/illustrations/pipelines_empty.svg
+++ /dev/null
@@ -1 +0,0 @@
-
\ No newline at end of file
diff --git a/app/assets/images/illustrations/pipelines_failed.svg b/app/assets/images/illustrations/pipelines_failed.svg
deleted file mode 100644
index 8daf7da86e..0000000000
--- a/app/assets/images/illustrations/pipelines_failed.svg
+++ /dev/null
@@ -1 +0,0 @@
-
\ No newline at end of file
diff --git a/app/assets/images/illustrations/pipelines_pending.svg b/app/assets/images/illustrations/pipelines_pending.svg
deleted file mode 100644
index 25038366e9..0000000000
--- a/app/assets/images/illustrations/pipelines_pending.svg
+++ /dev/null
@@ -1 +0,0 @@
-
\ No newline at end of file
diff --git a/app/assets/images/illustrations/priority_labels.svg b/app/assets/images/illustrations/priority_labels.svg
deleted file mode 100644
index b79c551d3d..0000000000
--- a/app/assets/images/illustrations/priority_labels.svg
+++ /dev/null
@@ -1 +0,0 @@
-
\ No newline at end of file
diff --git a/app/assets/images/illustrations/service_desk_callout.svg b/app/assets/images/illustrations/service_desk_callout.svg
deleted file mode 100644
index 2886388279..0000000000
--- a/app/assets/images/illustrations/service_desk_callout.svg
+++ /dev/null
@@ -1 +0,0 @@
-
\ No newline at end of file
diff --git a/app/assets/images/illustrations/service_desk_empty.svg b/app/assets/images/illustrations/service_desk_empty.svg
deleted file mode 100644
index daaaeae6a1..0000000000
--- a/app/assets/images/illustrations/service_desk_empty.svg
+++ /dev/null
@@ -1 +0,0 @@
-
\ No newline at end of file
diff --git a/app/assets/images/illustrations/slack_logo.svg b/app/assets/images/illustrations/slack_logo.svg
deleted file mode 100644
index b8d7906c2e..0000000000
--- a/app/assets/images/illustrations/slack_logo.svg
+++ /dev/null
@@ -1 +0,0 @@
-
\ No newline at end of file
diff --git a/app/assets/images/illustrations/todos_all_done.svg b/app/assets/images/illustrations/todos_all_done.svg
deleted file mode 100644
index 6387497a6f..0000000000
--- a/app/assets/images/illustrations/todos_all_done.svg
+++ /dev/null
@@ -1 +0,0 @@
-
\ No newline at end of file
diff --git a/app/assets/images/illustrations/todos_empty.svg b/app/assets/images/illustrations/todos_empty.svg
deleted file mode 100644
index 4de6cb403b..0000000000
--- a/app/assets/images/illustrations/todos_empty.svg
+++ /dev/null
@@ -1 +0,0 @@
-
\ No newline at end of file
diff --git a/app/assets/images/illustrations/welcome/add_new_group.svg b/app/assets/images/illustrations/welcome/add_new_group.svg
deleted file mode 100644
index b10a3ae881..0000000000
--- a/app/assets/images/illustrations/welcome/add_new_group.svg
+++ /dev/null
@@ -1 +0,0 @@
-
\ No newline at end of file
diff --git a/app/assets/images/illustrations/welcome/add_new_project.svg b/app/assets/images/illustrations/welcome/add_new_project.svg
deleted file mode 100644
index 4b8dc34c08..0000000000
--- a/app/assets/images/illustrations/welcome/add_new_project.svg
+++ /dev/null
@@ -1 +0,0 @@
-
\ No newline at end of file
diff --git a/app/assets/images/illustrations/welcome/add_new_user.svg b/app/assets/images/illustrations/welcome/add_new_user.svg
deleted file mode 100644
index d4c184989b..0000000000
--- a/app/assets/images/illustrations/welcome/add_new_user.svg
+++ /dev/null
@@ -1 +0,0 @@
-
\ No newline at end of file
diff --git a/app/assets/images/illustrations/welcome/configure_server.svg b/app/assets/images/illustrations/welcome/configure_server.svg
deleted file mode 100644
index f9dda816f1..0000000000
--- a/app/assets/images/illustrations/welcome/configure_server.svg
+++ /dev/null
@@ -1 +0,0 @@
-
\ No newline at end of file
diff --git a/app/assets/images/illustrations/welcome/ee_trial.svg b/app/assets/images/illustrations/welcome/ee_trial.svg
deleted file mode 100644
index 6d0dcf0020..0000000000
--- a/app/assets/images/illustrations/welcome/ee_trial.svg
+++ /dev/null
@@ -1 +0,0 @@
-
\ No newline at end of file
diff --git a/app/assets/images/illustrations/welcome/globe.svg b/app/assets/images/illustrations/welcome/globe.svg
deleted file mode 100644
index c2daae5f31..0000000000
--- a/app/assets/images/illustrations/welcome/globe.svg
+++ /dev/null
@@ -1 +0,0 @@
-
\ No newline at end of file
diff --git a/app/assets/images/illustrations/welcome/lightbulb.svg b/app/assets/images/illustrations/welcome/lightbulb.svg
deleted file mode 100644
index fce1031208..0000000000
--- a/app/assets/images/illustrations/welcome/lightbulb.svg
+++ /dev/null
@@ -1 +0,0 @@
-
\ No newline at end of file
diff --git a/app/assets/images/illustrations/wiki-fro-logged-out-users.svg b/app/assets/images/illustrations/wiki-fro-logged-out-users.svg
deleted file mode 100644
index c71841f72e..0000000000
--- a/app/assets/images/illustrations/wiki-fro-logged-out-users.svg
+++ /dev/null
@@ -1 +0,0 @@
-
\ No newline at end of file
diff --git a/app/assets/images/illustrations/wiki_login_empty.svg b/app/assets/images/illustrations/wiki_login_empty.svg
deleted file mode 100644
index 1cfa47220a..0000000000
--- a/app/assets/images/illustrations/wiki_login_empty.svg
+++ /dev/null
@@ -1 +0,0 @@
-
\ No newline at end of file
diff --git a/app/assets/images/illustrations/wiki_logout_empty.svg b/app/assets/images/illustrations/wiki_logout_empty.svg
deleted file mode 100644
index c71841f72e..0000000000
--- a/app/assets/images/illustrations/wiki_logout_empty.svg
+++ /dev/null
@@ -1 +0,0 @@
-
\ No newline at end of file
diff --git a/app/assets/javascripts/activities.js b/app/assets/javascripts/activities.js
index 6a0662ba90..c117d080bd 100644
--- a/app/assets/javascripts/activities.js
+++ b/app/assets/javascripts/activities.js
@@ -1,5 +1,6 @@
/* eslint-disable no-param-reassign, class-methods-use-this */
+import $ from 'jquery';
import Cookies from 'js-cookie';
import Pager from './pager';
import { localTimeAgo } from './lib/utils/datetime_utility';
diff --git a/app/assets/javascripts/ajax_loading_spinner.js b/app/assets/javascripts/ajax_loading_spinner.js
index 2bc77859c2..bd08308904 100644
--- a/app/assets/javascripts/ajax_loading_spinner.js
+++ b/app/assets/javascripts/ajax_loading_spinner.js
@@ -1,3 +1,5 @@
+import $ from 'jquery';
+
export default class AjaxLoadingSpinner {
static init() {
const $elements = $('.js-ajax-loading-spinner');
diff --git a/app/assets/javascripts/api.js b/app/assets/javascripts/api.js
index 464611f66f..8ad3d18b30 100644
--- a/app/assets/javascripts/api.js
+++ b/app/assets/javascripts/api.js
@@ -1,3 +1,4 @@
+import $ from 'jquery';
import _ from 'underscore';
import axios from './lib/utils/axios_utils';
@@ -9,6 +10,9 @@ const Api = {
projectsPath: '/api/:version/projects.json',
projectPath: '/api/:version/projects/:id',
projectLabelsPath: '/:namespace_path/:project_path/labels',
+ mergeRequestPath: '/api/:version/projects/:id/merge_requests/:mrid',
+ mergeRequestChangesPath: '/api/:version/projects/:id/merge_requests/:mrid/changes',
+ mergeRequestVersionsPath: '/api/:version/projects/:id/merge_requests/:mrid/versions',
groupLabelsPath: '/groups/:namespace_path/-/labels',
licensePath: '/api/:version/templates/licenses/:key',
gitignorePath: '/api/:version/templates/gitignores/:key',
@@ -21,25 +25,27 @@ const Api = {
createBranchPath: '/api/:version/projects/:id/repository/branches',
group(groupId, callback) {
- const url = Api.buildUrl(Api.groupPath)
- .replace(':id', groupId);
- return axios.get(url)
- .then(({ data }) => {
- callback(data);
+ const url = Api.buildUrl(Api.groupPath).replace(':id', groupId);
+ return axios.get(url).then(({ data }) => {
+ callback(data);
- return data;
- });
+ return data;
+ });
},
// Return groups list. Filtered by query
groups(query, options, callback = $.noop) {
const url = Api.buildUrl(Api.groupsPath);
- return axios.get(url, {
- params: Object.assign({
- search: query,
- per_page: 20,
- }, options),
- })
+ return axios
+ .get(url, {
+ params: Object.assign(
+ {
+ search: query,
+ per_page: 20,
+ },
+ options,
+ ),
+ })
.then(({ data }) => {
callback(data);
@@ -50,12 +56,13 @@ const Api = {
// Return namespaces list. Filtered by query
namespaces(query, callback) {
const url = Api.buildUrl(Api.namespacesPath);
- return axios.get(url, {
- params: {
- search: query,
- per_page: 20,
- },
- })
+ return axios
+ .get(url, {
+ params: {
+ search: query,
+ per_page: 20,
+ },
+ })
.then(({ data }) => callback(data));
},
@@ -72,9 +79,10 @@ const Api = {
defaults.membership = true;
}
- return axios.get(url, {
- params: Object.assign(defaults, options),
- })
+ return axios
+ .get(url, {
+ params: Object.assign(defaults, options),
+ })
.then(({ data }) => {
callback(data);
@@ -84,8 +92,32 @@ const Api = {
// Return single project
project(projectPath) {
- const url = Api.buildUrl(Api.projectPath)
- .replace(':id', encodeURIComponent(projectPath));
+ const url = Api.buildUrl(Api.projectPath).replace(':id', encodeURIComponent(projectPath));
+
+ return axios.get(url);
+ },
+
+ // Return Merge Request for project
+ mergeRequest(projectPath, mergeRequestId) {
+ const url = Api.buildUrl(Api.mergeRequestPath)
+ .replace(':id', encodeURIComponent(projectPath))
+ .replace(':mrid', mergeRequestId);
+
+ return axios.get(url);
+ },
+
+ mergeRequestChanges(projectPath, mergeRequestId) {
+ const url = Api.buildUrl(Api.mergeRequestChangesPath)
+ .replace(':id', encodeURIComponent(projectPath))
+ .replace(':mrid', mergeRequestId);
+
+ return axios.get(url);
+ },
+
+ mergeRequestVersions(projectPath, mergeRequestId) {
+ const url = Api.buildUrl(Api.mergeRequestVersionsPath)
+ .replace(':id', encodeURIComponent(projectPath))
+ .replace(':mrid', mergeRequestId);
return axios.get(url);
},
@@ -101,30 +133,30 @@ const Api = {
url = Api.buildUrl(Api.groupLabelsPath).replace(':namespace_path', namespacePath);
}
- return axios.post(url, {
- label: data,
- })
+ return axios
+ .post(url, {
+ label: data,
+ })
.then(res => callback(res.data))
.catch(e => callback(e.response.data));
},
// Return group projects list. Filtered by query
groupProjects(groupId, query, callback) {
- const url = Api.buildUrl(Api.groupProjectsPath)
- .replace(':id', groupId);
- return axios.get(url, {
- params: {
- search: query,
- per_page: 20,
- },
- })
+ const url = Api.buildUrl(Api.groupProjectsPath).replace(':id', groupId);
+ return axios
+ .get(url, {
+ params: {
+ search: query,
+ per_page: 20,
+ },
+ })
.then(({ data }) => callback(data));
},
commitMultiple(id, data) {
// see https://docs.gitlab.com/ce/api/commits.html#create-a-commit-with-multiple-files-and-actions
- const url = Api.buildUrl(Api.commitPath)
- .replace(':id', encodeURIComponent(id));
+ const url = Api.buildUrl(Api.commitPath).replace(':id', encodeURIComponent(id));
return axios.post(url, JSON.stringify(data), {
headers: {
'Content-Type': 'application/json; charset=utf-8',
@@ -135,39 +167,34 @@ const Api = {
branchSingle(id, branch) {
const url = Api.buildUrl(Api.branchSinglePath)
.replace(':id', encodeURIComponent(id))
- .replace(':branch', branch);
+ .replace(':branch', encodeURIComponent(branch));
return axios.get(url);
},
// Return text for a specific license
licenseText(key, data, callback) {
- const url = Api.buildUrl(Api.licensePath)
- .replace(':key', key);
- return axios.get(url, {
- params: data,
- })
+ const url = Api.buildUrl(Api.licensePath).replace(':key', key);
+ return axios
+ .get(url, {
+ params: data,
+ })
.then(res => callback(res.data));
},
gitignoreText(key, callback) {
- const url = Api.buildUrl(Api.gitignorePath)
- .replace(':key', key);
- return axios.get(url)
- .then(({ data }) => callback(data));
+ const url = Api.buildUrl(Api.gitignorePath).replace(':key', key);
+ return axios.get(url).then(({ data }) => callback(data));
},
gitlabCiYml(key, callback) {
- const url = Api.buildUrl(Api.gitlabCiYmlPath)
- .replace(':key', key);
- return axios.get(url)
- .then(({ data }) => callback(data));
+ const url = Api.buildUrl(Api.gitlabCiYmlPath).replace(':key', key);
+ return axios.get(url).then(({ data }) => callback(data));
},
dockerfileYml(key, callback) {
const url = Api.buildUrl(Api.dockerfilePath).replace(':key', key);
- return axios.get(url)
- .then(({ data }) => callback(data));
+ return axios.get(url).then(({ data }) => callback(data));
},
issueTemplate(namespacePath, projectPath, key, type, callback) {
@@ -176,7 +203,8 @@ const Api = {
.replace(':type', type)
.replace(':project_path', projectPath)
.replace(':namespace_path', namespacePath);
- return axios.get(url)
+ return axios
+ .get(url)
.then(({ data }) => callback(null, data))
.catch(callback);
},
@@ -184,10 +212,13 @@ const Api = {
users(query, options) {
const url = Api.buildUrl(this.usersPath);
return axios.get(url, {
- params: Object.assign({
- search: query,
- per_page: 20,
- }, options),
+ params: Object.assign(
+ {
+ search: query,
+ per_page: 20,
+ },
+ options,
+ ),
});
},
diff --git a/app/assets/javascripts/awards_handler.js b/app/assets/javascripts/awards_handler.js
index 26e62732b3..976d32abe9 100644
--- a/app/assets/javascripts/awards_handler.js
+++ b/app/assets/javascripts/awards_handler.js
@@ -1,8 +1,11 @@
/* eslint-disable class-methods-use-this */
+
+import $ from 'jquery';
import _ from 'underscore';
import Cookies from 'js-cookie';
import { __ } from './locale';
-import { isInIssuePage, isInMRPage, hasVueMRDiscussionsCookie, updateTooltipTitle } from './lib/utils/common_utils';
+import { updateTooltipTitle } from './lib/utils/common_utils';
+import { isInVueNoteablePage } from './lib/utils/dom_utils';
import flash from './flash';
import axios from './lib/utils/axios_utils';
@@ -241,7 +244,7 @@ class AwardsHandler {
addAward(votesBlock, awardUrl, emoji, checkMutuality, callback) {
const isMainAwardsBlock = votesBlock.closest('.js-noteable-awards').length;
- if (this.isInVueNoteablePage() && !isMainAwardsBlock) {
+ if (isInVueNoteablePage() && !isMainAwardsBlock) {
const id = votesBlock.attr('id').replace('note_', '');
this.hideMenuElement($('.emoji-menu'));
@@ -293,16 +296,8 @@ class AwardsHandler {
}
}
- isVueMRDiscussions() {
- return isInMRPage() && hasVueMRDiscussionsCookie() && !$('#diffs').is(':visible');
- }
-
- isInVueNoteablePage() {
- return isInIssuePage() || this.isVueMRDiscussions();
- }
-
getVotesBlock() {
- if (this.isInVueNoteablePage()) {
+ if (isInVueNoteablePage()) {
const $el = $('.js-add-award.is-active').closest('.note.timeline-entry');
if ($el.length) {
diff --git a/app/assets/javascripts/badges/components/badge.vue b/app/assets/javascripts/badges/components/badge.vue
new file mode 100644
index 0000000000..6e6cb31e3a
--- /dev/null
+++ b/app/assets/javascripts/badges/components/badge.vue
@@ -0,0 +1,121 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ s__('Badges|No badge image') }}
+
+
+
+
+
+
diff --git a/app/assets/javascripts/badges/components/badge_form.vue b/app/assets/javascripts/badges/components/badge_form.vue
new file mode 100644
index 0000000000..ae942b2c1a
--- /dev/null
+++ b/app/assets/javascripts/badges/components/badge_form.vue
@@ -0,0 +1,219 @@
+
+
+
+
+
diff --git a/app/assets/javascripts/badges/components/badge_list.vue b/app/assets/javascripts/badges/components/badge_list.vue
new file mode 100644
index 0000000000..ca7197e1e0
--- /dev/null
+++ b/app/assets/javascripts/badges/components/badge_list.vue
@@ -0,0 +1,57 @@
+
+
+
+
+
+ {{ s__('Badges|Your badges') }}
+ {{ badges.length }}
+
+
+
+ {{ s__('Badges|This group has no badges') }}
+ {{ s__('Badges|This project has no badges') }}
+
+
+
+
+
+
diff --git a/app/assets/javascripts/badges/components/badge_list_row.vue b/app/assets/javascripts/badges/components/badge_list_row.vue
new file mode 100644
index 0000000000..af062bdf8c
--- /dev/null
+++ b/app/assets/javascripts/badges/components/badge_list_row.vue
@@ -0,0 +1,89 @@
+
+
+
+
+
+
{{ badge.linkUrl }}
+
+ {{ badgeKindText }}
+
+
+
+
diff --git a/app/assets/javascripts/badges/components/badge_settings.vue b/app/assets/javascripts/badges/components/badge_settings.vue
new file mode 100644
index 0000000000..83f7839423
--- /dev/null
+++ b/app/assets/javascripts/badges/components/badge_settings.vue
@@ -0,0 +1,70 @@
+
+
+
+
+
diff --git a/app/assets/javascripts/badges/constants.js b/app/assets/javascripts/badges/constants.js
new file mode 100644
index 0000000000..8fbe3db5ef
--- /dev/null
+++ b/app/assets/javascripts/badges/constants.js
@@ -0,0 +1,2 @@
+export const GROUP_BADGE = 'group';
+export const PROJECT_BADGE = 'project';
diff --git a/app/assets/javascripts/badges/empty_badge.js b/app/assets/javascripts/badges/empty_badge.js
new file mode 100644
index 0000000000..49a9b5e1be
--- /dev/null
+++ b/app/assets/javascripts/badges/empty_badge.js
@@ -0,0 +1,7 @@
+export default () => ({
+ imageUrl: '',
+ isDeleting: false,
+ linkUrl: '',
+ renderedImageUrl: '',
+ renderedLinkUrl: '',
+});
diff --git a/app/assets/javascripts/badges/store/actions.js b/app/assets/javascripts/badges/store/actions.js
new file mode 100644
index 0000000000..5542278b3e
--- /dev/null
+++ b/app/assets/javascripts/badges/store/actions.js
@@ -0,0 +1,167 @@
+import axios from '~/lib/utils/axios_utils';
+import types from './mutation_types';
+
+export const transformBackendBadge = badge => ({
+ id: badge.id,
+ imageUrl: badge.image_url,
+ kind: badge.kind,
+ linkUrl: badge.link_url,
+ renderedImageUrl: badge.rendered_image_url,
+ renderedLinkUrl: badge.rendered_link_url,
+ isDeleting: false,
+});
+
+export default {
+ requestNewBadge({ commit }) {
+ commit(types.REQUEST_NEW_BADGE);
+ },
+ receiveNewBadge({ commit }, newBadge) {
+ commit(types.RECEIVE_NEW_BADGE, newBadge);
+ },
+ receiveNewBadgeError({ commit }) {
+ commit(types.RECEIVE_NEW_BADGE_ERROR);
+ },
+ addBadge({ dispatch, state }) {
+ const newBadge = state.badgeInAddForm;
+ const endpoint = state.apiEndpointUrl;
+ dispatch('requestNewBadge');
+ return axios
+ .post(endpoint, {
+ image_url: newBadge.imageUrl,
+ link_url: newBadge.linkUrl,
+ })
+ .catch(error => {
+ dispatch('receiveNewBadgeError');
+ throw error;
+ })
+ .then(res => {
+ dispatch('receiveNewBadge', transformBackendBadge(res.data));
+ });
+ },
+ requestDeleteBadge({ commit }, badgeId) {
+ commit(types.REQUEST_DELETE_BADGE, badgeId);
+ },
+ receiveDeleteBadge({ commit }, badgeId) {
+ commit(types.RECEIVE_DELETE_BADGE, badgeId);
+ },
+ receiveDeleteBadgeError({ commit }, badgeId) {
+ commit(types.RECEIVE_DELETE_BADGE_ERROR, badgeId);
+ },
+ deleteBadge({ dispatch, state }, badge) {
+ const badgeId = badge.id;
+ dispatch('requestDeleteBadge', badgeId);
+ const endpoint = `${state.apiEndpointUrl}/${badgeId}`;
+ return axios
+ .delete(endpoint)
+ .catch(error => {
+ dispatch('receiveDeleteBadgeError', badgeId);
+ throw error;
+ })
+ .then(() => {
+ dispatch('receiveDeleteBadge', badgeId);
+ });
+ },
+
+ editBadge({ commit }, badge) {
+ commit(types.START_EDITING, badge);
+ },
+
+ requestLoadBadges({ commit }, data) {
+ commit(types.REQUEST_LOAD_BADGES, data);
+ },
+ receiveLoadBadges({ commit }, badges) {
+ commit(types.RECEIVE_LOAD_BADGES, badges);
+ },
+ receiveLoadBadgesError({ commit }) {
+ commit(types.RECEIVE_LOAD_BADGES_ERROR);
+ },
+
+ loadBadges({ dispatch, state }, data) {
+ dispatch('requestLoadBadges', data);
+ const endpoint = state.apiEndpointUrl;
+ return axios
+ .get(endpoint)
+ .catch(error => {
+ dispatch('receiveLoadBadgesError');
+ throw error;
+ })
+ .then(res => {
+ dispatch('receiveLoadBadges', res.data.map(transformBackendBadge));
+ });
+ },
+
+ requestRenderedBadge({ commit }) {
+ commit(types.REQUEST_RENDERED_BADGE);
+ },
+ receiveRenderedBadge({ commit }, renderedBadge) {
+ commit(types.RECEIVE_RENDERED_BADGE, renderedBadge);
+ },
+ receiveRenderedBadgeError({ commit }) {
+ commit(types.RECEIVE_RENDERED_BADGE_ERROR);
+ },
+
+ renderBadge({ dispatch, state }) {
+ const badge = state.isEditing ? state.badgeInEditForm : state.badgeInAddForm;
+ const { linkUrl, imageUrl } = badge;
+ if (!linkUrl || linkUrl.trim() === '' || !imageUrl || imageUrl.trim() === '') {
+ return Promise.resolve(badge);
+ }
+
+ dispatch('requestRenderedBadge');
+
+ const parameters = [
+ `link_url=${encodeURIComponent(linkUrl)}`,
+ `image_url=${encodeURIComponent(imageUrl)}`,
+ ].join('&');
+ const renderEndpoint = `${state.apiEndpointUrl}/render?${parameters}`;
+ return axios
+ .get(renderEndpoint)
+ .catch(error => {
+ dispatch('receiveRenderedBadgeError');
+ throw error;
+ })
+ .then(res => {
+ dispatch('receiveRenderedBadge', transformBackendBadge(res.data));
+ });
+ },
+
+ requestUpdatedBadge({ commit }) {
+ commit(types.REQUEST_UPDATED_BADGE);
+ },
+ receiveUpdatedBadge({ commit }, updatedBadge) {
+ commit(types.RECEIVE_UPDATED_BADGE, updatedBadge);
+ },
+ receiveUpdatedBadgeError({ commit }) {
+ commit(types.RECEIVE_UPDATED_BADGE_ERROR);
+ },
+
+ saveBadge({ dispatch, state }) {
+ const badge = state.badgeInEditForm;
+ const endpoint = `${state.apiEndpointUrl}/${badge.id}`;
+ dispatch('requestUpdatedBadge');
+ return axios
+ .put(endpoint, {
+ image_url: badge.imageUrl,
+ link_url: badge.linkUrl,
+ })
+ .catch(error => {
+ dispatch('receiveUpdatedBadgeError');
+ throw error;
+ })
+ .then(res => {
+ dispatch('receiveUpdatedBadge', transformBackendBadge(res.data));
+ });
+ },
+
+ stopEditing({ commit }) {
+ commit(types.STOP_EDITING);
+ },
+
+ updateBadgeInForm({ commit }, badge) {
+ commit(types.UPDATE_BADGE_IN_FORM, badge);
+ },
+
+ updateBadgeInModal({ commit }, badge) {
+ commit(types.UPDATE_BADGE_IN_MODAL, badge);
+ },
+};
diff --git a/app/assets/javascripts/badges/store/index.js b/app/assets/javascripts/badges/store/index.js
new file mode 100644
index 0000000000..7a5df403a0
--- /dev/null
+++ b/app/assets/javascripts/badges/store/index.js
@@ -0,0 +1,13 @@
+import Vue from 'vue';
+import Vuex from 'vuex';
+import createState from './state';
+import actions from './actions';
+import mutations from './mutations';
+
+Vue.use(Vuex);
+
+export default new Vuex.Store({
+ state: createState(),
+ actions,
+ mutations,
+});
diff --git a/app/assets/javascripts/badges/store/mutation_types.js b/app/assets/javascripts/badges/store/mutation_types.js
new file mode 100644
index 0000000000..d73f91b600
--- /dev/null
+++ b/app/assets/javascripts/badges/store/mutation_types.js
@@ -0,0 +1,21 @@
+export default {
+ RECEIVE_DELETE_BADGE: 'RECEIVE_DELETE_BADGE',
+ RECEIVE_DELETE_BADGE_ERROR: 'RECEIVE_DELETE_BADGE_ERROR',
+ RECEIVE_LOAD_BADGES: 'RECEIVE_LOAD_BADGES',
+ RECEIVE_LOAD_BADGES_ERROR: 'RECEIVE_LOAD_BADGES_ERROR',
+ RECEIVE_NEW_BADGE: 'RECEIVE_NEW_BADGE',
+ RECEIVE_NEW_BADGE_ERROR: 'RECEIVE_NEW_BADGE_ERROR',
+ RECEIVE_RENDERED_BADGE: 'RECEIVE_RENDERED_BADGE',
+ RECEIVE_RENDERED_BADGE_ERROR: 'RECEIVE_RENDERED_BADGE_ERROR',
+ RECEIVE_UPDATED_BADGE: 'RECEIVE_UPDATED_BADGE',
+ RECEIVE_UPDATED_BADGE_ERROR: 'RECEIVE_UPDATED_BADGE_ERROR',
+ REQUEST_DELETE_BADGE: 'REQUEST_DELETE_BADGE',
+ REQUEST_LOAD_BADGES: 'REQUEST_LOAD_BADGES',
+ REQUEST_NEW_BADGE: 'REQUEST_NEW_BADGE',
+ REQUEST_RENDERED_BADGE: 'REQUEST_RENDERED_BADGE',
+ REQUEST_UPDATED_BADGE: 'REQUEST_UPDATED_BADGE',
+ START_EDITING: 'START_EDITING',
+ STOP_EDITING: 'STOP_EDITING',
+ UPDATE_BADGE_IN_FORM: 'UPDATE_BADGE_IN_FORM',
+ UPDATE_BADGE_IN_MODAL: 'UPDATE_BADGE_IN_MODAL',
+};
diff --git a/app/assets/javascripts/badges/store/mutations.js b/app/assets/javascripts/badges/store/mutations.js
new file mode 100644
index 0000000000..bd84e68c00
--- /dev/null
+++ b/app/assets/javascripts/badges/store/mutations.js
@@ -0,0 +1,158 @@
+import types from './mutation_types';
+import { PROJECT_BADGE } from '../constants';
+
+const reorderBadges = badges =>
+ badges.sort((a, b) => {
+ if (a.kind !== b.kind) {
+ return a.kind === PROJECT_BADGE ? 1 : -1;
+ }
+
+ return a.id - b.id;
+ });
+
+export default {
+ [types.RECEIVE_NEW_BADGE](state, newBadge) {
+ Object.assign(state, {
+ badgeInAddForm: null,
+ badges: reorderBadges(state.badges.concat(newBadge)),
+ isSaving: false,
+ renderedBadge: null,
+ });
+ },
+ [types.RECEIVE_NEW_BADGE_ERROR](state) {
+ Object.assign(state, {
+ isSaving: false,
+ });
+ },
+ [types.REQUEST_NEW_BADGE](state) {
+ Object.assign(state, {
+ isSaving: true,
+ });
+ },
+
+ [types.RECEIVE_UPDATED_BADGE](state, updatedBadge) {
+ const badges = state.badges.map(badge => {
+ if (badge.id === updatedBadge.id) {
+ return updatedBadge;
+ }
+ return badge;
+ });
+ Object.assign(state, {
+ badgeInEditForm: null,
+ badges,
+ isEditing: false,
+ isSaving: false,
+ renderedBadge: null,
+ });
+ },
+ [types.RECEIVE_UPDATED_BADGE_ERROR](state) {
+ Object.assign(state, {
+ isSaving: false,
+ });
+ },
+ [types.REQUEST_UPDATED_BADGE](state) {
+ Object.assign(state, {
+ isSaving: true,
+ });
+ },
+
+ [types.RECEIVE_LOAD_BADGES](state, badges) {
+ Object.assign(state, {
+ badges: reorderBadges(badges),
+ isLoading: false,
+ });
+ },
+ [types.RECEIVE_LOAD_BADGES_ERROR](state) {
+ Object.assign(state, {
+ isLoading: false,
+ });
+ },
+ [types.REQUEST_LOAD_BADGES](state, data) {
+ Object.assign(state, {
+ kind: data.kind, // project or group
+ apiEndpointUrl: data.apiEndpointUrl,
+ docsUrl: data.docsUrl,
+ isLoading: true,
+ });
+ },
+
+ [types.RECEIVE_DELETE_BADGE](state, badgeId) {
+ const badges = state.badges.filter(badge => badge.id !== badgeId);
+ Object.assign(state, {
+ badges,
+ });
+ },
+ [types.RECEIVE_DELETE_BADGE_ERROR](state, badgeId) {
+ const badges = state.badges.map(badge => {
+ if (badge.id === badgeId) {
+ return {
+ ...badge,
+ isDeleting: false,
+ };
+ }
+
+ return badge;
+ });
+ Object.assign(state, {
+ badges,
+ });
+ },
+ [types.REQUEST_DELETE_BADGE](state, badgeId) {
+ const badges = state.badges.map(badge => {
+ if (badge.id === badgeId) {
+ return {
+ ...badge,
+ isDeleting: true,
+ };
+ }
+
+ return badge;
+ });
+ Object.assign(state, {
+ badges,
+ });
+ },
+
+ [types.RECEIVE_RENDERED_BADGE](state, renderedBadge) {
+ Object.assign(state, { isRendering: false, renderedBadge });
+ },
+ [types.RECEIVE_RENDERED_BADGE_ERROR](state) {
+ Object.assign(state, { isRendering: false });
+ },
+ [types.REQUEST_RENDERED_BADGE](state) {
+ Object.assign(state, { isRendering: true });
+ },
+
+ [types.START_EDITING](state, badge) {
+ Object.assign(state, {
+ badgeInEditForm: { ...badge },
+ isEditing: true,
+ renderedBadge: { ...badge },
+ });
+ },
+ [types.STOP_EDITING](state) {
+ Object.assign(state, {
+ badgeInEditForm: null,
+ isEditing: false,
+ renderedBadge: null,
+ });
+ },
+
+ [types.UPDATE_BADGE_IN_FORM](state, badge) {
+ if (state.isEditing) {
+ Object.assign(state, {
+ badgeInEditForm: badge,
+ });
+ } else {
+ Object.assign(state, {
+ badgeInAddForm: badge,
+ });
+ }
+ },
+
+ [types.UPDATE_BADGE_IN_MODAL](state, badge) {
+ Object.assign(state, {
+ badgeInModal: badge,
+ });
+ },
+};
diff --git a/app/assets/javascripts/badges/store/state.js b/app/assets/javascripts/badges/store/state.js
new file mode 100644
index 0000000000..43413aeb5b
--- /dev/null
+++ b/app/assets/javascripts/badges/store/state.js
@@ -0,0 +1,13 @@
+export default () => ({
+ apiEndpointUrl: null,
+ badgeInAddForm: null,
+ badgeInEditForm: null,
+ badgeInModal: null,
+ badges: [],
+ docsUrl: null,
+ renderedBadge: null,
+ isEditing: false,
+ isLoading: false,
+ isRendering: false,
+ isSaving: false,
+});
diff --git a/app/assets/javascripts/behaviors/copy_to_clipboard.js b/app/assets/javascripts/behaviors/copy_to_clipboard.js
index b669b63d23..e2a73a1797 100644
--- a/app/assets/javascripts/behaviors/copy_to_clipboard.js
+++ b/app/assets/javascripts/behaviors/copy_to_clipboard.js
@@ -1,3 +1,4 @@
+import $ from 'jquery';
import Clipboard from 'clipboard';
function showTooltip(target, title) {
diff --git a/app/assets/javascripts/behaviors/details_behavior.js b/app/assets/javascripts/behaviors/details_behavior.js
index 7c9dbcc8d6..1d63f5baee 100644
--- a/app/assets/javascripts/behaviors/details_behavior.js
+++ b/app/assets/javascripts/behaviors/details_behavior.js
@@ -1,3 +1,4 @@
+import $ from 'jquery';
$(() => {
$('body').on('click', '.js-details-target', function target() {
diff --git a/app/assets/javascripts/behaviors/index.js b/app/assets/javascripts/behaviors/index.js
index 8d021de799..84fef4d8b4 100644
--- a/app/assets/javascripts/behaviors/index.js
+++ b/app/assets/javascripts/behaviors/index.js
@@ -1,6 +1,7 @@
import './autosize';
import './bind_in_out';
-import initCopyAsGFM from './copy_as_gfm';
+import './markdown/render_gfm';
+import initCopyAsGFM from './markdown/copy_as_gfm';
import initCopyToClipboard from './copy_to_clipboard';
import './details_behavior';
import installGlEmojiElement from './gl_emoji';
diff --git a/app/assets/javascripts/behaviors/copy_as_gfm.js b/app/assets/javascripts/behaviors/markdown/copy_as_gfm.js
similarity index 99%
rename from app/assets/javascripts/behaviors/copy_as_gfm.js
rename to app/assets/javascripts/behaviors/markdown/copy_as_gfm.js
index ffe90595b5..75cf90de0b 100644
--- a/app/assets/javascripts/behaviors/copy_as_gfm.js
+++ b/app/assets/javascripts/behaviors/markdown/copy_as_gfm.js
@@ -1,8 +1,9 @@
/* eslint-disable class-methods-use-this, object-shorthand, no-unused-vars, no-use-before-define, no-new, max-len, 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';
+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
diff --git a/app/assets/javascripts/render_gfm.js b/app/assets/javascripts/behaviors/markdown/render_gfm.js
similarity index 85%
rename from app/assets/javascripts/render_gfm.js
rename to app/assets/javascripts/behaviors/markdown/render_gfm.js
index 05a623ca6d..dbff2bd4b1 100644
--- a/app/assets/javascripts/render_gfm.js
+++ b/app/assets/javascripts/behaviors/markdown/render_gfm.js
@@ -1,6 +1,7 @@
+import $ from 'jquery';
+import syntaxHighlight from '~/syntax_highlight';
import renderMath from './render_math';
import renderMermaid from './render_mermaid';
-import syntaxHighlight from './syntax_highlight';
// Render Gitlab flavoured Markdown
//
diff --git a/app/assets/javascripts/render_math.js b/app/assets/javascripts/behaviors/markdown/render_math.js
similarity index 85%
rename from app/assets/javascripts/render_math.js
rename to app/assets/javascripts/behaviors/markdown/render_math.js
index eabdb01b2a..eb4e59d12b 100644
--- a/app/assets/javascripts/render_math.js
+++ b/app/assets/javascripts/behaviors/markdown/render_math.js
@@ -1,5 +1,6 @@
-import { __ } from './locale';
-import flash from './flash';
+import $ from 'jquery';
+import { __ } from '~/locale';
+import flash from '~/flash';
// Renders math using KaTeX in any element with the
// `js-render-math` class
@@ -30,7 +31,7 @@ export default function renderMath($els) {
if (!$els.length) return;
Promise.all([
import(/* webpackChunkName: 'katex' */ 'katex'),
- import(/* webpackChunkName: 'katex' */ 'katex/dist/katex.css'),
+ import(/* webpackChunkName: 'katex' */ 'katex/dist/katex.min.css'),
]).then(([katex]) => {
renderWithKaTeX($els, katex);
}).catch(() => flash(__('An error occurred while rendering KaTeX')));
diff --git a/app/assets/javascripts/render_mermaid.js b/app/assets/javascripts/behaviors/markdown/render_mermaid.js
similarity index 94%
rename from app/assets/javascripts/render_mermaid.js
rename to app/assets/javascripts/behaviors/markdown/render_mermaid.js
index d4f18955bd..56b1896e9f 100644
--- a/app/assets/javascripts/render_mermaid.js
+++ b/app/assets/javascripts/behaviors/markdown/render_mermaid.js
@@ -1,3 +1,5 @@
+import flash from '~/flash';
+
// Renders diagrams and flowcharts from text using Mermaid in any element with the
// `js-render-mermaid` class.
//
@@ -12,8 +14,6 @@
//
//
-import Flash from './flash';
-
export default function renderMermaid($els) {
if (!$els.length) return;
@@ -52,6 +52,6 @@ export default function renderMermaid($els) {
});
});
}).catch((err) => {
- Flash(`Can't load mermaid module: ${err}`);
+ flash(`Can't load mermaid module: ${err}`);
});
}
diff --git a/app/assets/javascripts/behaviors/quick_submit.js b/app/assets/javascripts/behaviors/quick_submit.js
index 312edc0cd6..3ec932bdb7 100644
--- a/app/assets/javascripts/behaviors/quick_submit.js
+++ b/app/assets/javascripts/behaviors/quick_submit.js
@@ -1,3 +1,4 @@
+import $ from 'jquery';
import '../commons/bootstrap';
import { isInIssuePage } from '../lib/utils/common_utils';
@@ -72,5 +73,5 @@ $(document).on('keyup.quick_submit', '.js-quick-submit input[type=submit], .js-q
title,
trigger: 'manual',
});
- $this.tooltip('show').one('blur', () => $this.tooltip('hide'));
+ $this.tooltip('show').one('blur click', () => $this.tooltip('hide'));
});
diff --git a/app/assets/javascripts/behaviors/requires_input.js b/app/assets/javascripts/behaviors/requires_input.js
index e10cb2e3dc..ffff4ddb71 100644
--- a/app/assets/javascripts/behaviors/requires_input.js
+++ b/app/assets/javascripts/behaviors/requires_input.js
@@ -1,3 +1,4 @@
+import $ from 'jquery';
import _ from 'underscore';
import '../commons/bootstrap';
diff --git a/app/assets/javascripts/behaviors/toggler_behavior.js b/app/assets/javascripts/behaviors/toggler_behavior.js
index 81c8944142..4446be0e52 100644
--- a/app/assets/javascripts/behaviors/toggler_behavior.js
+++ b/app/assets/javascripts/behaviors/toggler_behavior.js
@@ -1,3 +1,6 @@
+import $ from 'jquery';
+import { getLocationHash } from '../lib/utils/url_utility';
+
// Toggle button. Show/hide content inside parent container.
// Button does not change visibility. If button has icon - it changes chevron style.
//
@@ -5,7 +8,6 @@
// %button.js-toggle-button
// %div.js-toggle-content
//
-import { getLocationHash } from '../lib/utils/url_utility';
$(() => {
function toggleContainer(container, toggleState) {
diff --git a/app/assets/javascripts/blob/blob_file_dropzone.js b/app/assets/javascripts/blob/blob_file_dropzone.js
index 83cac896f8..ff1739b167 100644
--- a/app/assets/javascripts/blob/blob_file_dropzone.js
+++ b/app/assets/javascripts/blob/blob_file_dropzone.js
@@ -1,4 +1,6 @@
/* eslint-disable func-names, object-shorthand, prefer-arrow-callback */
+
+import $ from 'jquery';
import Dropzone from 'dropzone';
import { visitUrl } from '../lib/utils/url_utility';
import { HIDDEN_CLASS } from '../lib/utils/constants';
diff --git a/app/assets/javascripts/blob/blob_fork_suggestion.js b/app/assets/javascripts/blob/blob_fork_suggestion.js
index 47c431fb80..476b9405a9 100644
--- a/app/assets/javascripts/blob/blob_fork_suggestion.js
+++ b/app/assets/javascripts/blob/blob_fork_suggestion.js
@@ -1,3 +1,5 @@
+import $ from 'jquery';
+
const defaults = {
// Buttons that will show the `suggestionSections`
// has `data-fork-path`, and `data-action`
diff --git a/app/assets/javascripts/blob/file_template_mediator.js b/app/assets/javascripts/blob/file_template_mediator.js
index 37074301b5..030ca1907e 100644
--- a/app/assets/javascripts/blob/file_template_mediator.js
+++ b/app/assets/javascripts/blob/file_template_mediator.js
@@ -1,4 +1,6 @@
/* eslint-disable class-methods-use-this */
+
+import $ from 'jquery';
import Flash from '../flash';
import FileTemplateTypeSelector from './template_selectors/type_selector';
import BlobCiYamlSelector from './template_selectors/ci_yaml_selector';
diff --git a/app/assets/javascripts/blob/file_template_selector.js b/app/assets/javascripts/blob/file_template_selector.js
index 5ae30990ae..e52cf249f3 100644
--- a/app/assets/javascripts/blob/file_template_selector.js
+++ b/app/assets/javascripts/blob/file_template_selector.js
@@ -1,3 +1,5 @@
+import $ from 'jquery';
+
export default class FileTemplateSelector {
constructor(mediator) {
this.mediator = mediator;
diff --git a/app/assets/javascripts/blob/template_selector.js b/app/assets/javascripts/blob/template_selector.js
index 888883163c..9dfdb06007 100644
--- a/app/assets/javascripts/blob/template_selector.js
+++ b/app/assets/javascripts/blob/template_selector.js
@@ -1,5 +1,7 @@
/* eslint-disable class-methods-use-this, no-unused-vars */
+import $ from 'jquery';
+
export default class TemplateSelector {
constructor({ dropdown, data, pattern, wrapper, editor, $input } = {}) {
this.pattern = pattern;
@@ -76,7 +78,7 @@ export default class TemplateSelector {
if (!skipFocus) this.editor.focus();
- if (this.editor instanceof jQuery) {
+ if (this.editor instanceof $) {
this.editor.get(0).dispatchEvent(this.autosizeUpdateEvent);
}
}
diff --git a/app/assets/javascripts/blob/viewer/index.js b/app/assets/javascripts/blob/viewer/index.js
index 92ea91c45a..137e1f5a09 100644
--- a/app/assets/javascripts/blob/viewer/index.js
+++ b/app/assets/javascripts/blob/viewer/index.js
@@ -1,3 +1,4 @@
+import $ from 'jquery';
import Flash from '../../flash';
import { handleLocationHash } from '../../lib/utils/common_utils';
import axios from '../../lib/utils/axios_utils';
diff --git a/app/assets/javascripts/blob_edit/blob_bundle.js b/app/assets/javascripts/blob_edit/blob_bundle.js
index 931ed042df..4424232f64 100644
--- a/app/assets/javascripts/blob_edit/blob_bundle.js
+++ b/app/assets/javascripts/blob_edit/blob_bundle.js
@@ -1,5 +1,7 @@
/* eslint-disable func-names, space-before-function-paren, prefer-arrow-callback, no-var, quotes, vars-on-top, no-unused-vars, no-new, max-len */
/* global EditBlob */
+
+import $ from 'jquery';
import NewCommitForm from '../new_commit_form';
import EditBlob from './edit_blob';
import BlobFileDropzone from '../blob/blob_file_dropzone';
diff --git a/app/assets/javascripts/blob_edit/edit_blob.js b/app/assets/javascripts/blob_edit/edit_blob.js
index d4f6adaccb..82a3d494b6 100644
--- a/app/assets/javascripts/blob_edit/edit_blob.js
+++ b/app/assets/javascripts/blob_edit/edit_blob.js
@@ -1,5 +1,6 @@
/* global ace */
+import $ from 'jquery';
import axios from '~/lib/utils/axios_utils';
import createFlash from '~/flash';
import { __ } from '~/locale';
diff --git a/app/assets/javascripts/boards/components/board.js b/app/assets/javascripts/boards/components/board.js
index 9c4cc2338c..3cffd91716 100644
--- a/app/assets/javascripts/boards/components/board.js
+++ b/app/assets/javascripts/boards/components/board.js
@@ -1,4 +1,6 @@
/* eslint-disable comma-dangle, space-before-function-paren, one-var */
+
+import $ from 'jquery';
import Sortable from 'vendor/Sortable';
import Vue from 'vue';
import AccessorUtilities from '../../lib/utils/accessor';
diff --git a/app/assets/javascripts/boards/components/board_delete.js b/app/assets/javascripts/boards/components/board_delete.js
index 8a1b177bba..7be98825fd 100644
--- a/app/assets/javascripts/boards/components/board_delete.js
+++ b/app/assets/javascripts/boards/components/board_delete.js
@@ -1,5 +1,6 @@
/* eslint-disable comma-dangle, space-before-function-paren, no-alert */
+import $ from 'jquery';
import Vue from 'vue';
window.gl = window.gl || {};
diff --git a/app/assets/javascripts/boards/components/board_new_issue.vue b/app/assets/javascripts/boards/components/board_new_issue.vue
index 870d242e77..8d84c1735b 100644
--- a/app/assets/javascripts/boards/components/board_new_issue.vue
+++ b/app/assets/javascripts/boards/components/board_new_issue.vue
@@ -1,4 +1,5 @@
+
+
+
+
diff --git a/app/assets/javascripts/ide/components/commit_sidebar/actions.vue b/app/assets/javascripts/ide/components/commit_sidebar/actions.vue
new file mode 100644
index 0000000000..2cbd982af1
--- /dev/null
+++ b/app/assets/javascripts/ide/components/commit_sidebar/actions.vue
@@ -0,0 +1,65 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/assets/javascripts/ide/components/commit_sidebar/list.vue b/app/assets/javascripts/ide/components/commit_sidebar/list.vue
new file mode 100644
index 0000000000..453208f3f1
--- /dev/null
+++ b/app/assets/javascripts/ide/components/commit_sidebar/list.vue
@@ -0,0 +1,66 @@
+
+
+
+
+
diff --git a/app/assets/javascripts/ide/components/commit_sidebar/list_collapsed.vue b/app/assets/javascripts/ide/components/commit_sidebar/list_collapsed.vue
new file mode 100644
index 0000000000..15918ac963
--- /dev/null
+++ b/app/assets/javascripts/ide/components/commit_sidebar/list_collapsed.vue
@@ -0,0 +1,35 @@
+
+
+
+
+
+ {{ addedFiles.length }}
+
+ {{ modifiedFiles.length }}
+
+
diff --git a/app/assets/javascripts/ide/components/commit_sidebar/list_item.vue b/app/assets/javascripts/ide/components/commit_sidebar/list_item.vue
new file mode 100644
index 0000000000..560cdd941c
--- /dev/null
+++ b/app/assets/javascripts/ide/components/commit_sidebar/list_item.vue
@@ -0,0 +1,58 @@
+
+
+
+
+
+
+
+
diff --git a/app/assets/javascripts/ide/components/commit_sidebar/radio_group.vue b/app/assets/javascripts/ide/components/commit_sidebar/radio_group.vue
new file mode 100644
index 0000000000..4310d762c7
--- /dev/null
+++ b/app/assets/javascripts/ide/components/commit_sidebar/radio_group.vue
@@ -0,0 +1,94 @@
+
+
+
+
+
diff --git a/app/assets/javascripts/ide/components/editor_mode_dropdown.vue b/app/assets/javascripts/ide/components/editor_mode_dropdown.vue
new file mode 100644
index 0000000000..0c44a755f5
--- /dev/null
+++ b/app/assets/javascripts/ide/components/editor_mode_dropdown.vue
@@ -0,0 +1,130 @@
+
+
+
+
+
+
+
+
diff --git a/app/assets/javascripts/ide/components/ide.vue b/app/assets/javascripts/ide/components/ide.vue
new file mode 100644
index 0000000000..1c237c0ec9
--- /dev/null
+++ b/app/assets/javascripts/ide/components/ide.vue
@@ -0,0 +1,108 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Welcome to the GitLab IDE
+
+
+ You can select a file in the left sidebar to begin
+ editing and use the right sidebar to commit your changes.
+
+
+
+
+
+
+
+
+
+
diff --git a/app/assets/javascripts/ide/components/ide_context_bar.vue b/app/assets/javascripts/ide/components/ide_context_bar.vue
new file mode 100644
index 0000000000..79a83b4799
--- /dev/null
+++ b/app/assets/javascripts/ide/components/ide_context_bar.vue
@@ -0,0 +1,84 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/app/assets/javascripts/ide/components/ide_external_links.vue b/app/assets/javascripts/ide/components/ide_external_links.vue
new file mode 100644
index 0000000000..c6f6e0d234
--- /dev/null
+++ b/app/assets/javascripts/ide/components/ide_external_links.vue
@@ -0,0 +1,43 @@
+
+
+
+
+
diff --git a/app/assets/javascripts/ide/components/ide_file_buttons.vue b/app/assets/javascripts/ide/components/ide_file_buttons.vue
new file mode 100644
index 0000000000..a6c6f46a14
--- /dev/null
+++ b/app/assets/javascripts/ide/components/ide_file_buttons.vue
@@ -0,0 +1,84 @@
+
+
+
+
+
diff --git a/app/assets/javascripts/ide/components/ide_project_branches_tree.vue b/app/assets/javascripts/ide/components/ide_project_branches_tree.vue
new file mode 100644
index 0000000000..eb2749e615
--- /dev/null
+++ b/app/assets/javascripts/ide/components/ide_project_branches_tree.vue
@@ -0,0 +1,47 @@
+
+
+
+
+
+
+
+
diff --git a/app/assets/javascripts/ide/components/ide_project_tree.vue b/app/assets/javascripts/ide/components/ide_project_tree.vue
new file mode 100644
index 0000000000..a6f40286ac
--- /dev/null
+++ b/app/assets/javascripts/ide/components/ide_project_tree.vue
@@ -0,0 +1,65 @@
+
+
+
+
+
diff --git a/app/assets/javascripts/ide/components/ide_repo_tree.vue b/app/assets/javascripts/ide/components/ide_repo_tree.vue
new file mode 100644
index 0000000000..e6af88e04b
--- /dev/null
+++ b/app/assets/javascripts/ide/components/ide_repo_tree.vue
@@ -0,0 +1,41 @@
+
+
+
+
+
diff --git a/app/assets/javascripts/ide/components/ide_side_bar.vue b/app/assets/javascripts/ide/components/ide_side_bar.vue
new file mode 100644
index 0000000000..8cf1ccb4fc
--- /dev/null
+++ b/app/assets/javascripts/ide/components/ide_side_bar.vue
@@ -0,0 +1,51 @@
+
+
+
+
+
+
+
diff --git a/app/assets/javascripts/ide/components/ide_status_bar.vue b/app/assets/javascripts/ide/components/ide_status_bar.vue
new file mode 100644
index 0000000000..152a5f632a
--- /dev/null
+++ b/app/assets/javascripts/ide/components/ide_status_bar.vue
@@ -0,0 +1,60 @@
+
+
+
+
+
+
+ {{ file.branchId }}
+
+
+
+ {{ file.name }}
+
+
+ {{ file.eol }}
+
+
+ {{ file.editorRow }}:{{ file.editorColumn }}
+
+
+ {{ file.fileLanguage }}
+
+
+
diff --git a/app/assets/javascripts/ide/components/mr_file_icon.vue b/app/assets/javascripts/ide/components/mr_file_icon.vue
new file mode 100644
index 0000000000..8a440902df
--- /dev/null
+++ b/app/assets/javascripts/ide/components/mr_file_icon.vue
@@ -0,0 +1,23 @@
+
+
+
+
+
diff --git a/app/assets/javascripts/ide/components/new_dropdown/index.vue b/app/assets/javascripts/ide/components/new_dropdown/index.vue
new file mode 100644
index 0000000000..769e9b79ca
--- /dev/null
+++ b/app/assets/javascripts/ide/components/new_dropdown/index.vue
@@ -0,0 +1,111 @@
+
+
+
+
+
diff --git a/app/assets/javascripts/ide/components/new_dropdown/modal.vue b/app/assets/javascripts/ide/components/new_dropdown/modal.vue
new file mode 100644
index 0000000000..4b5a50785b
--- /dev/null
+++ b/app/assets/javascripts/ide/components/new_dropdown/modal.vue
@@ -0,0 +1,99 @@
+
+
+
+
+
+
+
diff --git a/app/assets/javascripts/ide/components/new_dropdown/upload.vue b/app/assets/javascripts/ide/components/new_dropdown/upload.vue
new file mode 100644
index 0000000000..c165af5ce5
--- /dev/null
+++ b/app/assets/javascripts/ide/components/new_dropdown/upload.vue
@@ -0,0 +1,75 @@
+
+
+
+
+
diff --git a/app/assets/javascripts/ide/components/repo_commit_section.vue b/app/assets/javascripts/ide/components/repo_commit_section.vue
new file mode 100644
index 0000000000..d885ed5e30
--- /dev/null
+++ b/app/assets/javascripts/ide/components/repo_commit_section.vue
@@ -0,0 +1,172 @@
+
+
+
+
+
+
+ {{ __(`This branch has changed since you started editing.
+ Would you like to create a new branch?`) }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ __('No changes') }}
+
+
+ {{ __('Edit files in the editor and commit changes here') }}
+
+
+
+
+ {{ __('All changes are committed') }}
+
+
+
+
+
+
+
+
diff --git a/app/assets/javascripts/ide/components/repo_editor.vue b/app/assets/javascripts/ide/components/repo_editor.vue
new file mode 100644
index 0000000000..711bafa17a
--- /dev/null
+++ b/app/assets/javascripts/ide/components/repo_editor.vue
@@ -0,0 +1,219 @@
+
+
+
+
+
diff --git a/app/assets/javascripts/ide/components/repo_file.vue b/app/assets/javascripts/ide/components/repo_file.vue
new file mode 100644
index 0000000000..3b5068d491
--- /dev/null
+++ b/app/assets/javascripts/ide/components/repo_file.vue
@@ -0,0 +1,127 @@
+
+
+
+
+
+
+
+
+ {{ file.name }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/assets/javascripts/ide/components/repo_file_status_icon.vue b/app/assets/javascripts/ide/components/repo_file_status_icon.vue
new file mode 100644
index 0000000000..97589e116c
--- /dev/null
+++ b/app/assets/javascripts/ide/components/repo_file_status_icon.vue
@@ -0,0 +1,39 @@
+
+
+
+
+
+
+
diff --git a/app/assets/javascripts/ide/components/repo_loading_file.vue b/app/assets/javascripts/ide/components/repo_loading_file.vue
new file mode 100644
index 0000000000..79af8c0b0c
--- /dev/null
+++ b/app/assets/javascripts/ide/components/repo_loading_file.vue
@@ -0,0 +1,42 @@
+
+
+
+
+
+
+ |
+
+
+
+ |
+
+
+
+ |
+
+
+
diff --git a/app/assets/javascripts/ide/components/repo_tab.vue b/app/assets/javascripts/ide/components/repo_tab.vue
new file mode 100644
index 0000000000..304a73ed1a
--- /dev/null
+++ b/app/assets/javascripts/ide/components/repo_tab.vue
@@ -0,0 +1,104 @@
+
+
+
+
+
+
+
+
+ {{ tab.name }}
+
+
+
+
diff --git a/app/assets/javascripts/ide/components/repo_tabs.vue b/app/assets/javascripts/ide/components/repo_tabs.vue
new file mode 100644
index 0000000000..7bd646ba9b
--- /dev/null
+++ b/app/assets/javascripts/ide/components/repo_tabs.vue
@@ -0,0 +1,82 @@
+
+
+
+
+
diff --git a/app/assets/javascripts/ide/components/resizable_panel.vue b/app/assets/javascripts/ide/components/resizable_panel.vue
new file mode 100644
index 0000000000..5ea2a2f682
--- /dev/null
+++ b/app/assets/javascripts/ide/components/resizable_panel.vue
@@ -0,0 +1,85 @@
+
+
+
+
+
diff --git a/app/assets/javascripts/ide/eventhub.js b/app/assets/javascripts/ide/eventhub.js
new file mode 100644
index 0000000000..0948c2e535
--- /dev/null
+++ b/app/assets/javascripts/ide/eventhub.js
@@ -0,0 +1,3 @@
+import Vue from 'vue';
+
+export default new Vue();
diff --git a/app/assets/javascripts/ide/ide_router.js b/app/assets/javascripts/ide/ide_router.js
new file mode 100644
index 0000000000..4a0a303d5a
--- /dev/null
+++ b/app/assets/javascripts/ide/ide_router.js
@@ -0,0 +1,173 @@
+import Vue from 'vue';
+import VueRouter from 'vue-router';
+import flash from '~/flash';
+import store from './stores';
+
+Vue.use(VueRouter);
+
+/**
+ * Routes below /-/ide/:
+
+/project/h5bp/html5-boilerplate/blob/master
+/project/h5bp/html5-boilerplate/blob/master/app/js/test.js
+
+/project/h5bp/html5-boilerplate/mr/123
+/project/h5bp/html5-boilerplate/mr/123/app/js/test.js
+
+/workspace/123
+/workspace/project/h5bp/html5-boilerplate/blob/my-special-branch
+/workspace/project/h5bp/html5-boilerplate/mr/123
+
+/ = /workspace
+
+/settings
+*/
+
+// Unfortunately Vue Router doesn't work without at least a fake component
+// If you do only data handling
+const EmptyRouterComponent = {
+ render(createElement) {
+ return createElement('div');
+ },
+};
+
+const router = new VueRouter({
+ mode: 'history',
+ base: `${gon.relative_url_root}/-/ide/`,
+ routes: [
+ {
+ path: '/project/:namespace/:project+',
+ component: EmptyRouterComponent,
+ children: [
+ {
+ path: ':targetmode(edit|tree|blob)/:branch/*',
+ component: EmptyRouterComponent,
+ },
+ {
+ path: 'merge_requests/:mrid',
+ component: EmptyRouterComponent,
+ },
+ ],
+ },
+ ],
+});
+
+router.beforeEach((to, from, next) => {
+ if (to.params.namespace && to.params.project) {
+ store
+ .dispatch('getProjectData', {
+ namespace: to.params.namespace,
+ projectId: to.params.project,
+ })
+ .then(() => {
+ const fullProjectId = `${to.params.namespace}/${to.params.project}`;
+
+ if (to.params.branch) {
+ store.dispatch('getBranchData', {
+ projectId: fullProjectId,
+ branchId: to.params.branch,
+ });
+
+ store
+ .dispatch('getFiles', {
+ projectId: fullProjectId,
+ branchId: to.params.branch,
+ })
+ .then(() => {
+ if (to.params[0]) {
+ const path =
+ to.params[0].slice(-1) === '/' ? to.params[0].slice(0, -1) : to.params[0];
+ const treeEntryKey = Object.keys(store.state.entries).find(
+ key => key === path && !store.state.entries[key].pending,
+ );
+ const treeEntry = store.state.entries[treeEntryKey];
+
+ if (treeEntry) {
+ store.dispatch('handleTreeEntryAction', treeEntry);
+ }
+ }
+ })
+ .catch(e => {
+ flash(
+ 'Error while loading the branch files. Please try again.',
+ 'alert',
+ document,
+ null,
+ false,
+ true,
+ );
+ throw e;
+ });
+ } else if (to.params.mrid) {
+ store.dispatch('updateViewer', 'mrdiff');
+
+ store
+ .dispatch('getMergeRequestData', {
+ projectId: fullProjectId,
+ mergeRequestId: to.params.mrid,
+ })
+ .then(mr => {
+ store.dispatch('getBranchData', {
+ projectId: fullProjectId,
+ branchId: mr.source_branch,
+ });
+
+ return store.dispatch('getFiles', {
+ projectId: fullProjectId,
+ branchId: mr.source_branch,
+ });
+ })
+ .then(() =>
+ store.dispatch('getMergeRequestVersions', {
+ projectId: fullProjectId,
+ mergeRequestId: to.params.mrid,
+ }),
+ )
+ .then(() =>
+ store.dispatch('getMergeRequestChanges', {
+ projectId: fullProjectId,
+ mergeRequestId: to.params.mrid,
+ }),
+ )
+ .then(mrChanges => {
+ mrChanges.changes.forEach((change, ind) => {
+ const changeTreeEntry = store.state.entries[change.new_path];
+
+ if (changeTreeEntry) {
+ store.dispatch('setFileMrChange', {
+ file: changeTreeEntry,
+ mrChange: change,
+ });
+
+ if (ind < 10) {
+ store.dispatch('getFileData', {
+ path: change.new_path,
+ makeFileActive: ind === 0,
+ });
+ }
+ }
+ });
+ })
+ .catch(e => {
+ flash('Error while loading the merge request. Please try again.');
+ throw e;
+ });
+ }
+ })
+ .catch(e => {
+ flash(
+ 'Error while loading the project data. Please try again.',
+ 'alert',
+ document,
+ null,
+ false,
+ true,
+ );
+ throw e;
+ });
+ }
+
+ next();
+});
+
+export default router;
diff --git a/app/assets/javascripts/ide/index.js b/app/assets/javascripts/ide/index.js
new file mode 100644
index 0000000000..cbfb3dc54f
--- /dev/null
+++ b/app/assets/javascripts/ide/index.js
@@ -0,0 +1,33 @@
+import Vue from 'vue';
+import Translate from '~/vue_shared/translate';
+import ide from './components/ide.vue';
+import store from './stores';
+import router from './ide_router';
+
+function initIde(el) {
+ if (!el) return null;
+
+ return new Vue({
+ el,
+ store,
+ router,
+ components: {
+ ide,
+ },
+ render(createElement) {
+ return createElement('ide', {
+ props: {
+ emptyStateSvgPath: el.dataset.emptyStateSvgPath,
+ noChangesStateSvgPath: el.dataset.noChangesStateSvgPath,
+ committedStateSvgPath: el.dataset.committedStateSvgPath,
+ },
+ });
+ },
+ });
+}
+
+const ideElement = document.getElementById('ide');
+
+Vue.use(Translate);
+
+initIde(ideElement);
diff --git a/app/assets/javascripts/ide/lib/common/disposable.js b/app/assets/javascripts/ide/lib/common/disposable.js
new file mode 100644
index 0000000000..84b29bdb60
--- /dev/null
+++ b/app/assets/javascripts/ide/lib/common/disposable.js
@@ -0,0 +1,14 @@
+export default class Disposable {
+ constructor() {
+ this.disposers = new Set();
+ }
+
+ add(...disposers) {
+ disposers.forEach(disposer => this.disposers.add(disposer));
+ }
+
+ dispose() {
+ this.disposers.forEach(disposer => disposer.dispose());
+ this.disposers.clear();
+ }
+}
diff --git a/app/assets/javascripts/ide/lib/common/model.js b/app/assets/javascripts/ide/lib/common/model.js
new file mode 100644
index 0000000000..e47adae99e
--- /dev/null
+++ b/app/assets/javascripts/ide/lib/common/model.js
@@ -0,0 +1,94 @@
+/* global monaco */
+import Disposable from './disposable';
+import eventHub from '../../eventhub';
+
+export default class Model {
+ constructor(monaco, file) {
+ this.monaco = monaco;
+ this.disposable = new Disposable();
+ this.file = file;
+ this.content = file.content !== '' ? file.content : file.raw;
+
+ this.disposable.add(
+ (this.originalModel = this.monaco.editor.createModel(
+ this.file.raw,
+ undefined,
+ new this.monaco.Uri(null, null, `original/${this.file.key}`),
+ )),
+ (this.model = this.monaco.editor.createModel(
+ this.content,
+ undefined,
+ new this.monaco.Uri(null, null, this.file.key),
+ )),
+ );
+ if (this.file.mrChange) {
+ this.disposable.add(
+ (this.baseModel = this.monaco.editor.createModel(
+ this.file.baseRaw,
+ undefined,
+ new this.monaco.Uri(null, null, `target/${this.file.path}`),
+ )),
+ );
+ }
+
+ this.events = new Map();
+
+ this.updateContent = this.updateContent.bind(this);
+ this.dispose = this.dispose.bind(this);
+
+ eventHub.$on(`editor.update.model.dispose.${this.file.key}`, this.dispose);
+ eventHub.$on(`editor.update.model.content.${this.file.path}`, this.updateContent);
+ }
+
+ get url() {
+ return this.model.uri.toString();
+ }
+
+ get language() {
+ return this.model.getModeId();
+ }
+
+ get eol() {
+ return this.model.getEOL() === '\n' ? 'LF' : 'CRLF';
+ }
+
+ get path() {
+ return this.file.key;
+ }
+
+ getModel() {
+ return this.model;
+ }
+
+ getOriginalModel() {
+ return this.originalModel;
+ }
+
+ getBaseModel() {
+ return this.baseModel;
+ }
+
+ setValue(value) {
+ this.getModel().setValue(value);
+ }
+
+ onChange(cb) {
+ this.events.set(
+ this.path,
+ this.disposable.add(this.model.onDidChangeContent(e => cb(this, e))),
+ );
+ }
+
+ updateContent(content) {
+ this.getOriginalModel().setValue(content);
+ this.getModel().setValue(content);
+ }
+
+ dispose() {
+ this.disposable.dispose();
+ this.events.clear();
+
+ eventHub.$off(`editor.update.model.dispose.${this.file.key}`, this.dispose);
+ eventHub.$off(`editor.update.model.content.${this.file.path}`, this.updateContent);
+ }
+}
diff --git a/app/assets/javascripts/ide/lib/common/model_manager.js b/app/assets/javascripts/ide/lib/common/model_manager.js
new file mode 100644
index 0000000000..0e7b563b5d
--- /dev/null
+++ b/app/assets/javascripts/ide/lib/common/model_manager.js
@@ -0,0 +1,48 @@
+import eventHub from '../../eventhub';
+import Disposable from './disposable';
+import Model from './model';
+
+export default class ModelManager {
+ constructor(monaco) {
+ this.monaco = monaco;
+ this.disposable = new Disposable();
+ this.models = new Map();
+ }
+
+ hasCachedModel(key) {
+ return this.models.has(key);
+ }
+
+ getModel(key) {
+ return this.models.get(key);
+ }
+
+ addModel(file) {
+ if (this.hasCachedModel(file.key)) {
+ return this.getModel(file.key);
+ }
+
+ const model = new Model(this.monaco, file);
+ this.models.set(model.path, model);
+ this.disposable.add(model);
+
+ eventHub.$on(
+ `editor.update.model.dispose.${file.key}`,
+ this.removeCachedModel.bind(this, file),
+ );
+
+ return model;
+ }
+
+ removeCachedModel(file) {
+ this.models.delete(file.key);
+
+ eventHub.$off(`editor.update.model.dispose.${file.key}`, this.removeCachedModel);
+ }
+
+ dispose() {
+ // dispose of all the models
+ this.disposable.dispose();
+ this.models.clear();
+ }
+}
diff --git a/app/assets/javascripts/ide/lib/decorations/controller.js b/app/assets/javascripts/ide/lib/decorations/controller.js
new file mode 100644
index 0000000000..4290477474
--- /dev/null
+++ b/app/assets/javascripts/ide/lib/decorations/controller.js
@@ -0,0 +1,45 @@
+export default class DecorationsController {
+ constructor(editor) {
+ this.editor = editor;
+ this.decorations = new Map();
+ this.editorDecorations = new Map();
+ }
+
+ getAllDecorationsForModel(model) {
+ if (!this.decorations.has(model.url)) return [];
+
+ const modelDecorations = this.decorations.get(model.url);
+ const decorations = [];
+
+ modelDecorations.forEach(val => decorations.push(...val));
+
+ return decorations;
+ }
+
+ addDecorations(model, decorationsKey, decorations) {
+ const decorationMap = this.decorations.get(model.url) || new Map();
+
+ decorationMap.set(decorationsKey, decorations);
+
+ this.decorations.set(model.url, decorationMap);
+
+ this.decorate(model);
+ }
+
+ decorate(model) {
+ if (!this.editor.instance) return;
+
+ const decorations = this.getAllDecorationsForModel(model);
+ const oldDecorations = this.editorDecorations.get(model.url) || [];
+
+ this.editorDecorations.set(
+ model.url,
+ this.editor.instance.deltaDecorations(oldDecorations, decorations),
+ );
+ }
+
+ dispose() {
+ this.decorations.clear();
+ this.editorDecorations.clear();
+ }
+}
diff --git a/app/assets/javascripts/ide/lib/diff/controller.js b/app/assets/javascripts/ide/lib/diff/controller.js
new file mode 100644
index 0000000000..b136545ad1
--- /dev/null
+++ b/app/assets/javascripts/ide/lib/diff/controller.js
@@ -0,0 +1,72 @@
+/* global monaco */
+import { throttle } from 'underscore';
+import DirtyDiffWorker from './diff_worker';
+import Disposable from '../common/disposable';
+
+export const getDiffChangeType = (change) => {
+ if (change.modified) {
+ return 'modified';
+ } else if (change.added) {
+ return 'added';
+ } else if (change.removed) {
+ return 'removed';
+ }
+
+ return '';
+};
+
+export const getDecorator = change => ({
+ range: new monaco.Range(
+ change.lineNumber,
+ 1,
+ change.endLineNumber,
+ 1,
+ ),
+ options: {
+ isWholeLine: true,
+ linesDecorationsClassName: `dirty-diff dirty-diff-${getDiffChangeType(change)}`,
+ },
+});
+
+export default class DirtyDiffController {
+ constructor(modelManager, decorationsController) {
+ this.disposable = new Disposable();
+ this.editorSimpleWorker = null;
+ this.modelManager = modelManager;
+ this.decorationsController = decorationsController;
+ this.dirtyDiffWorker = new DirtyDiffWorker();
+ this.throttledComputeDiff = throttle(this.computeDiff, 250);
+ this.decorate = this.decorate.bind(this);
+
+ this.dirtyDiffWorker.addEventListener('message', this.decorate);
+ }
+
+ attachModel(model) {
+ model.onChange(() => this.throttledComputeDiff(model));
+ }
+
+ computeDiff(model) {
+ this.dirtyDiffWorker.postMessage({
+ path: model.path,
+ originalContent: model.getOriginalModel().getValue(),
+ newContent: model.getModel().getValue(),
+ });
+ }
+
+ reDecorate(model) {
+ this.decorationsController.decorate(model);
+ }
+
+ decorate({ data }) {
+ const decorations = data.changes.map(change => getDecorator(change));
+ const model = this.modelManager.getModel(data.path);
+ this.decorationsController.addDecorations(model, 'dirtyDiff', decorations);
+ }
+
+ dispose() {
+ this.disposable.dispose();
+
+ this.dirtyDiffWorker.removeEventListener('message', this.decorate);
+ this.dirtyDiffWorker.terminate();
+ }
+}
diff --git a/app/assets/javascripts/ide/lib/diff/diff.js b/app/assets/javascripts/ide/lib/diff/diff.js
new file mode 100644
index 0000000000..0e37f5c470
--- /dev/null
+++ b/app/assets/javascripts/ide/lib/diff/diff.js
@@ -0,0 +1,30 @@
+import { diffLines } from 'diff';
+
+// eslint-disable-next-line import/prefer-default-export
+export const computeDiff = (originalContent, newContent) => {
+ const changes = diffLines(originalContent, newContent);
+
+ let lineNumber = 1;
+ return changes.reduce((acc, change) => {
+ const findOnLine = acc.find(c => c.lineNumber === lineNumber);
+
+ if (findOnLine) {
+ Object.assign(findOnLine, change, {
+ modified: true,
+ endLineNumber: (lineNumber + change.count) - 1,
+ });
+ } else if ('added' in change || 'removed' in change) {
+ acc.push(Object.assign({}, change, {
+ lineNumber,
+ modified: undefined,
+ endLineNumber: (lineNumber + change.count) - 1,
+ }));
+ }
+
+ if (!change.removed) {
+ lineNumber += change.count;
+ }
+
+ return acc;
+ }, []);
+};
diff --git a/app/assets/javascripts/ide/lib/diff/diff_worker.js b/app/assets/javascripts/ide/lib/diff/diff_worker.js
new file mode 100644
index 0000000000..e74c404633
--- /dev/null
+++ b/app/assets/javascripts/ide/lib/diff/diff_worker.js
@@ -0,0 +1,10 @@
+import { computeDiff } from './diff';
+
+self.addEventListener('message', (e) => {
+ const data = e.data;
+
+ self.postMessage({
+ path: data.path,
+ changes: computeDiff(data.originalContent, data.newContent),
+ });
+});
diff --git a/app/assets/javascripts/ide/lib/editor.js b/app/assets/javascripts/ide/lib/editor.js
new file mode 100644
index 0000000000..001737d6ee
--- /dev/null
+++ b/app/assets/javascripts/ide/lib/editor.js
@@ -0,0 +1,192 @@
+import _ from 'underscore';
+import DecorationsController from './decorations/controller';
+import DirtyDiffController from './diff/controller';
+import Disposable from './common/disposable';
+import ModelManager from './common/model_manager';
+import editorOptions, { defaultEditorOptions } from './editor_options';
+import gitlabTheme from './themes/gl_theme';
+
+export const clearDomElement = el => {
+ if (!el || !el.firstChild) return;
+
+ while (el.firstChild) {
+ el.removeChild(el.firstChild);
+ }
+};
+
+export default class Editor {
+ static create(monaco) {
+ if (this.editorInstance) return this.editorInstance;
+
+ this.editorInstance = new Editor(monaco);
+
+ return this.editorInstance;
+ }
+
+ constructor(monaco) {
+ this.monaco = monaco;
+ this.currentModel = null;
+ this.instance = null;
+ this.dirtyDiffController = null;
+ this.disposable = new Disposable();
+ this.modelManager = new ModelManager(this.monaco);
+ this.decorationsController = new DecorationsController(this);
+
+ this.setupMonacoTheme();
+
+ this.debouncedUpdate = _.debounce(() => {
+ this.updateDimensions();
+ }, 200);
+ }
+
+ createInstance(domElement) {
+ if (!this.instance) {
+ clearDomElement(domElement);
+
+ this.disposable.add(
+ (this.instance = this.monaco.editor.create(domElement, {
+ ...defaultEditorOptions,
+ })),
+ (this.dirtyDiffController = new DirtyDiffController(
+ this.modelManager,
+ this.decorationsController,
+ )),
+ );
+
+ window.addEventListener('resize', this.debouncedUpdate, false);
+ }
+ }
+
+ createDiffInstance(domElement) {
+ if (!this.instance) {
+ clearDomElement(domElement);
+
+ this.disposable.add(
+ (this.instance = this.monaco.editor.createDiffEditor(domElement, {
+ ...defaultEditorOptions,
+ readOnly: true,
+ quickSuggestions: false,
+ occurrencesHighlight: false,
+ renderLineHighlight: 'none',
+ hideCursorInOverviewRuler: true,
+ renderSideBySide: Editor.renderSideBySide(domElement),
+ })),
+ );
+
+ window.addEventListener('resize', this.debouncedUpdate, false);
+ }
+ }
+
+ createModel(file) {
+ return this.modelManager.addModel(file);
+ }
+
+ attachModel(model) {
+ if (this.isDiffEditorType) {
+ this.instance.setModel({
+ original: model.getOriginalModel(),
+ modified: model.getModel(),
+ });
+
+ return;
+ }
+
+ this.instance.setModel(model.getModel());
+ if (this.dirtyDiffController) this.dirtyDiffController.attachModel(model);
+
+ this.currentModel = model;
+
+ this.instance.updateOptions(
+ editorOptions.reduce((acc, obj) => {
+ Object.keys(obj).forEach(key => {
+ Object.assign(acc, {
+ [key]: obj[key](model),
+ });
+ });
+ return acc;
+ }, {}),
+ );
+
+ if (this.dirtyDiffController) this.dirtyDiffController.reDecorate(model);
+ }
+
+ attachMergeRequestModel(model) {
+ this.instance.setModel({
+ original: model.getBaseModel(),
+ modified: model.getModel(),
+ });
+
+ this.monaco.editor.createDiffNavigator(this.instance, {
+ alwaysRevealFirst: true,
+ });
+ }
+
+ setupMonacoTheme() {
+ this.monaco.editor.defineTheme(gitlabTheme.themeName, gitlabTheme.monacoTheme);
+
+ this.monaco.editor.setTheme('gitlab');
+ }
+
+ clearEditor() {
+ if (this.instance) {
+ this.instance.setModel(null);
+ }
+ }
+
+ dispose() {
+ window.removeEventListener('resize', this.debouncedUpdate);
+
+ // catch any potential errors with disposing the error
+ // this is mainly for tests caused by elements not existing
+ try {
+ this.disposable.dispose();
+
+ this.instance = null;
+ } catch (e) {
+ this.instance = null;
+
+ if (process.env.NODE_ENV !== 'test') {
+ // eslint-disable-next-line no-console
+ console.error(e);
+ }
+ }
+ }
+
+ updateDimensions() {
+ this.instance.layout();
+ this.updateDiffView();
+ }
+
+ setPosition({ lineNumber, column }) {
+ this.instance.revealPositionInCenter({
+ lineNumber,
+ column,
+ });
+ this.instance.setPosition({
+ lineNumber,
+ column,
+ });
+ }
+
+ onPositionChange(cb) {
+ if (!this.instance.onDidChangeCursorPosition) return;
+
+ this.disposable.add(this.instance.onDidChangeCursorPosition(e => cb(this.instance, e)));
+ }
+
+ updateDiffView() {
+ if (!this.isDiffEditorType) return;
+
+ this.instance.updateOptions({
+ renderSideBySide: Editor.renderSideBySide(this.instance.getDomNode()),
+ });
+ }
+
+ get isDiffEditorType() {
+ return this.instance.getEditorType() === 'vs.editor.IDiffEditor';
+ }
+
+ static renderSideBySide(domElement) {
+ return domElement.offsetWidth >= 700;
+ }
+}
diff --git a/app/assets/javascripts/ide/lib/editor_options.js b/app/assets/javascripts/ide/lib/editor_options.js
new file mode 100644
index 0000000000..9f895d49f2
--- /dev/null
+++ b/app/assets/javascripts/ide/lib/editor_options.js
@@ -0,0 +1,16 @@
+export const defaultEditorOptions = {
+ model: null,
+ readOnly: false,
+ contextmenu: true,
+ scrollBeyondLastLine: false,
+ minimap: {
+ enabled: false,
+ },
+ wordWrap: 'on',
+};
+
+export default [
+ {
+ readOnly: model => !!model.file.file_lock,
+ },
+];
diff --git a/app/assets/javascripts/ide/lib/themes/gl_theme.js b/app/assets/javascripts/ide/lib/themes/gl_theme.js
new file mode 100644
index 0000000000..2fc96250c7
--- /dev/null
+++ b/app/assets/javascripts/ide/lib/themes/gl_theme.js
@@ -0,0 +1,14 @@
+export default {
+ themeName: 'gitlab',
+ monacoTheme: {
+ base: 'vs',
+ inherit: true,
+ rules: [],
+ colors: {
+ 'editorLineNumber.foreground': '#CCCCCC',
+ 'diffEditor.insertedTextBackground': '#ddfbe6',
+ 'diffEditor.removedTextBackground': '#f9d7dc',
+ 'editor.selectionBackground': '#aad6f8',
+ },
+ },
+};
diff --git a/app/assets/javascripts/ide/monaco_loader.js b/app/assets/javascripts/ide/monaco_loader.js
new file mode 100644
index 0000000000..142a220097
--- /dev/null
+++ b/app/assets/javascripts/ide/monaco_loader.js
@@ -0,0 +1,16 @@
+import monacoContext from 'monaco-editor/dev/vs/loader';
+
+monacoContext.require.config({
+ paths: {
+ vs: `${__webpack_public_path__}monaco-editor/vs`, // eslint-disable-line camelcase
+ },
+});
+
+// ignore CDN config and use local assets path for service worker which cannot be cross-domain
+const relativeRootPath = (gon && gon.relative_url_root) || '';
+const monacoPath = `${relativeRootPath}/assets/webpack/monaco-editor/vs`;
+window.MonacoEnvironment = { getWorkerUrl: () => `${monacoPath}/base/worker/workerMain.js` };
+
+// eslint-disable-next-line no-underscore-dangle
+window.__monaco_context__ = monacoContext;
+export default monacoContext.require;
diff --git a/app/assets/javascripts/ide/services/index.js b/app/assets/javascripts/ide/services/index.js
new file mode 100644
index 0000000000..a12e637616
--- /dev/null
+++ b/app/assets/javascripts/ide/services/index.js
@@ -0,0 +1,78 @@
+import Vue from 'vue';
+import VueResource from 'vue-resource';
+import Api from '~/api';
+
+Vue.use(VueResource);
+
+export default {
+ getTreeData(endpoint) {
+ return Vue.http.get(endpoint, { params: { format: 'json' } });
+ },
+ getFileData(endpoint) {
+ return Vue.http.get(endpoint, { params: { format: 'json' } });
+ },
+ getRawFileData(file) {
+ if (file.tempFile) {
+ return Promise.resolve(file.content);
+ }
+
+ if (file.raw) {
+ return Promise.resolve(file.raw);
+ }
+
+ return Vue.http.get(file.rawPath, { params: { format: 'json' } }).then(res => res.text());
+ },
+ getBaseRawFileData(file, sha) {
+ if (file.tempFile) {
+ return Promise.resolve(file.baseRaw);
+ }
+
+ if (file.baseRaw) {
+ return Promise.resolve(file.baseRaw);
+ }
+
+ return Vue.http
+ .get(file.rawPath.replace(`/raw/${file.branchId}/${file.path}`, `/raw/${sha}/${file.path}`), {
+ params: { format: 'json' },
+ })
+ .then(res => res.text());
+ },
+ getProjectData(namespace, project) {
+ return Api.project(`${namespace}/${project}`);
+ },
+ getProjectMergeRequestData(projectId, mergeRequestId) {
+ return Api.mergeRequest(projectId, mergeRequestId);
+ },
+ getProjectMergeRequestChanges(projectId, mergeRequestId) {
+ return Api.mergeRequestChanges(projectId, mergeRequestId);
+ },
+ getProjectMergeRequestVersions(projectId, mergeRequestId) {
+ return Api.mergeRequestVersions(projectId, mergeRequestId);
+ },
+ getBranchData(projectId, currentBranchId) {
+ return Api.branchSingle(projectId, currentBranchId);
+ },
+ createBranch(projectId, payload) {
+ const url = Api.buildUrl(Api.createBranchPath).replace(':id', projectId);
+
+ return Vue.http.post(url, payload);
+ },
+ commit(projectId, payload) {
+ return Api.commitMultiple(projectId, payload);
+ },
+ getTreeLastCommit(endpoint) {
+ return Vue.http.get(endpoint, {
+ params: {
+ format: 'json',
+ },
+ });
+ },
+ getFiles(projectUrl, branchId) {
+ const url = `${projectUrl}/files/${branchId}`;
+ return Vue.http.get(url, {
+ params: {
+ format: 'json',
+ },
+ });
+ },
+};
diff --git a/app/assets/javascripts/ide/stores/actions.js b/app/assets/javascripts/ide/stores/actions.js
new file mode 100644
index 0000000000..c6ba679d99
--- /dev/null
+++ b/app/assets/javascripts/ide/stores/actions.js
@@ -0,0 +1,118 @@
+import Vue from 'vue';
+import { visitUrl } from '~/lib/utils/url_utility';
+import flash from '~/flash';
+import * as types from './mutation_types';
+import FilesDecoratorWorker from './workers/files_decorator_worker';
+
+export const redirectToUrl = (_, url) => visitUrl(url);
+
+export const setInitialData = ({ commit }, data) => commit(types.SET_INITIAL_DATA, data);
+
+export const discardAllChanges = ({ state, commit, dispatch }) => {
+ state.changedFiles.forEach(file => {
+ commit(types.DISCARD_FILE_CHANGES, file.path);
+
+ if (file.tempFile) {
+ dispatch('closeFile', file.path);
+ }
+ });
+
+ commit(types.REMOVE_ALL_CHANGES_FILES);
+};
+
+export const closeAllFiles = ({ state, dispatch }) => {
+ state.openFiles.forEach(file => dispatch('closeFile', file));
+};
+
+export const setPanelCollapsedStatus = ({ commit }, { side, collapsed }) => {
+ if (side === 'left') {
+ commit(types.SET_LEFT_PANEL_COLLAPSED, collapsed);
+ } else {
+ commit(types.SET_RIGHT_PANEL_COLLAPSED, collapsed);
+ }
+};
+
+export const setResizingStatus = ({ commit }, resizing) => {
+ commit(types.SET_RESIZING_STATUS, resizing);
+};
+
+export const createTempEntry = (
+ { state, commit, dispatch },
+ { branchId, name, type, content = '', base64 = false },
+) =>
+ new Promise(resolve => {
+ const worker = new FilesDecoratorWorker();
+ const fullName = name.slice(-1) !== '/' && type === 'tree' ? `${name}/` : name;
+
+ if (state.entries[name]) {
+ flash(
+ `The name "${name.split('/').pop()}" is already taken in this directory.`,
+ 'alert',
+ document,
+ null,
+ false,
+ true,
+ );
+
+ resolve();
+
+ return null;
+ }
+
+ worker.addEventListener('message', ({ data }) => {
+ const { file } = data;
+
+ worker.terminate();
+
+ commit(types.CREATE_TMP_ENTRY, {
+ data,
+ projectId: state.currentProjectId,
+ branchId,
+ });
+
+ if (type === 'blob') {
+ commit(types.TOGGLE_FILE_OPEN, file.path);
+ commit(types.ADD_FILE_TO_CHANGED, file.path);
+ dispatch('setFileActive', file.path);
+ }
+
+ resolve(file);
+ });
+
+ worker.postMessage({
+ data: [fullName],
+ projectId: state.currentProjectId,
+ branchId,
+ type,
+ tempFile: true,
+ base64,
+ content,
+ });
+
+ return null;
+ });
+
+export const scrollToTab = () => {
+ Vue.nextTick(() => {
+ const tabs = document.getElementById('tabs');
+
+ if (tabs) {
+ const tabEl = tabs.querySelector('.active .repo-tab');
+
+ tabEl.focus();
+ }
+ });
+};
+
+export const updateViewer = ({ commit }, viewer) => {
+ commit(types.UPDATE_VIEWER, viewer);
+};
+
+export const updateDelayViewerUpdated = ({ commit }, delay) => {
+ commit(types.UPDATE_DELAY_VIEWER_CHANGE, delay);
+};
+
+export * from './actions/tree';
+export * from './actions/file';
+export * from './actions/project';
+export * from './actions/merge_request';
diff --git a/app/assets/javascripts/ide/stores/actions/file.js b/app/assets/javascripts/ide/stores/actions/file.js
new file mode 100644
index 0000000000..66c60ad605
--- /dev/null
+++ b/app/assets/javascripts/ide/stores/actions/file.js
@@ -0,0 +1,187 @@
+import { normalizeHeaders } from '~/lib/utils/common_utils';
+import flash from '~/flash';
+import eventHub from '../../eventhub';
+import service from '../../services';
+import * as types from '../mutation_types';
+import router from '../../ide_router';
+import { setPageTitle } from '../utils';
+
+export const closeFile = ({ commit, state, dispatch }, file) => {
+ const path = file.path;
+ const indexOfClosedFile = state.openFiles.findIndex(f => f.key === file.key);
+ const fileWasActive = file.active;
+
+ if (file.pending) {
+ commit(types.REMOVE_PENDING_TAB, file);
+ } else {
+ commit(types.TOGGLE_FILE_OPEN, path);
+ commit(types.SET_FILE_ACTIVE, { path, active: false });
+ }
+
+ if (state.openFiles.length > 0 && fileWasActive) {
+ const nextIndexToOpen = indexOfClosedFile === 0 ? 0 : indexOfClosedFile - 1;
+ const nextFileToOpen = state.openFiles[nextIndexToOpen];
+
+ if (nextFileToOpen.pending) {
+ dispatch('updateViewer', 'diff');
+ dispatch('openPendingTab', nextFileToOpen);
+ } else {
+ dispatch('updateDelayViewerUpdated', true);
+ router.push(`/project${nextFileToOpen.url}`);
+ }
+ } else if (!state.openFiles.length) {
+ router.push(`/project/${file.projectId}/tree/${file.branchId}/`);
+ }
+
+ eventHub.$emit(`editor.update.model.dispose.${file.key}`);
+};
+
+export const setFileActive = ({ commit, state, getters, dispatch }, path) => {
+ const file = state.entries[path];
+ const currentActiveFile = getters.activeFile;
+
+ if (file.active) return;
+
+ if (currentActiveFile) {
+ commit(types.SET_FILE_ACTIVE, {
+ path: currentActiveFile.path,
+ active: false,
+ });
+ }
+
+ commit(types.SET_FILE_ACTIVE, { path, active: true });
+ dispatch('scrollToTab');
+
+ commit(types.SET_CURRENT_PROJECT, file.projectId);
+ commit(types.SET_CURRENT_BRANCH, file.branchId);
+};
+
+export const getFileData = ({ state, commit, dispatch }, { path, makeFileActive = true }) => {
+ const file = state.entries[path];
+ commit(types.TOGGLE_LOADING, { entry: file });
+ return service
+ .getFileData(`${gon.relative_url_root ? gon.relative_url_root : ''}${file.url}`)
+ .then(res => {
+ const pageTitle = decodeURI(normalizeHeaders(res.headers)['PAGE-TITLE']);
+ setPageTitle(pageTitle);
+
+ return res.json();
+ })
+ .then(data => {
+ commit(types.SET_FILE_DATA, { data, file });
+ commit(types.TOGGLE_FILE_OPEN, path);
+ if (makeFileActive) dispatch('setFileActive', path);
+ commit(types.TOGGLE_LOADING, { entry: file });
+ })
+ .catch(() => {
+ commit(types.TOGGLE_LOADING, { entry: file });
+ flash('Error loading file data. Please try again.', 'alert', document, null, false, true);
+ });
+};
+
+export const setFileMrChange = ({ state, commit }, { file, mrChange }) => {
+ commit(types.SET_FILE_MERGE_REQUEST_CHANGE, { file, mrChange });
+};
+
+export const getRawFileData = ({ state, commit, dispatch }, { path, baseSha }) => {
+ const file = state.entries[path];
+ return new Promise((resolve, reject) => {
+ service
+ .getRawFileData(file)
+ .then(raw => {
+ commit(types.SET_FILE_RAW_DATA, { file, raw });
+ if (file.mrChange && file.mrChange.new_file === false) {
+ service
+ .getBaseRawFileData(file, baseSha)
+ .then(baseRaw => {
+ commit(types.SET_FILE_BASE_RAW_DATA, {
+ file,
+ baseRaw,
+ });
+ resolve(raw);
+ })
+ .catch(e => {
+ reject(e);
+ });
+ } else {
+ resolve(raw);
+ }
+ })
+ .catch(() => {
+ flash('Error loading file content. Please try again.');
+ reject();
+ });
+ });
+};
+
+export const changeFileContent = ({ state, commit }, { path, content }) => {
+ const file = state.entries[path];
+ commit(types.UPDATE_FILE_CONTENT, { path, content });
+
+ const indexOfChangedFile = state.changedFiles.findIndex(f => f.path === path);
+
+ if (file.changed && indexOfChangedFile === -1) {
+ commit(types.ADD_FILE_TO_CHANGED, path);
+ } else if (!file.changed && indexOfChangedFile !== -1) {
+ commit(types.REMOVE_FILE_FROM_CHANGED, path);
+ }
+};
+
+export const setFileLanguage = ({ getters, commit }, { fileLanguage }) => {
+ if (getters.activeFile) {
+ commit(types.SET_FILE_LANGUAGE, { file: getters.activeFile, fileLanguage });
+ }
+};
+
+export const setFileEOL = ({ getters, commit }, { eol }) => {
+ if (getters.activeFile) {
+ commit(types.SET_FILE_EOL, { file: getters.activeFile, eol });
+ }
+};
+
+export const setEditorPosition = ({ getters, commit }, { editorRow, editorColumn }) => {
+ if (getters.activeFile) {
+ commit(types.SET_FILE_POSITION, {
+ file: getters.activeFile,
+ editorRow,
+ editorColumn,
+ });
+ }
+};
+
+export const setFileViewMode = ({ state, commit }, { file, viewMode }) => {
+ commit(types.SET_FILE_VIEWMODE, { file, viewMode });
+};
+
+export const discardFileChanges = ({ state, commit }, path) => {
+ const file = state.entries[path];
+
+ commit(types.DISCARD_FILE_CHANGES, path);
+ commit(types.REMOVE_FILE_FROM_CHANGED, path);
+
+ if (file.tempFile && file.opened) {
+ commit(types.TOGGLE_FILE_OPEN, path);
+ }
+
+ eventHub.$emit(`editor.update.model.content.${file.path}`, file.raw);
+};
+
+export const openPendingTab = ({ commit, getters, dispatch, state }, file) => {
+ if (getters.activeFile && getters.activeFile.path === file.path && state.viewer === 'diff') {
+ return false;
+ }
+
+ commit(types.ADD_PENDING_TAB, { file });
+
+ dispatch('scrollToTab');
+
+ router.push(`/project/${file.projectId}/tree/${state.currentBranchId}/`);
+
+ return true;
+};
+
+export const removePendingTab = ({ commit }, file) => {
+ commit(types.REMOVE_PENDING_TAB, file);
+
+ eventHub.$emit(`editor.update.model.dispose.${file.key}`);
+};
diff --git a/app/assets/javascripts/ide/stores/actions/merge_request.js b/app/assets/javascripts/ide/stores/actions/merge_request.js
new file mode 100644
index 0000000000..da73034fd7
--- /dev/null
+++ b/app/assets/javascripts/ide/stores/actions/merge_request.js
@@ -0,0 +1,84 @@
+import flash from '~/flash';
+import service from '../../services';
+import * as types from '../mutation_types';
+
+export const getMergeRequestData = (
+ { commit, state, dispatch },
+ { projectId, mergeRequestId, force = false } = {},
+) =>
+ new Promise((resolve, reject) => {
+ if (!state.projects[projectId].mergeRequests[mergeRequestId] || force) {
+ service
+ .getProjectMergeRequestData(projectId, mergeRequestId)
+ .then(res => res.data)
+ .then(data => {
+ commit(types.SET_MERGE_REQUEST, {
+ projectPath: projectId,
+ mergeRequestId,
+ mergeRequest: data,
+ });
+ if (!state.currentMergeRequestId) {
+ commit(types.SET_CURRENT_MERGE_REQUEST, mergeRequestId);
+ }
+ resolve(data);
+ })
+ .catch(() => {
+ flash('Error loading merge request data. Please try again.');
+ reject(new Error(`Merge Request not loaded ${projectId}`));
+ });
+ } else {
+ resolve(state.projects[projectId].mergeRequests[mergeRequestId]);
+ }
+ });
+
+export const getMergeRequestChanges = (
+ { commit, state, dispatch },
+ { projectId, mergeRequestId, force = false } = {},
+) =>
+ new Promise((resolve, reject) => {
+ if (!state.projects[projectId].mergeRequests[mergeRequestId].changes.length || force) {
+ service
+ .getProjectMergeRequestChanges(projectId, mergeRequestId)
+ .then(res => res.data)
+ .then(data => {
+ commit(types.SET_MERGE_REQUEST_CHANGES, {
+ projectPath: projectId,
+ mergeRequestId,
+ changes: data,
+ });
+ resolve(data);
+ })
+ .catch(() => {
+ flash('Error loading merge request changes. Please try again.');
+ reject(new Error(`Merge Request Changes not loaded ${projectId}`));
+ });
+ } else {
+ resolve(state.projects[projectId].mergeRequests[mergeRequestId].changes);
+ }
+ });
+
+export const getMergeRequestVersions = (
+ { commit, state, dispatch },
+ { projectId, mergeRequestId, force = false } = {},
+) =>
+ new Promise((resolve, reject) => {
+ if (!state.projects[projectId].mergeRequests[mergeRequestId].versions.length || force) {
+ service
+ .getProjectMergeRequestVersions(projectId, mergeRequestId)
+ .then(res => res.data)
+ .then(data => {
+ commit(types.SET_MERGE_REQUEST_VERSIONS, {
+ projectPath: projectId,
+ mergeRequestId,
+ versions: data,
+ });
+ resolve(data);
+ })
+ .catch(() => {
+ flash('Error loading merge request versions. Please try again.');
+ reject(new Error(`Merge Request Versions not loaded ${projectId}`));
+ });
+ } else {
+ resolve(state.projects[projectId].mergeRequests[mergeRequestId].versions);
+ }
+ });
diff --git a/app/assets/javascripts/ide/stores/actions/project.js b/app/assets/javascripts/ide/stores/actions/project.js
new file mode 100644
index 0000000000..b3882cb8d2
--- /dev/null
+++ b/app/assets/javascripts/ide/stores/actions/project.js
@@ -0,0 +1,49 @@
+import flash from '~/flash';
+import service from '../../services';
+import * as types from '../mutation_types';
+
+export const getProjectData = (
+ { commit, state, dispatch },
+ { namespace, projectId, force = false } = {},
+) => new Promise((resolve, reject) => {
+ if (!state.projects[`${namespace}/${projectId}`] || force) {
+ commit(types.TOGGLE_LOADING, { entry: state });
+ service.getProjectData(namespace, projectId)
+ .then(res => res.data)
+ .then((data) => {
+ commit(types.TOGGLE_LOADING, { entry: state });
+ commit(types.SET_PROJECT, { projectPath: `${namespace}/${projectId}`, project: data });
+ if (!state.currentProjectId) commit(types.SET_CURRENT_PROJECT, `${namespace}/${projectId}`);
+ resolve(data);
+ })
+ .catch(() => {
+ flash('Error loading project data. Please try again.', 'alert', document, null, false, true);
+ reject(new Error(`Project not loaded ${namespace}/${projectId}`));
+ });
+ } else {
+ resolve(state.projects[`${namespace}/${projectId}`]);
+ }
+});
+
+export const getBranchData = (
+ { commit, state, dispatch },
+ { projectId, branchId, force = false } = {},
+) => new Promise((resolve, reject) => {
+ if ((typeof state.projects[`${projectId}`] === 'undefined' ||
+ !state.projects[`${projectId}`].branches[branchId])
+ || force) {
+ service.getBranchData(`${projectId}`, branchId)
+ .then(({ data }) => {
+ const { id } = data.commit;
+ commit(types.SET_BRANCH, { projectPath: `${projectId}`, branchName: branchId, branch: data });
+ commit(types.SET_BRANCH_WORKING_REFERENCE, { projectId, branchId, reference: id });
+ resolve(data);
+ })
+ .catch(() => {
+ flash('Error loading branch data. Please try again.', 'alert', document, null, false, true);
+ reject(new Error(`Branch not loaded - ${projectId}/${branchId}`));
+ });
+ } else {
+ resolve(state.projects[`${projectId}`].branches[branchId]);
+ }
+});
diff --git a/app/assets/javascripts/ide/stores/actions/tree.js b/app/assets/javascripts/ide/stores/actions/tree.js
new file mode 100644
index 0000000000..6536be04f0
--- /dev/null
+++ b/app/assets/javascripts/ide/stores/actions/tree.js
@@ -0,0 +1,95 @@
+import { normalizeHeaders } from '~/lib/utils/common_utils';
+import flash from '~/flash';
+import service from '../../services';
+import * as types from '../mutation_types';
+import { findEntry } from '../utils';
+import FilesDecoratorWorker from '../workers/files_decorator_worker';
+
+export const toggleTreeOpen = ({ commit, dispatch }, path) => {
+ commit(types.TOGGLE_TREE_OPEN, path);
+};
+
+export const handleTreeEntryAction = ({ commit, dispatch }, row) => {
+ if (row.type === 'tree') {
+ dispatch('toggleTreeOpen', row.path);
+ } else if (row.type === 'blob' && (row.opened || row.changed)) {
+ if (row.changed && !row.opened) {
+ commit(types.TOGGLE_FILE_OPEN, row.path);
+ }
+
+ dispatch('setFileActive', row.path);
+ } else {
+ dispatch('getFileData', { path: row.path });
+ }
+};
+
+export const getLastCommitData = ({ state, commit, dispatch, getters }, tree = state) => {
+ if (!tree || tree.lastCommitPath === null || !tree.lastCommitPath) return;
+
+ service
+ .getTreeLastCommit(tree.lastCommitPath)
+ .then(res => {
+ const lastCommitPath = normalizeHeaders(res.headers)['MORE-LOGS-URL'] || null;
+
+ commit(types.SET_LAST_COMMIT_URL, { tree, url: lastCommitPath });
+
+ return res.json();
+ })
+ .then(data => {
+ data.forEach(lastCommit => {
+ const entry = findEntry(tree.tree, lastCommit.type, lastCommit.file_name);
+
+ if (entry) {
+ commit(types.SET_LAST_COMMIT_DATA, { entry, lastCommit });
+ }
+ });
+
+ dispatch('getLastCommitData', tree);
+ })
+ .catch(() => flash('Error fetching log data.', 'alert', document, null, false, true));
+};
+
+export const getFiles = ({ state, commit, dispatch }, { projectId, branchId } = {}) =>
+ new Promise((resolve, reject) => {
+ if (!state.trees[`${projectId}/${branchId}`]) {
+ const selectedProject = state.projects[projectId];
+ commit(types.CREATE_TREE, { treePath: `${projectId}/${branchId}` });
+
+ service
+ .getFiles(selectedProject.web_url, branchId)
+ .then(res => res.json())
+ .then(data => {
+ const worker = new FilesDecoratorWorker();
+ worker.addEventListener('message', e => {
+ const { entries, treeList } = e.data;
+ const selectedTree = state.trees[`${projectId}/${branchId}`];
+
+ commit(types.SET_ENTRIES, entries);
+ commit(types.SET_DIRECTORY_DATA, {
+ treePath: `${projectId}/${branchId}`,
+ data: treeList,
+ });
+ commit(types.TOGGLE_LOADING, {
+ entry: selectedTree,
+ forceValue: false,
+ });
+
+ worker.terminate();
+
+ resolve();
+ });
+
+ worker.postMessage({
+ data,
+ projectId,
+ branchId,
+ });
+ })
+ .catch(e => {
+ flash('Error loading tree data. Please try again.', 'alert', document, null, false, true);
+ reject(e);
+ });
+ } else {
+ resolve();
+ }
+ });
diff --git a/app/assets/javascripts/ide/stores/getters.js b/app/assets/javascripts/ide/stores/getters.js
new file mode 100644
index 0000000000..a77cdbc13c
--- /dev/null
+++ b/app/assets/javascripts/ide/stores/getters.js
@@ -0,0 +1,37 @@
+export const activeFile = state => state.openFiles.find(file => file.active) || null;
+
+export const addedFiles = state => state.changedFiles.filter(f => f.tempFile);
+
+export const modifiedFiles = state => state.changedFiles.filter(f => !f.tempFile);
+
+export const projectsWithTrees = state =>
+ Object.keys(state.projects).map(projectId => {
+ const project = state.projects[projectId];
+
+ return {
+ ...project,
+ branches: Object.keys(project.branches).map(branchId => {
+ const branch = project.branches[branchId];
+
+ return {
+ ...branch,
+ tree: state.trees[branch.treeId],
+ };
+ }),
+ };
+ });
+
+export const currentMergeRequest = state => {
+ if (state.projects[state.currentProjectId]) {
+ return state.projects[state.currentProjectId].mergeRequests[state.currentMergeRequestId];
+ }
+ return null;
+};
+
+// eslint-disable-next-line no-confusing-arrow
+export const currentIcon = state =>
+ state.rightPanelCollapsed ? 'angle-double-left' : 'angle-double-right';
+
+export const hasChanges = state => !!state.changedFiles.length;
+
+export const hasMergeRequest = state => !!state.currentMergeRequestId;
diff --git a/app/assets/javascripts/ide/stores/index.js b/app/assets/javascripts/ide/stores/index.js
new file mode 100644
index 0000000000..7c82ce7976
--- /dev/null
+++ b/app/assets/javascripts/ide/stores/index.js
@@ -0,0 +1,19 @@
+import Vue from 'vue';
+import Vuex from 'vuex';
+import state from './state';
+import * as actions from './actions';
+import * as getters from './getters';
+import mutations from './mutations';
+import commitModule from './modules/commit';
+
+Vue.use(Vuex);
+
+export default new Vuex.Store({
+ state: state(),
+ actions,
+ mutations,
+ getters,
+ modules: {
+ commit: commitModule,
+ },
+});
diff --git a/app/assets/javascripts/ide/stores/modules/commit/actions.js b/app/assets/javascripts/ide/stores/modules/commit/actions.js
new file mode 100644
index 0000000000..367c45f7e2
--- /dev/null
+++ b/app/assets/javascripts/ide/stores/modules/commit/actions.js
@@ -0,0 +1,200 @@
+import $ from 'jquery';
+import { sprintf, __ } from '~/locale';
+import flash from '~/flash';
+import { stripHtml } from '~/lib/utils/text_utility';
+import * as rootTypes from '../../mutation_types';
+import { createCommitPayload, createNewMergeRequestUrl } from '../../utils';
+import router from '../../../ide_router';
+import service from '../../../services';
+import * as types from './mutation_types';
+import * as consts from './constants';
+import eventHub from '../../../eventhub';
+
+export const updateCommitMessage = ({ commit }, message) => {
+ commit(types.UPDATE_COMMIT_MESSAGE, message);
+};
+
+export const discardDraft = ({ commit }) => {
+ commit(types.UPDATE_COMMIT_MESSAGE, '');
+};
+
+export const updateCommitAction = ({ commit }, commitAction) => {
+ commit(types.UPDATE_COMMIT_ACTION, commitAction);
+};
+
+export const updateBranchName = ({ commit }, branchName) => {
+ commit(types.UPDATE_NEW_BRANCH_NAME, branchName);
+};
+
+export const setLastCommitMessage = ({ rootState, commit }, data) => {
+ const currentProject = rootState.projects[rootState.currentProjectId];
+ const commitStats = data.stats
+ ? sprintf(__('with %{additions} additions, %{deletions} deletions.'), {
+ additions: data.stats.additions, // eslint-disable-line indent
+ deletions: data.stats.deletions, // eslint-disable-line indent
+ }) // eslint-disable-line indent
+ : '';
+ const commitMsg = sprintf(
+ __('Your changes have been committed. Commit %{commitId} %{commitStats}'),
+ {
+ commitId: `${
+ data.short_id
+ }`,
+ commitStats,
+ },
+ false,
+ );
+
+ commit(rootTypes.SET_LAST_COMMIT_MSG, commitMsg, { root: true });
+};
+
+export const checkCommitStatus = ({ rootState }) =>
+ service
+ .getBranchData(rootState.currentProjectId, rootState.currentBranchId)
+ .then(({ data }) => {
+ const { id } = data.commit;
+ const selectedBranch =
+ rootState.projects[rootState.currentProjectId].branches[rootState.currentBranchId];
+
+ if (selectedBranch.workingReference !== id) {
+ return true;
+ }
+
+ return false;
+ })
+ .catch(() =>
+ flash(
+ __('Error checking branch data. Please try again.'),
+ 'alert',
+ document,
+ null,
+ false,
+ true,
+ ),
+ );
+
+export const updateFilesAfterCommit = (
+ { commit, dispatch, state, rootState, rootGetters },
+ { data, branch },
+) => {
+ const selectedProject = rootState.projects[rootState.currentProjectId];
+ const lastCommit = {
+ commit_path: `${selectedProject.web_url}/commit/${data.id}`,
+ commit: {
+ id: data.id,
+ message: data.message,
+ authored_date: data.committed_date,
+ author_name: data.committer_name,
+ },
+ };
+
+ commit(
+ rootTypes.SET_BRANCH_WORKING_REFERENCE,
+ {
+ projectId: rootState.currentProjectId,
+ branchId: rootState.currentBranchId,
+ reference: data.id,
+ },
+ { root: true },
+ );
+
+ rootState.changedFiles.forEach(entry => {
+ commit(
+ rootTypes.SET_LAST_COMMIT_DATA,
+ {
+ entry,
+ lastCommit,
+ },
+ { root: true },
+ );
+
+ eventHub.$emit(`editor.update.model.content.${entry.path}`, entry.content);
+
+ commit(
+ rootTypes.SET_FILE_RAW_DATA,
+ {
+ file: entry,
+ raw: entry.content,
+ },
+ { root: true },
+ );
+
+ commit(
+ rootTypes.TOGGLE_FILE_CHANGED,
+ {
+ file: entry,
+ changed: false,
+ },
+ { root: true },
+ );
+ });
+
+ commit(rootTypes.REMOVE_ALL_CHANGES_FILES, null, { root: true });
+
+ if (state.commitAction === consts.COMMIT_TO_NEW_BRANCH) {
+ router.push(
+ `/project/${rootState.currentProjectId}/blob/${branch}/${rootGetters.activeFile.path}`,
+ );
+ }
+};
+
+export const commitChanges = ({ commit, state, getters, dispatch, rootState }) => {
+ const newBranch = state.commitAction !== consts.COMMIT_TO_CURRENT_BRANCH;
+ const payload = createCommitPayload(getters.branchName, newBranch, state, rootState);
+ const getCommitStatus = newBranch ? Promise.resolve(false) : dispatch('checkCommitStatus');
+
+ commit(types.UPDATE_LOADING, true);
+
+ return getCommitStatus
+ .then(
+ branchChanged =>
+ new Promise(resolve => {
+ if (branchChanged) {
+ // show the modal with a Bootstrap call
+ $('#ide-create-branch-modal').modal('show');
+ } else {
+ resolve();
+ }
+ }),
+ )
+ .then(() => service.commit(rootState.currentProjectId, payload))
+ .then(({ data }) => {
+ commit(types.UPDATE_LOADING, false);
+
+ if (!data.short_id) {
+ flash(data.message, 'alert', document, null, false, true);
+ return null;
+ }
+
+ dispatch('setLastCommitMessage', data);
+ dispatch('updateCommitMessage', '');
+ return dispatch('updateFilesAfterCommit', {
+ data,
+ branch: getters.branchName,
+ })
+ .then(() => {
+ if (state.commitAction === consts.COMMIT_TO_NEW_BRANCH_MR) {
+ dispatch(
+ 'redirectToUrl',
+ createNewMergeRequestUrl(
+ rootState.projects[rootState.currentProjectId].web_url,
+ getters.branchName,
+ rootState.currentBranchId,
+ ),
+ { root: true },
+ );
+ }
+ })
+ .then(() => dispatch('updateCommitAction', consts.COMMIT_TO_CURRENT_BRANCH));
+ })
+ .catch(err => {
+ let errMsg = __('Error committing changes. Please try again.');
+ if (err.response.data && err.response.data.message) {
+ errMsg += ` (${stripHtml(err.response.data.message)})`;
+ }
+ flash(errMsg, 'alert', document, null, false, true);
+ window.dispatchEvent(new Event('resize'));
+
+ commit(types.UPDATE_LOADING, false);
+ });
+};
diff --git a/app/assets/javascripts/ide/stores/modules/commit/constants.js b/app/assets/javascripts/ide/stores/modules/commit/constants.js
new file mode 100644
index 0000000000..230b0a3d9b
--- /dev/null
+++ b/app/assets/javascripts/ide/stores/modules/commit/constants.js
@@ -0,0 +1,3 @@
+export const COMMIT_TO_CURRENT_BRANCH = '1';
+export const COMMIT_TO_NEW_BRANCH = '2';
+export const COMMIT_TO_NEW_BRANCH_MR = '3';
diff --git a/app/assets/javascripts/ide/stores/modules/commit/getters.js b/app/assets/javascripts/ide/stores/modules/commit/getters.js
new file mode 100644
index 0000000000..f7cdd6adb0
--- /dev/null
+++ b/app/assets/javascripts/ide/stores/modules/commit/getters.js
@@ -0,0 +1,24 @@
+import * as consts from './constants';
+
+export const discardDraftButtonDisabled = state => state.commitMessage === '' || state.submitCommitLoading;
+
+export const commitButtonDisabled = (state, getters, rootState) =>
+ getters.discardDraftButtonDisabled || !rootState.changedFiles.length;
+
+export const newBranchName = (state, _, rootState) =>
+ `${gon.current_username}-${rootState.currentBranchId}-patch-${`${new Date().getTime()}`.substr(-5)}`;
+
+export const branchName = (state, getters, rootState) => {
+ if (
+ state.commitAction === consts.COMMIT_TO_NEW_BRANCH ||
+ state.commitAction === consts.COMMIT_TO_NEW_BRANCH_MR
+ ) {
+ if (state.newBranchName === '') {
+ return getters.newBranchName;
+ }
+
+ return state.newBranchName;
+ }
+
+ return rootState.currentBranchId;
+};
diff --git a/app/assets/javascripts/ide/stores/modules/commit/index.js b/app/assets/javascripts/ide/stores/modules/commit/index.js
new file mode 100644
index 0000000000..3bf65b0284
--- /dev/null
+++ b/app/assets/javascripts/ide/stores/modules/commit/index.js
@@ -0,0 +1,12 @@
+import state from './state';
+import mutations from './mutations';
+import * as actions from './actions';
+import * as getters from './getters';
+
+export default {
+ namespaced: true,
+ state: state(),
+ mutations,
+ actions,
+ getters,
+};
diff --git a/app/assets/javascripts/ide/stores/modules/commit/mutation_types.js b/app/assets/javascripts/ide/stores/modules/commit/mutation_types.js
new file mode 100644
index 0000000000..9221f054e9
--- /dev/null
+++ b/app/assets/javascripts/ide/stores/modules/commit/mutation_types.js
@@ -0,0 +1,4 @@
+export const UPDATE_COMMIT_MESSAGE = 'UPDATE_COMMIT_MESSAGE';
+export const UPDATE_COMMIT_ACTION = 'UPDATE_COMMIT_ACTION';
+export const UPDATE_NEW_BRANCH_NAME = 'UPDATE_NEW_BRANCH_NAME';
+export const UPDATE_LOADING = 'UPDATE_LOADING';
diff --git a/app/assets/javascripts/ide/stores/modules/commit/mutations.js b/app/assets/javascripts/ide/stores/modules/commit/mutations.js
new file mode 100644
index 0000000000..797357e3df
--- /dev/null
+++ b/app/assets/javascripts/ide/stores/modules/commit/mutations.js
@@ -0,0 +1,24 @@
+import * as types from './mutation_types';
+
+export default {
+ [types.UPDATE_COMMIT_MESSAGE](state, commitMessage) {
+ Object.assign(state, {
+ commitMessage,
+ });
+ },
+ [types.UPDATE_COMMIT_ACTION](state, commitAction) {
+ Object.assign(state, {
+ commitAction,
+ });
+ },
+ [types.UPDATE_NEW_BRANCH_NAME](state, newBranchName) {
+ Object.assign(state, {
+ newBranchName,
+ });
+ },
+ [types.UPDATE_LOADING](state, submitCommitLoading) {
+ Object.assign(state, {
+ submitCommitLoading,
+ });
+ },
+};
diff --git a/app/assets/javascripts/ide/stores/modules/commit/state.js b/app/assets/javascripts/ide/stores/modules/commit/state.js
new file mode 100644
index 0000000000..8dae50961b
--- /dev/null
+++ b/app/assets/javascripts/ide/stores/modules/commit/state.js
@@ -0,0 +1,6 @@
+export default () => ({
+ commitMessage: '',
+ commitAction: '1',
+ newBranchName: '',
+ submitCommitLoading: false,
+});
diff --git a/app/assets/javascripts/ide/stores/mutation_types.js b/app/assets/javascripts/ide/stores/mutation_types.js
new file mode 100644
index 0000000000..e3f504e5ab
--- /dev/null
+++ b/app/assets/javascripts/ide/stores/mutation_types.js
@@ -0,0 +1,55 @@
+export const SET_INITIAL_DATA = 'SET_INITIAL_DATA';
+export const TOGGLE_LOADING = 'TOGGLE_LOADING';
+export const SET_LAST_COMMIT_DATA = 'SET_LAST_COMMIT_DATA';
+export const SET_LAST_COMMIT_MSG = 'SET_LAST_COMMIT_MSG';
+export const SET_LEFT_PANEL_COLLAPSED = 'SET_LEFT_PANEL_COLLAPSED';
+export const SET_RIGHT_PANEL_COLLAPSED = 'SET_RIGHT_PANEL_COLLAPSED';
+export const SET_RESIZING_STATUS = 'SET_RESIZING_STATUS';
+
+// Project Mutation Types
+export const SET_PROJECT = 'SET_PROJECT';
+export const SET_CURRENT_PROJECT = 'SET_CURRENT_PROJECT';
+export const TOGGLE_PROJECT_OPEN = 'TOGGLE_PROJECT_OPEN';
+
+// Merge Request Mutation Types
+export const SET_MERGE_REQUEST = 'SET_MERGE_REQUEST';
+export const SET_CURRENT_MERGE_REQUEST = 'SET_CURRENT_MERGE_REQUEST';
+export const SET_MERGE_REQUEST_CHANGES = 'SET_MERGE_REQUEST_CHANGES';
+export const SET_MERGE_REQUEST_VERSIONS = 'SET_MERGE_REQUEST_VERSIONS';
+
+// Branch Mutation Types
+export const SET_BRANCH = 'SET_BRANCH';
+export const SET_BRANCH_WORKING_REFERENCE = 'SET_BRANCH_WORKING_REFERENCE';
+export const TOGGLE_BRANCH_OPEN = 'TOGGLE_BRANCH_OPEN';
+
+// Tree mutation types
+export const SET_DIRECTORY_DATA = 'SET_DIRECTORY_DATA';
+export const TOGGLE_TREE_OPEN = 'TOGGLE_TREE_OPEN';
+export const SET_LAST_COMMIT_URL = 'SET_LAST_COMMIT_URL';
+export const CREATE_TREE = 'CREATE_TREE';
+export const REMOVE_ALL_CHANGES_FILES = 'REMOVE_ALL_CHANGES_FILES';
+
+// File mutation types
+export const SET_FILE_DATA = 'SET_FILE_DATA';
+export const TOGGLE_FILE_OPEN = 'TOGGLE_FILE_OPEN';
+export const SET_FILE_ACTIVE = 'SET_FILE_ACTIVE';
+export const SET_FILE_RAW_DATA = 'SET_FILE_RAW_DATA';
+export const SET_FILE_BASE_RAW_DATA = 'SET_FILE_BASE_RAW_DATA';
+export const UPDATE_FILE_CONTENT = 'UPDATE_FILE_CONTENT';
+export const SET_FILE_LANGUAGE = 'SET_FILE_LANGUAGE';
+export const SET_FILE_POSITION = 'SET_FILE_POSITION';
+export const SET_FILE_VIEWMODE = 'SET_FILE_VIEWMODE';
+export const SET_FILE_EOL = 'SET_FILE_EOL';
+export const DISCARD_FILE_CHANGES = 'DISCARD_FILE_CHANGES';
+export const ADD_FILE_TO_CHANGED = 'ADD_FILE_TO_CHANGED';
+export const REMOVE_FILE_FROM_CHANGED = 'REMOVE_FILE_FROM_CHANGED';
+export const TOGGLE_FILE_CHANGED = 'TOGGLE_FILE_CHANGED';
+export const SET_CURRENT_BRANCH = 'SET_CURRENT_BRANCH';
+export const SET_ENTRIES = 'SET_ENTRIES';
+export const CREATE_TMP_ENTRY = 'CREATE_TMP_ENTRY';
+export const SET_FILE_MERGE_REQUEST_CHANGE = 'SET_FILE_MERGE_REQUEST_CHANGE';
+export const UPDATE_VIEWER = 'UPDATE_VIEWER';
+export const UPDATE_DELAY_VIEWER_CHANGE = 'UPDATE_DELAY_VIEWER_CHANGE';
+
+export const ADD_PENDING_TAB = 'ADD_PENDING_TAB';
+export const REMOVE_PENDING_TAB = 'REMOVE_PENDING_TAB';
diff --git a/app/assets/javascripts/ide/stores/mutations.js b/app/assets/javascripts/ide/stores/mutations.js
new file mode 100644
index 0000000000..5e5eb83166
--- /dev/null
+++ b/app/assets/javascripts/ide/stores/mutations.js
@@ -0,0 +1,103 @@
+import * as types from './mutation_types';
+import projectMutations from './mutations/project';
+import mergeRequestMutation from './mutations/merge_request';
+import fileMutations from './mutations/file';
+import treeMutations from './mutations/tree';
+import branchMutations from './mutations/branch';
+
+export default {
+ [types.SET_INITIAL_DATA](state, data) {
+ Object.assign(state, data);
+ },
+ [types.TOGGLE_LOADING](state, { entry, forceValue = undefined }) {
+ if (entry.path) {
+ Object.assign(state.entries[entry.path], {
+ loading: forceValue !== undefined ? forceValue : !state.entries[entry.path].loading,
+ });
+ } else {
+ Object.assign(entry, {
+ loading: forceValue !== undefined ? forceValue : !entry.loading,
+ });
+ }
+ },
+ [types.SET_LEFT_PANEL_COLLAPSED](state, collapsed) {
+ Object.assign(state, {
+ leftPanelCollapsed: collapsed,
+ });
+ },
+ [types.SET_RIGHT_PANEL_COLLAPSED](state, collapsed) {
+ Object.assign(state, {
+ rightPanelCollapsed: collapsed,
+ });
+ },
+ [types.SET_RESIZING_STATUS](state, resizing) {
+ Object.assign(state, {
+ panelResizing: resizing,
+ });
+ },
+ [types.SET_LAST_COMMIT_DATA](state, { entry, lastCommit }) {
+ Object.assign(entry.lastCommit, {
+ id: lastCommit.commit.id,
+ url: lastCommit.commit_path,
+ message: lastCommit.commit.message,
+ author: lastCommit.commit.author_name,
+ updatedAt: lastCommit.commit.authored_date,
+ });
+ },
+ [types.SET_LAST_COMMIT_MSG](state, lastCommitMsg) {
+ Object.assign(state, {
+ lastCommitMsg,
+ });
+ },
+ [types.SET_ENTRIES](state, entries) {
+ Object.assign(state, {
+ entries,
+ });
+ },
+ [types.CREATE_TMP_ENTRY](state, { data, projectId, branchId }) {
+ Object.keys(data.entries).reduce((acc, key) => {
+ const entry = data.entries[key];
+ const foundEntry = state.entries[key];
+
+ if (!foundEntry) {
+ Object.assign(state.entries, {
+ [key]: entry,
+ });
+ } else {
+ const tree = entry.tree.filter(
+ f => foundEntry.tree.find(e => e.path === f.path) === undefined,
+ );
+ Object.assign(foundEntry, {
+ tree: foundEntry.tree.concat(tree),
+ });
+ }
+
+ return acc.concat(key);
+ }, []);
+
+ const foundEntry = state.trees[`${projectId}/${branchId}`].tree.find(
+ e => e.path === data.treeList[0].path,
+ );
+
+ if (!foundEntry) {
+ Object.assign(state.trees[`${projectId}/${branchId}`], {
+ tree: state.trees[`${projectId}/${branchId}`].tree.concat(data.treeList),
+ });
+ }
+ },
+ [types.UPDATE_VIEWER](state, viewer) {
+ Object.assign(state, {
+ viewer,
+ });
+ },
+ [types.UPDATE_DELAY_VIEWER_CHANGE](state, delayViewerUpdated) {
+ Object.assign(state, {
+ delayViewerUpdated,
+ });
+ },
+ ...projectMutations,
+ ...mergeRequestMutation,
+ ...fileMutations,
+ ...treeMutations,
+ ...branchMutations,
+};
diff --git a/app/assets/javascripts/ide/stores/mutations/branch.js b/app/assets/javascripts/ide/stores/mutations/branch.js
new file mode 100644
index 0000000000..2972ba5e38
--- /dev/null
+++ b/app/assets/javascripts/ide/stores/mutations/branch.js
@@ -0,0 +1,26 @@
+import * as types from '../mutation_types';
+
+export default {
+ [types.SET_CURRENT_BRANCH](state, currentBranchId) {
+ Object.assign(state, {
+ currentBranchId,
+ });
+ },
+ [types.SET_BRANCH](state, { projectPath, branchName, branch }) {
+ Object.assign(state.projects[projectPath], {
+ branches: {
+ [branchName]: {
+ ...branch,
+ treeId: `${projectPath}/${branchName}`,
+ active: true,
+ workingReference: '',
+ },
+ },
+ });
+ },
+ [types.SET_BRANCH_WORKING_REFERENCE](state, { projectId, branchId, reference }) {
+ Object.assign(state.projects[projectId].branches[branchId], {
+ workingReference: reference,
+ });
+ },
+};
diff --git a/app/assets/javascripts/ide/stores/mutations/file.js b/app/assets/javascripts/ide/stores/mutations/file.js
new file mode 100644
index 0000000000..eeb14b5490
--- /dev/null
+++ b/app/assets/javascripts/ide/stores/mutations/file.js
@@ -0,0 +1,147 @@
+import * as types from '../mutation_types';
+
+export default {
+ [types.SET_FILE_ACTIVE](state, { path, active }) {
+ Object.assign(state.entries[path], {
+ active,
+ });
+
+ if (active && !state.entries[path].pending) {
+ Object.assign(state, {
+ openFiles: state.openFiles.map(f =>
+ Object.assign(f, { active: f.pending ? false : f.active }),
+ ),
+ });
+ }
+ },
+ [types.TOGGLE_FILE_OPEN](state, path) {
+ Object.assign(state.entries[path], {
+ opened: !state.entries[path].opened,
+ });
+
+ if (state.entries[path].opened) {
+ Object.assign(state, {
+ openFiles: state.openFiles.filter(f => f.path !== path).concat(state.entries[path]),
+ });
+ } else {
+ const file = state.entries[path];
+
+ Object.assign(state, {
+ openFiles: state.openFiles.filter(f => f.key !== file.key),
+ });
+ }
+ },
+ [types.SET_FILE_DATA](state, { data, file }) {
+ Object.assign(state.entries[file.path], {
+ id: data.id,
+ blamePath: data.blame_path,
+ commitsPath: data.commits_path,
+ permalink: data.permalink,
+ rawPath: data.raw_path,
+ binary: data.binary,
+ renderError: data.render_error,
+ raw: null,
+ baseRaw: null,
+ html: data.html,
+ size: data.size,
+ });
+ },
+ [types.SET_FILE_RAW_DATA](state, { file, raw }) {
+ Object.assign(state.entries[file.path], {
+ raw,
+ });
+ },
+ [types.SET_FILE_BASE_RAW_DATA](state, { file, baseRaw }) {
+ Object.assign(state.entries[file.path], {
+ baseRaw,
+ });
+ },
+ [types.UPDATE_FILE_CONTENT](state, { path, content }) {
+ const changed = content !== state.entries[path].raw;
+
+ Object.assign(state.entries[path], {
+ content,
+ changed,
+ });
+ },
+ [types.SET_FILE_LANGUAGE](state, { file, fileLanguage }) {
+ Object.assign(state.entries[file.path], {
+ fileLanguage,
+ });
+ },
+ [types.SET_FILE_EOL](state, { file, eol }) {
+ Object.assign(state.entries[file.path], {
+ eol,
+ });
+ },
+ [types.SET_FILE_POSITION](state, { file, editorRow, editorColumn }) {
+ Object.assign(state.entries[file.path], {
+ editorRow,
+ editorColumn,
+ });
+ },
+ [types.SET_FILE_MERGE_REQUEST_CHANGE](state, { file, mrChange }) {
+ Object.assign(state.entries[file.path], {
+ mrChange,
+ });
+ },
+ [types.SET_FILE_VIEWMODE](state, { file, viewMode }) {
+ Object.assign(state.entries[file.path], {
+ viewMode,
+ });
+ },
+ [types.DISCARD_FILE_CHANGES](state, path) {
+ Object.assign(state.entries[path], {
+ content: state.entries[path].raw,
+ changed: false,
+ });
+ },
+ [types.ADD_FILE_TO_CHANGED](state, path) {
+ Object.assign(state, {
+ changedFiles: state.changedFiles.concat(state.entries[path]),
+ });
+ },
+ [types.REMOVE_FILE_FROM_CHANGED](state, path) {
+ Object.assign(state, {
+ changedFiles: state.changedFiles.filter(f => f.path !== path),
+ });
+ },
+ [types.TOGGLE_FILE_CHANGED](state, { file, changed }) {
+ Object.assign(state.entries[file.path], {
+ changed,
+ });
+ },
+ [types.ADD_PENDING_TAB](state, { file, keyPrefix = 'pending' }) {
+ const pendingTab = state.openFiles.find(f => f.path === file.path && f.pending);
+ let openFiles = state.openFiles.map(f =>
+ Object.assign(f, { active: f.path === file.path, opened: false }),
+ );
+
+ if (!pendingTab) {
+ const openFile = openFiles.find(f => f.path === file.path);
+
+ openFiles = openFiles.concat(openFile ? null : file).reduce((acc, f) => {
+ if (!f) return acc;
+
+ if (f.path === file.path) {
+ return acc.concat({
+ ...f,
+ active: true,
+ pending: true,
+ opened: true,
+ key: `${keyPrefix}-${f.key}`,
+ });
+ }
+
+ return acc.concat(f);
+ }, []);
+ }
+
+ Object.assign(state, { openFiles });
+ },
+ [types.REMOVE_PENDING_TAB](state, file) {
+ Object.assign(state, {
+ openFiles: state.openFiles.filter(f => f.key !== file.key),
+ });
+ },
+};
diff --git a/app/assets/javascripts/ide/stores/mutations/merge_request.js b/app/assets/javascripts/ide/stores/mutations/merge_request.js
new file mode 100644
index 0000000000..334819fe70
--- /dev/null
+++ b/app/assets/javascripts/ide/stores/mutations/merge_request.js
@@ -0,0 +1,33 @@
+import * as types from '../mutation_types';
+
+export default {
+ [types.SET_CURRENT_MERGE_REQUEST](state, currentMergeRequestId) {
+ Object.assign(state, {
+ currentMergeRequestId,
+ });
+ },
+ [types.SET_MERGE_REQUEST](state, { projectPath, mergeRequestId, mergeRequest }) {
+ Object.assign(state.projects[projectPath], {
+ mergeRequests: {
+ [mergeRequestId]: {
+ ...mergeRequest,
+ active: true,
+ changes: [],
+ versions: [],
+ baseCommitSha: null,
+ },
+ },
+ });
+ },
+ [types.SET_MERGE_REQUEST_CHANGES](state, { projectPath, mergeRequestId, changes }) {
+ Object.assign(state.projects[projectPath].mergeRequests[mergeRequestId], {
+ changes,
+ });
+ },
+ [types.SET_MERGE_REQUEST_VERSIONS](state, { projectPath, mergeRequestId, versions }) {
+ Object.assign(state.projects[projectPath].mergeRequests[mergeRequestId], {
+ versions,
+ baseCommitSha: versions.length ? versions[0].base_commit_sha : null,
+ });
+ },
+};
diff --git a/app/assets/javascripts/ide/stores/mutations/project.js b/app/assets/javascripts/ide/stores/mutations/project.js
new file mode 100644
index 0000000000..284b39a2c7
--- /dev/null
+++ b/app/assets/javascripts/ide/stores/mutations/project.js
@@ -0,0 +1,24 @@
+import * as types from '../mutation_types';
+
+export default {
+ [types.SET_CURRENT_PROJECT](state, currentProjectId) {
+ Object.assign(state, {
+ currentProjectId,
+ });
+ },
+ [types.SET_PROJECT](state, { projectPath, project }) {
+ // Add client side properties
+ Object.assign(project, {
+ tree: [],
+ branches: {},
+ mergeRequests: {},
+ active: true,
+ });
+
+ Object.assign(state, {
+ projects: Object.assign({}, state.projects, {
+ [projectPath]: project,
+ }),
+ });
+ },
+};
diff --git a/app/assets/javascripts/ide/stores/mutations/tree.js b/app/assets/javascripts/ide/stores/mutations/tree.js
new file mode 100644
index 0000000000..1176c040fb
--- /dev/null
+++ b/app/assets/javascripts/ide/stores/mutations/tree.js
@@ -0,0 +1,34 @@
+import * as types from '../mutation_types';
+
+export default {
+ [types.TOGGLE_TREE_OPEN](state, path) {
+ Object.assign(state.entries[path], {
+ opened: !state.entries[path].opened,
+ });
+ },
+ [types.CREATE_TREE](state, { treePath }) {
+ Object.assign(state, {
+ trees: Object.assign({}, state.trees, {
+ [treePath]: {
+ tree: [],
+ loading: true,
+ },
+ }),
+ });
+ },
+ [types.SET_DIRECTORY_DATA](state, { data, treePath }) {
+ Object.assign(state.trees[treePath], {
+ tree: data,
+ });
+ },
+ [types.SET_LAST_COMMIT_URL](state, { tree = state, url }) {
+ Object.assign(tree, {
+ lastCommitPath: url,
+ });
+ },
+ [types.REMOVE_ALL_CHANGES_FILES](state) {
+ Object.assign(state, {
+ changedFiles: [],
+ });
+ },
+};
diff --git a/app/assets/javascripts/ide/stores/state.js b/app/assets/javascripts/ide/stores/state.js
new file mode 100644
index 0000000000..e5cc881400
--- /dev/null
+++ b/app/assets/javascripts/ide/stores/state.js
@@ -0,0 +1,20 @@
+export default () => ({
+ currentProjectId: '',
+ currentBranchId: '',
+ currentMergeRequestId: '',
+ changedFiles: [],
+ endpoints: {},
+ lastCommitMsg: '',
+ lastCommitPath: '',
+ loading: false,
+ openFiles: [],
+ parentTreeUrl: '',
+ trees: {},
+ projects: {},
+ leftPanelCollapsed: false,
+ rightPanelCollapsed: false,
+ panelResizing: false,
+ entries: {},
+ viewer: 'editor',
+ delayViewerUpdated: false,
+});
diff --git a/app/assets/javascripts/ide/stores/utils.js b/app/assets/javascripts/ide/stores/utils.js
new file mode 100644
index 0000000000..05a019de54
--- /dev/null
+++ b/app/assets/javascripts/ide/stores/utils.js
@@ -0,0 +1,134 @@
+export const dataStructure = () => ({
+ id: '',
+ // Key will contain a mixture of ID and path
+ // it can also contain a prefix `pending-` for files opened in review mode
+ key: '',
+ type: '',
+ projectId: '',
+ branchId: '',
+ name: '',
+ url: '',
+ path: '',
+ tempFile: false,
+ tree: [],
+ loading: false,
+ opened: false,
+ active: false,
+ changed: false,
+ lastCommitPath: '',
+ lastCommit: {
+ id: '',
+ url: '',
+ message: '',
+ updatedAt: '',
+ author: '',
+ },
+ blamePath: '',
+ commitsPath: '',
+ permalink: '',
+ rawPath: '',
+ binary: false,
+ html: '',
+ raw: '',
+ content: '',
+ parentTreeUrl: '',
+ renderError: false,
+ base64: false,
+ editorRow: 1,
+ editorColumn: 1,
+ fileLanguage: '',
+ eol: '',
+ viewMode: 'edit',
+ previewMode: null,
+ size: 0,
+});
+
+export const decorateData = entity => {
+ const {
+ id,
+ projectId,
+ branchId,
+ type,
+ url,
+ name,
+ path,
+ renderError,
+ content = '',
+ tempFile = false,
+ active = false,
+ opened = false,
+ changed = false,
+ parentTreeUrl = '',
+ base64 = false,
+ previewMode,
+ file_lock,
+ html,
+ } = entity;
+
+ return {
+ ...dataStructure(),
+ id,
+ projectId,
+ branchId,
+ key: `${name}-${type}-${id}`,
+ type,
+ name,
+ url,
+ path,
+ tempFile,
+ opened,
+ active,
+ parentTreeUrl,
+ changed,
+ renderError,
+ content,
+ base64,
+ previewMode,
+ file_lock,
+ html,
+ };
+};
+
+export const findEntry = (tree, type, name, prop = 'name') =>
+ tree.find(f => f.type === type && f[prop] === name);
+
+export const findIndexOfFile = (state, file) => state.findIndex(f => f.path === file.path);
+
+export const setPageTitle = title => {
+ document.title = title;
+};
+
+export const createCommitPayload = (branch, newBranch, state, rootState) => ({
+ branch,
+ commit_message: state.commitMessage,
+ actions: rootState.changedFiles.map(f => ({
+ action: f.tempFile ? 'create' : 'update',
+ file_path: f.path,
+ content: f.content,
+ encoding: f.base64 ? 'base64' : 'text',
+ })),
+ start_branch: newBranch ? rootState.currentBranchId : undefined,
+});
+
+export const createNewMergeRequestUrl = (projectUrl, source, target) =>
+ `${projectUrl}/merge_requests/new?merge_request[source_branch]=${source}&merge_request[target_branch]=${target}`;
+
+const sortTreesByTypeAndName = (a, b) => {
+ if (a.type === 'tree' && b.type === 'blob') {
+ return -1;
+ } else if (a.type === 'blob' && b.type === 'tree') {
+ return 1;
+ }
+ if (a.name.toLowerCase() < b.name.toLowerCase()) return -1;
+ if (a.name.toLowerCase() > b.name.toLowerCase()) return 1;
+ return 0;
+};
+
+export const sortTree = sortedTree =>
+ sortedTree
+ .map(entity =>
+ Object.assign(entity, {
+ tree: entity.tree.length ? sortTree(entity.tree) : [],
+ }),
+ )
+ .sort(sortTreesByTypeAndName);
diff --git a/app/assets/javascripts/ide/stores/workers/files_decorator_worker.js b/app/assets/javascripts/ide/stores/workers/files_decorator_worker.js
new file mode 100644
index 0000000000..a167327690
--- /dev/null
+++ b/app/assets/javascripts/ide/stores/workers/files_decorator_worker.js
@@ -0,0 +1,90 @@
+import { viewerInformationForPath } from '~/vue_shared/components/content_viewer/lib/viewer_utils';
+import { decorateData, sortTree } from '../utils';
+
+self.addEventListener('message', e => {
+ const { data, projectId, branchId, tempFile = false, content = '', base64 = false } = e.data;
+
+ const treeList = [];
+ let file;
+ const entries = data.reduce((acc, path) => {
+ const pathSplit = path.split('/');
+ const blobName = pathSplit.pop().trim();
+
+ if (pathSplit.length > 0) {
+ pathSplit.reduce((pathAcc, folderName) => {
+ const parentFolder = acc[pathAcc[pathAcc.length - 1]];
+ const folderPath = `${parentFolder ? `${parentFolder.path}/` : ''}${folderName}`;
+ const foundEntry = acc[folderPath];
+
+ if (!foundEntry) {
+ const tree = decorateData({
+ projectId,
+ branchId,
+ id: folderPath,
+ name: folderName,
+ path: folderPath,
+ url: `/${projectId}/tree/${branchId}/${folderPath}/`,
+ type: 'tree',
+ parentTreeUrl: parentFolder ? parentFolder.url : `/${projectId}/tree/${branchId}/`,
+ tempFile,
+ changed: tempFile,
+ opened: tempFile,
+ });
+
+ Object.assign(acc, {
+ [folderPath]: tree,
+ });
+
+ if (parentFolder) {
+ parentFolder.tree.push(tree);
+ } else {
+ treeList.push(tree);
+ }
+
+ pathAcc.push(tree.path);
+ } else {
+ pathAcc.push(foundEntry.path);
+ }
+
+ return pathAcc;
+ }, []);
+ }
+
+ if (blobName !== '') {
+ const fileFolder = acc[pathSplit.join('/')];
+ file = decorateData({
+ projectId,
+ branchId,
+ id: path,
+ name: blobName,
+ path,
+ url: `/${projectId}/blob/${branchId}/${path}`,
+ type: 'blob',
+ parentTreeUrl: fileFolder ? fileFolder.url : `/${projectId}/blob/${branchId}`,
+ tempFile,
+ changed: tempFile,
+ content,
+ base64,
+ previewMode: viewerInformationForPath(blobName),
+ });
+
+ Object.assign(acc, {
+ [path]: file,
+ });
+
+ if (fileFolder) {
+ fileFolder.tree.push(file);
+ } else {
+ treeList.push(file);
+ }
+ }
+
+ return acc;
+ }, {});
+
+ self.postMessage({
+ entries,
+ treeList: sortTree(treeList),
+ file,
+ });
+});
diff --git a/app/assets/javascripts/image_diff/image_diff.js b/app/assets/javascripts/image_diff/image_diff.js
index f3af92cf2b..fab0255c37 100644
--- a/app/assets/javascripts/image_diff/image_diff.js
+++ b/app/assets/javascripts/image_diff/image_diff.js
@@ -1,3 +1,4 @@
+import $ from 'jquery';
import imageDiffHelper from './helpers/index';
import ImageBadge from './image_badge';
import { isImageLoaded } from '../lib/utils/image_utility';
diff --git a/app/assets/javascripts/importer_status.js b/app/assets/javascripts/importer_status.js
index 523bd2adb9..b469e1e2ad 100644
--- a/app/assets/javascripts/importer_status.js
+++ b/app/assets/javascripts/importer_status.js
@@ -1,3 +1,4 @@
+import $ from 'jquery';
import _ from 'underscore';
import { __, sprintf } from './locale';
import axios from './lib/utils/axios_utils';
diff --git a/app/assets/javascripts/init_changes_dropdown.js b/app/assets/javascripts/init_changes_dropdown.js
index 1bab7965c1..09cca1dc7d 100644
--- a/app/assets/javascripts/init_changes_dropdown.js
+++ b/app/assets/javascripts/init_changes_dropdown.js
@@ -1,3 +1,4 @@
+import $ from 'jquery';
import stickyMonitor from './lib/utils/sticky';
export default (stickyTop) => {
diff --git a/app/assets/javascripts/init_labels.js b/app/assets/javascripts/init_labels.js
index 5f20055510..15da5d5cce 100644
--- a/app/assets/javascripts/init_labels.js
+++ b/app/assets/javascripts/init_labels.js
@@ -1,3 +1,4 @@
+import $ from 'jquery';
import LabelManager from './label_manager';
import GroupLabelSubscription from './group_label_subscription';
import ProjectLabelSubscription from './project_label_subscription';
diff --git a/app/assets/javascripts/integrations/integration_settings_form.js b/app/assets/javascripts/integrations/integration_settings_form.js
index 2848fe003c..741894b5e6 100644
--- a/app/assets/javascripts/integrations/integration_settings_form.js
+++ b/app/assets/javascripts/integrations/integration_settings_form.js
@@ -1,3 +1,4 @@
+import $ from 'jquery';
import axios from '../lib/utils/axios_utils';
import flash from '../flash';
diff --git a/app/assets/javascripts/issuable/auto_width_dropdown_select.js b/app/assets/javascripts/issuable/auto_width_dropdown_select.js
index 14a2bfbe4e..b2c2de9e5d 100644
--- a/app/assets/javascripts/issuable/auto_width_dropdown_select.js
+++ b/app/assets/javascripts/issuable/auto_width_dropdown_select.js
@@ -1,3 +1,5 @@
+import $ from 'jquery';
+
let instanceCount = 0;
class AutoWidthDropdownSelect {
diff --git a/app/assets/javascripts/issuable_bulk_update_actions.js b/app/assets/javascripts/issuable_bulk_update_actions.js
index 8c1b2e78ca..e003fb1d12 100644
--- a/app/assets/javascripts/issuable_bulk_update_actions.js
+++ b/app/assets/javascripts/issuable_bulk_update_actions.js
@@ -1,4 +1,6 @@
/* eslint-disable comma-dangle, quotes, consistent-return, func-names, array-callback-return, space-before-function-paren, prefer-arrow-callback, max-len, no-unused-expressions, no-sequences, no-underscore-dangle, no-unused-vars, no-param-reassign */
+
+import $ from 'jquery';
import _ from 'underscore';
import axios from './lib/utils/axios_utils';
import Flash from './flash';
diff --git a/app/assets/javascripts/issuable_bulk_update_sidebar.js b/app/assets/javascripts/issuable_bulk_update_sidebar.js
index 2056efe701..2307c8e0d8 100644
--- a/app/assets/javascripts/issuable_bulk_update_sidebar.js
+++ b/app/assets/javascripts/issuable_bulk_update_sidebar.js
@@ -1,5 +1,6 @@
/* eslint-disable class-methods-use-this, no-new */
+import $ from 'jquery';
import IssuableBulkUpdateActions from './issuable_bulk_update_actions';
import MilestoneSelect from './milestone_select';
import issueStatusSelect from './issue_status_select';
diff --git a/app/assets/javascripts/issuable_context.js b/app/assets/javascripts/issuable_context.js
index da99394ff9..7470d634b9 100644
--- a/app/assets/javascripts/issuable_context.js
+++ b/app/assets/javascripts/issuable_context.js
@@ -1,3 +1,4 @@
+import $ from 'jquery';
import Cookies from 'js-cookie';
import bp from './breakpoints';
import UsersSelect from './users_select';
diff --git a/app/assets/javascripts/issuable_form.js b/app/assets/javascripts/issuable_form.js
index fdfad0b6a4..bb8b3d91e4 100644
--- a/app/assets/javascripts/issuable_form.js
+++ b/app/assets/javascripts/issuable_form.js
@@ -1,6 +1,7 @@
/* eslint-disable func-names, prefer-rest-params, wrap-iife, no-use-before-define, no-useless-escape, no-new, object-shorthand, no-unused-vars, comma-dangle, no-alert, consistent-return, no-else-return, prefer-template, one-var, one-var-declaration-per-line, curly, max-len */
/* global GitLab */
+import $ from 'jquery';
import Pikaday from 'pikaday';
import Autosave from './autosave';
import UsersSelect from './users_select';
diff --git a/app/assets/javascripts/issuable_index.js b/app/assets/javascripts/issuable_index.js
index 0683ca82a3..06ec454616 100644
--- a/app/assets/javascripts/issuable_index.js
+++ b/app/assets/javascripts/issuable_index.js
@@ -1,3 +1,4 @@
+import $ from 'jquery';
import axios from './lib/utils/axios_utils';
import flash from './flash';
import { __ } from './locale';
diff --git a/app/assets/javascripts/issue.js b/app/assets/javascripts/issue.js
index 333bbd9e0b..5113ac6775 100644
--- a/app/assets/javascripts/issue.js
+++ b/app/assets/javascripts/issue.js
@@ -1,4 +1,6 @@
/* eslint-disable func-names, space-before-function-paren, no-var, prefer-rest-params, wrap-iife, one-var, no-underscore-dangle, one-var-declaration-per-line, object-shorthand, no-unused-vars, no-new, comma-dangle, consistent-return, quotes, dot-notation, quote-props, prefer-arrow-callback, max-len */
+
+import $ from 'jquery';
import axios from './lib/utils/axios_utils';
import { addDelimiter } from './lib/utils/text_utility';
import flash from './flash';
diff --git a/app/assets/javascripts/issue_show/components/description.vue b/app/assets/javascripts/issue_show/components/description.vue
index 1338be0ec4..ae577e04a5 100644
--- a/app/assets/javascripts/issue_show/components/description.vue
+++ b/app/assets/javascripts/issue_show/components/description.vue
@@ -1,4 +1,5 @@
@@ -28,5 +36,21 @@
{{ title }}:
{{ value }}
+
+
+
+
+
+
diff --git a/app/assets/javascripts/jobs/components/sidebar_details_block.vue b/app/assets/javascripts/jobs/components/sidebar_details_block.vue
index 56814a5252..af47056d98 100644
--- a/app/assets/javascripts/jobs/components/sidebar_details_block.vue
+++ b/app/assets/javascripts/jobs/components/sidebar_details_block.vue
@@ -22,6 +22,11 @@
type: Boolean,
required: true,
},
+ runnerHelpUrl: {
+ type: String,
+ required: false,
+ default: '',
+ },
},
computed: {
shouldRenderContent() {
@@ -39,6 +44,21 @@
runnerId() {
return `#${this.job.runner.id}`;
},
+ hasTimeout() {
+ return this.job.metadata != null && this.job.metadata.timeout_human_readable !== null;
+ },
+ timeout() {
+ if (this.job.metadata == null) {
+ return '';
+ }
+
+ let t = this.job.metadata.timeout_human_readable;
+ if (this.job.metadata.timeout_source !== '') {
+ t += ` (from ${this.job.metadata.timeout_source})`;
+ }
+
+ return t;
+ },
renderBlock() {
return this.job.merge_request ||
this.job.duration ||
@@ -114,6 +134,13 @@
title="Queued"
:value="queued"
/>
+
{
props: {
isLoading: this.mediator.state.isLoading,
job: this.mediator.store.state.job,
+ runnerHelpUrl: dataset.runnerHelpUrl,
},
});
},
diff --git a/app/assets/javascripts/label_manager.js b/app/assets/javascripts/label_manager.js
index 61b40f79db..e230dbbd4a 100644
--- a/app/assets/javascripts/label_manager.js
+++ b/app/assets/javascripts/label_manager.js
@@ -1,4 +1,6 @@
/* eslint-disable comma-dangle, class-methods-use-this, no-underscore-dangle, no-param-reassign, no-unused-vars, consistent-return, func-names, space-before-function-paren, max-len */
+
+import $ from 'jquery';
import Sortable from 'vendor/Sortable';
import flash from './flash';
diff --git a/app/assets/javascripts/labels.js b/app/assets/javascripts/labels.js
index 7aab13ed9c..d85ae85170 100644
--- a/app/assets/javascripts/labels.js
+++ b/app/assets/javascripts/labels.js
@@ -1,3 +1,5 @@
+import $ from 'jquery';
+
export default class Labels {
constructor() {
this.setSuggestedColor = this.setSuggestedColor.bind(this);
diff --git a/app/assets/javascripts/labels_select.js b/app/assets/javascripts/labels_select.js
index 9b46bbf83d..824d3f7ca0 100644
--- a/app/assets/javascripts/labels_select.js
+++ b/app/assets/javascripts/labels_select.js
@@ -1,6 +1,8 @@
/* eslint-disable no-useless-return, func-names, space-before-function-paren, wrap-iife, no-var, no-underscore-dangle, prefer-arrow-callback, max-len, one-var, no-unused-vars, one-var-declaration-per-line, prefer-template, no-new, consistent-return, object-shorthand, comma-dangle, no-shadow, no-param-reassign, brace-style, vars-on-top, quotes, no-lonely-if, no-else-return, dot-notation, no-empty, no-return-assign, camelcase, prefer-spread */
/* global Issuable */
/* global ListLabel */
+
+import $ from 'jquery';
import _ from 'underscore';
import { __ } from './locale';
import axios from './lib/utils/axios_utils';
diff --git a/app/assets/javascripts/layout_nav.js b/app/assets/javascripts/layout_nav.js
index 1b4900827b..e317718877 100644
--- a/app/assets/javascripts/layout_nav.js
+++ b/app/assets/javascripts/layout_nav.js
@@ -1,3 +1,4 @@
+import $ from 'jquery';
import ContextualSidebar from './contextual_sidebar';
import initFlyOutNav from './fly_out_nav';
diff --git a/app/assets/javascripts/lib/utils/bootstrap_linked_tabs.js b/app/assets/javascripts/lib/utils/bootstrap_linked_tabs.js
index 0bf2ba6acc..3873f4528c 100644
--- a/app/assets/javascripts/lib/utils/bootstrap_linked_tabs.js
+++ b/app/assets/javascripts/lib/utils/bootstrap_linked_tabs.js
@@ -1,3 +1,5 @@
+import $ from 'jquery';
+
/**
* Linked Tabs
*
diff --git a/app/assets/javascripts/lib/utils/common_utils.js b/app/assets/javascripts/lib/utils/common_utils.js
index ed90db317d..9ff2042475 100644
--- a/app/assets/javascripts/lib/utils/common_utils.js
+++ b/app/assets/javascripts/lib/utils/common_utils.js
@@ -1,4 +1,4 @@
-import jQuery from 'jquery';
+import $ from 'jquery';
import Cookies from 'js-cookie';
import axios from './axios_utils';
import { getLocationHash } from './url_utility';
@@ -33,6 +33,7 @@ export const checkPageAndAction = (page, action) => {
export const isInIssuePage = () => checkPageAndAction('issues', 'show');
export const isInMRPage = () => checkPageAndAction('merge_requests', 'show');
+export const isInEpicPage = () => checkPageAndAction('epics', 'show');
export const isInNoteablePage = () => isInIssuePage() || isInMRPage();
export const hasVueMRDiscussionsCookie = () => Cookies.get('vue_mr_discussions');
@@ -142,7 +143,7 @@ export const isMetaClick = e => e.metaKey || e.ctrlKey || e.which === 2;
export const scrollToElement = (element) => {
let $el = element;
- if (!(element instanceof jQuery)) {
+ if (!(element instanceof $)) {
$el = $(element);
}
const top = $el.offset().top;
diff --git a/app/assets/javascripts/lib/utils/csrf.js b/app/assets/javascripts/lib/utils/csrf.js
index 0bdb547d31..ca9828c468 100644
--- a/app/assets/javascripts/lib/utils/csrf.js
+++ b/app/assets/javascripts/lib/utils/csrf.js
@@ -1,3 +1,5 @@
+import $ from 'jquery';
+
/*
This module provides easy access to the CSRF token and caches
it for re-use. It also exposes some values commonly used in relation
diff --git a/app/assets/javascripts/lib/utils/datetime_utility.js b/app/assets/javascripts/lib/utils/datetime_utility.js
index d6cccbef42..c3d94d63c1 100644
--- a/app/assets/javascripts/lib/utils/datetime_utility.js
+++ b/app/assets/javascripts/lib/utils/datetime_utility.js
@@ -1,3 +1,4 @@
+import $ from 'jquery';
import timeago from 'timeago.js';
import dateFormat from 'vendor/date.format';
import { pluralize } from './text_utility';
diff --git a/app/assets/javascripts/lib/utils/dom_utils.js b/app/assets/javascripts/lib/utils/dom_utils.js
index de65ea15a6..914de9de94 100644
--- a/app/assets/javascripts/lib/utils/dom_utils.js
+++ b/app/assets/javascripts/lib/utils/dom_utils.js
@@ -1,7 +1,12 @@
-/* eslint-disable import/prefer-default-export */
+import $ from 'jquery';
+import { isInIssuePage, isInMRPage, isInEpicPage, hasVueMRDiscussionsCookie } from './common_utils';
+
+const isVueMRDiscussions = () => isInMRPage() && hasVueMRDiscussionsCookie() && !$('#diffs').is(':visible');
export const addClassIfElementExists = (element, className) => {
if (element) {
element.classList.add(className);
}
};
+
+export const isInVueNoteablePage = () => isInIssuePage() || isInEpicPage() || isVueMRDiscussions();
diff --git a/app/assets/javascripts/lib/utils/text_markdown.js b/app/assets/javascripts/lib/utils/text_markdown.js
index 5dc98b4a92..5a16adea4d 100644
--- a/app/assets/javascripts/lib/utils/text_markdown.js
+++ b/app/assets/javascripts/lib/utils/text_markdown.js
@@ -1,26 +1,25 @@
/* eslint-disable import/prefer-default-export, func-names, space-before-function-paren, wrap-iife, no-var, no-param-reassign, no-cond-assign, quotes, one-var, one-var-declaration-per-line, operator-assignment, no-else-return, prefer-template, prefer-arrow-callback, no-empty, max-len, consistent-return, no-unused-vars, no-return-assign, max-len, vars-on-top */
+import $ from 'jquery';
+import { insertText } from '~/lib/utils/common_utils';
-const textUtils = {};
-
-textUtils.selectedText = function(text, textarea) {
+function selectedText(text, textarea) {
return text.substring(textarea.selectionStart, textarea.selectionEnd);
-};
+}
-textUtils.lineBefore = function(text, textarea) {
+function lineBefore(text, textarea) {
var split;
split = text.substring(0, textarea.selectionStart).trim().split('\n');
return split[split.length - 1];
-};
+}
-textUtils.lineAfter = function(text, textarea) {
+function lineAfter(text, textarea) {
return text.substring(textarea.selectionEnd).trim().split('\n')[0];
-};
+}
-textUtils.blockTagText = function(text, textArea, blockTag, selected) {
- var lineAfter, lineBefore;
- lineBefore = this.lineBefore(text, textArea);
- lineAfter = this.lineAfter(text, textArea);
- if (lineBefore === blockTag && lineAfter === blockTag) {
+function blockTagText(text, textArea, blockTag, selected) {
+ const before = lineBefore(text, textArea);
+ const after = lineAfter(text, textArea);
+ if (before === blockTag && after === blockTag) {
// To remove the block tag we have to select the line before & after
if (blockTag != null) {
textArea.selectionStart = textArea.selectionStart - (blockTag.length + 1);
@@ -30,10 +29,30 @@ textUtils.blockTagText = function(text, textArea, blockTag, selected) {
} else {
return blockTag + "\n" + selected + "\n" + blockTag;
}
-};
+}
-textUtils.insertText = function(textArea, text, tag, blockTag, selected, wrap) {
- var insertText, inserted, selectedSplit, startChar, removedLastNewLine, removedFirstNewLine, currentLineEmpty, lastNewLine;
+function moveCursor(textArea, tag, wrapped, removedLastNewLine) {
+ var pos;
+ if (!textArea.setSelectionRange) {
+ return;
+ }
+ if (textArea.selectionStart === textArea.selectionEnd) {
+ if (wrapped) {
+ pos = textArea.selectionStart - tag.length;
+ } else {
+ pos = textArea.selectionStart;
+ }
+
+ if (removedLastNewLine) {
+ pos -= 1;
+ }
+
+ return textArea.setSelectionRange(pos, pos);
+ }
+}
+
+export function insertMarkdownText(textArea, text, tag, blockTag, selected, wrap) {
+ var textToInsert, inserted, selectedSplit, startChar, removedLastNewLine, removedFirstNewLine, currentLineEmpty, lastNewLine;
removedLastNewLine = false;
removedFirstNewLine = false;
currentLineEmpty = false;
@@ -65,9 +84,9 @@ textUtils.insertText = function(textArea, text, tag, blockTag, selected, wrap) {
if (selectedSplit.length > 1 && (!wrap || (blockTag != null && blockTag !== ''))) {
if (blockTag != null && blockTag !== '') {
- insertText = this.blockTagText(text, textArea, blockTag, selected);
+ textToInsert = blockTagText(text, textArea, blockTag, selected);
} else {
- insertText = selectedSplit.map(function(val) {
+ textToInsert = selectedSplit.map(function(val) {
if (val.indexOf(tag) === 0) {
return "" + (val.replace(tag, ''));
} else {
@@ -76,78 +95,42 @@ textUtils.insertText = function(textArea, text, tag, blockTag, selected, wrap) {
}).join('\n');
}
} else {
- insertText = "" + startChar + tag + selected + (wrap ? tag : ' ');
+ textToInsert = "" + startChar + tag + selected + (wrap ? tag : ' ');
}
if (removedFirstNewLine) {
- insertText = '\n' + insertText;
+ textToInsert = '\n' + textToInsert;
}
if (removedLastNewLine) {
- insertText += '\n';
+ textToInsert += '\n';
}
- if (document.queryCommandSupported('insertText')) {
- inserted = document.execCommand('insertText', false, insertText);
- }
- if (!inserted) {
- try {
- document.execCommand("ms-beginUndoUnit");
- } catch (error) {}
- textArea.value = this.replaceRange(text, textArea.selectionStart, textArea.selectionEnd, insertText);
- try {
- document.execCommand("ms-endUndoUnit");
- } catch (error) {}
- }
- return this.moveCursor(textArea, tag, wrap, removedLastNewLine);
-};
+ insertText(textArea, textToInsert);
+ return moveCursor(textArea, tag, wrap, removedLastNewLine);
+}
-textUtils.moveCursor = function(textArea, tag, wrapped, removedLastNewLine) {
- var pos;
- if (!textArea.setSelectionRange) {
- return;
- }
- if (textArea.selectionStart === textArea.selectionEnd) {
- if (wrapped) {
- pos = textArea.selectionStart - tag.length;
- } else {
- pos = textArea.selectionStart;
- }
-
- if (removedLastNewLine) {
- pos -= 1;
- }
-
- return textArea.setSelectionRange(pos, pos);
- }
-};
-
-textUtils.updateText = function(textArea, tag, blockTag, wrap) {
+function updateText(textArea, tag, blockTag, wrap) {
var $textArea, selected, text;
$textArea = $(textArea);
textArea = $textArea.get(0);
text = $textArea.val();
- selected = this.selectedText(text, textArea);
+ selected = selectedText(text, textArea);
$textArea.focus();
- return this.insertText(textArea, text, tag, blockTag, selected, wrap);
-};
+ return insertMarkdownText(textArea, text, tag, blockTag, selected, wrap);
+}
-textUtils.init = function(form) {
- var self;
- self = this;
- return $('.js-md', form).off('click').on('click', function() {
- var $this;
- $this = $(this);
- return self.updateText($this.closest('.md-area').find('textarea'), $this.data('mdTag'), $this.data('mdBlock'), !$this.data('mdPrepend'));
- });
-};
-
-textUtils.removeListeners = function(form) {
- return $('.js-md', form).off('click');
-};
-
-textUtils.replaceRange = function(s, start, end, substitute) {
+function replaceRange(s, start, end, substitute) {
return s.substring(0, start) + substitute + s.substring(end);
-};
+}
-export default textUtils;
+export function addMarkdownListeners(form) {
+ return $('.js-md', form).off('click').on('click', function() {
+ const $this = $(this);
+ return updateText($this.closest('.md-area').find('textarea'), $this.data('mdTag'), $this.data('mdBlock'), !$this.data('mdPrepend'));
+ });
+}
+
+export function removeMarkdownListeners(form) {
+ return $('.js-md', form).off('click');
+}
diff --git a/app/assets/javascripts/lib/utils/text_utility.js b/app/assets/javascripts/lib/utils/text_utility.js
index c0ce078651..b54ecd2d54 100644
--- a/app/assets/javascripts/lib/utils/text_utility.js
+++ b/app/assets/javascripts/lib/utils/text_utility.js
@@ -7,7 +7,8 @@
* @param {String} text
* @returns {String}
*/
-export const addDelimiter = text => (text ? text.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ',') : text);
+export const addDelimiter = text =>
+ (text ? text.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ',') : text);
/**
* Returns '99+' for numbers bigger than 99.
@@ -22,7 +23,8 @@ export const highCountTrim = count => (count > 99 ? '99+' : count);
* @param {String} string
* @requires {String}
*/
-export const humanize = string => string.charAt(0).toUpperCase() + string.replace(/_/g, ' ').slice(1);
+export const humanize = string =>
+ string.charAt(0).toUpperCase() + string.replace(/_/g, ' ').slice(1);
/**
* Adds an 's' to the end of the string when count is bigger than 0
@@ -53,7 +55,7 @@ export const slugify = str => str.trim().toLowerCase();
* @param {Number} maxLength
* @returns {String}
*/
-export const truncate = (string, maxLength) => `${string.substr(0, (maxLength - 3))}...`;
+export const truncate = (string, maxLength) => `${string.substr(0, maxLength - 3)}...`;
/**
* Capitalizes first character
@@ -65,20 +67,6 @@ export function capitalizeFirstCharacter(text) {
return `${text[0].toUpperCase()}${text.slice(1)}`;
}
-export function camelCase(str) {
- return str.replace(/_+([a-z])/gi, ($1, $2) => $2.toUpperCase());
-}
-
-export function camelCaseKeys(obj = {}) {
- return Object.keys(obj).reduce((acc, key) => {
- const camelKey = camelCase(key);
- return {
- ...acc,
- [camelKey]: obj[key],
- };
- }, {});
-}
-
/**
* Replaces all html tags from a string with the given replacement.
*
@@ -94,3 +82,15 @@ export const stripHtml = (string, replace = '') => string.replace(/<[^>]*>/g, re
* @param {*} string
*/
export const convertToCamelCase = string => string.replace(/(_\w)/g, s => s[1].toUpperCase());
+
+/**
+ * Converts a sentence to lower case from the second word onwards
+ * e.g. Hello World => Hello world
+ *
+ * @param {*} string
+ */
+export const convertToSentenceCase = string => {
+ const splitWord = string.split(' ').map((word, index) => (index > 0 ? word.toLowerCase() : word));
+
+ return splitWord.join(' ');
+};
diff --git a/app/assets/javascripts/lib/utils/url_utility.js b/app/assets/javascripts/lib/utils/url_utility.js
index a266bb6771..dd17544b65 100644
--- a/app/assets/javascripts/lib/utils/url_utility.js
+++ b/app/assets/javascripts/lib/utils/url_utility.js
@@ -51,7 +51,7 @@ export function removeParams(params) {
const url = document.createElement('a');
url.href = window.location.href;
- params.forEach((param) => {
+ params.forEach(param => {
url.search = removeParamQueryString(url.search, param);
});
@@ -83,3 +83,11 @@ export function refreshCurrentPage() {
export function redirectTo(url) {
return window.location.assign(url);
}
+
+export function webIDEUrl(route = undefined) {
+ let returnUrl = `${gon.relative_url_root}/-/ide/`;
+ if (route) {
+ returnUrl += `project${route}`;
+ }
+ return returnUrl;
+}
diff --git a/app/assets/javascripts/line_highlighter.js b/app/assets/javascripts/line_highlighter.js
index e5c1fce3db..f2323f5745 100644
--- a/app/assets/javascripts/line_highlighter.js
+++ b/app/assets/javascripts/line_highlighter.js
@@ -1,5 +1,7 @@
/* eslint-disable func-names, space-before-function-paren, no-var, prefer-rest-params, wrap-iife, no-use-before-define, no-underscore-dangle, no-param-reassign, prefer-template, quotes, comma-dangle, prefer-arrow-callback, consistent-return, one-var, one-var-declaration-per-line, no-else-return, max-len */
+import $ from 'jquery';
+
// LineHighlighter
//
// Handles single- and multi-line selection and highlight for blob views.
diff --git a/app/assets/javascripts/logo.js b/app/assets/javascripts/logo.js
index 3688a57937..403e216e70 100644
--- a/app/assets/javascripts/logo.js
+++ b/app/assets/javascripts/logo.js
@@ -1,3 +1,5 @@
+import $ from 'jquery';
+
export default function initLogoAnimation() {
window.addEventListener('beforeunload', () => {
$('.tanuki-logo').addClass('animate');
diff --git a/app/assets/javascripts/main.js b/app/assets/javascripts/main.js
index 53b01cca1d..2c80baba10 100644
--- a/app/assets/javascripts/main.js
+++ b/app/assets/javascripts/main.js
@@ -1,5 +1,5 @@
/* eslint-disable import/first */
-/* global ConfirmDangerModal */
+/* global $ */
import jQuery from 'jquery';
import Cookies from 'js-cookie';
@@ -20,7 +20,6 @@ import './behaviors/';
// everything else
import loadAwardsHandler from './awards_handler';
import bp from './breakpoints';
-import './confirm_danger_modal';
import Flash, { removeFlashClickListener } from './flash';
import './gl_dropdown';
import initTodoToggle from './header';
@@ -31,7 +30,6 @@ import LazyLoader from './lazy_loader';
import initLogoAnimation from './logo';
import './milestone_select';
import './projects_dropdown';
-import './render_gfm';
import initBreadcrumbs from './breadcrumb';
import initDispatcher from './dispatcher';
@@ -214,16 +212,6 @@ document.addEventListener('DOMContentLoaded', () => {
$(document).trigger('toggle.comments');
});
- $document.on('click', '.js-confirm-danger', (e) => {
- const btn = $(e.target);
- const form = btn.closest('form');
- const text = btn.data('confirmDangerMessage');
- e.preventDefault();
-
- // eslint-disable-next-line no-new
- new ConfirmDangerModal(form, text);
- });
-
$document.on('breakpoint:change', (e, breakpoint) => {
if (breakpoint === 'sm' || breakpoint === 'xs') {
const $gutterIcon = $sidebarGutterToggle.find('i');
diff --git a/app/assets/javascripts/member_expiration_date.js b/app/assets/javascripts/member_expiration_date.js
index 84e70e35ba..d27922a209 100644
--- a/app/assets/javascripts/member_expiration_date.js
+++ b/app/assets/javascripts/member_expiration_date.js
@@ -1,3 +1,4 @@
+import $ from 'jquery';
import Pikaday from 'pikaday';
import { parsePikadayDate, pikadayToString } from './lib/utils/datefix';
diff --git a/app/assets/javascripts/members.js b/app/assets/javascripts/members.js
index 330ebed5f7..7d0c701fd7 100644
--- a/app/assets/javascripts/members.js
+++ b/app/assets/javascripts/members.js
@@ -1,3 +1,5 @@
+import $ from 'jquery';
+
export default class Members {
constructor() {
this.addListeners();
diff --git a/app/assets/javascripts/merge_conflicts/merge_conflict_store.js b/app/assets/javascripts/merge_conflicts/merge_conflict_store.js
index 8be7314ded..db1d09eb2f 100644
--- a/app/assets/javascripts/merge_conflicts/merge_conflict_store.js
+++ b/app/assets/javascripts/merge_conflicts/merge_conflict_store.js
@@ -1,5 +1,6 @@
/* eslint-disable comma-dangle, object-shorthand, no-param-reassign, camelcase, no-nested-ternary, no-continue, max-len */
+import $ from 'jquery';
import Vue from 'vue';
import Cookies from 'js-cookie';
diff --git a/app/assets/javascripts/merge_conflicts/merge_conflicts_bundle.js b/app/assets/javascripts/merge_conflicts/merge_conflicts_bundle.js
index 66b258839a..4abd5433bb 100644
--- a/app/assets/javascripts/merge_conflicts/merge_conflicts_bundle.js
+++ b/app/assets/javascripts/merge_conflicts/merge_conflicts_bundle.js
@@ -1,5 +1,6 @@
/* eslint-disable new-cap, comma-dangle, no-new */
+import $ from 'jquery';
import Vue from 'vue';
import Flash from '../flash';
import initIssuableSidebar from '../init_issuable_sidebar';
diff --git a/app/assets/javascripts/merge_request.js b/app/assets/javascripts/merge_request.js
index a64093afcf..d8222ebec6 100644
--- a/app/assets/javascripts/merge_request.js
+++ b/app/assets/javascripts/merge_request.js
@@ -1,4 +1,6 @@
/* eslint-disable func-names, space-before-function-paren, no-var, prefer-rest-params, wrap-iife, quotes, no-underscore-dangle, one-var, one-var-declaration-per-line, consistent-return, dot-notation, quote-props, comma-dangle, object-shorthand, max-len, prefer-arrow-callback */
+
+import $ from 'jquery';
import { __ } from '~/locale';
import TaskList from './task_list';
import MergeRequestTabs from './merge_request_tabs';
diff --git a/app/assets/javascripts/merge_request_tabs.js b/app/assets/javascripts/merge_request_tabs.js
index 46789e324c..3f84f4b949 100644
--- a/app/assets/javascripts/merge_request_tabs.js
+++ b/app/assets/javascripts/merge_request_tabs.js
@@ -1,16 +1,13 @@
/* eslint-disable no-new, class-methods-use-this */
+import $ from 'jquery';
import Cookies from 'js-cookie';
import axios from './lib/utils/axios_utils';
import flash from './flash';
import BlobForkSuggestion from './blob/blob_fork_suggestion';
import initChangesDropdown from './init_changes_dropdown';
import bp from './breakpoints';
-import {
- parseUrlPathname,
- handleLocationHash,
- isMetaClick,
-} from './lib/utils/common_utils';
+import { parseUrlPathname, handleLocationHash, isMetaClick } from './lib/utils/common_utils';
import { getLocationHash } from './lib/utils/url_utility';
import initDiscussionTab from './image_diff/init_discussion_tab';
import Diff from './diff';
@@ -68,10 +65,10 @@ import Notes from './notes';
let location = window.location;
export default class MergeRequestTabs {
-
constructor({ action, setUrl, stubLocation } = {}) {
const mergeRequestTabs = document.querySelector('.js-tabs-affix');
const navbar = document.querySelector('.navbar-gitlab');
+ const peek = document.getElementById('js-peek');
const paddingTop = 16;
this.diffsLoaded = false;
@@ -85,6 +82,10 @@ export default class MergeRequestTabs {
this.showTab = this.showTab.bind(this);
this.stickyTop = navbar ? navbar.offsetHeight - paddingTop : 0;
+ if (peek) {
+ this.stickyTop += peek.offsetHeight;
+ }
+
if (mergeRequestTabs) {
this.stickyTop += mergeRequestTabs.offsetHeight;
}
@@ -103,8 +104,7 @@ export default class MergeRequestTabs {
.on('shown.bs.tab', '.merge-request-tabs a[data-toggle="tab"]', this.tabShown)
.on('click', '.js-show-tab', this.showTab);
- $('.merge-request-tabs a[data-toggle="tab"]')
- .on('click', this.clickTab);
+ $('.merge-request-tabs a[data-toggle="tab"]').on('click', this.clickTab);
}
// Used in tests
@@ -113,8 +113,7 @@ export default class MergeRequestTabs {
.off('shown.bs.tab', '.merge-request-tabs a[data-toggle="tab"]', this.tabShown)
.off('click', '.js-show-tab', this.showTab);
- $('.merge-request-tabs a[data-toggle="tab"]')
- .off('click', this.clickTab);
+ $('.merge-request-tabs a[data-toggle="tab"]').off('click', this.clickTab);
}
destroyPipelinesView() {
@@ -177,10 +176,7 @@ export default class MergeRequestTabs {
scrollToElement(container) {
if (location.hash) {
- const offset = 0 - (
- $('.navbar-gitlab').outerHeight() +
- $('.js-tabs-affix').outerHeight()
- );
+ const offset = 0 - ($('.navbar-gitlab').outerHeight() + $('.js-tabs-affix').outerHeight());
const $el = $(`${container} ${location.hash}:not(.match)`);
if ($el.length) {
$.scrollTo($el[0], { offset });
@@ -234,9 +230,13 @@ export default class MergeRequestTabs {
// Turbolinks' history.
//
// See https://github.com/rails/turbolinks/issues/363
- window.history.replaceState({
- url: newState,
- }, document.title, newState);
+ window.history.replaceState(
+ {
+ url: newState,
+ },
+ document.title,
+ newState,
+ );
return newState;
}
@@ -252,7 +252,8 @@ export default class MergeRequestTabs {
this.toggleLoading(true);
- axios.get(`${source}.json`)
+ axios
+ .get(`${source}.json`)
.then(({ data }) => {
document.querySelector('div#commits').innerHTML = data.html;
localTimeAgo($('.js-timeago', 'div#commits'));
@@ -297,7 +298,8 @@ export default class MergeRequestTabs {
this.toggleLoading(true);
- axios.get(`${urlPathname}.json${location.search}`)
+ axios
+ .get(`${urlPathname}.json${location.search}`)
.then(({ data }) => {
const $container = $('#diffs');
$container.html(data.html);
@@ -326,8 +328,7 @@ export default class MergeRequestTabs {
cancelButtons: $(el).find('.js-cancel-fork-suggestion-button'),
suggestionSections: $(el).find('.js-file-fork-suggestion-section'),
actionTextPieces: $(el).find('.js-file-fork-suggestion-section-action'),
- })
- .init();
+ }).init();
});
// Scroll any linked note into view
@@ -382,8 +383,7 @@ export default class MergeRequestTabs {
resetViewContainer() {
if (this.fixedLayoutPref !== null) {
- $('.content-wrapper .container-fluid')
- .toggleClass('container-limited', this.fixedLayoutPref);
+ $('.content-wrapper .container-fluid').toggleClass('container-limited', this.fixedLayoutPref);
}
}
@@ -432,12 +432,11 @@ export default class MergeRequestTabs {
const $diffTabs = $('#diff-notes-app');
- $tabs.off('affix.bs.affix affix-top.bs.affix')
+ $tabs
+ .off('affix.bs.affix affix-top.bs.affix')
.affix({
offset: {
- top: () => (
- $diffTabs.offset().top - $tabs.height() - $fixedNav.height()
- ),
+ top: () => $diffTabs.offset().top - $tabs.height() - $fixedNav.height(),
},
})
.on('affix.bs.affix', () => $diffTabs.css({ marginTop: $tabs.height() }))
diff --git a/app/assets/javascripts/milestone.js b/app/assets/javascripts/milestone.js
index b1d74250df..e6e3a66aa2 100644
--- a/app/assets/javascripts/milestone.js
+++ b/app/assets/javascripts/milestone.js
@@ -1,3 +1,4 @@
+import $ from 'jquery';
import axios from './lib/utils/axios_utils';
import flash from './flash';
diff --git a/app/assets/javascripts/milestone_select.js b/app/assets/javascripts/milestone_select.js
index 7fa3e25a0e..c749042a14 100644
--- a/app/assets/javascripts/milestone_select.js
+++ b/app/assets/javascripts/milestone_select.js
@@ -1,6 +1,8 @@
/* eslint-disable func-names, space-before-function-paren, wrap-iife, no-underscore-dangle, prefer-arrow-callback, max-len, one-var, one-var-declaration-per-line, no-unused-vars, object-shorthand, comma-dangle, no-else-return, no-self-compare, consistent-return, no-param-reassign, no-shadow */
/* global Issuable */
/* global ListMilestone */
+
+import $ from 'jquery';
import _ from 'underscore';
import axios from './lib/utils/axios_utils';
import { timeFor } from './lib/utils/datetime_utility';
diff --git a/app/assets/javascripts/mini_pipeline_graph_dropdown.js b/app/assets/javascripts/mini_pipeline_graph_dropdown.js
index c7bccd483a..01399de4c6 100644
--- a/app/assets/javascripts/mini_pipeline_graph_dropdown.js
+++ b/app/assets/javascripts/mini_pipeline_graph_dropdown.js
@@ -1,4 +1,6 @@
/* eslint-disable no-new */
+
+import $ from 'jquery';
import flash from './flash';
import axios from './lib/utils/axios_utils';
diff --git a/app/assets/javascripts/monitoring/components/dashboard.vue b/app/assets/javascripts/monitoring/components/dashboard.vue
index 8ca94ef3e2..f5572be5fb 100644
--- a/app/assets/javascripts/monitoring/components/dashboard.vue
+++ b/app/assets/javascripts/monitoring/components/dashboard.vue
@@ -1,158 +1,155 @@
@@ -188,6 +185,7 @@
:clusters-path="clustersPath"
:empty-getting-started-svg-path="emptyGettingStartedSvgPath"
:empty-loading-svg-path="emptyLoadingSvgPath"
+ :empty-no-data-svg-path="emptyNoDataSvgPath"
:empty-unable-to-connect-svg-path="emptyUnableToConnectSvgPath"
/>
diff --git a/app/assets/javascripts/monitoring/components/empty_state.vue b/app/assets/javascripts/monitoring/components/empty_state.vue
index 9517b8ccb6..c77f451c2d 100644
--- a/app/assets/javascripts/monitoring/components/empty_state.vue
+++ b/app/assets/javascripts/monitoring/components/empty_state.vue
@@ -1,87 +1,90 @@
diff --git a/app/assets/javascripts/monitoring/components/graph.vue b/app/assets/javascripts/monitoring/components/graph.vue
index 9e67a6f214..f93b1da4f5 100644
--- a/app/assets/javascripts/monitoring/components/graph.vue
+++ b/app/assets/javascripts/monitoring/components/graph.vue
@@ -1,235 +1,230 @@
@@ -257,17 +252,13 @@
class="y-axis"
transform="translate(70, 20)"
/>
-
+
diff --git a/app/assets/javascripts/monitoring/components/graph/axis.vue b/app/assets/javascripts/monitoring/components/graph/axis.vue
new file mode 100644
index 0000000000..fc4b3689df
--- /dev/null
+++ b/app/assets/javascripts/monitoring/components/graph/axis.vue
@@ -0,0 +1,142 @@
+
+
+
+
+
+
+
+ {{ yAxisLabelSentenceCase }}
+
+
+
+ {{ timeString }}
+
+
+
diff --git a/app/assets/javascripts/monitoring/components/graph/deployment.vue b/app/assets/javascripts/monitoring/components/graph/deployment.vue
index 98c25307b7..4012191ceb 100644
--- a/app/assets/javascripts/monitoring/components/graph/deployment.vue
+++ b/app/assets/javascripts/monitoring/components/graph/deployment.vue
@@ -1,32 +1,30 @@
diff --git a/app/assets/javascripts/monitoring/components/graph/flag.vue b/app/assets/javascripts/monitoring/components/graph/flag.vue
index 07aa6a3e5d..b8202e2568 100644
--- a/app/assets/javascripts/monitoring/components/graph/flag.vue
+++ b/app/assets/javascripts/monitoring/components/graph/flag.vue
@@ -1,127 +1,116 @@
@@ -168,28 +157,13 @@
-
+
-
-
- |
- {{ seriesMetricLabel(index, series) }} |
+
+ {{ series.track }} {{ seriesMetricLabel(index, series) }} |
{{ seriesMetricValue(series) }}
|
diff --git a/app/assets/javascripts/monitoring/components/graph/legend.vue b/app/assets/javascripts/monitoring/components/graph/legend.vue
index 3149397b61..da9280cf1f 100644
--- a/app/assets/javascripts/monitoring/components/graph/legend.vue
+++ b/app/assets/javascripts/monitoring/components/graph/legend.vue
@@ -1,212 +1,72 @@
-
-
-
-
-
- {{ yAxisLabel }}
-
-
-
- Time
-
-
-
+
+
-
-
+ {{ series.trackName }}
+
+
+
- {{ createSeriesString(index, series) }}
-
-
- {{ legendTitle }} {{ formatMetricUsage(series) }}
-
-
-
-
+ v-if="timeSeries.length > 1">
+
+
+ {{ legendTitle }} series {{ index + 1 }}
+
+ |
+
+
+ {{ legendTitle }}
+
+ |
+
+
+
+
+ |
+
+
+
+
diff --git a/app/assets/javascripts/monitoring/components/graph/path.vue b/app/assets/javascripts/monitoring/components/graph/path.vue
index c9721c4cb0..881560124a 100644
--- a/app/assets/javascripts/monitoring/components/graph/path.vue
+++ b/app/assets/javascripts/monitoring/components/graph/path.vue
@@ -1,36 +1,36 @@
diff --git a/app/assets/javascripts/monitoring/components/graph/track_info.vue b/app/assets/javascripts/monitoring/components/graph/track_info.vue
new file mode 100644
index 0000000000..ec1c2222af
--- /dev/null
+++ b/app/assets/javascripts/monitoring/components/graph/track_info.vue
@@ -0,0 +1,29 @@
+
+
+
+
+ {{ track.metricTag }}
+
+ {{ summaryMetrics }}
+
+
+
diff --git a/app/assets/javascripts/monitoring/components/graph/track_line.vue b/app/assets/javascripts/monitoring/components/graph/track_line.vue
new file mode 100644
index 0000000000..79b322e2e4
--- /dev/null
+++ b/app/assets/javascripts/monitoring/components/graph/track_line.vue
@@ -0,0 +1,36 @@
+
+
+
+
+ |
+
+
diff --git a/app/assets/javascripts/monitoring/components/graph_group.vue b/app/assets/javascripts/monitoring/components/graph_group.vue
index f71cf61455..a6dbe42a8f 100644
--- a/app/assets/javascripts/monitoring/components/graph_group.vue
+++ b/app/assets/javascripts/monitoring/components/graph_group.vue
@@ -1,17 +1,17 @@
diff --git a/app/assets/javascripts/monitoring/stores/monitoring_store.js b/app/assets/javascripts/monitoring/stores/monitoring_store.js
index 854636e9a8..535c415cd6 100644
--- a/app/assets/javascripts/monitoring/stores/monitoring_store.js
+++ b/app/assets/javascripts/monitoring/stores/monitoring_store.js
@@ -1,7 +1,7 @@
import _ from 'underscore';
function sortMetrics(metrics) {
- return _.chain(metrics).sortBy('weight').sortBy('title').value();
+ return _.chain(metrics).sortBy('title').sortBy('weight').value();
}
function normalizeMetrics(metrics) {
diff --git a/app/assets/javascripts/monitoring/utils/multiple_time_series.js b/app/assets/javascripts/monitoring/utils/multiple_time_series.js
index b5b8e3c255..8a93c7e6ba 100644
--- a/app/assets/javascripts/monitoring/utils/multiple_time_series.js
+++ b/app/assets/javascripts/monitoring/utils/multiple_time_series.js
@@ -1,10 +1,21 @@
import _ from 'underscore';
import { scaleLinear, scaleTime } from 'd3-scale';
import { line, area, curveLinear } from 'd3-shape';
-import { extent, max } from 'd3-array';
+import { extent, max, sum } from 'd3-array';
import { timeMinute } from 'd3-time';
+import { capitalizeFirstCharacter } from '~/lib/utils/text_utility';
-const d3 = { scaleLinear, scaleTime, line, area, curveLinear, extent, max, timeMinute };
+const d3 = {
+ scaleLinear,
+ scaleTime,
+ line,
+ area,
+ curveLinear,
+ extent,
+ max,
+ timeMinute,
+ sum,
+};
const defaultColorPalette = {
blue: ['#1f78d1', '#8fbce8'],
@@ -20,6 +31,8 @@ const defaultStyleOrder = ['solid', 'dashed', 'dotted'];
function queryTimeSeries(query, graphWidth, graphHeight, graphHeightOffset, xDom, yDom, lineStyle) {
let usedColors = [];
+ let renderCanary = false;
+ const timeSeriesParsed = [];
function pickColor(name) {
let pick;
@@ -38,16 +51,23 @@ function queryTimeSeries(query, graphWidth, graphHeight, graphHeightOffset, xDom
return defaultColorPalette[pick];
}
- return query.result.map((timeSeries, timeSeriesNumber) => {
+ query.result.forEach((timeSeries, timeSeriesNumber) => {
let metricTag = '';
let lineColor = '';
let areaColor = '';
+ let shouldRenderLegend = true;
+ const timeSeriesValues = timeSeries.values.map(d => d.value);
+ const maximumValue = d3.max(timeSeriesValues);
+ const accum = d3.sum(timeSeriesValues);
+ const trackName = capitalizeFirstCharacter(query.track ? query.track : 'Stable');
- const timeSeriesScaleX = d3.scaleTime()
- .range([0, graphWidth - 70]);
+ if (trackName === 'Canary') {
+ renderCanary = true;
+ }
- const timeSeriesScaleY = d3.scaleLinear()
- .range([graphHeight - graphHeightOffset, 0]);
+ const timeSeriesScaleX = d3.scaleTime().range([0, graphWidth - 70]);
+
+ const timeSeriesScaleY = d3.scaleLinear().range([graphHeight - graphHeightOffset, 0]);
timeSeriesScaleX.domain(xDom);
timeSeriesScaleX.ticks(d3.timeMinute, 60);
@@ -55,13 +75,15 @@ function queryTimeSeries(query, graphWidth, graphHeight, graphHeightOffset, xDom
const defined = d => !isNaN(d.value) && d.value != null;
- const lineFunction = d3.line()
+ const lineFunction = d3
+ .line()
.defined(defined)
.curve(d3.curveLinear) // d3 v4 uses curbe instead of interpolate
.x(d => timeSeriesScaleX(d.time))
.y(d => timeSeriesScaleY(d.value));
- const areaFunction = d3.area()
+ const areaFunction = d3
+ .area()
.defined(defined)
.curve(d3.curveLinear)
.x(d => timeSeriesScaleX(d.time))
@@ -69,38 +91,62 @@ function queryTimeSeries(query, graphWidth, graphHeight, graphHeightOffset, xDom
.y1(d => timeSeriesScaleY(d.value));
const timeSeriesMetricLabel = timeSeries.metric[Object.keys(timeSeries.metric)[0]];
- const seriesCustomizationData = query.series != null &&
- _.findWhere(query.series[0].when, { value: timeSeriesMetricLabel });
+ const seriesCustomizationData =
+ query.series != null && _.findWhere(query.series[0].when, { value: timeSeriesMetricLabel });
if (seriesCustomizationData) {
metricTag = seriesCustomizationData.value || timeSeriesMetricLabel;
[lineColor, areaColor] = pickColor(seriesCustomizationData.color);
+ shouldRenderLegend = false;
} else {
metricTag = timeSeriesMetricLabel || query.label || `series ${timeSeriesNumber + 1}`;
[lineColor, areaColor] = pickColor();
+ if (timeSeriesParsed.length > 1) {
+ shouldRenderLegend = false;
+ }
}
- if (query.track) {
- metricTag += ` - ${query.track}`;
+ if (!shouldRenderLegend) {
+ if (!timeSeriesParsed[0].tracksLegend) {
+ timeSeriesParsed[0].tracksLegend = [];
+ }
+ timeSeriesParsed[0].tracksLegend.push({
+ max: maximumValue,
+ average: accum / timeSeries.values.length,
+ lineStyle,
+ lineColor,
+ metricTag,
+ });
}
- return {
+ timeSeriesParsed.push({
linePath: lineFunction(timeSeries.values),
areaPath: areaFunction(timeSeries.values),
timeSeriesScaleX,
values: timeSeries.values,
+ max: maximumValue,
+ average: accum / timeSeries.values.length,
lineStyle,
lineColor,
areaColor,
metricTag,
- };
+ trackName,
+ shouldRenderLegend,
+ renderCanary,
+ });
});
+
+ return timeSeriesParsed;
}
export default function createTimeSeries(queries, graphWidth, graphHeight, graphHeightOffset) {
- const allValues = queries.reduce((allQueryResults, query) => allQueryResults.concat(
- query.result.reduce((allResults, result) => allResults.concat(result.values), []),
- ), []);
+ const allValues = queries.reduce(
+ (allQueryResults, query) =>
+ allQueryResults.concat(
+ query.result.reduce((allResults, result) => allResults.concat(result.values), []),
+ ),
+ [],
+ );
const xDom = d3.extent(allValues, d => d.time);
const yDom = [0, d3.max(allValues.map(d => d.value))];
diff --git a/app/assets/javascripts/mr_notes/index.js b/app/assets/javascripts/mr_notes/index.js
index 972fdb2b79..e3c5bf06b3 100644
--- a/app/assets/javascripts/mr_notes/index.js
+++ b/app/assets/javascripts/mr_notes/index.js
@@ -4,15 +4,20 @@ import discussionCounter from '../notes/components/discussion_counter.vue';
import store from '../notes/stores';
export default function initMrNotes() {
- new Vue({ // eslint-disable-line
+ // eslint-disable-next-line no-new
+ new Vue({
el: '#js-vue-mr-discussions',
components: {
notesApp,
},
data() {
- const notesDataset = document.getElementById('js-vue-mr-discussions').dataset;
+ const notesDataset = document.getElementById('js-vue-mr-discussions')
+ .dataset;
+ const noteableData = JSON.parse(notesDataset.noteableData);
+ noteableData.noteableType = notesDataset.noteableType;
+
return {
- noteableData: JSON.parse(notesDataset.noteableData),
+ noteableData,
currentUserData: JSON.parse(notesDataset.currentUserData),
notesData: JSON.parse(notesDataset.notesData),
};
@@ -28,7 +33,8 @@ export default function initMrNotes() {
},
});
- new Vue({ // eslint-disable-line
+ // eslint-disable-next-line no-new
+ new Vue({
el: '#js-vue-discussion-counter',
components: {
discussionCounter,
diff --git a/app/assets/javascripts/namespace_select.js b/app/assets/javascripts/namespace_select.js
index aa37732710..c7a8aac79d 100644
--- a/app/assets/javascripts/namespace_select.js
+++ b/app/assets/javascripts/namespace_select.js
@@ -1,4 +1,6 @@
/* eslint-disable func-names, space-before-function-paren, no-var, comma-dangle, object-shorthand, no-else-return, prefer-template, quotes, prefer-arrow-callback, max-len */
+
+import $ from 'jquery';
import Api from './api';
import { mergeUrlParams } from './lib/utils/url_utility';
diff --git a/app/assets/javascripts/network/branch_graph.js b/app/assets/javascripts/network/branch_graph.js
index d3edcb724f..bd007c707f 100644
--- a/app/assets/javascripts/network/branch_graph.js
+++ b/app/assets/javascripts/network/branch_graph.js
@@ -1,5 +1,6 @@
/* eslint-disable func-names, space-before-function-paren, no-var, wrap-iife, quotes, comma-dangle, one-var, one-var-declaration-per-line, no-mixed-operators, no-loop-func, no-floating-decimal, consistent-return, no-unused-vars, prefer-template, prefer-arrow-callback, camelcase, max-len */
+import $ from 'jquery';
import { __ } from '../locale';
import axios from '../lib/utils/axios_utils';
import flash from '../flash';
diff --git a/app/assets/javascripts/new_branch_form.js b/app/assets/javascripts/new_branch_form.js
index 77733b67c4..40c08ee0ac 100644
--- a/app/assets/javascripts/new_branch_form.js
+++ b/app/assets/javascripts/new_branch_form.js
@@ -1,4 +1,6 @@
/* eslint-disable func-names, space-before-function-paren, no-var, one-var, prefer-rest-params, max-len, vars-on-top, wrap-iife, consistent-return, comma-dangle, one-var-declaration-per-line, quotes, no-return-assign, prefer-arrow-callback, prefer-template, no-shadow, no-else-return, max-len, object-shorthand */
+
+import $ from 'jquery';
import RefSelectDropdown from './ref_select_dropdown';
export default class NewBranchForm {
diff --git a/app/assets/javascripts/notes.js b/app/assets/javascripts/notes.js
index 750ed27873..96f2b3eac9 100644
--- a/app/assets/javascripts/notes.js
+++ b/app/assets/javascripts/notes.js
@@ -16,6 +16,9 @@ import Autosize from 'autosize';
import 'vendor/jquery.caret'; // required by jquery.atwho
import 'vendor/jquery.atwho';
import AjaxCache from '~/lib/utils/ajax_cache';
+import Vue from 'vue';
+import syntaxHighlight from '~/syntax_highlight';
+import SkeletonLoadingContainer from '~/vue_shared/components/skeleton_loading_container.vue';
import axios from './lib/utils/axios_utils';
import { getLocationHash } from './lib/utils/url_utility';
import Flash from './flash';
@@ -24,7 +27,13 @@ import GLForm from './gl_form';
import loadAwardsHandler from './awards_handler';
import Autosave from './autosave';
import TaskList from './task_list';
-import { isInViewport, getPagePath, scrollToElement, isMetaKey, hasVueMRDiscussionsCookie } from './lib/utils/common_utils';
+import {
+ isInViewport,
+ getPagePath,
+ scrollToElement,
+ isMetaKey,
+ hasVueMRDiscussionsCookie,
+} from './lib/utils/common_utils';
import imageDiffHelper from './image_diff/helpers/index';
import { localTimeAgo } from './lib/utils/datetime_utility';
@@ -38,9 +47,21 @@ const MAX_VISIBLE_COMMIT_LIST_COUNT = 3;
const REGEX_QUICK_ACTIONS = /^\/\w+.*$/gm;
export default class Notes {
- static initialize(notes_url, note_ids, last_fetched_at, view, enableGFM = true) {
+ static initialize(
+ notes_url,
+ note_ids,
+ last_fetched_at,
+ view,
+ enableGFM = true,
+ ) {
if (!this.instance) {
- this.instance = new Notes(notes_url, note_ids, last_fetched_at, view, enableGFM);
+ this.instance = new Notes(
+ notes_url,
+ note_ids,
+ last_fetched_at,
+ view,
+ enableGFM,
+ );
}
}
@@ -78,7 +99,8 @@ export default class Notes {
this.updatedNotesTrackingMap = {};
this.last_fetched_at = last_fetched_at;
this.noteable_url = document.URL;
- this.notesCountBadge || (this.notesCountBadge = $('.issuable-details').find('.notes-tab .badge'));
+ this.notesCountBadge ||
+ (this.notesCountBadge = $('.issuable-details').find('.notes-tab .badge'));
this.basePollingInterval = 15000;
this.maxPollingSteps = 4;
@@ -92,15 +114,24 @@ export default class Notes {
this.taskList = new TaskList({
dataType: 'note',
fieldName: 'note',
- selector: '.notes'
+ selector: '.notes',
});
this.collapseLongCommitList();
this.setViewType(view);
// We are in the Merge Requests page so we need another edit form for Changes tab
if (getPagePath(1) === 'merge_requests') {
- $('.note-edit-form').clone()
- .addClass('mr-note-edit-form').insertAfter('.note-edit-form');
+ $('.note-edit-form')
+ .clone()
+ .addClass('mr-note-edit-form')
+ .insertAfter('.note-edit-form');
+ }
+
+ const hash = getLocationHash();
+ const $anchor = hash && document.getElementById(hash);
+
+ if ($anchor) {
+ this.loadLazyDiff({ currentTarget: $anchor });
}
}
@@ -115,36 +146,80 @@ export default class Notes {
// Reopen and close actions for Issue/MR combined with note form submit
this.$wrapperEl.on('click', '.js-comment-submit-button', this.postComment);
this.$wrapperEl.on('click', '.js-comment-save-button', this.updateComment);
- this.$wrapperEl.on('keyup input', '.js-note-text', this.updateTargetButtons);
+ this.$wrapperEl.on(
+ 'keyup input',
+ '.js-note-text',
+ this.updateTargetButtons,
+ );
// resolve a discussion
this.$wrapperEl.on('click', '.js-comment-resolve-button', this.postComment);
// remove a note (in general)
this.$wrapperEl.on('click', '.js-note-delete', this.removeNote);
// delete note attachment
- this.$wrapperEl.on('click', '.js-note-attachment-delete', this.removeAttachment);
+ this.$wrapperEl.on(
+ 'click',
+ '.js-note-attachment-delete',
+ this.removeAttachment,
+ );
// reset main target form when clicking discard
this.$wrapperEl.on('click', '.js-note-discard', this.resetMainTargetForm);
// update the file name when an attachment is selected
- this.$wrapperEl.on('change', '.js-note-attachment-input', this.updateFormAttachment);
+ this.$wrapperEl.on(
+ 'change',
+ '.js-note-attachment-input',
+ this.updateFormAttachment,
+ );
// reply to diff/discussion notes
- this.$wrapperEl.on('click', '.js-discussion-reply-button', this.onReplyToDiscussionNote);
+ this.$wrapperEl.on(
+ 'click',
+ '.js-discussion-reply-button',
+ this.onReplyToDiscussionNote,
+ );
// add diff note
this.$wrapperEl.on('click', '.js-add-diff-note-button', this.onAddDiffNote);
// add diff note for images
- this.$wrapperEl.on('click', '.js-add-image-diff-note-button', this.onAddImageDiffNote);
+ this.$wrapperEl.on(
+ 'click',
+ '.js-add-image-diff-note-button',
+ this.onAddImageDiffNote,
+ );
// hide diff note form
- this.$wrapperEl.on('click', '.js-close-discussion-note-form', this.cancelDiscussionForm);
+ this.$wrapperEl.on(
+ 'click',
+ '.js-close-discussion-note-form',
+ this.cancelDiscussionForm,
+ );
// toggle commit list
- this.$wrapperEl.on('click', '.system-note-commit-list-toggler', this.toggleCommitList);
+ this.$wrapperEl.on(
+ 'click',
+ '.system-note-commit-list-toggler',
+ this.toggleCommitList,
+ );
+
+ this.$wrapperEl.on('click', '.js-toggle-lazy-diff', this.loadLazyDiff);
+ this.$wrapperEl.on('click', '.js-toggle-lazy-diff-retry-button', this.onClickRetryLazyLoad.bind(this));
+
// fetch notes when tab becomes visible
this.$wrapperEl.on('visibilitychange', this.visibilityChange);
// when issue status changes, we need to refresh data
this.$wrapperEl.on('issuable:change', this.refresh);
// ajax:events that happen on Form when actions like Reopen, Close are performed on Issues and MRs.
this.$wrapperEl.on('ajax:success', '.js-main-target-form', this.addNote);
- this.$wrapperEl.on('ajax:success', '.js-discussion-note-form', this.addDiscussionNote);
- this.$wrapperEl.on('ajax:success', '.js-main-target-form', this.resetMainTargetForm);
- this.$wrapperEl.on('ajax:complete', '.js-main-target-form', this.reenableTargetFormSubmitButton);
+ this.$wrapperEl.on(
+ 'ajax:success',
+ '.js-discussion-note-form',
+ this.addDiscussionNote,
+ );
+ this.$wrapperEl.on(
+ 'ajax:success',
+ '.js-main-target-form',
+ this.resetMainTargetForm,
+ );
+ this.$wrapperEl.on(
+ 'ajax:complete',
+ '.js-main-target-form',
+ this.reenableTargetFormSubmitButton,
+ );
// when a key is clicked on the notes
this.$wrapperEl.on('keydown', '.js-note-text', this.keydownNoteText);
// When the URL fragment/hash has changed, `#note_xxx`
@@ -169,6 +244,8 @@ export default class Notes {
this.$wrapperEl.off('keydown', '.js-note-text');
this.$wrapperEl.off('click', '.js-comment-resolve-button');
this.$wrapperEl.off('click', '.system-note-commit-list-toggler');
+ this.$wrapperEl.off('click', '.js-toggle-lazy-diff');
+ this.$wrapperEl.off('click', '.js-toggle-lazy-diff-retry-button');
this.$wrapperEl.off('ajax:success', '.js-main-target-form');
this.$wrapperEl.off('ajax:success', '.js-discussion-note-form');
this.$wrapperEl.off('ajax:complete', '.js-main-target-form');
@@ -177,10 +254,16 @@ export default class Notes {
}
static initCommentTypeToggle(form) {
- const dropdownTrigger = form.querySelector('.js-comment-type-dropdown .dropdown-toggle');
- const dropdownList = form.querySelector('.js-comment-type-dropdown .dropdown-menu');
+ const dropdownTrigger = form.querySelector(
+ '.js-comment-type-dropdown .dropdown-toggle',
+ );
+ const dropdownList = form.querySelector(
+ '.js-comment-type-dropdown .dropdown-menu',
+ );
const noteTypeInput = form.querySelector('#note_type');
- const submitButton = form.querySelector('.js-comment-type-dropdown .js-comment-submit-button');
+ const submitButton = form.querySelector(
+ '.js-comment-type-dropdown .js-comment-submit-button',
+ );
const closeButton = form.querySelector('.js-note-target-close');
const reopenButton = form.querySelector('.js-note-target-reopen');
@@ -197,7 +280,13 @@ export default class Notes {
}
keydownNoteText(e) {
- var $textarea, discussionNoteForm, editNote, myLastNote, myLastNoteEditBtn, newText, originalText;
+ var $textarea,
+ discussionNoteForm,
+ editNote,
+ myLastNote,
+ myLastNoteEditBtn,
+ newText,
+ originalText;
if (isMetaKey(e)) {
return;
}
@@ -209,7 +298,12 @@ export default class Notes {
if ($textarea.val() !== '') {
return;
}
- myLastNote = $(`li.note[data-author-id='${gon.current_user_id}'][data-editable]:last`, $textarea.closest('.note, .notes_holder, #notes'));
+ myLastNote = $(
+ `li.note[data-author-id='${
+ gon.current_user_id
+ }'][data-editable]:last`,
+ $textarea.closest('.note, .notes_holder, #notes'),
+ );
if (myLastNote.length) {
myLastNoteEditBtn = myLastNote.find('.js-note-edit');
return myLastNoteEditBtn.trigger('click', [true, myLastNote]);
@@ -220,7 +314,9 @@ export default class Notes {
discussionNoteForm = $textarea.closest('.js-discussion-note-form');
if (discussionNoteForm.length) {
if ($textarea.val() !== '') {
- if (!confirm('Are you sure you want to cancel creating this comment?')) {
+ if (
+ !confirm('Are you sure you want to cancel creating this comment?')
+ ) {
return;
}
}
@@ -232,7 +328,9 @@ export default class Notes {
originalText = $textarea.closest('form').data('originalNote');
newText = $textarea.val();
if (originalText !== newText) {
- if (!confirm('Are you sure you want to cancel editing this comment?')) {
+ if (
+ !confirm('Are you sure you want to cancel editing this comment?')
+ ) {
return;
}
}
@@ -245,11 +343,14 @@ export default class Notes {
if (Notes.interval) {
clearInterval(Notes.interval);
}
- return Notes.interval = setInterval((function(_this) {
- return function() {
- return _this.refresh();
- };
- })(this), this.pollingInterval);
+ return (Notes.interval = setInterval(
+ (function(_this) {
+ return function() {
+ return _this.refresh();
+ };
+ })(this),
+ this.pollingInterval,
+ ));
}
refresh() {
@@ -265,20 +366,23 @@ export default class Notes {
this.refreshing = true;
- axios.get(`${this.notes_url}?html=true`, {
- headers: {
- 'X-Last-Fetched-At': this.last_fetched_at,
- },
- }).then(({ data }) => {
- const notes = data.notes;
- this.last_fetched_at = data.last_fetched_at;
- this.setPollingInterval(data.notes.length);
- $.each(notes, (i, note) => this.renderNote(note));
+ axios
+ .get(`${this.notes_url}?html=true`, {
+ headers: {
+ 'X-Last-Fetched-At': this.last_fetched_at,
+ },
+ })
+ .then(({ data }) => {
+ const notes = data.notes;
+ this.last_fetched_at = data.last_fetched_at;
+ this.setPollingInterval(data.notes.length);
+ $.each(notes, (i, note) => this.renderNote(note));
- this.refreshing = false;
- }).catch(() => {
- this.refreshing = false;
- });
+ this.refreshing = false;
+ })
+ .catch(() => {
+ this.refreshing = false;
+ });
}
/**
@@ -294,7 +398,8 @@ export default class Notes {
if (shouldReset == null) {
shouldReset = true;
}
- nthInterval = this.basePollingInterval * Math.pow(2, this.maxPollingSteps - 1);
+ nthInterval =
+ this.basePollingInterval * Math.pow(2, this.maxPollingSteps - 1);
if (shouldReset) {
this.pollingInterval = this.basePollingInterval;
} else if (this.pollingInterval < nthInterval) {
@@ -313,12 +418,17 @@ export default class Notes {
if ('emoji_award' in noteEntity.commands_changes) {
votesBlock = $('.js-awards-block').eq(0);
- loadAwardsHandler().then((awardsHandler) => {
- awardsHandler.addAwardToEmojiBar(votesBlock, noteEntity.commands_changes.emoji_award);
- awardsHandler.scrollToAwards();
- }).catch(() => {
- // ignore
- });
+ loadAwardsHandler()
+ .then(awardsHandler => {
+ awardsHandler.addAwardToEmojiBar(
+ votesBlock,
+ noteEntity.commands_changes.emoji_award,
+ );
+ awardsHandler.scrollToAwards();
+ })
+ .catch(() => {
+ // ignore
+ });
}
}
}
@@ -363,11 +473,17 @@ export default class Notes {
if (!noteEntity.valid) {
if (noteEntity.errors && noteEntity.errors.commands_only) {
- if (noteEntity.commands_changes &&
- Object.keys(noteEntity.commands_changes).length > 0) {
+ if (
+ noteEntity.commands_changes &&
+ Object.keys(noteEntity.commands_changes).length > 0
+ ) {
$notesList.find('.system-note.being-posted').remove();
}
- this.addFlash(noteEntity.errors.commands_only, 'notice', this.parentTimeline.get(0));
+ this.addFlash(
+ noteEntity.errors.commands_only,
+ 'notice',
+ this.parentTimeline.get(0),
+ );
this.refresh();
}
return;
@@ -389,28 +505,30 @@ export default class Notes {
this.setupNewNote($newNote);
this.refresh();
return this.updateNotesCount(1);
- }
- // The server can send the same update multiple times so we need to make sure to only update once per actual update.
- else if (Notes.isUpdatedNote(noteEntity, $note)) {
+ } else if (Notes.isUpdatedNote(noteEntity, $note)) {
+ // The server can send the same update multiple times so we need to make sure to only update once per actual update.
const isEditing = $note.hasClass('is-editing');
const initialContent = normalizeNewlines(
- $note.find('.original-note-content').text().trim()
+ $note
+ .find('.original-note-content')
+ .text()
+ .trim(),
);
const $textarea = $note.find('.js-note-text');
const currentContent = $textarea.val();
// There can be CRLF vs LF mismatches if we don't sanitize and compare the same way
const sanitizedNoteNote = normalizeNewlines(noteEntity.note);
- const isTextareaUntouched = currentContent === initialContent || currentContent === sanitizedNoteNote;
+ const isTextareaUntouched =
+ currentContent === initialContent ||
+ currentContent === sanitizedNoteNote;
if (isEditing && isTextareaUntouched) {
$textarea.val(noteEntity.note);
this.updatedNotesTrackingMap[noteEntity.id] = noteEntity;
- }
- else if (isEditing && !isTextareaUntouched) {
+ } else if (isEditing && !isTextareaUntouched) {
this.putConflictEditWarningInPlace(noteEntity, $note);
this.updatedNotesTrackingMap[noteEntity.id] = noteEntity;
- }
- else {
+ } else {
const $updatedNote = Notes.animateUpdateNote(noteEntity.html, $note);
this.setupNewNote($updatedNote);
}
@@ -434,17 +552,31 @@ export default class Notes {
}
this.note_ids.push(noteEntity.id);
- form = $form || $(`.js-discussion-note-form[data-discussion-id="${noteEntity.discussion_id}"]`);
- row = (form.length || !noteEntity.discussion_line_code) ? form.closest('tr') : $(`#${noteEntity.discussion_line_code}`);
+ form =
+ $form ||
+ $(
+ `.js-discussion-note-form[data-discussion-id="${
+ noteEntity.discussion_id
+ }"]`,
+ );
+ row =
+ form.length || !noteEntity.discussion_line_code
+ ? form.closest('tr')
+ : $(`#${noteEntity.discussion_line_code}`);
if (noteEntity.on_image) {
row = form;
}
lineType = this.isParallelView() ? form.find('#line_type').val() : 'old';
- diffAvatarContainer = row.prevAll('.line_holder').first().find('.js-avatar-container.' + lineType + '_line');
+ diffAvatarContainer = row
+ .prevAll('.line_holder')
+ .first()
+ .find('.js-avatar-container.' + lineType + '_line');
// is this the first note of discussion?
- discussionContainer = $(`.notes[data-discussion-id="${noteEntity.discussion_id}"]`);
+ discussionContainer = $(
+ `.notes[data-discussion-id="${noteEntity.discussion_id}"]`,
+ );
if (!discussionContainer.length) {
discussionContainer = form.closest('.discussion').find('.notes');
}
@@ -452,25 +584,42 @@ export default class Notes {
if (noteEntity.diff_discussion_html) {
var $discussion = $(noteEntity.diff_discussion_html).renderGFM();
- if (!this.isParallelView() || row.hasClass('js-temp-notes-holder') || noteEntity.on_image) {
+ if (
+ !this.isParallelView() ||
+ row.hasClass('js-temp-notes-holder') ||
+ noteEntity.on_image
+ ) {
// insert the note and the reply button after the temp row
row.after($discussion);
} else {
// Merge new discussion HTML in
- var $notes = $discussion.find(`.notes[data-discussion-id="${noteEntity.discussion_id}"]`);
- var contentContainerClass = '.' + $notes.closest('.notes_content')
- .attr('class')
- .split(' ')
- .join('.');
+ var $notes = $discussion.find(
+ `.notes[data-discussion-id="${noteEntity.discussion_id}"]`,
+ );
+ var contentContainerClass =
+ '.' +
+ $notes
+ .closest('.notes_content')
+ .attr('class')
+ .split(' ')
+ .join('.');
- row.find(contentContainerClass + ' .content').append($notes.closest('.content').children());
+ row
+ .find(contentContainerClass + ' .content')
+ .append($notes.closest('.content').children());
}
}
// Init discussion on 'Discussion' page if it is merge request page
const page = $('body').attr('data-page');
- if ((page && page.indexOf('projects:merge_request') !== -1) || !noteEntity.diff_discussion_html) {
+ if (
+ (page && page.indexOf('projects:merge_request') !== -1) ||
+ !noteEntity.diff_discussion_html
+ ) {
if (!hasVueMRDiscussionsCookie()) {
- Notes.animateAppendNote(noteEntity.discussion_html, $('.main-notes-list'));
+ Notes.animateAppendNote(
+ noteEntity.discussion_html,
+ $('.main-notes-list'),
+ );
}
}
} else {
@@ -478,7 +627,10 @@ export default class Notes {
Notes.animateAppendNote(noteEntity.html, discussionContainer);
}
- if (typeof gl.diffNotesCompileComponents !== 'undefined' && noteEntity.discussion_resolvable) {
+ if (
+ typeof gl.diffNotesCompileComponents !== 'undefined' &&
+ noteEntity.discussion_resolvable
+ ) {
gl.diffNotesCompileComponents();
this.renderDiscussionAvatar(diffAvatarContainer, noteEntity);
@@ -490,7 +642,8 @@ export default class Notes {
}
getLineHolder(changesDiscussionContainer) {
- return $(changesDiscussionContainer).closest('.notes_holder')
+ return $(changesDiscussionContainer)
+ .closest('.notes_holder')
.prevAll('.line_holder')
.first()
.get(0);
@@ -523,8 +676,14 @@ export default class Notes {
form.find('.js-errors').remove();
// reset text and preview
form.find('.js-md-write-button').click();
- form.find('.js-note-text').val('').trigger('input');
- form.find('.js-note-text').data('autosave').reset();
+ form
+ .find('.js-note-text')
+ .val('')
+ .trigger('input');
+ form
+ .find('.js-note-text')
+ .data('autosave')
+ .reset();
var event = document.createEvent('Event');
event.initEvent('autosize:update', true, false);
@@ -560,7 +719,10 @@ export default class Notes {
form.find('#note_type').val('');
form.find('#note_project_id').remove();
form.find('#in_reply_to_discussion_id').remove();
- form.find('.js-comment-resolve-button').closest('comment-and-resolve-btn').remove();
+ form
+ .find('.js-comment-resolve-button')
+ .closest('comment-and-resolve-btn')
+ .remove();
this.parentTimeline = form.parents('.timeline');
if (form.length) {
@@ -614,11 +776,17 @@ export default class Notes {
} else if ($form.hasClass('js-discussion-note-form')) {
formParentTimeline = $form.closest('.discussion-notes').find('.notes');
}
- return this.addFlash('Your comment could not be submitted! Please check your network connection and try again.', 'alert', formParentTimeline.get(0));
+ return this.addFlash(
+ 'Your comment could not be submitted! Please check your network connection and try again.',
+ 'alert',
+ formParentTimeline.get(0),
+ );
}
updateNoteError($parentTimeline) {
- new Flash('Your comment could not be updated! Please check your network connection and try again.');
+ new Flash(
+ 'Your comment could not be updated! Please check your network connection and try again.',
+ );
}
/**
@@ -667,14 +835,16 @@ export default class Notes {
}
checkContentToAllowEditing($el) {
- var initialContent = $el.find('.original-note-content').text().trim();
+ var initialContent = $el
+ .find('.original-note-content')
+ .text()
+ .trim();
var currentContent = $el.find('.js-note-text').val();
var isAllowed = true;
if (currentContent === initialContent) {
this.removeNoteEditForm($el);
- }
- else {
+ } else {
var $buttons = $el.find('.note-form-actions');
var isWidgetVisible = isInViewport($el.get(0));
@@ -736,8 +906,7 @@ export default class Notes {
this.setupNewNote($newNote);
// Now that we have taken care of the update, clear it out
delete this.updatedNotesTrackingMap[noteId];
- }
- else {
+ } else {
$note.find('.js-finish-edit-warning').hide();
this.removeNoteEditForm($note);
}
@@ -770,7 +939,9 @@ export default class Notes {
form.removeClass('current-note-edit-form');
form.find('.js-finish-edit-warning').hide();
// Replace markdown textarea text with original note text.
- return form.find('.js-note-text').val(form.find('form.edit-note').data('originalNote'));
+ return form
+ .find('.js-note-text')
+ .val(form.find('form.edit-note').data('originalNote'));
}
/**
@@ -784,58 +955,67 @@ export default class Notes {
$note = $(e.currentTarget).closest('.note');
noteElId = $note.attr('id');
noteId = $note.attr('data-note-id');
- lineHolder = $(e.currentTarget).closest('.notes[data-discussion-id]')
+ lineHolder = $(e.currentTarget)
+ .closest('.notes[data-discussion-id]')
.closest('.notes_holder')
.prev('.line_holder');
- $(`.note[id="${noteElId}"]`).each((function(_this) {
- // A same note appears in the "Discussion" and in the "Changes" tab, we have
- // to remove all. Using $('.note[id='noteId']') ensure we get all the notes,
- // where $('#noteId') would return only one.
- return function(i, el) {
- var $note, $notes;
- $note = $(el);
- $notes = $note.closest('.discussion-notes');
- const discussionId = $('.notes', $notes).data('discussionId');
+ $(`.note[id="${noteElId}"]`).each(
+ (function(_this) {
+ // A same note appears in the "Discussion" and in the "Changes" tab, we have
+ // to remove all. Using $('.note[id='noteId']') ensure we get all the notes,
+ // where $('#noteId') would return only one.
+ return function(i, el) {
+ var $note, $notes;
+ $note = $(el);
+ $notes = $note.closest('.discussion-notes');
+ const discussionId = $('.notes', $notes).data('discussionId');
- if (typeof gl.diffNotesCompileComponents !== 'undefined') {
- if (gl.diffNoteApps[noteElId]) {
- gl.diffNoteApps[noteElId].$destroy();
- }
- }
-
- $note.remove();
-
- // check if this is the last note for this line
- if ($notes.find('.note').length === 0) {
- var notesTr = $notes.closest('tr');
-
- // "Discussions" tab
- $notes.closest('.timeline-entry').remove();
-
- $(`.js-diff-avatars-${discussionId}`).trigger('remove.vue');
-
- // The notes tr can contain multiple lists of notes, like on the parallel diff
- // notesTr does not exist for image diffs
- if (notesTr.find('.discussion-notes').length > 1 || notesTr.length === 0) {
- const $diffFile = $notes.closest('.diff-file');
- if ($diffFile.length > 0) {
- const removeBadgeEvent = new CustomEvent('removeBadge.imageDiff', {
- detail: {
- // badgeNumber's start with 1 and index starts with 0
- badgeNumber: $notes.index() + 1,
- },
- });
-
- $diffFile[0].dispatchEvent(removeBadgeEvent);
+ if (typeof gl.diffNotesCompileComponents !== 'undefined') {
+ if (gl.diffNoteApps[noteElId]) {
+ gl.diffNoteApps[noteElId].$destroy();
}
-
- $notes.remove();
- } else if (notesTr.length > 0) {
- notesTr.remove();
}
- }
- };
- })(this));
+
+ $note.remove();
+
+ // check if this is the last note for this line
+ if ($notes.find('.note').length === 0) {
+ var notesTr = $notes.closest('tr');
+
+ // "Discussions" tab
+ $notes.closest('.timeline-entry').remove();
+
+ $(`.js-diff-avatars-${discussionId}`).trigger('remove.vue');
+
+ // The notes tr can contain multiple lists of notes, like on the parallel diff
+ // notesTr does not exist for image diffs
+ if (
+ notesTr.find('.discussion-notes').length > 1 ||
+ notesTr.length === 0
+ ) {
+ const $diffFile = $notes.closest('.diff-file');
+ if ($diffFile.length > 0) {
+ const removeBadgeEvent = new CustomEvent(
+ 'removeBadge.imageDiff',
+ {
+ detail: {
+ // badgeNumber's start with 1 and index starts with 0
+ badgeNumber: $notes.index() + 1,
+ },
+ },
+ );
+
+ $diffFile[0].dispatchEvent(removeBadgeEvent);
+ }
+
+ $notes.remove();
+ } else if (notesTr.length > 0) {
+ notesTr.remove();
+ }
+ }
+ };
+ })(this),
+ );
Notes.refreshVueNotes();
Notes.checkMergeRequestStatus();
@@ -917,7 +1097,12 @@ export default class Notes {
// DiffNote
form.find('#note_position').val(dataHolder.attr('data-position'));
- form.find('.js-note-discard').show().removeClass('js-note-discard').addClass('js-close-discussion-note-form').text(form.find('.js-close-discussion-note-form').data('cancelText'));
+ form
+ .find('.js-note-discard')
+ .show()
+ .removeClass('js-note-discard')
+ .addClass('js-close-discussion-note-form')
+ .text(form.find('.js-close-discussion-note-form').data('cancelText'));
form.find('.js-note-target-close').remove();
form.find('.js-note-new-discussion').remove();
this.setupNoteForm(form);
@@ -953,7 +1138,7 @@ export default class Notes {
this.toggleDiffNote({
target: $link,
lineType: link.dataset.lineType,
- showReplyInput
+ showReplyInput,
});
}
@@ -969,7 +1154,9 @@ export default class Notes {
// Setup comment form
let newForm;
- const $noteContainer = $link.closest('.diff-viewer').find('.note-container');
+ const $noteContainer = $link
+ .closest('.diff-viewer')
+ .find('.note-container');
const $form = $noteContainer.find('> .discussion-form');
if ($form.length === 0) {
@@ -982,13 +1169,17 @@ export default class Notes {
this.setupDiscussionNoteForm($link, newForm);
}
- toggleDiffNote({
- target,
- lineType,
- forceShow,
- showReplyInput = false,
- }) {
- var $link, addForm, hasNotes, newForm, noteForm, replyButton, row, rowCssToAdd, targetContent, isDiffCommentAvatar;
+ toggleDiffNote({ target, lineType, forceShow, showReplyInput = false }) {
+ var $link,
+ addForm,
+ hasNotes,
+ newForm,
+ noteForm,
+ replyButton,
+ row,
+ rowCssToAdd,
+ targetContent,
+ isDiffCommentAvatar;
$link = $(target);
row = $link.closest('tr');
const nextRow = row.next();
@@ -1000,11 +1191,13 @@ export default class Notes {
hasNotes = nextRow.is('.notes_holder');
addForm = false;
let lineTypeSelector = '';
- rowCssToAdd = ' | |
';
+ rowCssToAdd =
+ ' | |
';
// In parallel view, look inside the correct left/right pane
if (this.isParallelView()) {
lineTypeSelector = `.${lineType}`;
- rowCssToAdd = ' | | | |
';
+ rowCssToAdd =
+ ' | | | |
';
}
const notesContentSelector = `.notes_content${lineTypeSelector} .content`;
let notesContent = targetRow.find(notesContentSelector);
@@ -1032,7 +1225,9 @@ export default class Notes {
notesContent = targetRow.find(notesContentSelector);
addForm = true;
} else {
- const isCurrentlyShown = targetRow.find('.content:not(:empty)').is(':visible');
+ const isCurrentlyShown = targetRow
+ .find('.content:not(:empty)')
+ .is(':visible');
const isForced = forceShow === true || forceShow === false;
const showNow = forceShow === true || (!isCurrentlyShown && !isForced);
@@ -1059,11 +1254,12 @@ export default class Notes {
row = form.closest('tr');
glForm = form.data('glForm');
glForm.destroy();
- form.find('.js-note-text').data('autosave').reset();
- // show the reply button (will only work for replies)
form
- .prev('.discussion-reply-holder')
- .show();
+ .find('.js-note-text')
+ .data('autosave')
+ .reset();
+ // show the reply button (will only work for replies)
+ form.prev('.discussion-reply-holder').show();
if (row.is('.js-temp-notes-holder')) {
// remove temporary row for diff lines
return row.remove();
@@ -1104,7 +1300,9 @@ export default class Notes {
var filename, form;
form = $(this).closest('form');
// get only the basename
- filename = $(this).val().replace(/^.*[\\\/]/, '');
+ filename = $(this)
+ .val()
+ .replace(/^.*[\\\/]/, '');
return form.find('.js-attachment-filename').text(filename);
}
@@ -1176,12 +1374,16 @@ export default class Notes {
this.glForm = new GLForm($editForm.find('form'), this.enableGFM);
- $editForm.find('form')
+ $editForm
+ .find('form')
.attr('action', `${postUrl}?html=true`)
.attr('data-remote', 'true');
$editForm.find('.js-form-target-id').val(targetId);
$editForm.find('.js-form-target-type').val(targetType);
- $editForm.find('.js-note-text').focus().val(originalContent);
+ $editForm
+ .find('.js-note-text')
+ .focus()
+ .val(originalContent);
$editForm.find('.js-md-write-button').trigger('click');
$editForm.find('.referenced-users').hide();
}
@@ -1190,7 +1392,9 @@ export default class Notes {
if ($note.find('.js-conflict-edit-warning').length === 0) {
const $alert = $(`
This comment has changed since you started editing, please review the
-
+
updated comment
to ensure information is not lost
@@ -1200,14 +1404,93 @@ export default class Notes {
}
updateNotesCount(updateCount) {
- return this.notesCountBadge.text(parseInt(this.notesCountBadge.text(), 10) + updateCount);
+ return this.notesCountBadge.text(
+ parseInt(this.notesCountBadge.text(), 10) + updateCount,
+ );
+ }
+
+ static renderPlaceholderComponent($container) {
+ const el = $container.find('.js-code-placeholder').get(0);
+ new Vue({
+ // eslint-disable-line no-new
+ el,
+ components: {
+ SkeletonLoadingContainer,
+ },
+ render(createElement) {
+ return createElement('skeleton-loading-container');
+ },
+ });
+ }
+
+ static renderDiffContent($container, data) {
+ const { discussion_html } = data;
+ const lines = $(discussion_html).find('.line_holder');
+ lines.addClass('fade-in');
+ $container.find('.diff-content > table > tbody').prepend(lines);
+ const fileHolder = $container.find('.file-holder');
+ $container.find('.line-holder-placeholder').remove();
+ syntaxHighlight(fileHolder);
+ }
+
+ onClickRetryLazyLoad(e) {
+ const $retryButton = $(e.currentTarget);
+
+ $retryButton.prop('disabled', true);
+
+ return this.loadLazyDiff(e)
+ .then(() => {
+ $retryButton.prop('disabled', false);
+ });
+ }
+
+ loadLazyDiff(e) {
+ const $container = $(e.currentTarget).closest('.js-toggle-container');
+ Notes.renderPlaceholderComponent($container);
+
+ $container.find('.js-toggle-lazy-diff').removeClass('js-toggle-lazy-diff');
+
+ const $tableEl = $container.find('tbody');
+ if ($tableEl.length === 0) return;
+
+ const fileHolder = $container.find('.file-holder');
+ const url = fileHolder.data('linesPath');
+
+ const $errorContainer = $container.find('.js-error-lazy-load-diff');
+ const $successContainer = $container.find('.js-success-lazy-load');
+
+ /**
+ * We only fetch resolved discussions.
+ * Unresolved discussions don't have an endpoint being provided.
+ */
+ if (url) {
+ return axios
+ .get(url)
+ .then(({ data }) => {
+ // Reset state in case last request returned error
+ $successContainer.removeClass('hidden');
+ $errorContainer.addClass('hidden');
+
+ Notes.renderDiffContent($container, data);
+ })
+ .catch(() => {
+ $successContainer.addClass('hidden');
+ $errorContainer.removeClass('hidden');
+ });
+ }
+ return Promise.resolve();
}
toggleCommitList(e) {
const $element = $(e.currentTarget);
- const $closestSystemCommitList = $element.siblings('.system-note-commit-list');
+ const $closestSystemCommitList = $element.siblings(
+ '.system-note-commit-list',
+ );
- $element.find('.fa').toggleClass('fa-angle-down').toggleClass('fa-angle-up');
+ $element
+ .find('.fa')
+ .toggleClass('fa-angle-down')
+ .toggleClass('fa-angle-up');
$closestSystemCommitList.toggleClass('hide-shade');
}
@@ -1217,11 +1500,17 @@ export default class Notes {
* intrusive.
*/
collapseLongCommitList() {
- const systemNotes = $('#notes-list').find('li.system-note').has('ul');
+ const systemNotes = $('#notes-list')
+ .find('li.system-note')
+ .has('ul');
$.each(systemNotes, function(index, systemNote) {
const $systemNote = $(systemNote);
- const headerMessage = $systemNote.find('.note-text').find('p:first').text().replace(':', '');
+ const headerMessage = $systemNote
+ .find('.note-text')
+ .find('p:first')
+ .text()
+ .replace(':', '');
$systemNote.find('.note-header .system-note-message').html(headerMessage);
@@ -1229,7 +1518,9 @@ export default class Notes {
$systemNote.find('.note-text').addClass('system-note-commit-list');
$systemNote.find('.system-note-commit-list-toggler').show();
} else {
- $systemNote.find('.note-text').addClass('system-note-commit-list hide-shade');
+ $systemNote
+ .find('.note-text')
+ .addClass('system-note-commit-list hide-shade');
}
});
}
@@ -1247,14 +1538,10 @@ export default class Notes {
cleanForm($form) {
// Remove JS classes that are not needed here
- $form
- .find('.js-comment-type-dropdown')
- .removeClass('btn-group');
+ $form.find('.js-comment-type-dropdown').removeClass('btn-group');
// Remove dropdown
- $form
- .find('.dropdown-menu')
- .remove();
+ $form.find('.dropdown-menu').remove();
return $form;
}
@@ -1273,7 +1560,11 @@ export default class Notes {
// There can be CRLF vs LF mismatches if we don't sanitize and compare the same way
const sanitizedNoteEntityText = normalizeNewlines(noteEntity.note.trim());
const currentNoteText = normalizeNewlines(
- $note.find('.original-note-content').first().text().trim()
+ $note
+ .find('.original-note-content')
+ .first()
+ .text()
+ .trim(),
);
return sanitizedNoteEntityText !== currentNoteText;
}
@@ -1363,7 +1654,14 @@ export default class Notes {
* Once comment is _actually_ posted on server, we will have final element
* in response that we will show in place of this temporary element.
*/
- createPlaceholderNote({ formContent, uniqueId, isDiscussionNote, currentUsername, currentUserFullname, currentUserAvatar }) {
+ createPlaceholderNote({
+ formContent,
+ uniqueId,
+ isDiscussionNote,
+ currentUsername,
+ currentUserFullname,
+ currentUserAvatar,
+ }) {
const discussionClass = isDiscussionNote ? 'discussion' : '';
const $tempNote = $(
`
@@ -1377,8 +1675,12 @@ export default class Notes {
@@ -1389,11 +1691,13 @@ export default class Notes {
- `
+ `,
);
$tempNote.find('.hidden-xs').text(_.escape(currentUserFullname));
- $tempNote.find('.note-headline-light').text(`@${_.escape(currentUsername)}`);
+ $tempNote
+ .find('.note-headline-light')
+ .text(`@${_.escape(currentUsername)}`);
return $tempNote;
}
@@ -1409,7 +1713,7 @@ export default class Notes {
${formContent}
- `
+ `,
);
return $tempNote;
@@ -1439,13 +1743,25 @@ export default class Notes {
// Get Form metadata
const $submitBtn = $(e.target);
+ $submitBtn.prop('disabled', true);
let $form = $submitBtn.parents('form');
const $closeBtn = $form.find('.js-note-target-close');
- const isDiscussionNote = $submitBtn.parent().find('li.droplab-item-selected').attr('id') === 'discussion';
+ const isDiscussionNote =
+ $submitBtn
+ .parent()
+ .find('li.droplab-item-selected')
+ .attr('id') === 'discussion';
const isMainForm = $form.hasClass('js-main-target-form');
const isDiscussionForm = $form.hasClass('js-discussion-note-form');
- const isDiscussionResolve = $submitBtn.hasClass('js-comment-resolve-button');
- const { formData, formContent, formAction, formContentOriginal } = this.getFormData($form);
+ const isDiscussionResolve = $submitBtn.hasClass(
+ 'js-comment-resolve-button',
+ );
+ const {
+ formData,
+ formContent,
+ formAction,
+ formContentOriginal,
+ } = this.getFormData($form);
let noteUniqueId;
let systemNoteUniqueId;
let hasQuickActions = false;
@@ -1462,7 +1778,6 @@ export default class Notes {
// If comment is to resolve discussion, disable submit buttons while
// comment posting is finished.
if (isDiscussionResolve) {
- $submitBtn.disable();
$form.find('.js-comment-submit-button').disable();
}
@@ -1475,23 +1790,30 @@ export default class Notes {
// Show placeholder note
if (tempFormContent) {
noteUniqueId = _.uniqueId('tempNote_');
- $notesContainer.append(this.createPlaceholderNote({
- formContent: tempFormContent,
- uniqueId: noteUniqueId,
- isDiscussionNote,
- currentUsername: gon.current_username,
- currentUserFullname: gon.current_user_fullname,
- currentUserAvatar: gon.current_user_avatar_url,
- }));
+ $notesContainer.append(
+ this.createPlaceholderNote({
+ formContent: tempFormContent,
+ uniqueId: noteUniqueId,
+ isDiscussionNote,
+ currentUsername: gon.current_username,
+ currentUserFullname: gon.current_user_fullname,
+ currentUserAvatar: gon.current_user_avatar_url,
+ }),
+ );
}
// Show placeholder system note
if (hasQuickActions) {
systemNoteUniqueId = _.uniqueId('tempSystemNote_');
- $notesContainer.append(this.createPlaceholderSystemNote({
- formContent: this.getQuickActionDescription(formContent, AjaxCache.get(gl.GfmAutoComplete.dataSources.commands)),
- uniqueId: systemNoteUniqueId,
- }));
+ $notesContainer.append(
+ this.createPlaceholderSystemNote({
+ formContent: this.getQuickActionDescription(
+ formContent,
+ AjaxCache.get(gl.GfmAutoComplete.dataSources.commands),
+ ),
+ uniqueId: systemNoteUniqueId,
+ }),
+ );
}
// Clear the form textarea
@@ -1503,12 +1825,16 @@ export default class Notes {
}
}
+ $closeBtn.text($closeBtn.data('originalText'));
+
/* eslint-disable promise/catch-or-return */
// Make request to submit comment on server
- axios.post(`${formAction}?html=true`, formData)
- .then((res) => {
+ return axios
+ .post(`${formAction}?html=true`, formData)
+ .then(res => {
const note = res.data;
+ $submitBtn.prop('disabled', false);
// Submission successful! remove placeholder
$notesContainer.find(`#${noteUniqueId}`).remove();
@@ -1523,7 +1849,9 @@ export default class Notes {
// Reset cached commands list when command is applied
if (hasQuickActions) {
- $form.find('textarea.js-note-text').trigger('clear-commands-cache.atwho');
+ $form
+ .find('textarea.js-note-text')
+ .trigger('clear-commands-cache.atwho');
}
// Clear previous form errors
@@ -1568,11 +1896,14 @@ export default class Notes {
// append flash-container to the Notes list
if ($notesContainer.length) {
- $notesContainer.append('');
+ $notesContainer.append(
+ '',
+ );
}
Notes.refreshVueNotes();
- } else if (isMainForm) { // Check if this was main thread comment
+ } else if (isMainForm) {
+ // Check if this was main thread comment
// Show final note element on UI and perform form and action buttons cleanup
this.addNote($form, note);
this.reenableTargetFormSubmitButton(e);
@@ -1583,10 +1914,11 @@ export default class Notes {
}
$form.trigger('ajax:success', [note]);
- }).catch(() => {
+ })
+ .catch(() => {
// Submission failed, remove placeholder note and show Flash error message
$notesContainer.find(`#${noteUniqueId}`).remove();
-
+ $submitBtn.prop('disabled', false);
const blurEvent = new CustomEvent('blur.imageDiff', {
detail: e,
});
@@ -1603,7 +1935,9 @@ export default class Notes {
// Show form again on UI on failure
if (isDiscussionForm && $notesContainer.length) {
- const replyButton = $notesContainer.parent().find('.js-discussion-reply-button');
+ const replyButton = $notesContainer
+ .parent()
+ .find('.js-discussion-reply-button');
this.replyToDiscussionNote(replyButton[0]);
$form = $notesContainer.parent().find('form');
}
@@ -1612,8 +1946,6 @@ export default class Notes {
this.reenableTargetFormSubmitButton(e);
this.addNoteError($form);
});
-
- return $closeBtn.text($closeBtn.data('originalText'));
}
/**
@@ -1648,12 +1980,19 @@ export default class Notes {
// Show updated comment content temporarily
$noteBodyText.html(formContent);
- $editingNote.removeClass('is-editing fade-in-full').addClass('being-posted fade-in-half');
- $editingNote.find('.note-headline-meta a').html('');
+ $editingNote
+ .removeClass('is-editing fade-in-full')
+ .addClass('being-posted fade-in-half');
+ $editingNote
+ .find('.note-headline-meta a')
+ .html(
+ '',
+ );
/* eslint-disable promise/catch-or-return */
// Make request to update comment on server
- axios.post(`${formAction}?html=true`, formData)
+ axios
+ .post(`${formAction}?html=true`, formData)
.then(({ data }) => {
// Submission successful! render final note element
this.updateNote(data, $editingNote);
diff --git a/app/assets/javascripts/notes/components/comment_form.vue b/app/assets/javascripts/notes/components/comment_form.vue
index 42bc383f4d..396a675b4a 100644
--- a/app/assets/javascripts/notes/components/comment_form.vue
+++ b/app/assets/javascripts/notes/components/comment_form.vue
@@ -1,305 +1,315 @@
@@ -307,10 +317,10 @@ Please check your network connection and try again.`;