Add latest changes from gitlab-org/gitlab@master
This commit is contained in:
parent
1ccebc7b3f
commit
2cba761741
65 changed files with 798 additions and 305 deletions
|
@ -15,27 +15,7 @@ build-qa-image:
|
|||
stage: build-images
|
||||
needs: []
|
||||
script:
|
||||
# Tag with commit SHA by default
|
||||
- export QA_IMAGE="${CI_REGISTRY}/${CI_PROJECT_PATH}/gitlab-ee-qa:${CI_COMMIT_SHA}"
|
||||
# For branches, tag with slugified branch name. For tags, use the tag directly
|
||||
- export QA_IMAGE_BRANCH="${CI_REGISTRY}/${CI_PROJECT_PATH}/gitlab-ee-qa:${CI_COMMIT_TAG:-$CI_COMMIT_REF_SLUG}"
|
||||
# Auto-deploy tag format uses first 12 letters of commit SHA. Tag with that
|
||||
# reference also
|
||||
- export QA_IMAGE_FOR_AUTO_DEPLOY="${CI_REGISTRY}/${CI_PROJECT_PATH}/gitlab-ee-qa:${CI_COMMIT_SHA:0:11}"
|
||||
- echo $QA_IMAGE
|
||||
- echo $QA_IMAGE_BRANCH
|
||||
- echo $QA_IMAGE_FOR_AUTO_DEPLOY
|
||||
- |
|
||||
/kaniko/executor \
|
||||
--context=${CI_PROJECT_DIR} \
|
||||
--dockerfile=${CI_PROJECT_DIR}/qa/Dockerfile \
|
||||
--destination=${QA_IMAGE} \
|
||||
--destination=${QA_IMAGE_BRANCH} \
|
||||
--destination=${QA_IMAGE_FOR_AUTO_DEPLOY} \
|
||||
--build-arg=CHROME_VERSION=${CHROME_VERSION} \
|
||||
--build-arg=DOCKER_VERSION=${DOCKER_VERSION} \
|
||||
--build-arg=QA_BUILD_TARGET=${QA_BUILD_TARGET:-qa} \
|
||||
--cache=true
|
||||
- ./scripts/build_qa_image
|
||||
|
||||
# This image is used by:
|
||||
# - The `CNG` pipelines (via the `review-build-cng` job): https://gitlab.com/gitlab-org/build/CNG/-/blob/cfc67136d711e1c8c409bf8e57427a644393da2f/.gitlab-ci.yml#L335
|
||||
|
|
|
@ -1 +1 @@
|
|||
c13d9d902ef8175a0b1165ef0bc8643fb37b7897
|
||||
d7181e813e602f80bf53e47089da92b6342b355f
|
||||
|
|
|
@ -281,7 +281,7 @@ export default {
|
|||
'gl-z-dropdown-menu!': idState.moreActionsShown,
|
||||
'is-sidebar-moved': glFeatures.movedMrSidebar,
|
||||
}"
|
||||
class="js-file-title file-title file-title-flex-parent"
|
||||
class="js-file-title file-title file-title-flex-parent gl-border"
|
||||
data-qa-selector="file_title_container"
|
||||
:data-qa-file-name="filePath"
|
||||
@click.self="handleToggleFile"
|
||||
|
|
|
@ -0,0 +1,40 @@
|
|||
<script>
|
||||
import { GlAlert } from '@gitlab/ui';
|
||||
import { s__ } from '~/locale';
|
||||
import UserCalloutDismisser from '~/vue_shared/components/user_callout_dismisser.vue';
|
||||
import { helpPagePath } from '~/helpers/help_page_helper';
|
||||
|
||||
export default {
|
||||
name: 'NewTopLevelGroupAlert',
|
||||
components: {
|
||||
GlAlert,
|
||||
UserCalloutDismisser,
|
||||
},
|
||||
i18n: {
|
||||
titleText: s__("Groups|You're creating a new top-level group"),
|
||||
bodyText: s__(
|
||||
'Groups|Members, projects, trials, and paid subscriptions are tied to a specific top-level group. If you are already a member of a top-level group, you can create a subgroup so your new work is part of your existing top-level group. Do you want to create a subgroup instead?',
|
||||
),
|
||||
primaryBtnText: s__('Groups|Learn more about subgroups'),
|
||||
},
|
||||
subgroupsDocsPath: helpPagePath('user/group/subgroups/index'),
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<user-callout-dismisser feature-name="new_top_level_group_alert">
|
||||
<template #default="{ dismiss, shouldShowCallout }">
|
||||
<gl-alert
|
||||
v-if="shouldShowCallout"
|
||||
ref="newTopLevelAlert"
|
||||
data-testid="new-top-level-alert"
|
||||
:title="$options.i18n.titleText"
|
||||
:primary-button-text="$options.i18n.primaryBtnText"
|
||||
:primary-button-link="$options.subgroupsDocsPath"
|
||||
@dismiss="dismiss"
|
||||
>
|
||||
{{ $options.i18n.bodyText }}
|
||||
</gl-alert>
|
||||
</template>
|
||||
</user-callout-dismisser>
|
||||
</template>
|
|
@ -84,8 +84,8 @@ export default {
|
|||
|
||||
return sprintf(text, { commitDisplay, linkStart, linkEnd }, false);
|
||||
},
|
||||
adaptiveAvatarSize() {
|
||||
return { default: 24, md: 32 };
|
||||
toggleClass() {
|
||||
return this.discussion.expanded ? 'expanded' : 'collapsed';
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
|
@ -98,16 +98,13 @@ export default {
|
|||
</script>
|
||||
|
||||
<template>
|
||||
<div class="discussion-header gl-display-flex gl-align-items-center gl-p-5">
|
||||
<div
|
||||
v-once
|
||||
class="timeline-icon gl-align-self-start gl-flex-shrink-0 gl-flex-shrink gl-mx-3 gl-md-ml-2 gl-md-mr-5"
|
||||
>
|
||||
<div class="discussion-header gl-display-flex gl-align-items-center">
|
||||
<div v-once class="timeline-avatar gl-align-self-start gl-flex-shrink-0 gl-flex-shrink">
|
||||
<gl-avatar-link v-if="author" :href="author.path">
|
||||
<gl-avatar :src="author.avatar_url" :alt="author.name" :size="adaptiveAvatarSize" />
|
||||
<gl-avatar :src="author.avatar_url" :alt="author.name" :size="32" />
|
||||
</gl-avatar-link>
|
||||
</div>
|
||||
<div class="timeline-content w-100">
|
||||
<div class="timeline-content w-100 gl-ml-3" :class="toggleClass">
|
||||
<note-header
|
||||
:author="author"
|
||||
:created-at="firstNote.created_at"
|
||||
|
@ -123,14 +120,14 @@ export default {
|
|||
:edited-at="discussion.resolved_at"
|
||||
:edited-by="discussion.resolved_by"
|
||||
:action-text="resolvedText"
|
||||
class-name="discussion-headline-light js-discussion-headline gl-pl-2"
|
||||
class-name="discussion-headline-light js-discussion-headline gl-pl-3"
|
||||
/>
|
||||
<note-edited-text
|
||||
v-else-if="lastUpdatedAt"
|
||||
:edited-at="lastUpdatedAt"
|
||||
:edited-by="lastUpdatedBy"
|
||||
:action-text="__('Last updated')"
|
||||
class-name="discussion-headline-light js-discussion-headline gl-pl-2"
|
||||
class-name="discussion-headline-light js-discussion-headline gl-pl-3"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -142,7 +142,7 @@ export default {
|
|||
:edited-at="discussion.resolved_at"
|
||||
:edited-by="discussion.resolved_by"
|
||||
:action-text="resolvedText"
|
||||
class-name="discussion-headline-light js-discussion-headline discussion-resolved-text"
|
||||
class-name="discussion-headline-light js-discussion-headline discussion-resolved-text gl-mb-2"
|
||||
/>
|
||||
</template>
|
||||
<template #avatar-badge>
|
||||
|
|
|
@ -199,9 +199,6 @@ export default {
|
|||
isMRDiffView() {
|
||||
return this.line && !this.isOverviewTab;
|
||||
},
|
||||
authorAvatarAdaptiveSize() {
|
||||
return { default: 24, md: 32 };
|
||||
},
|
||||
},
|
||||
created() {
|
||||
const line = this.note.position?.line_range?.start || this.line;
|
||||
|
@ -409,7 +406,7 @@ export default {
|
|||
:class="{ ...classNameBindings, 'internal-note': note.internal }"
|
||||
:data-award-url="note.toggle_award_path"
|
||||
:data-note-id="note.id"
|
||||
class="note note-wrapper"
|
||||
class="note note-wrapper note-comment"
|
||||
data-qa-selector="noteable_note_container"
|
||||
>
|
||||
<div
|
||||
|
@ -427,7 +424,7 @@ export default {
|
|||
</gl-sprintf>
|
||||
</div>
|
||||
|
||||
<div v-if="isMRDiffView" class="gl-float-left gl-mt-n1 gl-mr-3">
|
||||
<div v-if="isMRDiffView" class="gl-float-left gl-mt-2">
|
||||
<gl-avatar-link :href="author.path">
|
||||
<gl-avatar
|
||||
:src="author.avatar_url"
|
||||
|
@ -440,13 +437,13 @@ export default {
|
|||
</gl-avatar-link>
|
||||
</div>
|
||||
|
||||
<div v-else class="gl-float-left gl-pl-3 gl-md-pl-2">
|
||||
<div v-else class="timeline-avatar gl-float-left">
|
||||
<gl-avatar-link :href="author.path">
|
||||
<gl-avatar
|
||||
:src="author.avatar_url"
|
||||
:entity-name="author.username"
|
||||
:alt="author.name"
|
||||
:size="authorAvatarAdaptiveSize"
|
||||
:size="32"
|
||||
/>
|
||||
|
||||
<slot name="avatar-badge"></slot>
|
||||
|
|
|
@ -292,7 +292,11 @@ export default {
|
|||
<template #comments>
|
||||
<ul id="notes-list" class="notes main-notes-list timeline">
|
||||
<template v-for="discussion in allDiscussions">
|
||||
<skeleton-loading-container v-if="discussion.isSkeletonNote" :key="discussion.id" />
|
||||
<skeleton-loading-container
|
||||
v-if="discussion.isSkeletonNote"
|
||||
:key="discussion.id"
|
||||
class="note-skeleton"
|
||||
/>
|
||||
<timeline-entry-item v-else-if="discussion.isDraft" :key="discussion.id">
|
||||
<draft-note :draft="discussion" />
|
||||
</timeline-entry-item>
|
||||
|
@ -327,7 +331,7 @@ export default {
|
|||
:help-page-path="helpPagePath"
|
||||
/>
|
||||
</template>
|
||||
<discussion-filter-note v-show="commentsDisabled" />
|
||||
<discussion-filter-note v-if="commentsDisabled" />
|
||||
</ul>
|
||||
</template>
|
||||
</ordered-layout>
|
||||
|
|
|
@ -61,7 +61,7 @@ export default {
|
|||
<template>
|
||||
<li
|
||||
:class="liClasses"
|
||||
class="gl-display-flex! gl-align-items-center gl-flex-wrap gl-bg-gray-10 gl-py-3 gl-px-5 gl-border-t"
|
||||
class="toggle-replies-widget gl-display-flex! gl-align-items-center gl-flex-wrap gl-bg-gray-10 gl-py-3 gl-px-5 gl-border"
|
||||
>
|
||||
<gl-button
|
||||
ref="toggle"
|
||||
|
@ -75,7 +75,7 @@ export default {
|
|||
<user-avatar-link
|
||||
v-for="author in uniqueAuthors"
|
||||
:key="author.username"
|
||||
class="gl-mr-3"
|
||||
class="gl-mr-3 reply-author-avatar"
|
||||
:link-href="author.path"
|
||||
:img-alt="author.name"
|
||||
img-css-classes="gl-mr-0!"
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
import Vue from 'vue';
|
||||
import VueApollo from 'vue-apollo';
|
||||
import createDefaultClient from '~/lib/graphql';
|
||||
import BindInOut from '~/behaviors/bind_in_out';
|
||||
import initFilePickers from '~/file_pickers';
|
||||
import Group from '~/group';
|
||||
|
@ -8,6 +10,8 @@ import NewGroupCreationApp from './components/app.vue';
|
|||
import GroupPathValidator from './group_path_validator';
|
||||
import initToggleInviteMembers from './toggle_invite_members';
|
||||
|
||||
Vue.use(VueApollo);
|
||||
|
||||
new GroupPathValidator(); // eslint-disable-line no-new
|
||||
new Group(); // eslint-disable-line no-new
|
||||
initGroupNameAndPath();
|
||||
|
@ -31,8 +35,13 @@ function initNewGroupCreation(el) {
|
|||
hasErrors: parseBoolean(hasErrors),
|
||||
};
|
||||
|
||||
const apolloProvider = new VueApollo({
|
||||
defaultClient: createDefaultClient(),
|
||||
});
|
||||
|
||||
return new Vue({
|
||||
el,
|
||||
apolloProvider,
|
||||
provide: {
|
||||
verificationRequired: parseBoolean(verificationRequired),
|
||||
verificationFormUrl,
|
||||
|
|
|
@ -50,29 +50,19 @@ export default {
|
|||
renderedNote() {
|
||||
return renderMarkdown(this.note.body);
|
||||
},
|
||||
avatarSize() {
|
||||
if (this.line && !this.isOverviewTab) {
|
||||
return 24;
|
||||
}
|
||||
|
||||
return {
|
||||
default: 24,
|
||||
md: 32,
|
||||
};
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<timeline-entry-item class="note note-wrapper being-posted fade-in-half">
|
||||
<div class="timeline-icon">
|
||||
<gl-avatar-link class="gl-mr-3" :href="getUserData.path">
|
||||
<timeline-entry-item class="note note-wrapper note-comment being-posted fade-in-half">
|
||||
<div class="timeline-avatar gl-float-left">
|
||||
<gl-avatar-link :href="getUserData.path">
|
||||
<gl-avatar
|
||||
:src="getUserData.avatar_url"
|
||||
:entity-name="getUserData.username"
|
||||
:alt="getUserData.name"
|
||||
:size="avatarSize"
|
||||
:size="32"
|
||||
/>
|
||||
</gl-avatar-link>
|
||||
</div>
|
||||
|
@ -85,8 +75,10 @@ export default {
|
|||
</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="note-body">
|
||||
<div v-safe-html="renderedNote" class="note-text md"></div>
|
||||
<div class="timeline-discussion-body">
|
||||
<div class="note-body">
|
||||
<div v-safe-html="renderedNote" class="note-text md"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</timeline-entry-item>
|
||||
|
|
|
@ -141,7 +141,7 @@ export default {
|
|||
variant="link"
|
||||
:icon="descriptionVersionToggleIcon"
|
||||
data-testid="compare-btn"
|
||||
class="gl-vertical-align-text-bottom"
|
||||
class="gl-vertical-align-text-bottom gl-font-sm!"
|
||||
@click="toggleDescriptionVersion"
|
||||
>{{ __('Compare with previous version') }}</gl-button
|
||||
>
|
||||
|
@ -150,7 +150,7 @@ export default {
|
|||
:icon="showLines ? 'chevron-up' : 'chevron-down'"
|
||||
variant="link"
|
||||
data-testid="outdated-lines-change-btn"
|
||||
class="gl-vertical-align-text-bottom"
|
||||
class="gl-vertical-align-text-bottom gl-font-sm!"
|
||||
@click="toggleDiff"
|
||||
>
|
||||
{{ __('Compare changes') }}
|
||||
|
@ -190,7 +190,7 @@ export default {
|
|||
</div>
|
||||
<div
|
||||
v-if="lines.length && showLines"
|
||||
class="diff-content gl-border-solid gl-border-1 gl-border-gray-200 gl-mt-4 gl-rounded-small gl-overflow-hidden"
|
||||
class="diff-content outdated-lines-wrapper gl-border-solid gl-border-1 gl-border-gray-200 gl-mt-4 gl-rounded-small gl-overflow-hidden"
|
||||
>
|
||||
<table
|
||||
:class="$options.userColorSchemeClass"
|
||||
|
|
|
@ -18,15 +18,15 @@ export default {
|
|||
</script>
|
||||
|
||||
<template>
|
||||
<timeline-entry-item class="system-note note-wrapper gl-mb-6!">
|
||||
<timeline-entry-item class="system-note note-wrapper">
|
||||
<div class="timeline-icon">
|
||||
<gl-icon :name="icon" />
|
||||
</div>
|
||||
<div class="timeline-content">
|
||||
<div class="note-header">
|
||||
<span>
|
||||
<div class="note-header-info">
|
||||
<slot></slot>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="note-body">
|
||||
<slot name="body"></slot>
|
||||
|
|
|
@ -1,11 +1,13 @@
|
|||
<script>
|
||||
import { GlBreadcrumb, GlIcon, GlSafeHtmlDirective as SafeHtml } from '@gitlab/ui';
|
||||
import NewTopLevelGroupAlert from '~/groups/components/new_top_level_group_alert.vue';
|
||||
|
||||
import LegacyContainer from './components/legacy_container.vue';
|
||||
import WelcomePage from './components/welcome.vue';
|
||||
|
||||
export default {
|
||||
components: {
|
||||
NewTopLevelGroupAlert,
|
||||
GlBreadcrumb,
|
||||
GlIcon,
|
||||
WelcomePage,
|
||||
|
@ -79,6 +81,14 @@ export default {
|
|||
shouldVerify() {
|
||||
return this.verificationRequired && !this.verificationCompleted;
|
||||
},
|
||||
|
||||
showNewTopLevelGroupAlert() {
|
||||
if (this.activePanel.detailProps === undefined) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return this.activePanel.detailProps.parentGroupName === '';
|
||||
},
|
||||
},
|
||||
|
||||
created() {
|
||||
|
@ -130,6 +140,7 @@ export default {
|
|||
<slot name="extra-description"></slot>
|
||||
</div>
|
||||
<div class="col-lg-9">
|
||||
<new-top-level-group-alert v-if="showNewTopLevelGroupAlert" />
|
||||
<gl-breadcrumb v-if="breadcrumbs" :items="breadcrumbs" />
|
||||
<legacy-container :key="activePanel.name" :selector="activePanel.selector" />
|
||||
</div>
|
||||
|
|
|
@ -10,7 +10,7 @@ import {
|
|||
GlDropdownDivider,
|
||||
GlIntersectionObserver,
|
||||
} from '@gitlab/ui';
|
||||
import { debounce } from 'lodash';
|
||||
import { debounce, uniqueId } from 'lodash';
|
||||
import { getIdFromGraphQLId } from '~/graphql_shared/utils';
|
||||
import currentUserQuery from '~/graphql_shared/queries/current_user.query.graphql';
|
||||
import userSearchQuery from '~/graphql_shared/queries/users_search.query.graphql';
|
||||
|
@ -126,6 +126,9 @@ export default {
|
|||
},
|
||||
},
|
||||
computed: {
|
||||
assigneesTitleId() {
|
||||
return uniqueId('assignees-title-');
|
||||
},
|
||||
searchUsers() {
|
||||
return this.users.nodes.map((node) => addClass({ ...node, ...node.user }));
|
||||
},
|
||||
|
@ -296,12 +299,14 @@ export default {
|
|||
<template>
|
||||
<div class="form-row gl-mb-5 work-item-assignees gl-relative gl-flex-nowrap">
|
||||
<span
|
||||
:id="assigneesTitleId"
|
||||
class="gl-font-weight-bold col-lg-2 col-3 gl-pt-2 min-w-fit-content gl-overflow-wrap-break"
|
||||
data-testid="assignees-title"
|
||||
>{{ assigneeText }}</span
|
||||
>
|
||||
<gl-token-selector
|
||||
ref="tokenSelector"
|
||||
:aria-labelledby="assigneesTitleId"
|
||||
:selected-tokens="localAssignees"
|
||||
:container-class="containerClass"
|
||||
:class="{ 'gl-hover-border-gray-200': canUpdate }"
|
||||
|
@ -319,7 +324,7 @@ export default {
|
|||
>
|
||||
<template #empty-placeholder>
|
||||
<div
|
||||
class="add-assignees gl-min-w-fit-content gl-display-flex gl-align-items-center gl-text-gray-300 gl-pr-4 gl-pl-2 gl-top-2"
|
||||
class="add-assignees gl-min-w-fit-content gl-display-flex gl-align-items-center gl-text-secondary gl-pr-4 gl-pl-2 gl-top-2"
|
||||
data-testid="empty-state"
|
||||
>
|
||||
<gl-icon name="profile" />
|
||||
|
|
|
@ -228,7 +228,7 @@ export default {
|
|||
class="gl-ml-auto"
|
||||
icon="pencil"
|
||||
data-testid="edit-description"
|
||||
:aria-label="__('Edit')"
|
||||
:aria-label="__('Edit description')"
|
||||
@click="startEditing"
|
||||
/>
|
||||
</div>
|
||||
|
|
|
@ -198,7 +198,7 @@ export default {
|
|||
label-cols="3"
|
||||
label-cols-lg="2"
|
||||
>
|
||||
<span v-if="isReadonlyWithNoDates" class="gl-text-gray-400 gl-ml-4">
|
||||
<span v-if="isReadonlyWithNoDates" class="gl-text-secondary gl-ml-4">
|
||||
{{ $options.i18n.none }}
|
||||
</span>
|
||||
<div v-else class="gl-display-flex gl-flex-wrap gl-gap-5">
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<script>
|
||||
import { GlTokenSelector, GlLabel, GlSkeletonLoader } from '@gitlab/ui';
|
||||
import { debounce } from 'lodash';
|
||||
import { debounce, uniqueId } from 'lodash';
|
||||
import { getIdFromGraphQLId } from '~/graphql_shared/utils';
|
||||
import Tracking from '~/tracking';
|
||||
import labelSearchQuery from '~/vue_shared/components/sidebar/labels_select_widget/graphql/project_labels.query.graphql';
|
||||
|
@ -89,6 +89,9 @@ export default {
|
|||
},
|
||||
},
|
||||
computed: {
|
||||
labelsTitleId() {
|
||||
return uniqueId('labels-title-');
|
||||
},
|
||||
tracking() {
|
||||
return {
|
||||
category: TRACKING_CATEGORY_SHOW,
|
||||
|
@ -194,6 +197,7 @@ export default {
|
|||
<template>
|
||||
<div class="form-row gl-mb-5 work-item-labels gl-relative gl-flex-nowrap">
|
||||
<span
|
||||
:id="labelsTitleId"
|
||||
class="gl-font-weight-bold gl-mt-2 col-lg-2 col-3 gl-pt-2 min-w-fit-content gl-overflow-wrap-break"
|
||||
data-testid="labels-title"
|
||||
>{{ __('Labels') }}</span
|
||||
|
@ -201,6 +205,7 @@ export default {
|
|||
<gl-token-selector
|
||||
ref="tokenSelector"
|
||||
v-model="localLabels"
|
||||
:aria-labelledby="labelsTitleId"
|
||||
:container-class="containerClass"
|
||||
:dropdown-items="searchLabels"
|
||||
:loading="isLoading"
|
||||
|
@ -216,7 +221,7 @@ export default {
|
|||
>
|
||||
<template #empty-placeholder>
|
||||
<div
|
||||
class="add-labels gl-min-w-fit-content gl-display-flex gl-align-items-center gl-text-gray-400 gl-pr-4 gl-top-2"
|
||||
class="add-labels gl-min-w-fit-content gl-display-flex gl-align-items-center gl-text-secondary gl-pr-4 gl-top-2"
|
||||
data-testid="empty-state"
|
||||
>
|
||||
<span v-if="canUpdate" class="gl-ml-2">{{ __('Add labels') }}</span>
|
||||
|
|
|
@ -257,7 +257,7 @@ export default {
|
|||
class="gl-display-inline-flex gl-align-items-center gl-line-height-24 gl-ml-3"
|
||||
data-testid="children-count"
|
||||
>
|
||||
<gl-icon :name="$options.WIDGET_TYPE_TASK_ICON" class="gl-mr-2 gl-text-gray-500" />
|
||||
<gl-icon :name="$options.WIDGET_TYPE_TASK_ICON" class="gl-mr-2 gl-text-secondary" />
|
||||
{{ childrenCountLabel }}
|
||||
</span>
|
||||
</div>
|
||||
|
|
|
@ -182,7 +182,7 @@ export default {
|
|||
>
|
||||
<template #result="{ item }">
|
||||
<div class="gl-display-flex">
|
||||
<div class="gl-text-gray-400 gl-mr-4">{{ getIdFromGraphQLId(item.id) }}</div>
|
||||
<div class="gl-text-secondary gl-mr-4">{{ getIdFromGraphQLId(item.id) }}</div>
|
||||
<div>{{ item.title }}</div>
|
||||
</div>
|
||||
</template>
|
||||
|
|
|
@ -53,7 +53,7 @@ export default {
|
|||
v-gl-tooltip.hover="showTooltipOnHover"
|
||||
:name="iconName"
|
||||
:title="workItemTooltipTitle"
|
||||
class="gl-mr-2 gl-text-gray-500"
|
||||
class="gl-mr-2 gl-text-secondary"
|
||||
/>
|
||||
<span v-if="workItemTypeName" :class="{ 'gl-sr-only': !showText }">{{ workItemTypeName }}</span>
|
||||
</span>
|
||||
|
|
|
@ -1013,7 +1013,7 @@ table.code {
|
|||
clear: left;
|
||||
|
||||
.note-body {
|
||||
margin-top: 0 !important;
|
||||
padding: 0 0 $gl-padding-8;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1023,8 +1023,12 @@ table.code {
|
|||
}
|
||||
|
||||
// tiny adjustment to vertical align with the note header text
|
||||
.discussion-collapsible .timeline-icon {
|
||||
padding-top: 2px;
|
||||
.discussion-collapsible {
|
||||
margin-left: 1rem;
|
||||
|
||||
.timeline-icon {
|
||||
padding-top: 2px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1097,6 +1101,7 @@ table.code {
|
|||
|
||||
.discussion-notes {
|
||||
min-height: 35px;
|
||||
background-color: transparent;
|
||||
|
||||
&:first-child {
|
||||
// First child does not have the jagged borders
|
||||
|
@ -1121,6 +1126,17 @@ table.code {
|
|||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
ul.notes {
|
||||
li.toggle-replies-widget,
|
||||
.discussion-reply-holder {
|
||||
margin-left: 2.5rem;
|
||||
|
||||
.reply-author-avatar {
|
||||
height: 1.5rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.discussion-body .image .frame {
|
||||
|
|
|
@ -28,15 +28,9 @@
|
|||
.timeline-entry {
|
||||
color: $gl-text-color;
|
||||
|
||||
// [dark-theme]: only give background color to actual notes
|
||||
// in the timeline, the note form textarea has a background
|
||||
// of it's own
|
||||
&:not(.note-form) {
|
||||
background-color: $white;
|
||||
}
|
||||
|
||||
&:not(.note-form).internal-note {
|
||||
background-color: $orange-50;
|
||||
&:not(.note-form).internal-note .timeline-content,
|
||||
&:not(.note-form).draft-note .timeline-content {
|
||||
background-color: $orange-50 !important;
|
||||
}
|
||||
|
||||
.timeline-entry-inner {
|
||||
|
@ -45,23 +39,15 @@
|
|||
|
||||
&:target,
|
||||
&.target {
|
||||
background: $line-target-blue;
|
||||
.timeline-content {
|
||||
background: $line-target-blue !important;
|
||||
}
|
||||
|
||||
&.system-note .note-body .note-text.system-note-commit-list::after {
|
||||
background: linear-gradient(rgba($line-target-blue, 0.1) -100px, $line-target-blue 100%);
|
||||
}
|
||||
}
|
||||
|
||||
img.avatar {
|
||||
margin-right: $gl-padding-12;
|
||||
|
||||
@include media-breakpoint-down(sm) {
|
||||
width: $gl-spacing-scale-6;
|
||||
height: $gl-spacing-scale-6;
|
||||
margin-right: $gl-padding-8;
|
||||
}
|
||||
}
|
||||
|
||||
.controls {
|
||||
padding-top: 10px;
|
||||
float: right;
|
||||
|
|
|
@ -661,10 +661,10 @@ $tabs-holder-z-index: 250;
|
|||
|
||||
&:not(:last-child)::before {
|
||||
content: '';
|
||||
border-left: 1px solid var(--gray-100, $gray-100);
|
||||
border-left: 2px solid var(--gray-10, $gray-10);
|
||||
position: absolute;
|
||||
left: 28px;
|
||||
bottom: -17px;
|
||||
left: calc(1rem - 1px);
|
||||
height: 16px;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -946,6 +946,7 @@
|
|||
.timeline-event-note {
|
||||
p {
|
||||
margin-bottom: 0;
|
||||
font-size: 0.875rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -961,7 +962,7 @@
|
|||
content: '';
|
||||
border-left: 2px solid $gray-50;
|
||||
position: absolute;
|
||||
left: 39px;
|
||||
left: 20px;
|
||||
height: calc(100% + #{$gl-spacing-scale-5});
|
||||
top: -#{$gl-spacing-scale-5};
|
||||
}
|
||||
|
@ -990,10 +991,6 @@
|
|||
}
|
||||
}
|
||||
|
||||
.timeline-event-note-form {
|
||||
padding-left: 20px;
|
||||
}
|
||||
|
||||
.timeline-entry:not(:last-child) {
|
||||
.timeline-event-border {
|
||||
@include gl-pb-5;
|
||||
|
|
|
@ -1,15 +1,15 @@
|
|||
$system-note-icon-size: 32px;
|
||||
$system-note-svg-size: 16px;
|
||||
$system-note-icon-size: 2rem;
|
||||
$system-note-svg-size: 1rem;
|
||||
|
||||
@mixin vertical-line($left) {
|
||||
&::before {
|
||||
content: '';
|
||||
border-left: 2px solid $gray-10;
|
||||
border-left: 2px solid var(--gray-10, $gray-10);
|
||||
position: absolute;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
left: $left;
|
||||
height: calc(100% - 20px);
|
||||
left: calc(#{$left} - 1px);
|
||||
height: calc(100% + 1.5rem);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -19,17 +19,10 @@ $system-note-svg-size: 16px;
|
|||
border-radius: $border-radius-default;
|
||||
}
|
||||
|
||||
.note-wrapper {
|
||||
padding: $gl-padding $gl-padding-8 $gl-padding $gl-padding;
|
||||
|
||||
&.outlined {
|
||||
@include outline-comment();
|
||||
}
|
||||
}
|
||||
|
||||
.issuable-discussion {
|
||||
.main-notes-list {
|
||||
@include vertical-line(35px);
|
||||
.issuable-discussion:not(.incident-timeline-events),
|
||||
.limited-width-notes {
|
||||
.main-notes-list > li.timeline-entry:not(:last-of-type) {
|
||||
@include vertical-line(1rem);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -41,8 +34,6 @@ $system-note-svg-size: 16px;
|
|||
position: relative;
|
||||
|
||||
&.timeline > .timeline-entry {
|
||||
border: 1px solid $border-color;
|
||||
border-radius: $border-radius-default;
|
||||
margin: $gl-padding 0;
|
||||
|
||||
&.system-note,
|
||||
|
@ -50,6 +41,103 @@ $system-note-svg-size: 16px;
|
|||
border: 0;
|
||||
}
|
||||
|
||||
.timeline-avatar {
|
||||
height: 2rem;
|
||||
}
|
||||
|
||||
&.note-comment,
|
||||
&.note-skeleton,
|
||||
.draft-note {
|
||||
.timeline-avatar {
|
||||
margin-top: 5px;
|
||||
}
|
||||
|
||||
.timeline-content:not(.flash-container) {
|
||||
margin-left: 2.5rem;
|
||||
border: 1px solid $border-color;
|
||||
border-radius: $gl-border-radius-base;
|
||||
background-color: $white;
|
||||
padding: $gl-padding-4 $gl-padding-8;
|
||||
}
|
||||
|
||||
.note-header-info {
|
||||
min-height: 2rem;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0 0.25rem;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
}
|
||||
|
||||
&.note-discussion {
|
||||
.timeline-content .discussion-wrapper {
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
.timeline-content {
|
||||
ul li {
|
||||
&:first-of-type {
|
||||
.timeline-avatar {
|
||||
margin-top: 5px;
|
||||
}
|
||||
|
||||
.timeline-content {
|
||||
margin-left: 2.5rem;
|
||||
border-left: 1px solid $border-color;
|
||||
border-right: 1px solid $border-color;
|
||||
border-top: 1px solid $border-color;
|
||||
border-top-left-radius: $gl-border-radius-base;
|
||||
border-top-right-radius: $gl-border-radius-base;
|
||||
background-color: $white;
|
||||
padding: $gl-padding-4 $gl-padding-8;
|
||||
}
|
||||
}
|
||||
|
||||
&:not(:first-of-type) .timeline-entry-inner {
|
||||
margin-left: 2.5rem;
|
||||
border-left: 1px solid $border-color;
|
||||
border-right: 1px solid $border-color;
|
||||
background-color: $white;
|
||||
padding: $gl-padding-8 $gl-padding-8 $gl-padding-8 $gl-padding;
|
||||
|
||||
.timeline-discussion-body {
|
||||
margin-left: 2rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.diff-content {
|
||||
ul li:first-of-type {
|
||||
.timeline-avatar {
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
.timeline-content {
|
||||
margin-left: 0;
|
||||
border: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.timeline-entry-inner {
|
||||
margin-left: 2.5rem;
|
||||
border-left: 1px solid $border-color;
|
||||
border-right: 1px solid $border-color;
|
||||
background-color: $white;
|
||||
padding: $gl-padding-8 $gl-padding-8 $gl-padding-4 $gl-padding;
|
||||
|
||||
.timeline-discussion-body {
|
||||
margin-left: 2rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.discussion-reply-holder {
|
||||
border: 1px solid $border-color;
|
||||
}
|
||||
}
|
||||
|
||||
&.note-form {
|
||||
margin-left: 0;
|
||||
|
||||
|
@ -88,10 +176,14 @@ $system-note-svg-size: 16px;
|
|||
.card {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.timeline-discussion-body {
|
||||
margin-top: -$gl-padding-8;
|
||||
.note-header-info {
|
||||
min-height: 2rem;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0 0.25rem;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
}
|
||||
|
||||
.discussion {
|
||||
|
@ -116,16 +208,11 @@ $system-note-svg-size: 16px;
|
|||
&.being-posted {
|
||||
pointer-events: none;
|
||||
opacity: 0.5;
|
||||
padding: $gl-padding;
|
||||
|
||||
.dummy-avatar {
|
||||
background-color: $gray-100;
|
||||
border: 1px solid darken($gray-100, 25%);
|
||||
}
|
||||
|
||||
.note-headline-light {
|
||||
margin-left: 3px;
|
||||
}
|
||||
}
|
||||
|
||||
.editing-spinner {
|
||||
|
@ -156,6 +243,7 @@ $system-note-svg-size: 16px;
|
|||
.note-edit-form {
|
||||
display: block;
|
||||
margin-left: 0;
|
||||
margin-top: 0.5rem;
|
||||
|
||||
&.current-note-edit-form + .note-awards {
|
||||
display: none;
|
||||
|
@ -164,13 +252,17 @@ $system-note-svg-size: 16px;
|
|||
}
|
||||
|
||||
.note-body {
|
||||
padding: $gl-padding-4 $gl-padding-4 $gl-padding-4 $gl-padding-8;
|
||||
padding: $gl-padding-8;
|
||||
overflow-x: auto;
|
||||
overflow-y: hidden;
|
||||
|
||||
.note-text {
|
||||
word-wrap: break-word;
|
||||
}
|
||||
|
||||
.suggestions {
|
||||
margin-top: 4px;
|
||||
}
|
||||
}
|
||||
|
||||
.note-awards {
|
||||
|
@ -186,9 +278,10 @@ $system-note-svg-size: 16px;
|
|||
}
|
||||
|
||||
.system-note {
|
||||
padding: $gl-padding-4 20px;
|
||||
padding: $gl-padding-8 0;
|
||||
margin: $gl-padding 0;
|
||||
background-color: transparent;
|
||||
font-size: $gl-font-size-sm;
|
||||
|
||||
.note-header-info {
|
||||
padding-bottom: 0;
|
||||
|
@ -229,6 +322,15 @@ $system-note-svg-size: 16px;
|
|||
|
||||
.note-body {
|
||||
overflow: hidden;
|
||||
padding: 0;
|
||||
|
||||
ul {
|
||||
margin: 0.5rem 0;
|
||||
}
|
||||
|
||||
p {
|
||||
margin-left: 1rem;
|
||||
}
|
||||
|
||||
.description-version {
|
||||
position: relative;
|
||||
|
@ -305,7 +407,7 @@ $system-note-svg-size: 16px;
|
|||
height: $system-note-icon-size;
|
||||
border: 1px solid $gray-10;
|
||||
border-radius: $system-note-icon-size;
|
||||
margin: -6px 0 0;
|
||||
margin: -8px 0 0;
|
||||
|
||||
svg {
|
||||
width: $system-note-svg-size;
|
||||
|
@ -330,8 +432,9 @@ $system-note-svg-size: 16px;
|
|||
.discussion-body .diff-file {
|
||||
.file-title {
|
||||
cursor: default;
|
||||
border-top: 1px solid $border-color;
|
||||
border-top: 0;
|
||||
border-radius: 0;
|
||||
margin-left: 2.5rem;
|
||||
|
||||
@media (min-width: map-get($grid-breakpoints, md)) {
|
||||
--initial-top: calc(#{$header-height} + #{$mr-tabs-height});
|
||||
|
@ -357,6 +460,40 @@ $system-note-svg-size: 16px;
|
|||
.line_content {
|
||||
white-space: pre-wrap;
|
||||
}
|
||||
|
||||
.diff-content {
|
||||
margin-left: 2.5rem;
|
||||
|
||||
&.outdated-lines-wrapper {
|
||||
margin-left: 0;
|
||||
}
|
||||
|
||||
.line_holder td:first-of-type {
|
||||
@include gl-border-l;
|
||||
}
|
||||
|
||||
.line_holder td:last-of-type {
|
||||
@include gl-border-r;
|
||||
}
|
||||
|
||||
.discussion-notes {
|
||||
margin-left: -2.5rem;
|
||||
|
||||
.notes {
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
.notes-content {
|
||||
border: 0;
|
||||
}
|
||||
|
||||
.timeline-content {
|
||||
border-top: 0 !important;
|
||||
border-top-left-radius: 0 !important;
|
||||
border-top-right-radius: 0 !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.tab-pane.notes {
|
||||
|
@ -394,8 +531,12 @@ $system-note-svg-size: 16px;
|
|||
}
|
||||
|
||||
.system-note {
|
||||
background-color: $white;
|
||||
padding: $gl-padding;
|
||||
background-color: transparent;
|
||||
padding: 0;
|
||||
|
||||
.timeline-icon {
|
||||
margin-top: -2px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -487,6 +628,19 @@ $system-note-svg-size: 16px;
|
|||
.code-commit .notes-content,
|
||||
.diff-viewer > .image ~ .note-container {
|
||||
background-color: $white;
|
||||
|
||||
li.note-comment {
|
||||
padding: $gl-padding-8 $gl-padding-8 $gl-padding-8 $gl-padding;
|
||||
|
||||
.avatar {
|
||||
margin-right: 0;
|
||||
}
|
||||
|
||||
.note-body {
|
||||
padding: $gl-padding-4 0 $gl-padding-8;
|
||||
margin-left: 2.5rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.diff-viewer > .image ~ .note-container form.new-note {
|
||||
|
@ -540,9 +694,21 @@ $system-note-svg-size: 16px;
|
|||
padding-bottom: 0;
|
||||
}
|
||||
|
||||
.timeline-avatar {
|
||||
margin-top: 5px;
|
||||
}
|
||||
|
||||
.timeline-content {
|
||||
overflow-x: auto;
|
||||
overflow-y: hidden;
|
||||
border-radius: $gl-border-radius-base;
|
||||
padding: $gl-padding-8 !important;
|
||||
@include gl-border;
|
||||
|
||||
&.expanded {
|
||||
border-bottom-left-radius: 0;
|
||||
border-bottom-right-radius: 0;
|
||||
}
|
||||
}
|
||||
|
||||
&.note-wrapper {
|
||||
|
@ -568,19 +734,10 @@ $system-note-svg-size: 16px;
|
|||
.note {
|
||||
@include notes-media('max', map-get($grid-breakpoints, sm) - 1) {
|
||||
.note-header {
|
||||
.note-actions {
|
||||
flex-wrap: wrap;
|
||||
margin-bottom: $gl-padding-12;
|
||||
|
||||
> :first-child {
|
||||
margin-left: 0;
|
||||
}
|
||||
.note-actions > :first-child {
|
||||
margin-left: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.note-header-author-name {
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -593,11 +750,6 @@ $system-note-svg-size: 16px;
|
|||
}
|
||||
}
|
||||
|
||||
.note-header-info,
|
||||
.note-actions {
|
||||
padding-bottom: $gl-padding-4;
|
||||
}
|
||||
|
||||
.system-note .note-header-info {
|
||||
padding-bottom: 0;
|
||||
}
|
||||
|
@ -618,10 +770,6 @@ $system-note-svg-size: 16px;
|
|||
}
|
||||
|
||||
.note-headline-meta {
|
||||
.system-note-separator {
|
||||
color: $gray-500;
|
||||
}
|
||||
|
||||
.note-timestamp {
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
@ -674,7 +822,6 @@ $system-note-svg-size: 16px;
|
|||
align-items: center;
|
||||
margin-left: 10px;
|
||||
color: $gray-400;
|
||||
margin-top: -4px;
|
||||
|
||||
@include notes-media('max', map-get($grid-breakpoints, sm) - 1) {
|
||||
float: none;
|
||||
|
@ -719,7 +866,7 @@ $system-note-svg-size: 16px;
|
|||
}
|
||||
|
||||
.discussion-toggle-button {
|
||||
padding: 0;
|
||||
padding: 0 $gl-padding-8 0 0;
|
||||
background-color: transparent;
|
||||
border: 0;
|
||||
line-height: 20px;
|
||||
|
@ -868,6 +1015,22 @@ $system-note-svg-size: 16px;
|
|||
.note-discussion.timeline-entry {
|
||||
padding-left: 0;
|
||||
|
||||
ul.notes li.note-wrapper {
|
||||
padding: $gl-padding-8 $gl-padding-8 $gl-padding-8 $gl-padding;
|
||||
}
|
||||
|
||||
ul.notes {
|
||||
li.toggle-replies-widget {
|
||||
margin-left: 0;
|
||||
border-left: 0;
|
||||
border-right: 0;
|
||||
}
|
||||
|
||||
div.discussion-reply-holder {
|
||||
margin-left: 0;
|
||||
}
|
||||
}
|
||||
|
||||
&:last-child {
|
||||
border-bottom: 0;
|
||||
}
|
||||
|
|
|
@ -11,6 +11,7 @@ module Ci
|
|||
include Gitlab::Utils::StrongMemoize
|
||||
|
||||
self.table_name = 'ci_builds_metadata'
|
||||
self.primary_key = 'id'
|
||||
|
||||
belongs_to :build, class_name: 'CommitStatus'
|
||||
belongs_to :project
|
||||
|
|
|
@ -61,7 +61,8 @@ module Users
|
|||
namespace_storage_limit_banner_alert_threshold: 57, # EE-only
|
||||
namespace_storage_limit_banner_error_threshold: 58, # EE-only
|
||||
project_quality_summary_feedback: 59, # EE-only
|
||||
merge_request_settings_moved_callout: 60
|
||||
merge_request_settings_moved_callout: 60,
|
||||
new_top_level_group_alert: 61
|
||||
}
|
||||
|
||||
validates :feature_name,
|
||||
|
|
|
@ -197,6 +197,10 @@ class WebHookService
|
|||
Gitlab::WebHooks::GITLAB_EVENT_HEADER => self.class.hook_to_event(hook_name)
|
||||
}
|
||||
|
||||
if Feature.enabled?(:webhooks_gitlab_instance_header)
|
||||
headers[Gitlab::WebHooks::GITLAB_INSTANCE_HEADER] = Gitlab.config.gitlab.base_url
|
||||
end
|
||||
|
||||
headers['X-Gitlab-Token'] = Gitlab::Utils.remove_line_breaks(hook.token) if hook.token.present?
|
||||
headers.merge!(Gitlab::WebHooks::RecursionDetection.header(hook))
|
||||
end
|
||||
|
|
|
@ -34,4 +34,4 @@
|
|||
= f.gitlab_ui_checkbox_component :write_package_registry, 'write_package_registry', help_text: s_('DeployTokens|Allows read and write access to the package registry.'), checkbox_options: { data: { qa_selector: 'deploy_token_write_package_registry_checkbox' } }
|
||||
|
||||
.gl-mt-3
|
||||
= f.submit s_('DeployTokens|Create deploy token'), class: 'btn gl-button btn-confirm', data: { qa_selector: 'create_deploy_token_button' }
|
||||
= f.submit s_('DeployTokens|Create deploy token'), data: { qa_selector: 'create_deploy_token_button' }, pajamas_button: true
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
= form_for @label, as: :label, url: url, html: { class: 'label-form js-quick-submit js-requires-input' } do |f|
|
||||
= gitlab_ui_form_for @label, as: :label, url: url, html: { class: 'label-form js-quick-submit js-requires-input' } do |f|
|
||||
= form_errors(@label)
|
||||
|
||||
.form-group.row
|
||||
|
@ -26,9 +26,9 @@
|
|||
.gl-display-flex.gl-justify-content-space-between
|
||||
%div
|
||||
- if @label.persisted?
|
||||
= f.submit _('Save changes'), class: 'btn gl-button btn-confirm js-save-button gl-mr-2'
|
||||
= f.submit _('Save changes'), class: 'js-save-button gl-mr-2', pajamas_button: true
|
||||
- else
|
||||
= f.submit _('Create label'), class: 'btn gl-button btn-confirm js-save-button gl-mr-2', data: { qa_selector: 'label_create_button' }
|
||||
= f.submit _('Create label'), class: 'js-save-button gl-mr-2', data: { qa_selector: 'label_create_button' }, pajamas_button: true
|
||||
= link_to _('Cancel'), back_path, class: 'btn gl-button btn-default btn-cancel gl-mr-2'
|
||||
- if @label.persisted?
|
||||
- presented_label = @label.present
|
||||
|
|
|
@ -6,17 +6,18 @@
|
|||
- note_counter = local_assigns.fetch(:note_counter, 0)
|
||||
|
||||
%li.timeline-entry.note-wrapper{ id: dom_id(note),
|
||||
class: ["note", "note-row-#{note.id}", ('system-note' if note.system)],
|
||||
class: ["note", "note-comment", "note-row-#{note.id}", ('system-note' if note.system)],
|
||||
data: { author_id: note.author.id,
|
||||
editable: note_editable,
|
||||
note_id: note.id } }
|
||||
.timeline-entry-inner
|
||||
.timeline-icon
|
||||
- if note.system
|
||||
- if note.system
|
||||
.timeline-icon
|
||||
= icon_for_system_note(note)
|
||||
- else
|
||||
- else
|
||||
.timeline-avatar.gl-float-left
|
||||
%a.image-diff-avatar-link{ href: user_path(note.author) }
|
||||
= image_tag avatar_icon_for_user(note.author), alt: '', class: 'avatar s40'
|
||||
= image_tag avatar_icon_for_user(note.author), alt: '', class: 'avatar s32'
|
||||
- if note.is_a?(DiffNote) && note.on_image?
|
||||
- if show_image_comment_badge && note_counter == 0
|
||||
-# Only show this for the first comment in the discussion
|
||||
|
@ -34,9 +35,9 @@
|
|||
%span.note-header-author-name.bold
|
||||
= note.author.name
|
||||
= user_status(note.author)
|
||||
%span.note-headline-light{ data: { qa_selector: 'note_author_content' } }
|
||||
%spannote-headline-light{ data: { qa_selector: 'note_author_content' } }
|
||||
= note.author.to_reference
|
||||
%span.note-headline-light.note-headline-meta
|
||||
%span.note-headline-ligh.note-headline-meta
|
||||
- if note.system
|
||||
%span.system-note-message
|
||||
= markdown_field(note, :note)
|
||||
|
|
|
@ -0,0 +1,8 @@
|
|||
---
|
||||
name: webhooks_gitlab_instance_header
|
||||
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/98624
|
||||
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/375001
|
||||
milestone: '15.5'
|
||||
type: development
|
||||
group: group::integrations
|
||||
default_enabled: false
|
|
@ -0,0 +1,7 @@
|
|||
---
|
||||
name: sidekiq_memory_killer_read_only_mode
|
||||
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/98519
|
||||
milestone: '15.5'
|
||||
type: ops
|
||||
group: group::application performance
|
||||
default_enabled: false
|
|
@ -3,7 +3,7 @@ key_path: database.flavor
|
|||
description: What PostgreSQL flavor is being used. Possible values are
|
||||
"Amazon Aurora PostgreSQL", "PostgreSQL on Amazon RDS", "Cloud SQL for PostgreSQL",
|
||||
"Azure Database for PostgreSQL - Single Server", "Azure Database for PostgreSQL - Flexible Server",
|
||||
or "null".
|
||||
"AlloyDB for PostgreSQL", or "null".
|
||||
product_section: enablement
|
||||
product_stage: enablement
|
||||
product_group: database
|
||||
|
|
|
@ -0,0 +1,36 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class PrepareCiBuildsMetadataForPartitioningPrimaryKey < Gitlab::Database::Migration[2.0]
|
||||
disable_ddl_transaction!
|
||||
|
||||
TABLE_NAME = 'ci_builds_metadata'
|
||||
PRIMARY_KEY = 'ci_builds_metadata_pkey'
|
||||
NEW_INDEX_NAME = 'index_ci_builds_metadata_on_id_partition_id_unique'
|
||||
OLD_INDEX_NAME = 'index_ci_builds_metadata_on_id_unique'
|
||||
|
||||
def up
|
||||
with_lock_retries(raise_on_exhaustion: true) do
|
||||
execute("ALTER TABLE #{TABLE_NAME} DROP CONSTRAINT #{PRIMARY_KEY} CASCADE")
|
||||
|
||||
rename_index(TABLE_NAME, NEW_INDEX_NAME, PRIMARY_KEY)
|
||||
|
||||
execute("ALTER TABLE #{TABLE_NAME} ADD CONSTRAINT #{PRIMARY_KEY} " \
|
||||
"PRIMARY KEY USING INDEX #{PRIMARY_KEY}")
|
||||
end
|
||||
end
|
||||
|
||||
# rolling back this migration is time consuming with the creation of these two indexes
|
||||
def down
|
||||
add_concurrent_index(TABLE_NAME, :id, unique: true, name: OLD_INDEX_NAME)
|
||||
add_concurrent_index(TABLE_NAME, [:id, :partition_id], unique: true, name: NEW_INDEX_NAME)
|
||||
|
||||
with_lock_retries(raise_on_exhaustion: true) do
|
||||
execute("ALTER TABLE #{TABLE_NAME} DROP CONSTRAINT #{PRIMARY_KEY} CASCADE")
|
||||
|
||||
rename_index(TABLE_NAME, OLD_INDEX_NAME, PRIMARY_KEY)
|
||||
|
||||
execute("ALTER TABLE #{TABLE_NAME} ADD CONSTRAINT #{PRIMARY_KEY} " \
|
||||
"PRIMARY KEY USING INDEX #{PRIMARY_KEY}")
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,15 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class AddIndexOnInternalNotes < Gitlab::Database::Migration[2.0]
|
||||
INDEX_NAME = 'index_notes_on_id_where_internal'
|
||||
|
||||
disable_ddl_transaction!
|
||||
|
||||
def up
|
||||
add_concurrent_index :notes, :id, where: 'internal = true', name: INDEX_NAME
|
||||
end
|
||||
|
||||
def down
|
||||
remove_concurrent_index_by_name :notes, INDEX_NAME
|
||||
end
|
||||
end
|
1
db/schema_migrations/20220920081631
Normal file
1
db/schema_migrations/20220920081631
Normal file
|
@ -0,0 +1 @@
|
|||
081480492cbe6e631f0357b181a883a2bc7f34566f23f119c0ba4df59ee363d6
|
1
db/schema_migrations/20220920141001
Normal file
1
db/schema_migrations/20220920141001
Normal file
|
@ -0,0 +1 @@
|
|||
368d6e417d6ac9c4ed3815b67f3247d55a6e4ec8a6e7ac255c7f9f24d3721f59
|
|
@ -25045,7 +25045,7 @@ ALTER TABLE ONLY ci_build_trace_metadata
|
|||
ADD CONSTRAINT ci_build_trace_metadata_pkey PRIMARY KEY (build_id);
|
||||
|
||||
ALTER TABLE ONLY ci_builds_metadata
|
||||
ADD CONSTRAINT ci_builds_metadata_pkey PRIMARY KEY (id);
|
||||
ADD CONSTRAINT ci_builds_metadata_pkey PRIMARY KEY (id, partition_id);
|
||||
|
||||
ALTER TABLE ONLY ci_builds
|
||||
ADD CONSTRAINT ci_builds_pkey PRIMARY KEY (id);
|
||||
|
@ -29502,6 +29502,8 @@ CREATE INDEX index_notes_on_discussion_id ON notes USING btree (discussion_id);
|
|||
|
||||
CREATE INDEX index_notes_on_id_where_confidential ON notes USING btree (id) WHERE (confidential = true);
|
||||
|
||||
CREATE INDEX index_notes_on_id_where_internal ON notes USING btree (id) WHERE (internal = true);
|
||||
|
||||
CREATE INDEX index_notes_on_line_code ON notes USING btree (line_code);
|
||||
|
||||
CREATE INDEX index_notes_on_noteable_id_and_noteable_type_and_system ON notes USING btree (noteable_id, noteable_type, system);
|
||||
|
|
|
@ -21386,6 +21386,7 @@ Name of the feature that the callout is for.
|
|||
| <a id="usercalloutfeaturenameenumnamespace_storage_limit_banner_error_threshold"></a>`NAMESPACE_STORAGE_LIMIT_BANNER_ERROR_THRESHOLD` | Callout feature name for namespace_storage_limit_banner_error_threshold. |
|
||||
| <a id="usercalloutfeaturenameenumnamespace_storage_limit_banner_info_threshold"></a>`NAMESPACE_STORAGE_LIMIT_BANNER_INFO_THRESHOLD` | Callout feature name for namespace_storage_limit_banner_info_threshold. |
|
||||
| <a id="usercalloutfeaturenameenumnamespace_storage_limit_banner_warning_threshold"></a>`NAMESPACE_STORAGE_LIMIT_BANNER_WARNING_THRESHOLD` | Callout feature name for namespace_storage_limit_banner_warning_threshold. |
|
||||
| <a id="usercalloutfeaturenameenumnew_top_level_group_alert"></a>`NEW_TOP_LEVEL_GROUP_ALERT` | Callout feature name for new_top_level_group_alert. |
|
||||
| <a id="usercalloutfeaturenameenumnew_user_signups_cap_reached"></a>`NEW_USER_SIGNUPS_CAP_REACHED` | Callout feature name for new_user_signups_cap_reached. |
|
||||
| <a id="usercalloutfeaturenameenumpersonal_access_token_expiry"></a>`PERSONAL_ACCESS_TOKEN_EXPIRY` | Callout feature name for personal_access_token_expiry. |
|
||||
| <a id="usercalloutfeaturenameenumpersonal_project_limitations_banner"></a>`PERSONAL_PROJECT_LIMITATIONS_BANNER` | Callout feature name for personal_project_limitations_banner. |
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
---
|
||||
stage: Create
|
||||
group: Source Code
|
||||
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
|
||||
stage: Data Stores
|
||||
group: Global Search
|
||||
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
|
||||
---
|
||||
|
||||
# Search API **(FREE)**
|
||||
|
@ -10,28 +10,30 @@ info: To determine the technical writer assigned to the Stage/Group associated w
|
|||
|
||||
Every API call to search must be authenticated.
|
||||
|
||||
## Additional scopes **(PREMIUM)**
|
||||
|
||||
Additional scopes are available for the [Advanced Search API](#advanced-search-api)
|
||||
and [Group Search API](#group-search-api) if
|
||||
[Elasticsearch is enabled](../integration/advanced_search/elasticsearch.md):
|
||||
`blobs`, `commits`, `notes`, `wiki_blobs`.
|
||||
|
||||
## Advanced Search API
|
||||
|
||||
Search globally across the GitLab instance.
|
||||
Search for an expression globally across the GitLab instance, in a specified scope.
|
||||
The response depends on the requested scope.
|
||||
|
||||
```plaintext
|
||||
GET /search
|
||||
```
|
||||
|
||||
| Attribute | Type | Required | Description |
|
||||
| ------------------- | ---------------- | ---------- | ---------------------------------------------------------------------------------------|
|
||||
| `scope` | string | yes | The scope to search in |
|
||||
| `search` | string | yes | The search query |
|
||||
| `state` | string | no | Filter by state. Issues and merge requests are supported; it is ignored for other scopes. |
|
||||
| `confidential` | boolean | no | Filter by confidentiality. Issues scope is supported; it is ignored for other scopes. |
|
||||
| `order_by` | string | no | Allowed values are `created_at` only. If this is not set, the results are either sorted by `created_at` in descending order for basic search, or by the most relevant documents when using advanced search.|
|
||||
| `sort` | string | no | Allowed values are `asc` or `desc` only. If this is not set, the results are either sorted by `created_at` in descending order for basic search, or by the most relevant documents when using advanced search.|
|
||||
|
||||
Search the expression in the specified scope. These scopes are supported: `projects`, `issues`, `merge_requests`, `milestones`, `snippet_titles`, `users`.
|
||||
|
||||
If Elasticsearch is enabled additional scopes available are `blobs`, `wiki_blobs`, `notes`, and `commits`. Find more about [the feature](../integration/advanced_search/elasticsearch.md). **(PREMIUM)**
|
||||
|
||||
The response depends on the requested scope.
|
||||
| Attribute | Type | Required | Description |
|
||||
| ------------- | -------- | ---------- | ------------|
|
||||
| `scope` | string | Yes | The scope to search in. Values include `projects`, `issues`, `merge_requests`, `milestones`, `snippet_titles`, `users`. [Additional scopes](#additional-scopes): `blobs`, `commits`, `notes`, `wiki_blobs`. |
|
||||
| `search` | string | Yes | The search query. |
|
||||
| `confidential` | boolean | No | Filter by confidentiality. Supports `issues` scope; other scopes are ignored. |
|
||||
| `order_by` | string | No | Allowed values are `created_at` only. If not set, results are sorted by `created_at` in descending order for basic search, or by the most relevant documents for Advanced Search.|
|
||||
| `sort` | string | No | Allowed values are `asc` or `desc` only. If not set, results are sorted by `created_at` in descending order for basic search, or by the most relevant documents for Advanced Search.|
|
||||
| `state` | string | No | Filter by state. Supports `issues` and `merge_requests` scopes; other scopes are ignored. |
|
||||
|
||||
### Scope: `projects`
|
||||
|
||||
|
@ -129,7 +131,7 @@ Example response:
|
|||
```
|
||||
|
||||
NOTE:
|
||||
`assignee` column is deprecated, now we show it as a single-sized array `assignees` to conform to the GitLab EE API.
|
||||
The `assignee` column is deprecated. It is shown as a single-sized array `assignees` to conform to the GitLab EE API.
|
||||
|
||||
### Scope: `merge_requests`
|
||||
|
||||
|
@ -432,27 +434,23 @@ Example response:
|
|||
|
||||
## Group Search API
|
||||
|
||||
Search in the specified group.
|
||||
Search for an expression in the specified group.
|
||||
|
||||
If a user is not a member of a group and the group is private, a `GET` request on that group results in a `404` status code.
|
||||
If a user is not a member of a group and the group is private, a `GET` request on that group results in a `404 Not Found` status code.
|
||||
|
||||
```plaintext
|
||||
GET /groups/:id/search
|
||||
```
|
||||
|
||||
| Attribute | Type | Required | Description |
|
||||
| ------------------- | ---------------- | ---------- | ---------------------------------------------------------------------------------------|
|
||||
| `id` | integer/string | yes | The ID or [URL-encoded path of the group](index.md#namespaced-path-encoding) owned by the authenticated user |
|
||||
| `scope` | string | yes | The scope to search in |
|
||||
| `search` | string | yes | The search query |
|
||||
| `state` | string | no | Filter by state. Issues and merge requests are supported; it is ignored for other scopes. |
|
||||
| `confidential` | boolean | no | Filter by confidentiality. Issues scope is supported; it is ignored for other scopes. |
|
||||
| `order_by` | string | no | Allowed values are `created_at` only. If this is not set, the results are either sorted by `created_at` in descending order for basic search, or by the most relevant documents when using advanced search.|
|
||||
| `sort` | string | no | Allowed values are `asc` or `desc` only. If this is not set, the results are either sorted by `created_at` in descending order for basic search, or by the most relevant documents when using advanced search.|
|
||||
|
||||
Search the expression in the specified scope. These scopes are supported: `projects`, `issues`, `merge_requests`, `milestones`, `users`.
|
||||
|
||||
If Elasticsearch is enabled additional scopes available are `blobs`, `wiki_blobs`, `notes`, and `commits`. Find more about [the feature](../integration/advanced_search/elasticsearch.md). **(PREMIUM)**
|
||||
| Attribute | Type | Required | Description |
|
||||
| --------- | ---- | -------- | -------------|
|
||||
| `id` | integer or string | Yes | The ID or [URL-encoded path of the group](index.md#namespaced-path-encoding) owned by the authenticated user. |
|
||||
| `scope` | string | Yes | The scope to search in. Values include `issues`, `merge_requests`, `milestones`, `projects`, `users`. [Additional scopes](#additional-scopes): `blobs`, `commits`, `notes`, `wiki_blobs`. |
|
||||
| `search` | string | Yes | The search query. |
|
||||
| `confidential` | boolean | No | Filter by confidentiality. Supports only `issues` scope; other scopes are ignored. |
|
||||
| `order_by` | string | No | Allowed values are `created_at` only. If not set, results are sorted by `created_at` in descending order for basic search, or by the most relevant documents for Advanced Search.|
|
||||
| `sort` | string | No | Allowed values are `asc` or `desc` only. If not set, results are sorted by `created_at` in descending order for basic search, or by the most relevant documents for Advanced Search.|
|
||||
| `state` | string | No | Filter by state. Supports `issues` and `merge_requests` only; other scopes are ignored. |
|
||||
|
||||
The response depends on the requested scope.
|
||||
|
||||
|
@ -824,7 +822,7 @@ Example response:
|
|||
|
||||
## Project Search API
|
||||
|
||||
Search in the specified project.
|
||||
Search for an expression in the specified project.
|
||||
|
||||
If a user is not a member of a project and the project is private, a `GET` request on that project results in a `404` status code.
|
||||
|
||||
|
@ -832,18 +830,16 @@ If a user is not a member of a project and the project is private, a `GET` reque
|
|||
GET /projects/:id/search
|
||||
```
|
||||
|
||||
| Attribute | Type | Required | Description |
|
||||
| ------------------- | ---------------- | ---------- | ---------------------------------------------------------------------------------------|
|
||||
| `id` | integer/string | yes | The ID or [URL-encoded path of the project](index.md#namespaced-path-encoding) owned by the authenticated user |
|
||||
| `scope` | string | yes | The scope to search in |
|
||||
| `search` | string | yes | The search query |
|
||||
| `ref` | string | no | The name of a repository branch or tag to search on. The project's default branch is used by default. This is only applicable for scopes: `commits`, `blobs`, and `wiki_blobs`. |
|
||||
| `state` | string | no | Filter by state. Issues and merge requests are supported; it is ignored for other scopes. |
|
||||
| `confidential` | boolean | no | Filter by confidentiality. Issues scope is supported; it is ignored for other scopes. |
|
||||
| `order_by` | string | no | Allowed values are `created_at` only. If this is not set, the results are either sorted by `created_at` in descending order for basic search, or by the most relevant documents when using advanced search.|
|
||||
| `sort` | string | no | Allowed values are `asc` or `desc` only. If this is not set, the results are either sorted by `created_at` in descending order for basic search, or by the most relevant documents when using advanced search.|
|
||||
|
||||
Search the expression in the specified scope. These scopes are supported: `issues`, `merge_requests`, `milestones`, `notes`, `wiki_blobs`, `commits`, `blobs`, `users`.
|
||||
| Attribute | Type | Required | Description |
|
||||
| --------- | ---- | -------- | ------------|
|
||||
| `id` | integer or string | Yes | The ID or [URL-encoded path of the project](index.md#namespaced-path-encoding) owned by the authenticated user. |
|
||||
| `scope` | string | Yes | The scope to search in. Values include `blobs`, `commits`, `issues`, `merge_requests`, `milestones`, `notes`, `users`, and `wiki_blobs`. |
|
||||
| `search` | string | Yes | The search query. |
|
||||
| `confidential` | boolean | No | Filter by confidentiality. Supports `issues` scope; other scopes are ignored. |
|
||||
| `ref` | string | No | The name of a repository branch or tag to search on. The project's default branch is used by default. Applicable only for scopes `blobs`, `commits`, and `wiki_blobs`. |
|
||||
| `order_by` | string | No | Allowed values are `created_at` only. If not set, results are sorted by `created_at` in descending order for basic search, or by the most relevant documents for Advanced Search.|
|
||||
| `sort` | string | No | Allowed values are `asc` or `desc` only. If not set, results are sorted by `created_at` in descending order for basic search, or by the most relevant documents for Advanced Search.|
|
||||
| `state` | string | No | Filter by state. Supports the `issues` and `merge_requests` scopes; other scopes are ignored. |
|
||||
|
||||
The response depends on the requested scope.
|
||||
|
||||
|
@ -1144,9 +1140,9 @@ This scope is available only if [Elasticsearch](../integration/advanced_search/e
|
|||
|
||||
Filters are available for this scope:
|
||||
|
||||
- filename
|
||||
- path
|
||||
- extension
|
||||
- Filename
|
||||
- Path
|
||||
- Extension
|
||||
|
||||
To use a filter, include it in your query. For example: `a query filename:some_name*`.
|
||||
You may use wildcards (`*`) to use glob matching.
|
||||
|
|
|
@ -234,6 +234,23 @@ Image URLs are not rewritten if:
|
|||
|
||||
For more information about supported events for Webhooks, go to [Webhook events](webhook_events.md).
|
||||
|
||||
## Delivery headers
|
||||
|
||||
> `X-Gitlab-Instance` header introduced in GitLab 15.5 [with a flag](../../../administration/feature_flags.md) named `webhooks_gitlab_instance_header`. Disabled by default.
|
||||
|
||||
FLAG:
|
||||
On self-managed GitLab, by default this feature is not available. To make it available,
|
||||
ask an administrator to [enable the feature flag](../../../administration/feature_flags.md) named `webhooks_gitlab_instance_header`.
|
||||
The feature is not ready for production use.
|
||||
|
||||
Webhook requests to your endpoint include the following headers:
|
||||
|
||||
| Header | Description | Example |
|
||||
| ------ | ------ | ------ |
|
||||
| `User-Agent` | In the format `"Gitlab/<VERSION>"`. | `"GitLab/15.5.0-pre"` |
|
||||
| `X-Gitlab-Event` | Name of the webhook type. Corresponds to [event types](webhook_events.md) but in the format `"<EVENT> Hook"`. | `"Push Hook"` |
|
||||
| `X-Gitlab-Instance` | Hostname of the GitLab instance that sent the webhook. | `"https://gitlab.com"` |
|
||||
|
||||
## Troubleshoot webhooks
|
||||
|
||||
> **Recent events** for group webhooks [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/325642) in GitLab 15.3.
|
||||
|
|
|
@ -124,7 +124,11 @@ module Gitlab
|
|||
# - https://docs.microsoft.com/en-us/azure/postgresql/flexible-server/concepts-servers
|
||||
# - https://docs.microsoft.com/en-us/azure/postgresql/concepts-servers#managing-your-server
|
||||
# this database is present on both Flexible and Single server, so we should check the former first.
|
||||
'Azure Database for PostgreSQL - Single Server' => { statement: "SELECT datname FROM pg_database WHERE datname = 'azure_maintenance'" }
|
||||
'Azure Database for PostgreSQL - Single Server' => { statement: "SELECT datname FROM pg_database WHERE datname = 'azure_maintenance'" },
|
||||
# Based on
|
||||
# - https://cloud.google.com/sql/docs/postgres/flags
|
||||
# running a query to detect flag names that begin with 'alloydb
|
||||
'AlloyDB for PostgreSQL' => { statement: "SELECT name FROM pg_settings WHERE name LIKE 'alloydb%'" }
|
||||
}.each do |flavor, conditions|
|
||||
return flavor if connection.execute(conditions[:statement]).to_a.present?
|
||||
rescue ActiveRecord::StatementInvalid => e
|
||||
|
|
|
@ -107,6 +107,8 @@ module Gitlab
|
|||
end
|
||||
|
||||
def restart_sidekiq
|
||||
return if Feature.enabled?(:sidekiq_memory_killer_read_only_mode, type: :ops)
|
||||
|
||||
# Tell Sidekiq to stop fetching new jobs
|
||||
# We first SIGNAL and then wait given time
|
||||
# We also monitor a number of running jobs and allow to restart early
|
||||
|
|
|
@ -3,5 +3,6 @@
|
|||
module Gitlab
|
||||
module WebHooks
|
||||
GITLAB_EVENT_HEADER = 'X-Gitlab-Event'
|
||||
GITLAB_INSTANCE_HEADER = 'X-Gitlab-Instance'
|
||||
end
|
||||
end
|
||||
|
|
|
@ -18703,6 +18703,9 @@ msgstr ""
|
|||
msgid "GroupRoadmap|Loading epics"
|
||||
msgstr ""
|
||||
|
||||
msgid "GroupRoadmap|New epic"
|
||||
msgstr ""
|
||||
|
||||
msgid "GroupRoadmap|No start and end date"
|
||||
msgstr ""
|
||||
|
||||
|
@ -18739,6 +18742,9 @@ msgstr ""
|
|||
msgid "GroupRoadmap|To widen your search, change or remove filters; from %{startDate} to %{endDate}."
|
||||
msgstr ""
|
||||
|
||||
msgid "GroupRoadmap|View epics list"
|
||||
msgstr ""
|
||||
|
||||
msgid "GroupRoadmap|Within 3 years"
|
||||
msgstr ""
|
||||
|
||||
|
@ -19300,6 +19306,12 @@ msgstr ""
|
|||
msgid "Groups|Learn more"
|
||||
msgstr ""
|
||||
|
||||
msgid "Groups|Learn more about subgroups"
|
||||
msgstr ""
|
||||
|
||||
msgid "Groups|Members, projects, trials, and paid subscriptions are tied to a specific top-level group. If you are already a member of a top-level group, you can create a subgroup so your new work is part of your existing top-level group. Do you want to create a subgroup instead?"
|
||||
msgstr ""
|
||||
|
||||
msgid "Groups|Must start with letter, digit, emoji, or underscore. Can also contain periods, dashes, spaces, and parentheses."
|
||||
msgstr ""
|
||||
|
||||
|
@ -19318,6 +19330,9 @@ msgstr ""
|
|||
msgid "Groups|Subgroup slug"
|
||||
msgstr ""
|
||||
|
||||
msgid "Groups|You're creating a new top-level group"
|
||||
msgstr ""
|
||||
|
||||
msgid "Guideline"
|
||||
msgstr ""
|
||||
|
||||
|
@ -43932,9 +43947,6 @@ msgstr ""
|
|||
msgid "View entire blame"
|
||||
msgstr ""
|
||||
|
||||
msgid "View epics list"
|
||||
msgstr ""
|
||||
|
||||
msgid "View exposed artifact"
|
||||
msgid_plural "View %d exposed artifacts"
|
||||
msgstr[0] ""
|
||||
|
|
|
@ -52,8 +52,8 @@
|
|||
"@codesandbox/sandpack-client": "^1.2.2",
|
||||
"@gitlab/at.js": "1.5.7",
|
||||
"@gitlab/favicon-overlay": "2.0.0",
|
||||
"@gitlab/svgs": "3.3.0",
|
||||
"@gitlab/ui": "43.17.1",
|
||||
"@gitlab/svgs": "3.4.0",
|
||||
"@gitlab/ui": "43.18.0",
|
||||
"@gitlab/visual-review-tools": "1.7.3",
|
||||
"@gitlab/web-ide": "0.0.1-dev-20220815034418",
|
||||
"@rails/actioncable": "6.1.4-7",
|
||||
|
|
32
scripts/build_qa_image
Executable file
32
scripts/build_qa_image
Executable file
|
@ -0,0 +1,32 @@
|
|||
#!/bin/sh
|
||||
|
||||
QA_IMAGE_NAME="gitlab-ee-qa"
|
||||
|
||||
if [ "${CI_PROJECT_NAME}" == "gitlabhq" ] || [ "${CI_PROJECT_NAME}" == "gitlab-foss" ]; then
|
||||
QA_IMAGE_NAME="gitlab-ce-qa"
|
||||
fi
|
||||
|
||||
# Tag with commit SHA by default
|
||||
QA_IMAGE="${CI_REGISTRY}/${CI_PROJECT_PATH}/${QA_IMAGE_NAME}:${CI_COMMIT_SHA}"
|
||||
# For branches, tag with slugified branch name. For tags, use the tag directly
|
||||
QA_IMAGE_BRANCH="${CI_REGISTRY}/${CI_PROJECT_PATH}/${QA_IMAGE_NAME}:${CI_COMMIT_TAG:-$CI_COMMIT_REF_SLUG}"
|
||||
|
||||
DESTINATIONS="--destination=${QA_IMAGE} --destination=${QA_IMAGE_BRANCH}"
|
||||
|
||||
# Auto-deploy tag format uses first 12 letters of commit SHA. Tag with that
|
||||
# reference also for EE images.
|
||||
if [ "${QA_IMAGE_NAME}" == "gitlab-ee-qa" ]; then
|
||||
QA_IMAGE_FOR_AUTO_DEPLOY="${CI_REGISTRY}/${CI_PROJECT_PATH}/${QA_IMAGE_NAME}:${CI_COMMIT_SHA:0:11}"
|
||||
DESTINATIONS="${DESTINATIONS} --destination=$QA_IMAGE_FOR_AUTO_DEPLOY"
|
||||
fi
|
||||
|
||||
echo "Building QA image for destinations: ${DESTINATIONS}"
|
||||
|
||||
/kaniko/executor \
|
||||
--context="${CI_PROJECT_DIR}" \
|
||||
--dockerfile="${CI_PROJECT_DIR}/qa/Dockerfile" \
|
||||
--build-arg=CHROME_VERSION="${CHROME_VERSION}" \
|
||||
--build-arg=DOCKER_VERSION="${DOCKER_VERSION}" \
|
||||
--build-arg=QA_BUILD_TARGET="${QA_BUILD_TARGET:-qa}" \
|
||||
--cache=true \
|
||||
${DESTINATIONS}
|
32
spec/features/groups/new_group_page_spec.rb
Normal file
32
spec/features/groups/new_group_page_spec.rb
Normal file
|
@ -0,0 +1,32 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'spec_helper'
|
||||
|
||||
RSpec.describe 'New group page', :js do
|
||||
let(:user) { create(:user) }
|
||||
let(:group) { create(:group) }
|
||||
|
||||
before do
|
||||
sign_in(user)
|
||||
end
|
||||
|
||||
describe 'new top level group alert' do
|
||||
context 'when a user visits the new group page' do
|
||||
it 'shows the new top level group alert' do
|
||||
visit new_group_path(anchor: 'create-group-pane')
|
||||
|
||||
expect(page).to have_selector('[data-testid="new-top-level-alert"]')
|
||||
end
|
||||
end
|
||||
|
||||
context 'when a user visits the new sub group page' do
|
||||
let(:parent_group) { create(:group) }
|
||||
|
||||
it 'does not show the new top level group alert' do
|
||||
visit new_group_path(parent_id: parent_group.id, anchor: 'create-group-pane')
|
||||
|
||||
expect(page).not_to have_selector('[data-testid="new-top-level-alert"]')
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,75 @@
|
|||
import { shallowMount } from '@vue/test-utils';
|
||||
import NewTopLevelGroupAlert from '~/groups/components/new_top_level_group_alert.vue';
|
||||
import { makeMockUserCalloutDismisser } from 'helpers/mock_user_callout_dismisser';
|
||||
import { helpPagePath } from '~/helpers/help_page_helper';
|
||||
|
||||
describe('NewTopLevelGroupAlert', () => {
|
||||
let wrapper;
|
||||
let userCalloutDismissSpy;
|
||||
|
||||
const findAlert = () => wrapper.findComponent({ ref: 'newTopLevelAlert' });
|
||||
const createSubGroupPath = '/groups/new?parent_id=1#create-group-pane';
|
||||
|
||||
const createComponent = ({ shouldShowCallout = true } = {}) => {
|
||||
userCalloutDismissSpy = jest.fn();
|
||||
|
||||
wrapper = shallowMount(NewTopLevelGroupAlert, {
|
||||
provide: {
|
||||
createSubGroupPath,
|
||||
},
|
||||
stubs: {
|
||||
UserCalloutDismisser: makeMockUserCalloutDismisser({
|
||||
dismiss: userCalloutDismissSpy,
|
||||
shouldShowCallout,
|
||||
}),
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
beforeEach(() => {
|
||||
createComponent();
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
wrapper.destroy();
|
||||
});
|
||||
|
||||
describe('when the component is created', () => {
|
||||
beforeEach(() => {
|
||||
createComponent({
|
||||
shouldShowCallout: true,
|
||||
});
|
||||
});
|
||||
|
||||
it('renders a button with a link to create a new sub-group', () => {
|
||||
expect(findAlert().props('primaryButtonText')).toBe(
|
||||
NewTopLevelGroupAlert.i18n.primaryBtnText,
|
||||
);
|
||||
expect(findAlert().props('primaryButtonLink')).toBe(
|
||||
helpPagePath('user/group/subgroups/index'),
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('dismissing the alert', () => {
|
||||
beforeEach(() => {
|
||||
findAlert().vm.$emit('dismiss');
|
||||
});
|
||||
|
||||
it('calls the dismiss callback', () => {
|
||||
expect(userCalloutDismissSpy).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
describe('when the alert has been dismissed', () => {
|
||||
beforeEach(() => {
|
||||
createComponent({
|
||||
shouldShowCallout: false,
|
||||
});
|
||||
});
|
||||
|
||||
it('does not show the alert', () => {
|
||||
expect(findAlert().exists()).toBe(false);
|
||||
});
|
||||
});
|
||||
});
|
|
@ -3,15 +3,15 @@
|
|||
exports[`note_app when sort direction is asc shows skeleton notes after the loaded discussions 1`] = `
|
||||
"<ul id=\\"notes-list\\" class=\\"notes main-notes-list timeline\\">
|
||||
<noteable-discussion-stub discussion=\\"[object Object]\\" renderdifffile=\\"true\\" helppagepath=\\"\\" isoverviewtab=\\"true\\"></noteable-discussion-stub>
|
||||
<skeleton-loading-container-stub></skeleton-loading-container-stub>
|
||||
<discussion-filter-note-stub style=\\"display: none;\\"></discussion-filter-note-stub>
|
||||
<skeleton-loading-container-stub class=\\"note-skeleton\\"></skeleton-loading-container-stub>
|
||||
<!---->
|
||||
</ul>"
|
||||
`;
|
||||
|
||||
exports[`note_app when sort direction is desc shows skeleton notes before the loaded discussions 1`] = `
|
||||
"<ul id=\\"notes-list\\" class=\\"notes main-notes-list timeline\\">
|
||||
<skeleton-loading-container-stub></skeleton-loading-container-stub>
|
||||
<skeleton-loading-container-stub class=\\"note-skeleton\\"></skeleton-loading-container-stub>
|
||||
<noteable-discussion-stub discussion=\\"[object Object]\\" renderdifffile=\\"true\\" helppagepath=\\"\\" isoverviewtab=\\"true\\"></noteable-discussion-stub>
|
||||
<discussion-filter-note-stub style=\\"display: none;\\"></discussion-filter-note-stub>
|
||||
<!---->
|
||||
</ul>"
|
||||
`;
|
||||
|
|
|
@ -42,7 +42,7 @@ describe('diff_discussion_header component', () => {
|
|||
expect(props).toMatchObject({
|
||||
src: firstNoteAuthor.avatar_url,
|
||||
alt: firstNoteAuthor.name,
|
||||
size: { default: 24, md: 32 },
|
||||
size: 32,
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -149,7 +149,7 @@ describe('NoteHeader component', () => {
|
|||
it('renders busy status if author availability is set', () => {
|
||||
createComponent({ author: { ...author, availability: AVAILABILITY_STATUS.BUSY } });
|
||||
|
||||
expect(wrapper.find('.js-user-link').text()).toContain('(Busy)');
|
||||
expect(wrapper.find('.note-header-info').text()).toContain('(Busy)');
|
||||
});
|
||||
|
||||
it('renders author status', () => {
|
||||
|
|
|
@ -214,7 +214,7 @@ describe('issue_note', () => {
|
|||
expect(avatarProps.src).toBe(author.avatar_url);
|
||||
expect(avatarProps.entityName).toBe(author.username);
|
||||
expect(avatarProps.alt).toBe(author.name);
|
||||
expect(avatarProps.size).toEqual({ default: 24, md: 32 });
|
||||
expect(avatarProps.size).toEqual(32);
|
||||
});
|
||||
|
||||
it('should render note header content', () => {
|
||||
|
|
|
@ -2,13 +2,12 @@
|
|||
|
||||
exports[`Issue placeholder note component matches snapshot 1`] = `
|
||||
<timeline-entry-item-stub
|
||||
class="note note-wrapper being-posted fade-in-half"
|
||||
class="note note-wrapper note-comment being-posted fade-in-half"
|
||||
>
|
||||
<div
|
||||
class="timeline-icon"
|
||||
class="timeline-avatar gl-float-left"
|
||||
>
|
||||
<gl-avatar-link-stub
|
||||
class="gl-mr-3"
|
||||
href="/root"
|
||||
>
|
||||
<gl-avatar-stub
|
||||
|
@ -16,7 +15,7 @@ exports[`Issue placeholder note component matches snapshot 1`] = `
|
|||
entityid="0"
|
||||
entityname="root"
|
||||
shape="circle"
|
||||
size="[object Object]"
|
||||
size="32"
|
||||
src="mock_path"
|
||||
/>
|
||||
</gl-avatar-link-stub>
|
||||
|
@ -50,16 +49,20 @@ exports[`Issue placeholder note component matches snapshot 1`] = `
|
|||
</div>
|
||||
|
||||
<div
|
||||
class="note-body"
|
||||
class="timeline-discussion-body"
|
||||
>
|
||||
<div
|
||||
class="note-text md"
|
||||
class="note-body"
|
||||
>
|
||||
<p>
|
||||
Foo
|
||||
</p>
|
||||
|
||||
<div
|
||||
class="note-text md"
|
||||
>
|
||||
<p>
|
||||
Foo
|
||||
</p>
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
import { shallowMount } from '@vue/test-utils';
|
||||
import { GlAvatar } from '@gitlab/ui';
|
||||
import Vue from 'vue';
|
||||
import Vuex from 'vuex';
|
||||
import IssuePlaceholderNote from '~/vue_shared/components/notes/placeholder_note.vue';
|
||||
|
@ -53,17 +52,4 @@ describe('Issue placeholder note component', () => {
|
|||
|
||||
expect(findNote().classes()).toContain('discussion');
|
||||
});
|
||||
|
||||
describe('avatar size', () => {
|
||||
it.each`
|
||||
size | line | isOverviewTab
|
||||
${{ default: 24, md: 32 }} | ${null} | ${false}
|
||||
${24} | ${{ line_code: '123' }} | ${false}
|
||||
${{ default: 24, md: 32 }} | ${{ line_code: '123' }} | ${true}
|
||||
`('renders avatar $size for $line and $isOverviewTab', ({ size, line, isOverviewTab }) => {
|
||||
createComponent(false, { line, isOverviewTab });
|
||||
|
||||
expect(wrapper.findComponent(GlAvatar).props('size')).toEqual(size);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
exports[`History Item renders the correct markup 1`] = `
|
||||
<li
|
||||
class="timeline-entry system-note note-wrapper gl-mb-6!"
|
||||
class="timeline-entry system-note note-wrapper"
|
||||
>
|
||||
<div
|
||||
class="timeline-entry-inner"
|
||||
|
@ -22,11 +22,13 @@ exports[`History Item renders the correct markup 1`] = `
|
|||
<div
|
||||
class="note-header"
|
||||
>
|
||||
<span>
|
||||
<div
|
||||
class="note-header-info"
|
||||
>
|
||||
<div
|
||||
data-testid="default-slot"
|
||||
/>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div
|
||||
|
|
|
@ -157,6 +157,12 @@ describe('WorkItemAssignees component', () => {
|
|||
expect(findTokenSelector().props('viewOnly')).toBe(true);
|
||||
});
|
||||
|
||||
it('has a label', () => {
|
||||
createComponent();
|
||||
|
||||
expect(findTokenSelector().props('ariaLabelledby')).toContain('assignees-title-');
|
||||
});
|
||||
|
||||
describe('when clicking outside the token selector', () => {
|
||||
function arrange(args) {
|
||||
createComponent(args);
|
||||
|
|
|
@ -60,6 +60,12 @@ describe('WorkItemLabels component', () => {
|
|||
wrapper.destroy();
|
||||
});
|
||||
|
||||
it('has a label', () => {
|
||||
createComponent();
|
||||
|
||||
expect(findTokenSelector().props('ariaLabelledby')).toContain('labels-title-');
|
||||
});
|
||||
|
||||
it('focuses token selector on token selector input event', async () => {
|
||||
createComponent();
|
||||
findTokenSelector().vm.$emit('input', [mockLabels[0]]);
|
||||
|
|
|
@ -51,7 +51,7 @@ describe('Work Item type component', () => {
|
|||
});
|
||||
|
||||
it('renders the icon in gray color', () => {
|
||||
expect(findIcon().classes()).toContain('gl-text-gray-500');
|
||||
expect(findIcon().classes()).toContain('gl-text-secondary');
|
||||
});
|
||||
|
||||
it('shows tooltip on hover when props passed', () => {
|
||||
|
|
|
@ -314,6 +314,12 @@ RSpec.describe Gitlab::Database::Reflection do
|
|||
expect(database.flavor).to eq('Azure Database for PostgreSQL - Single Server')
|
||||
end
|
||||
|
||||
it 'recognizes AlloyDB for PostgreSQL' do
|
||||
stub_statements("SELECT name FROM pg_settings WHERE name LIKE 'alloydb%'")
|
||||
|
||||
expect(database.flavor).to eq('AlloyDB for PostgreSQL')
|
||||
end
|
||||
|
||||
it 'returns nil if can not recognize the flavor' do
|
||||
expect(database.flavor).to be_nil
|
||||
end
|
||||
|
|
|
@ -235,40 +235,56 @@ RSpec.describe Gitlab::SidekiqDaemon::MemoryKiller do
|
|||
|
||||
subject { memory_killer.send(:restart_sidekiq) }
|
||||
|
||||
before do
|
||||
stub_const("#{described_class}::SHUTDOWN_TIMEOUT_SECONDS", shutdown_timeout_seconds)
|
||||
allow(Sidekiq).to receive(:options).and_return(timeout: 9)
|
||||
allow(memory_killer).to receive(:get_rss).and_return(100)
|
||||
allow(memory_killer).to receive(:get_soft_limit_rss).and_return(200)
|
||||
allow(memory_killer).to receive(:get_hard_limit_rss).and_return(300)
|
||||
context 'when sidekiq_memory_killer_read_only_mode is enabled' do
|
||||
before do
|
||||
stub_feature_flags(sidekiq_memory_killer_read_only_mode: true)
|
||||
end
|
||||
|
||||
it 'does not send signal' do
|
||||
expect(memory_killer).not_to receive(:refresh_state)
|
||||
expect(memory_killer).not_to receive(:signal_and_wait)
|
||||
|
||||
subject
|
||||
end
|
||||
end
|
||||
|
||||
it 'send signal' do
|
||||
expect(memory_killer).to receive(:refresh_state)
|
||||
.with(:stop_fetching_new_jobs)
|
||||
.ordered
|
||||
.and_call_original
|
||||
expect(memory_killer).to receive(:signal_and_wait)
|
||||
.with(shutdown_timeout_seconds, 'SIGTSTP', 'stop fetching new jobs')
|
||||
.ordered
|
||||
context 'when sidekiq_memory_killer_read_only_mode is disabled' do
|
||||
before do
|
||||
stub_const("#{described_class}::SHUTDOWN_TIMEOUT_SECONDS", shutdown_timeout_seconds)
|
||||
stub_feature_flags(sidekiq_memory_killer_read_only_mode: false)
|
||||
allow(Sidekiq).to receive(:options).and_return(timeout: 9)
|
||||
allow(memory_killer).to receive(:get_rss).and_return(100)
|
||||
allow(memory_killer).to receive(:get_soft_limit_rss).and_return(200)
|
||||
allow(memory_killer).to receive(:get_hard_limit_rss).and_return(300)
|
||||
end
|
||||
|
||||
expect(memory_killer).to receive(:refresh_state)
|
||||
.with(:shutting_down)
|
||||
.ordered
|
||||
.and_call_original
|
||||
expect(memory_killer).to receive(:signal_and_wait)
|
||||
.with(11, 'SIGTERM', 'gracefully shut down')
|
||||
.ordered
|
||||
it 'send signal' do
|
||||
expect(memory_killer).to receive(:refresh_state)
|
||||
.with(:stop_fetching_new_jobs)
|
||||
.ordered
|
||||
.and_call_original
|
||||
expect(memory_killer).to receive(:signal_and_wait)
|
||||
.with(shutdown_timeout_seconds, 'SIGTSTP', 'stop fetching new jobs')
|
||||
.ordered
|
||||
|
||||
expect(memory_killer).to receive(:refresh_state)
|
||||
.with(:killing_sidekiq)
|
||||
.ordered
|
||||
.and_call_original
|
||||
expect(memory_killer).to receive(:signal_pgroup)
|
||||
.with('SIGKILL', 'die')
|
||||
.ordered
|
||||
expect(memory_killer).to receive(:refresh_state)
|
||||
.with(:shutting_down)
|
||||
.ordered
|
||||
.and_call_original
|
||||
expect(memory_killer).to receive(:signal_and_wait)
|
||||
.with(11, 'SIGTERM', 'gracefully shut down')
|
||||
.ordered
|
||||
|
||||
subject
|
||||
expect(memory_killer).to receive(:refresh_state)
|
||||
.with(:killing_sidekiq)
|
||||
.ordered
|
||||
.and_call_original
|
||||
expect(memory_killer).to receive(:signal_pgroup)
|
||||
.with('SIGKILL', 'die')
|
||||
.ordered
|
||||
|
||||
subject
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -75,7 +75,8 @@ RSpec.describe WebHookService, :request_store, :clean_gitlab_redis_shared_state
|
|||
'Content-Type' => 'application/json',
|
||||
'User-Agent' => "GitLab/#{Gitlab::VERSION}",
|
||||
'X-Gitlab-Event' => 'Push Hook',
|
||||
'X-Gitlab-Event-UUID' => uuid
|
||||
'X-Gitlab-Event-UUID' => uuid,
|
||||
'X-Gitlab-Instance' => Gitlab.config.gitlab.base_url
|
||||
}
|
||||
end
|
||||
|
||||
|
@ -164,7 +165,7 @@ RSpec.describe WebHookService, :request_store, :clean_gitlab_redis_shared_state
|
|||
end
|
||||
end
|
||||
|
||||
it 'POSTs the data as JSON' do
|
||||
it 'POSTs the data as JSON and returns expected headers' do
|
||||
stub_full_request(project_hook.url, method: :post)
|
||||
|
||||
service_instance.execute
|
||||
|
@ -174,6 +175,22 @@ RSpec.describe WebHookService, :request_store, :clean_gitlab_redis_shared_state
|
|||
).once
|
||||
end
|
||||
|
||||
context 'when webhooks_gitlab_instance_header flag is disabled' do
|
||||
before do
|
||||
stub_feature_flags(webhooks_gitlab_instance_header: false)
|
||||
end
|
||||
|
||||
it 'excludes the X-Gitlab-Instance header' do
|
||||
stub_full_request(project_hook.url, method: :post)
|
||||
|
||||
service_instance.execute
|
||||
|
||||
expect(WebMock).to have_requested(:post, stubbed_hostname(project_hook.url)).with(
|
||||
headers: headers.except('X-Gitlab-Instance')
|
||||
).once
|
||||
end
|
||||
end
|
||||
|
||||
context 'when the data is a Gitlab::DataBuilder::Pipeline' do
|
||||
let(:pipeline) { create(:ci_pipeline, project: project) }
|
||||
let(:data) { ::Gitlab::DataBuilder::Pipeline.new(pipeline) }
|
||||
|
|
16
yarn.lock
16
yarn.lock
|
@ -1059,15 +1059,15 @@
|
|||
stylelint-declaration-strict-value "1.8.0"
|
||||
stylelint-scss "4.2.0"
|
||||
|
||||
"@gitlab/svgs@3.3.0":
|
||||
version "3.3.0"
|
||||
resolved "https://registry.yarnpkg.com/@gitlab/svgs/-/svgs-3.3.0.tgz#99b044484fcf3d5a6431281e320e2405540ff5a9"
|
||||
integrity sha512-S8Hqf+ms8aNrSgmci9SVoIyj/0qQnizU5uV5vUPAOwiufMDFDyI5qfcgn4EYZ6mnju3LiO+ReSL/PPTD4qNgHA==
|
||||
"@gitlab/svgs@3.4.0":
|
||||
version "3.4.0"
|
||||
resolved "https://registry.yarnpkg.com/@gitlab/svgs/-/svgs-3.4.0.tgz#cfc8319e259e5914ad0f48ee0ab6e0eec75d03da"
|
||||
integrity sha512-myCYbjViOI2k6oHGRqL1iKaMKbYvPqWL6tYZ07QkUKziVz5kYjECWk5c0Qp6yu9NsFAMWuow5PkR3oFTGBHmbg==
|
||||
|
||||
"@gitlab/ui@43.17.1":
|
||||
version "43.17.1"
|
||||
resolved "https://registry.yarnpkg.com/@gitlab/ui/-/ui-43.17.1.tgz#0b667f1f2dd8010d0a178d0b231641ab5a1ff7dd"
|
||||
integrity sha512-/vHNW6WbznJM19ti+1Li88+MIXUFnNjAoJjmxXV36h93BNMSzTnUSQi6mGmMbklOkSbHMsS6ilyA9hh63ggsoA==
|
||||
"@gitlab/ui@43.18.0":
|
||||
version "43.18.0"
|
||||
resolved "https://registry.yarnpkg.com/@gitlab/ui/-/ui-43.18.0.tgz#7c412eebe362052dae811502586e1fd100c28be0"
|
||||
integrity sha512-hAyBjYQtOFbVWt4XhUBgth/OtNg2cTQ7KMv0JSLLTnvrrrASJu0Li1ROaat81YsT+kGWytM/Fgr283ISNzy/vw==
|
||||
dependencies:
|
||||
"@popperjs/core" "^2.11.2"
|
||||
bootstrap-vue "2.20.1"
|
||||
|
|
Loading…
Reference in a new issue