Add latest changes from gitlab-org/gitlab@master
This commit is contained in:
parent
9882aeb510
commit
bf5cf27dfb
39 changed files with 423 additions and 199 deletions
|
@ -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:
|
||||
|
|
|
@ -10,7 +10,7 @@ const typeWithPlaceholder = {
|
|||
};
|
||||
|
||||
const placeholderForType = {
|
||||
[typeWithPlaceholder.SLACK]: __('general, development'),
|
||||
[typeWithPlaceholder.SLACK]: __('#general, #development'),
|
||||
[typeWithPlaceholder.MATTERMOST]: __('my-channel'),
|
||||
};
|
||||
|
||||
|
|
|
@ -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);
|
||||
});
|
||||
|
||||
/**
|
||||
|
|
30
app/assets/javascripts/nav/components/responsive_app.vue
Normal file
30
app/assets/javascripts/nav/components/responsive_app.vue
Normal file
|
@ -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>
|
5
app/assets/javascripts/nav/event_hub.js
Normal file
5
app/assets/javascripts/nav/event_hub.js
Normal file
|
@ -0,0 +1,5 @@
|
|||
import eventHubFactory from '~/helpers/event_hub_factory';
|
||||
|
||||
export const EVENT_RESPONSIVE_TOGGLE = 'top-nav-responsive-toggle';
|
||||
|
||||
export default eventHubFactory();
|
|
@ -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()]);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -25,7 +25,7 @@ module Integrations
|
|||
end
|
||||
|
||||
def default_channel_placeholder
|
||||
_('general, development')
|
||||
_('#general, #development')
|
||||
end
|
||||
|
||||
def webhook_placeholder
|
||||
|
|
|
@ -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'
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 } }
|
||||
|
|
|
@ -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')
|
||||
|
|
7
app/views/layouts/nav/_top_nav_responsive.html.haml
Normal file
7
app/views/layouts/nav/_top_nav_responsive.html.haml
Normal file
|
@ -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 } }
|
|
@ -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
|
||||
|
|
16
doc/administration/configure.md
Normal file
16
doc/administration/configure.md
Normal file
|
@ -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)
|
|
@ -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)
|
||||
```
|
||||
|
|
|
@ -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`
|
||||
```
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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.
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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 ""
|
||||
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -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',
|
||||
];
|
||||
|
|
|
@ -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
|
||||
|
|
38
spec/features/nav/top_nav_responsive_spec.rb
Normal file
38
spec/features/nav/top_nav_responsive_spec.rb
Normal file
|
@ -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
|
|
@ -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',
|
||||
},
|
||||
];
|
||||
|
||||
|
|
62
spec/frontend/nav/components/responsive_app_spec.js
Normal file
62
spec/frontend/nav/components/responsive_app_spec.js
Normal file
|
@ -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);
|
||||
});
|
||||
});
|
||||
});
|
|
@ -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
|
|
@ -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"
|
||||
|
|
Loading…
Reference in a new issue