Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2021-06-09 03:10:20 +0300
committerGitLab Bot <gitlab-bot@gitlab.com>2021-06-09 03:10:20 +0300
commitbf5cf27dfbe4e4cfb58d46cea9f14b81f5559fb5 (patch)
tree353aec9f04b3fe50147adff787fbfe77b419d4fd
parent9882aeb510f9e3125a6451eb08681ea9d90dd5e2 (diff)
Add latest changes from gitlab-org/gitlab@master
-rw-r--r--.gitlab/ci/rules.gitlab-ci.yml1
-rw-r--r--app/assets/javascripts/integrations/edit/components/trigger_fields.vue2
-rw-r--r--app/assets/javascripts/main.js2
-rw-r--r--app/assets/javascripts/nav/components/responsive_app.vue30
-rw-r--r--app/assets/javascripts/nav/event_hub.js5
-rw-r--r--app/assets/javascripts/nav/index.js22
-rw-r--r--app/assets/javascripts/nav/mount.js9
-rw-r--r--app/assets/javascripts/profile/gl_crop.js4
-rw-r--r--app/assets/stylesheets/framework/header.scss25
-rw-r--r--app/assets/stylesheets/startup/startup-dark.scss41
-rw-r--r--app/assets/stylesheets/startup/startup-general.scss37
-rw-r--r--app/assets/stylesheets/themes/theme_helper.scss5
-rw-r--r--app/models/integrations/slack.rb2
-rw-r--r--app/views/layouts/_page.html.haml4
-rw-r--r--app/views/layouts/fullscreen.html.haml5
-rw-r--r--app/views/layouts/header/_default.html.haml23
-rw-r--r--app/views/layouts/header/_new_dropdown.html.haml3
-rw-r--r--app/views/layouts/nav/_top_nav_responsive.html.haml7
-rw-r--r--db/post_migrate/20210526222715_backfill_draft_status_on_merge_requests.rb27
-rw-r--r--doc/administration/configure.md16
-rw-r--r--doc/administration/gitaly/index.md99
-rw-r--r--doc/administration/gitaly/praefect.md61
-rw-r--r--doc/user/project/clusters/protect/container_host_security/index.md2
-rw-r--r--doc/user/project/clusters/protect/container_host_security/quick_start_guide.md2
-rw-r--r--doc/user/project/clusters/protect/container_network_security/index.md2
-rw-r--r--doc/user/project/clusters/protect/container_network_security/quick_start_guide.md4
-rw-r--r--doc/user/project/clusters/protect/index.md2
-rw-r--r--doc/user/project/merge_requests/accessibility_testing.md6
-rw-r--r--doc/user/project/merge_requests/test_coverage_visualization.md2
-rw-r--r--doc/user/project/merge_requests/testing_and_reports_in_merge_requests.md2
-rw-r--r--locale/gitlab.pot6
-rw-r--r--package.json2
-rw-r--r--scripts/frontend/startup_css/constants.js2
-rw-r--r--spec/features/admin/admin_mode_spec.rb4
-rw-r--r--spec/features/nav/top_nav_responsive_spec.rb38
-rw-r--r--spec/frontend/integrations/edit/components/trigger_fields_spec.js4
-rw-r--r--spec/frontend/nav/components/responsive_app_spec.js62
-rw-r--r--spec/migrations/backfill_draft_status_on_merge_requests_spec.rb44
-rw-r--r--yarn.lock8
39 files changed, 423 insertions, 199 deletions
diff --git a/.gitlab/ci/rules.gitlab-ci.yml b/.gitlab/ci/rules.gitlab-ci.yml
index 01d3b3260a1..dc1923a22c3 100644
--- a/.gitlab/ci/rules.gitlab-ci.yml
+++ b/.gitlab/ci/rules.gitlab-ci.yml
@@ -1134,6 +1134,7 @@
allow_failure: true
- <<: *if-dot-com-gitlab-org-merge-request
changes: *code-qa-patterns
+ allow_failure: true
.review:rules:review-qa-smoke-report:
rules:
diff --git a/app/assets/javascripts/integrations/edit/components/trigger_fields.vue b/app/assets/javascripts/integrations/edit/components/trigger_fields.vue
index 42bc9e4c8a1..433fe21ad76 100644
--- a/app/assets/javascripts/integrations/edit/components/trigger_fields.vue
+++ b/app/assets/javascripts/integrations/edit/components/trigger_fields.vue
@@ -10,7 +10,7 @@ const typeWithPlaceholder = {
};
const placeholderForType = {
- [typeWithPlaceholder.SLACK]: __('general, development'),
+ [typeWithPlaceholder.SLACK]: __('#general, #development'),
[typeWithPlaceholder.MATTERMOST]: __('my-channel'),
};
diff --git a/app/assets/javascripts/main.js b/app/assets/javascripts/main.js
index 6200ade3595..7b57ad94bb4 100644
--- a/app/assets/javascripts/main.js
+++ b/app/assets/javascripts/main.js
@@ -36,6 +36,7 @@ import GlFieldErrors from './gl_field_errors';
import initUserPopovers from './user_popovers';
import initBroadcastNotifications from './broadcast_notification';
import { initTopNav } from './nav';
+import navEventHub, { EVENT_RESPONSIVE_TOGGLE } from './nav/event_hub';
import 'ee_else_ce/main_ee';
@@ -203,6 +204,7 @@ document.addEventListener('DOMContentLoaded', () => {
$('.navbar-toggler').on('click', () => {
$('.header-content').toggleClass('menu-expanded');
+ navEventHub.$emit(EVENT_RESPONSIVE_TOGGLE);
});
/**
diff --git a/app/assets/javascripts/nav/components/responsive_app.vue b/app/assets/javascripts/nav/components/responsive_app.vue
new file mode 100644
index 00000000000..01b0fa370b5
--- /dev/null
+++ b/app/assets/javascripts/nav/components/responsive_app.vue
@@ -0,0 +1,30 @@
+<script>
+import eventHub, { EVENT_RESPONSIVE_TOGGLE } from '../event_hub';
+
+const TEMPORARY_PLACEHOLDER = 'Placeholder for responsive top nav';
+
+export default {
+ props: {
+ navData: {
+ type: Object,
+ required: true,
+ },
+ },
+ created() {
+ eventHub.$on(EVENT_RESPONSIVE_TOGGLE, this.onToggle);
+ },
+ beforeDestroy() {
+ eventHub.$off(EVENT_RESPONSIVE_TOGGLE, this.onToggle);
+ },
+ methods: {
+ onToggle() {
+ document.body.classList.toggle('top-nav-responsive-open');
+ },
+ },
+ TEMPORARY_PLACEHOLDER,
+};
+</script>
+
+<template>
+ <p>{{ $options.TEMPORARY_PLACEHOLDER }}</p>
+</template>
diff --git a/app/assets/javascripts/nav/event_hub.js b/app/assets/javascripts/nav/event_hub.js
new file mode 100644
index 00000000000..2c8b1371fe3
--- /dev/null
+++ b/app/assets/javascripts/nav/event_hub.js
@@ -0,0 +1,5 @@
+import eventHubFactory from '~/helpers/event_hub_factory';
+
+export const EVENT_RESPONSIVE_TOGGLE = 'top-nav-responsive-toggle';
+
+export default eventHubFactory();
diff --git a/app/assets/javascripts/nav/index.js b/app/assets/javascripts/nav/index.js
index 646ce3f0ecf..86d6b42e4ea 100644
--- a/app/assets/javascripts/nav/index.js
+++ b/app/assets/javascripts/nav/index.js
@@ -1,12 +1,28 @@
-export const initTopNav = async () => {
+// With combined_menu feature flag, there's a benefit to splitting up the import
+const importModule = () => import(/* webpackChunkName: 'top_nav' */ './mount');
+
+const tryMountTopNav = async () => {
const el = document.getElementById('js-top-nav');
if (!el) {
return;
}
- // With combined_menu feature flag, there's a benefit to splitting up the import
- const { mountTopNav } = await import(/* webpackChunkName: 'top_nav' */ './mount');
+ const { mountTopNav } = await importModule();
mountTopNav(el);
};
+
+const tryMountTopNavResponsive = async () => {
+ const el = document.getElementById('js-top-nav-responsive');
+
+ if (!el) {
+ return;
+ }
+
+ const { mountTopNavResponsive } = await importModule();
+
+ mountTopNavResponsive(el);
+};
+
+export const initTopNav = async () => Promise.all([tryMountTopNav(), tryMountTopNavResponsive()]);
diff --git a/app/assets/javascripts/nav/mount.js b/app/assets/javascripts/nav/mount.js
index 0d46ff56249..51b6a31b8cb 100644
--- a/app/assets/javascripts/nav/mount.js
+++ b/app/assets/javascripts/nav/mount.js
@@ -1,11 +1,12 @@
import Vue from 'vue';
import Vuex from 'vuex';
+import ResponsiveApp from './components/responsive_app.vue';
import App from './components/top_nav_app.vue';
import { createStore } from './stores';
Vue.use(Vuex);
-export const mountTopNav = (el) => {
+const mount = (el, Component) => {
const viewModel = JSON.parse(el.dataset.viewModel);
const store = createStore();
@@ -13,7 +14,7 @@ export const mountTopNav = (el) => {
el,
store,
render(h) {
- return h(App, {
+ return h(Component, {
props: {
navData: viewModel,
},
@@ -21,3 +22,7 @@ export const mountTopNav = (el) => {
},
});
};
+
+export const mountTopNav = (el) => mount(el, App);
+
+export const mountTopNavResponsive = (el) => mount(el, ResponsiveApp);
diff --git a/app/assets/javascripts/profile/gl_crop.js b/app/assets/javascripts/profile/gl_crop.js
index afc78cbe78a..722f7d467a2 100644
--- a/app/assets/javascripts/profile/gl_crop.js
+++ b/app/assets/javascripts/profile/gl_crop.js
@@ -114,7 +114,9 @@ import { loadCSSFile } from '../lib/utils/css_utils';
}
onModalHide() {
- return this.modalCropImg.attr('src', '').cropper('destroy');
+ this.modalCropImg.attr('src', '').cropper('destroy');
+ const modalElement = document.querySelector('.modal-profile-crop');
+ if (modalElement) modalElement.remove();
}
onUploadImageBtnClick(e) {
diff --git a/app/assets/stylesheets/framework/header.scss b/app/assets/stylesheets/framework/header.scss
index 7566a533911..8639b9a7f84 100644
--- a/app/assets/stylesheets/framework/header.scss
+++ b/app/assets/stylesheets/framework/header.scss
@@ -106,7 +106,7 @@ $top-nav-hover-bg: var(--indigo-900-alpha-008, $indigo-900-alpha-008) !important
&.menu-expanded {
@include media-breakpoint-down(xs) {
- .title-container {
+ .hide-when-menu-expanded {
display: none;
}
@@ -665,3 +665,26 @@ $top-nav-hover-bg: var(--indigo-900-alpha-008, $indigo-900-alpha-008) !important
color: inherit !important;
}
}
+
+.top-nav-responsive {
+ @include gl-display-none;
+ color: var(--indigo-900, $theme-indigo-900);
+}
+
+.top-nav-responsive-open {
+ .hide-when-top-nav-responsive-open {
+ @include media-breakpoint-down(xs) {
+ display: none !important;
+ }
+ }
+
+ .top-nav-responsive {
+ @include media-breakpoint-down(xs) {
+ @include gl-display-block;
+ }
+ }
+
+ .navbar-gitlab .header-content .title-container {
+ flex: 0;
+ }
+}
diff --git a/app/assets/stylesheets/startup/startup-dark.scss b/app/assets/stylesheets/startup/startup-dark.scss
index dafa89465d1..d5e349ab72c 100644
--- a/app/assets/stylesheets/startup/startup-dark.scss
+++ b/app/assets/stylesheets/startup/startup-dark.scss
@@ -337,9 +337,6 @@ h1 {
.d-none {
display: none !important;
}
-.d-inline-block {
- display: inline-block !important;
-}
.d-block {
display: block !important;
}
@@ -354,9 +351,6 @@ h1 {
}
}
@media (min-width: 992px) {
- .d-lg-none {
- display: none !important;
- }
.d-lg-block {
display: block !important;
}
@@ -1957,9 +1951,7 @@ body.gl-dark .navbar-gitlab .navbar-collapse {
}
body.gl-dark .navbar-gitlab .container-fluid .navbar-toggler {
border-left: 1px solid #b3b3b3;
-}
-body.gl-dark .navbar-gitlab .container-fluid .navbar-toggler svg {
- fill: #fafafa;
+ color: #fafafa;
}
body.gl-dark .navbar-gitlab .navbar-sub-nav > li.active > a,
body.gl-dark .navbar-gitlab .navbar-sub-nav > li.active > button,
@@ -2146,9 +2138,40 @@ body.gl-dark {
white-space: nowrap;
width: 1px;
}
+.gl-border-none\! {
+ border-style: none !important;
+}
+.gl-display-none {
+ display: none;
+}
+@media (min-width: 62rem) {
+ .gl-lg-display-none {
+ display: none;
+ }
+}
+@media (min-width: 36rem) {
+ .gl-sm-display-block {
+ display: block;
+ }
+}
+.gl-display-inline-block {
+ display: inline-block;
+}
+@media (min-width: 36rem) {
+ .gl-sm-display-inline-block {
+ display: inline-block;
+ }
+}
.gl-absolute {
position: absolute;
}
+.gl-px-3 {
+ padding-left: 0.5rem;
+ padding-right: 0.5rem;
+}
+.gl-pr-2 {
+ padding-right: 0.25rem;
+}
.gl-ml-3 {
margin-left: 0.5rem;
}
diff --git a/app/assets/stylesheets/startup/startup-general.scss b/app/assets/stylesheets/startup/startup-general.scss
index c7020e8af55..9f15b107bc7 100644
--- a/app/assets/stylesheets/startup/startup-general.scss
+++ b/app/assets/stylesheets/startup/startup-general.scss
@@ -322,9 +322,6 @@ h1 {
.d-none {
display: none !important;
}
-.d-inline-block {
- display: inline-block !important;
-}
.d-block {
display: block !important;
}
@@ -339,9 +336,6 @@ h1 {
}
}
@media (min-width: 992px) {
- .d-lg-none {
- display: none !important;
- }
.d-lg-block {
display: block !important;
}
@@ -1927,9 +1921,40 @@ body.sidebar-refactoring
white-space: nowrap;
width: 1px;
}
+.gl-border-none\! {
+ border-style: none !important;
+}
+.gl-display-none {
+ display: none;
+}
+@media (min-width: 62rem) {
+ .gl-lg-display-none {
+ display: none;
+ }
+}
+@media (min-width: 36rem) {
+ .gl-sm-display-block {
+ display: block;
+ }
+}
+.gl-display-inline-block {
+ display: inline-block;
+}
+@media (min-width: 36rem) {
+ .gl-sm-display-inline-block {
+ display: inline-block;
+ }
+}
.gl-absolute {
position: absolute;
}
+.gl-px-3 {
+ padding-left: 0.5rem;
+ padding-right: 0.5rem;
+}
+.gl-pr-2 {
+ padding-right: 0.25rem;
+}
.gl-ml-3 {
margin-left: 0.5rem;
}
diff --git a/app/assets/stylesheets/themes/theme_helper.scss b/app/assets/stylesheets/themes/theme_helper.scss
index 5b3e2ab4cd0..6a60978b954 100644
--- a/app/assets/stylesheets/themes/theme_helper.scss
+++ b/app/assets/stylesheets/themes/theme_helper.scss
@@ -22,10 +22,7 @@
.container-fluid {
.navbar-toggler {
border-left: 1px solid lighten($border-and-box-shadow, 10%);
-
- svg {
- fill: $search-and-nav-links;
- }
+ color: $search-and-nav-links;
}
}
diff --git a/app/models/integrations/slack.rb b/app/models/integrations/slack.rb
index a83fd3bcbeb..0381db3a67e 100644
--- a/app/models/integrations/slack.rb
+++ b/app/models/integrations/slack.rb
@@ -25,7 +25,7 @@ module Integrations
end
def default_channel_placeholder
- _('general, development')
+ _('#general, #development')
end
def webhook_placeholder
diff --git a/app/views/layouts/_page.html.haml b/app/views/layouts/_page.html.haml
index 61f03c0540d..2b63e2c647c 100644
--- a/app/views/layouts/_page.html.haml
+++ b/app/views/layouts/_page.html.haml
@@ -1,4 +1,4 @@
-.layout-page{ class: page_with_sidebar_class }
+.layout-page.hide-when-top-nav-responsive-open{ class: page_with_sidebar_class }
- if defined?(nav) && nav
= render "layouts/nav/sidebar/#{nav}"
.content-wrapper.content-wrapper-margin{ class: "#{@content_wrapper_class}" }
@@ -27,3 +27,5 @@
= render "layouts/flash", extra_flash_class: 'limit-container-width'
= yield :before_content
= yield
+
+= render "layouts/nav/top_nav_responsive", class: 'layout-page content-wrapper-margin'
diff --git a/app/views/layouts/fullscreen.html.haml b/app/views/layouts/fullscreen.html.haml
index f46c58f96ee..b2536090520 100644
--- a/app/views/layouts/fullscreen.html.haml
+++ b/app/views/layouts/fullscreen.html.haml
@@ -6,11 +6,12 @@
= header_message
= render partial: "layouts/header/default", locals: { project: @project, group: @group }
.mobile-overlay
- .alert-wrapper
+ .alert-wrapper.hide-when-top-nav-responsive-open
= render 'shared/outdated_browser'
= render "layouts/broadcast"
= yield :flash_message
= render "layouts/flash"
- .content-wrapper{ id: "content-body", class: "d-flex flex-column align-items-stretch" }
+ .content-wrapper.hide-when-top-nav-responsive-open{ id: "content-body", class: "d-flex flex-column align-items-stretch" }
= yield
+ = render "layouts/nav/top_nav_responsive", class: "gl-flex-fill-1 gl-overflow-y-auto"
= footer_message
diff --git a/app/views/layouts/header/_default.html.haml b/app/views/layouts/header/_default.html.haml
index ae333cffb84..a0f6f35a5be 100644
--- a/app/views/layouts/header/_default.html.haml
+++ b/app/views/layouts/header/_default.html.haml
@@ -1,11 +1,12 @@
- has_impersonation_link = header_link?(:admin_impersonation)
- user_status_data = user_status_properties(current_user)
+- use_top_nav_redesign = Feature.enabled?(:combined_menu, current_user, default_enabled: :yaml)
%header.navbar.navbar-gitlab.navbar-expand-sm.js-navbar{ data: { qa_selector: 'navbar' } }
%a.gl-sr-only.gl-accessibility{ href: "#content-body" } Skip to content
.container-fluid
.header-content
- .title-container
+ .title-container{ class: ('hide-when-menu-expanded' if !use_top_nav_redesign) }
%h1.title
%span.gl-sr-only GitLab
= link_to root_path, title: _('Dashboard'), id: 'logo', **tracking_attrs('main_navigation', 'click_gitlab_logo_link', 'navigation') do
@@ -19,8 +20,9 @@
%span.gl-badge.gl-bg-green-500.gl-text-white.gl-rounded-pill.gl-font-weight-bold.gl-py-1
= _('Next')
- - if Feature.enabled?(:combined_menu, current_user, default_enabled: :yaml)
- = render "layouts/nav/top_nav"
+ - if use_top_nav_redesign
+ .gl-display-none.gl-sm-display-block
+ = render "layouts/nav/top_nav"
- else
- if current_user
= render "layouts/nav/dashboard"
@@ -30,11 +32,11 @@
.navbar-collapse.collapse
%ul.nav.navbar-nav
- if current_user
- = render 'layouts/header/new_dropdown'
+ = render 'layouts/header/new_dropdown', class: ('gl-display-none gl-sm-display-block' if use_top_nav_redesign)
- if header_link?(:search)
%li.nav-item.d-none.d-lg-block.m-auto
= render 'layouts/search' unless current_controller?(:search)
- %li.nav-item.d-inline-block.d-lg-none
+ %li.nav-item{ class: use_top_nav_redesign ? "gl-display-none gl-sm-display-inline-block gl-lg-display-none" : "gl-display-inline-block gl-lg-display-none" }
= link_to search_context.search_url, title: _('Search'), aria: { label: _('Search') }, data: {toggle: 'tooltip', placement: 'bottom', container: 'body'} do
= sprite_icon('search')
- if header_link?(:issues)
@@ -115,10 +117,15 @@
- sign_in_text = allow_signup? ? _('Sign in / Register') : _('Sign in')
= link_to sign_in_text, new_session_path(:user, redirect_to_referer: 'yes'), class: 'gl-button btn btn-default btn-sign-in'
- %button.navbar-toggler.d-block.d-sm-none{ type: 'button' }
+ %button.navbar-toggler.d-block.d-sm-none{ type: 'button', class: ('gl-border-none!' if use_top_nav_redesign) }
%span.sr-only= _('Toggle navigation')
- = sprite_icon('ellipsis_h', size: 12, css_class: 'more-icon js-navbar-toggle-right')
- = sprite_icon('close', size: 12, css_class: 'close-icon js-navbar-toggle-left')
+ - if use_top_nav_redesign
+ %span.more-icon.gl-px-3
+ %span.gl-pr-2= _('Menu')
+ = sprite_icon('dot-grid', size: 16)
+ - else
+ = sprite_icon('ellipsis_h', size: 12, css_class: 'more-icon')
+ = sprite_icon('close', size: 12, css_class: 'close-icon')
- if display_whats_new?
#whats-new-app{ data: { version_digest: whats_new_version_digest } }
diff --git a/app/views/layouts/header/_new_dropdown.html.haml b/app/views/layouts/header/_new_dropdown.html.haml
index 47846207978..c5f43fb2c16 100644
--- a/app/views/layouts/header/_new_dropdown.html.haml
+++ b/app/views/layouts/header/_new_dropdown.html.haml
@@ -2,10 +2,11 @@
- menu_sections = view_model.fetch(:menu_sections)
- title = view_model.fetch(:title)
- show_headers = menu_sections.length > 1
+- top_class = local_assigns.fetch(:class, nil)
- return if menu_sections.empty?
-%li.header-new.dropdown{ data: { track_label: "new_dropdown", track_event: "click_dropdown", track_experiment: "new_repo" } }
+%li.header-new.dropdown{ class: top_class, data: { track_label: "new_dropdown", track_event: "click_dropdown", track_experiment: "new_repo" } }
= link_to new_project_path, class: "header-new-dropdown-toggle has-tooltip", id: "js-onboarding-new-project-link", title: title, ref: 'tooltip', aria: { label: title }, data: { toggle: 'dropdown', placement: 'bottom', container: 'body', display: 'static', qa_selector: 'new_menu_toggle' } do
= sprite_icon('plus-square')
= sprite_icon('chevron-down', css_class: 'caret-down')
diff --git a/app/views/layouts/nav/_top_nav_responsive.html.haml b/app/views/layouts/nav/_top_nav_responsive.html.haml
new file mode 100644
index 00000000000..701bc603391
--- /dev/null
+++ b/app/views/layouts/nav/_top_nav_responsive.html.haml
@@ -0,0 +1,7 @@
+- return unless Feature.enabled?(:combined_menu, current_user, default_enabled: :yaml)
+
+- top_class = local_assigns.fetch(:class, nil)
+- view_model = top_nav_view_model(project: @project, group: @group)
+
+.top-nav-responsive{ class: top_class }
+ #js-top-nav-responsive{ data: { view_model: view_model.to_json } }
diff --git a/db/post_migrate/20210526222715_backfill_draft_status_on_merge_requests.rb b/db/post_migrate/20210526222715_backfill_draft_status_on_merge_requests.rb
index 300c180acc3..8ff0e306ad5 100644
--- a/db/post_migrate/20210526222715_backfill_draft_status_on_merge_requests.rb
+++ b/db/post_migrate/20210526222715_backfill_draft_status_on_merge_requests.rb
@@ -1,30 +1,17 @@
# frozen_string_literal: true
class BackfillDraftStatusOnMergeRequests < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- INDEX_NAME = "tmp_index_merge_requests_draft_and_status"
-
- disable_ddl_transaction!
+ # include Gitlab::Database::MigrationHelpers
+ # Marking these as no-op as the original contents caused timeouts on
+ # staging. Removing the code here per
+ # #https://docs.gitlab.com/ee/development/deleting_migrations.html#how-to-disable-a-data-migration
+ # =>
def up
- add_concurrent_index :merge_requests, :id,
- where: "draft = false AND state_id = 1 AND ((title)::text ~* '^\\[draft\\]|\\(draft\\)|draft:|draft|\\[WIP\\]|WIP:|WIP'::text)",
- name: INDEX_NAME
-
- update_column_in_batches(:merge_requests, :draft, true, batch_size: 100) do |table, query|
- query
- .where(table[:state_id].eq(1))
- .where(table[:draft].eq(false))
- .where(table[:title].matches_regexp('^\\[draft\\]|\\(draft\\)|draft:|draft|\\[WIP\\]|WIP:|WIP', false))
- end
-
- remove_concurrent_index_by_name :merge_requests, INDEX_NAME
+ # no-op
end
def down
- remove_concurrent_index_by_name :merge_requests, INDEX_NAME
+ # no-op
end
end
diff --git a/doc/administration/configure.md b/doc/administration/configure.md
new file mode 100644
index 00000000000..12a8f721ccf
--- /dev/null
+++ b/doc/administration/configure.md
@@ -0,0 +1,16 @@
+---
+stage: Enablement
+group: Distribution
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+type: reference
+---
+
+# Configure your GitLab installation
+
+Customize and configure your self-managed GitLab installation.
+
+- [Authentication](auth/README.md)
+- [Configuration](../user/admin_area/index.md)
+- [Repository storage](repository_storage_paths.md)
+- [Geo](geo/index.md)
+- [Packages](packages/index.md)
diff --git a/doc/administration/gitaly/index.md b/doc/administration/gitaly/index.md
index 8e8df73e581..6177932937c 100644
--- a/doc/administration/gitaly/index.md
+++ b/doc/administration/gitaly/index.md
@@ -403,18 +403,27 @@ GitLab recommends:
We welcome your feedback on this process: raise a support ticket, or [comment on the epic](https://gitlab.com/groups/gitlab-org/-/epics/4916).
-## Troubleshooting Gitaly
+## Troubleshooting
-Check [Gitaly timeouts](../../user/admin_area/settings/gitaly_timeouts.md) when troubleshooting
-Gitaly.
+Refer to the information below when troubleshooting Gitaly and Gitaly Cluster.
-### Check versions when using standalone Gitaly servers
+### Troubleshoot Gitaly
+
+The following sections provide possible solutions to Gitaly errors.
+
+See also:
+
+- [Gitaly timeout](../../user/admin_area/settings/gitaly_timeouts.md) settings.
+- [Gitaly troubleshooting information](../reference_architectures/troubleshooting.md#troubleshooting-gitaly)
+ in reference architecture documentation.
+
+#### Check versions when using standalone Gitaly servers
When using standalone Gitaly servers, you must make sure they are the same version
as GitLab to ensure full compatibility. Check **Admin Area > Overview > Gitaly Servers** on
your GitLab instance and confirm all Gitaly servers indicate that they are up to date.
-### `gitaly-debug`
+#### `gitaly-debug`
The `gitaly-debug` command provides "production debugging" tools for Gitaly and Git
performance. It is intended to help production engineers and support
@@ -437,7 +446,7 @@ To see the help page of `gitaly-debug` for a list of supported sub-commands, run
gitaly-debug -h
```
-### Commits, pushes, and clones return a 401
+#### Commits, pushes, and clones return a 401
```plaintext
remote: GitLab: 401 Unauthorized
@@ -446,7 +455,7 @@ remote: GitLab: 401 Unauthorized
You need to sync your `gitlab-secrets.json` file with your Gitaly clients (GitLab
app nodes).
-### Client side gRPC logs
+#### Client side gRPC logs
Gitaly uses the [gRPC](https://grpc.io/) RPC framework. The Ruby gRPC
client has its own log file which may contain debugging information when
@@ -460,7 +469,7 @@ You can run a gRPC trace with:
sudo GRPC_TRACE=all GRPC_VERBOSITY=DEBUG gitlab-rake gitlab:gitaly:check
```
-### Server side gRPC logs
+#### Server side gRPC logs
gRPC tracing can also be enabled in Gitaly itself with the `GODEBUG=http2debug`
environment variable. To set this in an Omnibus GitLab install:
@@ -475,7 +484,7 @@ environment variable. To set this in an Omnibus GitLab install:
1. [Reconfigure](../restart_gitlab.md#omnibus-gitlab-reconfigure) GitLab.
-### Correlating Git processes with RPCs
+#### Correlating Git processes with RPCs
Sometimes you need to find out which Gitaly RPC created a particular Git process.
@@ -493,7 +502,7 @@ sudo cat /proc/$PID/environ | tr '\0' '\n' | grep ^CORRELATION_ID=
This method isn't reliable for `git cat-file` processes, because Gitaly
internally pools and re-uses those across RPCs.
-### Observing `gitaly-ruby` traffic
+#### Observing `gitaly-ruby` traffic
[`gitaly-ruby`](configure_gitaly.md#gitaly-ruby) is an internal implementation detail of Gitaly,
so, there's not that much visibility into what goes on inside
@@ -514,7 +523,7 @@ implemented as calls to `gitaly-ruby`:
sum(rate(grpc_client_handled_total[5m])) by (grpc_method) > 0
```
-### Repository changes fail with a `401 Unauthorized` error
+#### Repository changes fail with a `401 Unauthorized` error
If you run Gitaly on its own server and notice these conditions:
@@ -609,7 +618,7 @@ on the Gitaly server matches the one on Gitaly client. If it doesn't match,
update the secrets file on the Gitaly server to match the Gitaly client, then
[reconfigure](../restart_gitlab.md#omnibus-gitlab-reconfigure).
-### Command line tools cannot connect to Gitaly
+#### Command line tools cannot connect to Gitaly
gRPC cannot reach your Gitaly server if:
@@ -646,7 +655,7 @@ unset http_proxy
unset https_proxy
```
-### Permission denied errors appearing in Gitaly or Praefect logs when accessing repositories
+#### Permission denied errors appearing in Gitaly or Praefect logs when accessing repositories
You might see the following in Gitaly and Praefect logs:
@@ -667,9 +676,71 @@ This is a GRPC call
[error response code](https://grpc.github.io/grpc/core/md_doc_statuscodes.html).
If this error occurs, even though
-[the Gitaly auth tokens are correctly setup](../gitaly/praefect.md#debugging-praefect),
+[the Gitaly auth tokens are set up correctly](#praefect-errors-in-logs),
it's likely that the Gitaly servers are experiencing
[clock drift](https://en.wikipedia.org/wiki/Clock_drift).
Ensure the Gitaly clients and servers are synchronized, and use an NTP time
server to keep them synchronized.
+
+### Troubleshoot Praefect (Gitaly Cluster)
+
+The following sections provide possible solutions to Gitaly Cluster errors.
+
+#### Praefect errors in logs
+
+If you receive an error, check `/var/log/gitlab/gitlab-rails/production.log`.
+
+Here are common errors and potential causes:
+
+- 500 response code
+ - **ActionView::Template::Error (7:permission denied)**
+ - `praefect['auth_token']` and `gitlab_rails['gitaly_token']` do not match on the GitLab server.
+ - **Unable to save project. Error: 7:permission denied**
+ - Secret token in `praefect['storage_nodes']` on GitLab server does not match the
+ value in `gitaly['auth_token']` on one or more Gitaly servers.
+- 503 response code
+ - **GRPC::Unavailable (14:failed to connect to all addresses)**
+ - GitLab was unable to reach Praefect.
+ - **GRPC::Unavailable (14:all SubCons are in TransientFailure...)**
+ - Praefect cannot reach one or more of its child Gitaly nodes. Try running
+ the Praefect connection checker to diagnose.
+
+#### Determine primary Gitaly node
+
+To determine the current primary Gitaly node for a specific Praefect node:
+
+- Use the `Shard Primary Election` [Grafana chart](praefect.md#grafana) on the
+ [`Gitlab Omnibus - Praefect` dashboard](https://gitlab.com/gitlab-org/grafana-dashboards/-/blob/master/omnibus/praefect.json).
+ This is recommended.
+- If you do not have Grafana set up, use the following command on each host of each
+ Praefect node:
+
+ ```shell
+ curl localhost:9652/metrics | grep gitaly_praefect_primaries`
+ ```
+
+#### Relation does not exist errors
+
+By default Praefect database tables are created automatically by `gitlab-ctl reconfigure` task.
+However, if the `gitlab-ctl reconfigure` command isn't executed or there are errors during the
+execution, the Praefect database tables are not created on initial reconfigure and can throw
+errors that relations do not exist.
+
+For example:
+
+- `ERROR: relation "node_status" does not exist at character 13`
+- `ERROR: relation "replication_queue_lock" does not exist at character 40`
+- This error:
+
+ ```json
+ {"level":"error","msg":"Error updating node: pq: relation \"node_status\" does not exist","pid":210882,"praefectName":"gitlab1x4m:0.0.0.0:2305","time":"2021-04-01T19:26:19.473Z","virtual_storage":"praefect-cluster-1"}
+ ```
+
+To solve this, the database schema migration can be done using `sql-migrate` subcommand of
+the `praefect` command:
+
+```shell
+$ sudo /opt/gitlab/embedded/bin/praefect -config /var/opt/gitlab/praefect/config.toml sql-migrate
+praefect sql-migrate: OK (applied 21 migrations)
+```
diff --git a/doc/administration/gitaly/praefect.md b/doc/administration/gitaly/praefect.md
index 613899df5cb..def2ca0d6ef 100644
--- a/doc/administration/gitaly/praefect.md
+++ b/doc/administration/gitaly/praefect.md
@@ -162,32 +162,7 @@ node, using `psql` which is installed by Omnibus GitLab.
The database used by Praefect is now configured.
If you see Praefect database errors after configuring PostgreSQL, see
-[troubleshooting steps below](#relation-does-not-exist-errors).
-
-#### Relation does not exist errors
-
-By default Praefect database tables are created automatically by `gitlab-ctl reconfigure` task.
-However, if the `gitlab-ctl reconfigure` command isn't executed or there are errors during the
-execution, the Praefect database tables are not created on initial reconfigure and can throw
-errors that relations do not exist.
-
-For example:
-
-- `ERROR: relation "node_status" does not exist at character 13`
-- `ERROR: relation "replication_queue_lock" does not exist at character 40`
-- This error:
-
- ```json
- {"level":"error","msg":"Error updating node: pq: relation \"node_status\" does not exist","pid":210882,"praefectName":"gitlab1x4m:0.0.0.0:2305","time":"2021-04-01T19:26:19.473Z","virtual_storage":"praefect-cluster-1"}
- ```
-
-To solve this, the database schema migration can be done using `sql-migrate` subcommand of
-the `praefect` command:
-
-```shell
-$ sudo /opt/gitlab/embedded/bin/praefect -config /var/opt/gitlab/praefect/config.toml sql-migrate
-praefect sql-migrate: OK (applied 21 migrations)
-```
+[troubleshooting steps](index.md#relation-does-not-exist-errors).
#### PgBouncer
@@ -906,7 +881,7 @@ Particular attention should be shown to:
When adding Gitaly Cluster to an existing Gitaly instance, the existing Gitaly storage
must use a TCP address. If `gitaly_address` is not specified, then a Unix socket is used,
-which will prevent the communication with the cluster.
+which prevents the communication with the cluster.
For example:
@@ -1578,35 +1553,3 @@ After creating and configuring Gitaly Cluster:
```
1. Repeat for each storage as required.
-
-## Debugging Praefect
-
-If you receive an error, check `/var/log/gitlab/gitlab-rails/production.log`.
-
-Here are common errors and potential causes:
-
-- 500 response code
- - **ActionView::Template::Error (7:permission denied)**
- - `praefect['auth_token']` and `gitlab_rails['gitaly_token']` do not match on the GitLab server.
- - **Unable to save project. Error: 7:permission denied**
- - Secret token in `praefect['storage_nodes']` on GitLab server does not match the
- value in `gitaly['auth_token']` on one or more Gitaly servers.
-- 503 response code
- - **GRPC::Unavailable (14:failed to connect to all addresses)**
- - GitLab was unable to reach Praefect.
- - **GRPC::Unavailable (14:all SubCons are in TransientFailure...)**
- - Praefect cannot reach one or more of its child Gitaly nodes. Try running
- the Praefect connection checker to diagnose.
-
-### Determine primary Gitaly node
-
-To determine the current primary Gitaly node for a specific Praefect node:
-
-- Use the `Shard Primary Election` [Grafana chart](#grafana) on the [`Gitlab Omnibus - Praefect` dashboard](https://gitlab.com/gitlab-org/grafana-dashboards/-/blob/master/omnibus/praefect.json).
- This is recommended.
-- If you do not have Grafana set up, use the following command on each host of each
- Praefect node:
-
- ```shell
- curl localhost:9652/metrics | grep gitaly_praefect_primaries`
- ```
diff --git a/doc/user/project/clusters/protect/container_host_security/index.md b/doc/user/project/clusters/protect/container_host_security/index.md
index 33121c0dd52..5e4df6009f0 100644
--- a/doc/user/project/clusters/protect/container_host_security/index.md
+++ b/doc/user/project/clusters/protect/container_host_security/index.md
@@ -4,7 +4,7 @@ group: Container Security
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
---
-# Container Host Security
+# Container Host Security **(FREE)**
Container Host Security in GitLab provides Intrusion Detection and Prevention capabilities that can
monitor and (optionally) block activity inside the containers themselves. This is done by leveraging
diff --git a/doc/user/project/clusters/protect/container_host_security/quick_start_guide.md b/doc/user/project/clusters/protect/container_host_security/quick_start_guide.md
index 456036fc926..b999ae5b933 100644
--- a/doc/user/project/clusters/protect/container_host_security/quick_start_guide.md
+++ b/doc/user/project/clusters/protect/container_host_security/quick_start_guide.md
@@ -4,7 +4,7 @@ group: Container Security
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
---
-# Getting started with Container Host Security
+# Getting started with Container Host Security **(FREE)**
The following steps are recommended for installing Container Host Security.
diff --git a/doc/user/project/clusters/protect/container_network_security/index.md b/doc/user/project/clusters/protect/container_network_security/index.md
index 461b44a77ef..3daa48e1811 100644
--- a/doc/user/project/clusters/protect/container_network_security/index.md
+++ b/doc/user/project/clusters/protect/container_network_security/index.md
@@ -4,7 +4,7 @@ group: Container Security
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
---
-# Container Network Security
+# Container Network Security **(FREE)**
Container Network Security in GitLab provides basic firewall functionality by leveraging Cilium
NetworkPolicies to filter traffic going in and out of the cluster as well as traffic between pods
diff --git a/doc/user/project/clusters/protect/container_network_security/quick_start_guide.md b/doc/user/project/clusters/protect/container_network_security/quick_start_guide.md
index 16eb86d74e2..3acb44c61ac 100644
--- a/doc/user/project/clusters/protect/container_network_security/quick_start_guide.md
+++ b/doc/user/project/clusters/protect/container_network_security/quick_start_guide.md
@@ -4,7 +4,7 @@ group: Container Security
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
---
-# Getting started with Container Network Security
+# Getting started with Container Network Security **(FREE)**
The following steps are recommended for installing Container Network Security.
@@ -58,7 +58,7 @@ use both methods simultaneously, when the application project pipeline runs the
NetworkPolicy in the `auto-deploy-values.yaml` file may override policies configured in the UI
editor.
-## Monitoring throughput `**(ULTIMATE)**`
+## Monitoring throughput **(ULTIMATE)**
To view statistics for Container Network Security, you must follow the installation steps above and
configure GitLab integration with Prometheus. Also, if you use custom Helm values for Cilium, you
diff --git a/doc/user/project/clusters/protect/index.md b/doc/user/project/clusters/protect/index.md
index 7b43ff316a4..1314a1948d5 100644
--- a/doc/user/project/clusters/protect/index.md
+++ b/doc/user/project/clusters/protect/index.md
@@ -4,7 +4,7 @@ group: Container Security
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
---
-# Protecting your deployed applications
+# Protecting your deployed applications **(FREE)**
GitLab makes it straightforward to protect applications deployed in [connected Kubernetes clusters](index.md).
These protections are available in the Kubernetes network layer and in the container itself. At
diff --git a/doc/user/project/merge_requests/accessibility_testing.md b/doc/user/project/merge_requests/accessibility_testing.md
index 061ba1ddbf3..76aff18b00d 100644
--- a/doc/user/project/merge_requests/accessibility_testing.md
+++ b/doc/user/project/merge_requests/accessibility_testing.md
@@ -5,7 +5,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
type: reference, howto
---
-# Accessibility Testing
+# Accessibility testing **(FREE)**
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/25144) in GitLab 12.8.
@@ -21,7 +21,7 @@ measuring the accessibility of web sites, and has built a simple
This job outputs accessibility violations, warnings, and notices for each page
analyzed to a file called `accessibility`.
-## Accessibility Merge Request widget
+## Accessibility merge request widget
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/39425) in GitLab 13.0 behind the disabled [feature flag](../../../administration/feature_flags.md) `:accessibility_report_view`.
> - [Feature Flag removed](https://gitlab.com/gitlab-org/gitlab/-/issues/217372) in GitLab 13.1.
@@ -29,7 +29,7 @@ analyzed to a file called `accessibility`.
In addition to the report artifact that is created, GitLab will also show the
Accessibility Report in the merge request widget area:
-![Accessibility Merge Request Widget](img/accessibility_mr_widget_v13_0.png)
+![Accessibility merge request widget](img/accessibility_mr_widget_v13_0.png)
## Configure Accessibility Testing
diff --git a/doc/user/project/merge_requests/test_coverage_visualization.md b/doc/user/project/merge_requests/test_coverage_visualization.md
index c240aff1857..e044d50d246 100644
--- a/doc/user/project/merge_requests/test_coverage_visualization.md
+++ b/doc/user/project/merge_requests/test_coverage_visualization.md
@@ -5,7 +5,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
type: reference, howto
---
-# Test Coverage Visualization
+# Test coverage visualization **(FREE)**
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/3708) in GitLab 12.9.
> - [Feature flag removed](https://gitlab.com/gitlab-org/gitlab/-/issues/249811) in GitLab 13.5.
diff --git a/doc/user/project/merge_requests/testing_and_reports_in_merge_requests.md b/doc/user/project/merge_requests/testing_and_reports_in_merge_requests.md
index cc0be389891..55e122dec76 100644
--- a/doc/user/project/merge_requests/testing_and_reports_in_merge_requests.md
+++ b/doc/user/project/merge_requests/testing_and_reports_in_merge_requests.md
@@ -6,7 +6,7 @@ type: index
description: "Test your code and display reports in merge requests"
---
-# Tests and reports in merge requests
+# Tests and reports in merge requests **(FREE)**
GitLab has the ability to test the changes included in a feature branch and display reports
or link to useful information directly from merge requests:
diff --git a/locale/gitlab.pot b/locale/gitlab.pot
index 6a8d42a5090..5daeb97fa0f 100644
--- a/locale/gitlab.pot
+++ b/locale/gitlab.pot
@@ -89,6 +89,9 @@ msgstr ""
msgid "\"el\" parameter is required for createInstance()"
msgstr ""
+msgid "#general, #development"
+msgstr ""
+
msgid "%d Approval"
msgid_plural "%d Approvals"
msgstr[0] ""
@@ -38678,9 +38681,6 @@ msgid_plural "from %d jobs"
msgstr[0] ""
msgstr[1] ""
-msgid "general, development"
-msgstr ""
-
msgid "group"
msgstr ""
diff --git a/package.json b/package.json
index f5e8e4d8431..50fdeb60019 100644
--- a/package.json
+++ b/package.json
@@ -129,7 +129,7 @@
"immer": "^7.0.7",
"ipaddr.js": "^1.9.1",
"jed": "^1.1.1",
- "jquery": "^3.5.0",
+ "jquery": "^3.6.0",
"jquery.caret": "^0.3.1",
"jquery.waitforimages": "^2.2.0",
"js-cookie": "^2.2.1",
diff --git a/scripts/frontend/startup_css/constants.js b/scripts/frontend/startup_css/constants.js
index a76092f8b45..5f6189d9e59 100644
--- a/scripts/frontend/startup_css/constants.js
+++ b/scripts/frontend/startup_css/constants.js
@@ -10,6 +10,8 @@ const HTML_TO_REMOVE = [
'#js-peek',
'.modal',
'.feature-highlight',
+ // The user has to open up the responsive nav, so we don't need it on load
+ '.top-nav-responsive',
// We don't want to capture all the children of a dropdown-menu
'.dropdown-menu',
];
diff --git a/spec/features/admin/admin_mode_spec.rb b/spec/features/admin/admin_mode_spec.rb
index dfb6ebc0211..37d77beb2bb 100644
--- a/spec/features/admin/admin_mode_spec.rb
+++ b/spec/features/admin/admin_mode_spec.rb
@@ -97,6 +97,8 @@ RSpec.describe 'Admin mode' do
end
it 'can leave admin mode using dropdown menu on smaller screens', :js do
+ skip('pending responsive development under :combined_menu feature flag') if Feature.enabled?(:combined_menu)
+
resize_screen_xs
visit root_dashboard_path
@@ -131,7 +133,7 @@ RSpec.describe 'Admin mode' do
end
it 'relocates admin dashboard links to dropdown list on smaller screen', :js do
- skip('not applicable with :combined_menu feature flag enabled') if Feature.enabled?(:combined_menu)
+ skip('pending responsive development under :combined_menu feature flag') if Feature.enabled?(:combined_menu)
resize_screen_xs
visit root_dashboard_path
diff --git a/spec/features/nav/top_nav_responsive_spec.rb b/spec/features/nav/top_nav_responsive_spec.rb
new file mode 100644
index 00000000000..0d8c75a099d
--- /dev/null
+++ b/spec/features/nav/top_nav_responsive_spec.rb
@@ -0,0 +1,38 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe 'top nav responsive', :js do
+ include MobileHelpers
+
+ let_it_be(:user) { create(:user) }
+ let_it_be(:responsive_menu_text) { 'Placeholder for responsive top nav' }
+
+ before do
+ stub_feature_flags(combined_menu: true)
+
+ sign_in(user)
+ visit explore_projects_path
+
+ resize_screen_xs
+ end
+
+ context 'before opened' do
+ it 'has page content and hides responsive menu', :aggregate_failures do
+ expect(page).to have_css('.page-title', text: 'Projects')
+ expect(page).to have_no_text(responsive_menu_text)
+ end
+ end
+
+ context 'when opened' do
+ before do
+ click_button('Menu')
+ end
+
+ it 'hides everything and shows responsive menu', :aggregate_failures do
+ expect(page).to have_no_css('.page-title', text: 'Projects')
+ expect(page).to have_link('Dashboard', id: 'logo')
+ expect(page).to have_text(responsive_menu_text)
+ end
+ end
+end
diff --git a/spec/frontend/integrations/edit/components/trigger_fields_spec.js b/spec/frontend/integrations/edit/components/trigger_fields_spec.js
index 5f85c58da28..a0816682741 100644
--- a/spec/frontend/integrations/edit/components/trigger_fields_spec.js
+++ b/spec/frontend/integrations/edit/components/trigger_fields_spec.js
@@ -137,11 +137,11 @@ describe('TriggerFields', () => {
const expectedResults = [
{
name: 'service[push_channel]',
- placeholder: 'general, development',
+ placeholder: '#general, #development',
},
{
name: 'service[merge_request_channel]',
- placeholder: 'general, development',
+ placeholder: '#general, #development',
},
];
diff --git a/spec/frontend/nav/components/responsive_app_spec.js b/spec/frontend/nav/components/responsive_app_spec.js
new file mode 100644
index 00000000000..1a153b38a05
--- /dev/null
+++ b/spec/frontend/nav/components/responsive_app_spec.js
@@ -0,0 +1,62 @@
+import { shallowMount } from '@vue/test-utils';
+import { range } from 'lodash';
+import ResponsiveApp from '~/nav/components/responsive_app.vue';
+import eventHub, { EVENT_RESPONSIVE_TOGGLE } from '~/nav/event_hub';
+import { TEST_NAV_DATA } from '../mock_data';
+
+describe('~/nav/components/responsive_app.vue', () => {
+ let wrapper;
+
+ const createComponent = () => {
+ wrapper = shallowMount(ResponsiveApp, {
+ propsData: {
+ navData: TEST_NAV_DATA,
+ },
+ });
+ };
+ const triggerResponsiveToggle = () => eventHub.$emit(EVENT_RESPONSIVE_TOGGLE);
+
+ const hasBodyResponsiveOpen = () => document.body.classList.contains('top-nav-responsive-open');
+
+ beforeEach(() => {
+ // Add test class to reset state + assert that we're adding classes correctly
+ document.body.className = 'test-class';
+ });
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ describe('default', () => {
+ beforeEach(() => {
+ createComponent();
+ });
+
+ it.each`
+ times | expectation
+ ${0} | ${false}
+ ${1} | ${true}
+ ${2} | ${false}
+ `(
+ 'with responsive toggle event triggered $times, body responsive open = $expectation',
+ ({ times, expectation }) => {
+ range(times).forEach(triggerResponsiveToggle);
+
+ expect(hasBodyResponsiveOpen()).toBe(expectation);
+ },
+ );
+ });
+
+ describe('when destroyed', () => {
+ beforeEach(() => {
+ createComponent();
+ wrapper.destroy();
+ });
+
+ it('responsive toggle event does nothing', () => {
+ triggerResponsiveToggle();
+
+ expect(hasBodyResponsiveOpen()).toBe(false);
+ });
+ });
+});
diff --git a/spec/migrations/backfill_draft_status_on_merge_requests_spec.rb b/spec/migrations/backfill_draft_status_on_merge_requests_spec.rb
deleted file mode 100644
index 2015f947f15..00000000000
--- a/spec/migrations/backfill_draft_status_on_merge_requests_spec.rb
+++ /dev/null
@@ -1,44 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-require Rails.root.join('db', 'post_migrate', '20210526222715_backfill_draft_status_on_merge_requests.rb')
-
-RSpec.describe BackfillDraftStatusOnMergeRequests, :migration do
- let(:namespaces) { table(:namespaces) }
- let(:projects) { table(:projects) }
- let(:merge_requests) { table(:merge_requests) }
-
- let(:group) { namespaces.create!(name: 'gitlab', path: 'gitlab') }
- let(:project) { projects.create!(namespace_id: group.id) }
-
- let(:draft_prefixes) { ["[Draft]", "(Draft)", "Draft:", "Draft", "[WIP]", "WIP:", "WIP"] }
-
- def create_merge_request(params)
- common_params = {
- target_project_id: project.id,
- target_branch: 'feature1',
- source_branch: 'master'
- }
-
- merge_requests.create!(common_params.merge(params))
- end
-
- context "for MRs with #draft? == true titles but draft attribute false" do
- before do
- draft_prefixes.each do |prefix|
- (1..4).each do |n|
- merge_request = create_merge_request(title: "#{prefix} This is a title", state_id: n)
- merge_request.update_columns(draft: false)
- end
- end
- end
-
- it "updates all open draft merge request's draft field to true" do
- mr_count = merge_requests.all.count
-
- expect { disable_migrations_output { migrate! } }
- .to change { MergeRequest.where(draft: false).count }
- .from(mr_count).to(mr_count - draft_prefixes.length)
- end
- end
-end
diff --git a/yarn.lock b/yarn.lock
index 8c549491e58..4dfe1a5fd5c 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -7336,10 +7336,10 @@ jquery.waitforimages@^2.2.0:
resolved "https://registry.yarnpkg.com/jquery.waitforimages/-/jquery.waitforimages-2.2.0.tgz#63f23131055a1b060dc913e6d874bcc9b9e6b16b"
integrity sha1-Y/IxMQVaGwYNyRPm2HS8ybnmsWs=
-"jquery@>= 1.9.1", jquery@^3.5.0:
- version "3.5.1"
- resolved "https://registry.yarnpkg.com/jquery/-/jquery-3.5.1.tgz#d7b4d08e1bfdb86ad2f1a3d039ea17304717abb5"
- integrity sha512-XwIBPqcMn57FxfT+Go5pzySnm4KWkT1Tv7gjrpT1srtf8Weynl6R273VJ5GjkRb51IzMp5nbaPjJXMWeju2MKg==
+"jquery@>= 1.9.1", jquery@^3.6.0:
+ version "3.6.0"
+ resolved "https://registry.yarnpkg.com/jquery/-/jquery-3.6.0.tgz#c72a09f15c1bdce142f49dbf1170bdf8adac2470"
+ integrity sha512-JVzAR/AjBvVt2BmYhxRCSYysDsPcssdmTFnzyLEts9qNwmjmu4JTAMYubEfwVOSwpQ1I1sKKFcxhZCI2buerfw==
js-beautify@^1.6.12, js-beautify@^1.8.8:
version "1.11.0"