Add latest changes from gitlab-org/gitlab@master

This commit is contained in:
GitLab Bot 2022-03-04 18:20:01 +00:00
parent 73e15fde38
commit 698fe342b9
107 changed files with 1394 additions and 950 deletions

View File

@ -1,11 +1,13 @@
import $ from 'jquery'; import $ from 'jquery';
import { memoize, throttle } from 'lodash'; import { memoize, throttle } from 'lodash';
import createEventHub from '~/helpers/event_hub_factory';
class DirtySubmitForm { class DirtySubmitForm {
constructor(form) { constructor(form) {
this.form = form; this.form = form;
this.dirtyInputs = []; this.dirtyInputs = [];
this.isDisabled = true; this.isDisabled = true;
this.events = createEventHub();
this.init(); this.init();
} }
@ -36,11 +38,21 @@ class DirtySubmitForm {
this.form.addEventListener('submit', (event) => this.formSubmit(event)); this.form.addEventListener('submit', (event) => this.formSubmit(event));
} }
addInputsListener(callback) {
this.events.$on('input', callback);
}
removeInputsListener(callback) {
this.events.$off('input', callback);
}
updateDirtyInput(event) { updateDirtyInput(event) {
const { target } = event; const { target } = event;
if (!target.dataset.isDirtySubmitInput) return; if (!target.dataset.isDirtySubmitInput) return;
this.events.$emit('input', event);
this.updateDirtyInputs(target); this.updateDirtyInputs(target);
this.toggleSubmission(); this.toggleSubmission();
} }

View File

@ -92,6 +92,9 @@ export default {
hasUpstreamPipelines() { hasUpstreamPipelines() {
return Boolean(this.pipeline?.upstream?.length > 0); return Boolean(this.pipeline?.upstream?.length > 0);
}, },
isMultiProjectVizAvailable() {
return Boolean(this.pipeline?.user?.namespace?.crossProjectPipelineAvailable);
},
isStageView() { isStageView() {
return this.viewType === STAGE_VIEW; return this.viewType === STAGE_VIEW;
}, },
@ -178,6 +181,7 @@ export default {
<linked-pipelines-column <linked-pipelines-column
v-if="showUpstreamPipelines" v-if="showUpstreamPipelines"
:config-paths="configPaths" :config-paths="configPaths"
:is-multi-project-viz-available="isMultiProjectVizAvailable"
:linked-pipelines="upstreamPipelines" :linked-pipelines="upstreamPipelines"
:column-title="__('Upstream')" :column-title="__('Upstream')"
:show-links="showJobLinks" :show-links="showJobLinks"
@ -226,6 +230,7 @@ export default {
v-if="showDownstreamPipelines" v-if="showDownstreamPipelines"
class="gl-mr-6" class="gl-mr-6"
:config-paths="configPaths" :config-paths="configPaths"
:is-multi-project-viz-available="isMultiProjectVizAvailable"
:linked-pipelines="downstreamPipelines" :linked-pipelines="downstreamPipelines"
:column-title="__('Downstream')" :column-title="__('Downstream')"
:show-links="showJobLinks" :show-links="showJobLinks"

View File

@ -1,12 +1,29 @@
<script> <script>
import { GlBadge, GlButton, GlLink, GlLoadingIcon, GlTooltipDirective } from '@gitlab/ui'; import {
GlBadge,
GlButton,
GlLink,
GlLoadingIcon,
GlPopover,
GlSprintf,
GlTooltipDirective,
} from '@gitlab/ui';
import TierBadge from '~/vue_shared/components/tier_badge.vue';
import { BV_HIDE_TOOLTIP } from '~/lib/utils/constants'; import { BV_HIDE_TOOLTIP } from '~/lib/utils/constants';
import { __, sprintf } from '~/locale'; import { __, s__, sprintf } from '~/locale';
import CiStatus from '~/vue_shared/components/ci_icon.vue'; import CiStatus from '~/vue_shared/components/ci_icon.vue';
import { reportToSentry } from '../../utils'; import { reportToSentry } from '../../utils';
import { DOWNSTREAM, UPSTREAM } from './constants'; import { DOWNSTREAM, UPSTREAM } from './constants';
export default { export default {
i18n: {
popover: {
title: s__('Pipelines|Multi-project pipeline graphs'),
description: s__(
'Pipelines|Gitlab Premium users have access to the multi-project pipeline graph to improve the visualization of these pipelines. %{linkStart}Learn More%{linkEnd}',
),
},
},
directives: { directives: {
GlTooltip: GlTooltipDirective, GlTooltip: GlTooltipDirective,
}, },
@ -16,7 +33,11 @@ export default {
GlButton, GlButton,
GlLink, GlLink,
GlLoadingIcon, GlLoadingIcon,
GlPopover,
GlSprintf,
TierBadge,
}, },
inject: ['multiProjectHelpPath'],
props: { props: {
columnTitle: { columnTitle: {
type: String, type: String,
@ -26,6 +47,10 @@ export default {
type: Boolean, type: Boolean,
required: true, required: true,
}, },
isMultiProjectVizAvailable: {
type: Boolean,
required: true,
},
isLoading: { isLoading: {
type: Boolean, type: Boolean,
required: true, required: true,
@ -90,6 +115,9 @@ export default {
pipelineStatus() { pipelineStatus() {
return this.pipeline.status; return this.pipeline.status;
}, },
popoverContainerId() {
return `popoverContainer-${this.pipeline.id}`;
},
projectName() { projectName() {
return this.pipeline.project.name; return this.pipeline.project.name;
}, },
@ -128,16 +156,21 @@ export default {
<template> <template>
<div <div
ref="linkedPipeline"
v-gl-tooltip
class="gl-h-full gl-display-flex! gl-border-solid gl-border-gray-100 gl-border-1" class="gl-h-full gl-display-flex! gl-border-solid gl-border-gray-100 gl-border-1"
:class="flexDirection" :class="flexDirection"
:title="tooltipText"
data-qa-selector="child_pipeline" data-qa-selector="child_pipeline"
data-testid="linkedPipeline"
@mouseover="onDownstreamHovered" @mouseover="onDownstreamHovered"
@mouseleave="onDownstreamHoverLeave" @mouseleave="onDownstreamHoverLeave"
> >
<div class="gl-w-full gl-bg-white gl-p-3" :class="cardSpacingClass"> <div
v-gl-tooltip
class="gl-w-full gl-bg-white gl-p-3"
:class="cardSpacingClass"
data-testid="linkedPipelineBody"
data-qa-selector="linked_pipeline_body"
:title="tooltipText"
>
<div class="gl-display-flex gl-pr-3"> <div class="gl-display-flex gl-pr-3">
<ci-status <ci-status
v-if="!pipelineIsLoading" v-if="!pipelineIsLoading"
@ -163,17 +196,38 @@ export default {
</gl-badge> </gl-badge>
</div> </div>
</div> </div>
<div class="gl-display-flex"> <div :id="popoverContainerId" class="gl-display-flex">
<gl-button <gl-button
:id="buttonId" :id="buttonId"
class="gl-shadow-none! gl-rounded-0!" class="gl-shadow-none! gl-rounded-0!"
:class="`js-pipeline-expand-${pipeline.id} ${buttonBorderClass}`" :class="`js-pipeline-expand-${pipeline.id} ${buttonBorderClass}`"
:icon="expandedIcon" :icon="expandedIcon"
:aria-label="__('Expand pipeline')" :aria-label="__('Expand pipeline')"
:disabled="!isMultiProjectVizAvailable"
data-testid="expand-pipeline-button" data-testid="expand-pipeline-button"
data-qa-selector="expand_pipeline_button" data-qa-selector="expand_pipeline_button"
@click="onClickLinkedPipeline" @click="onClickLinkedPipeline"
/> />
<gl-popover
v-if="!isMultiProjectVizAvailable"
placement="top"
:target="popoverContainerId"
triggers="hover"
>
<template #title>
<b>{{ $options.i18n.popover.title }}</b>
<tier-badge class="gl-mt-3" tier="premium"
/></template>
<p class="gl-my-0">
<gl-sprintf :message="$options.i18n.popover.description">
<template #link="{ content }"
><gl-link :href="multiProjectHelpPath" class="gl-font-sm" target="_blank">{{
content
}}</gl-link>
</template>
</gl-sprintf>
</p>
</gl-popover>
</div> </div>
</div> </div>
</template> </template>

View File

@ -28,6 +28,10 @@ export default {
required: true, required: true,
validator: validateConfigPaths, validator: validateConfigPaths,
}, },
isMultiProjectVizAvailable: {
type: Boolean,
required: true,
},
linkedPipelines: { linkedPipelines: {
type: Array, type: Array,
required: true, required: true,
@ -208,6 +212,7 @@ export default {
<linked-pipeline <linked-pipeline
class="gl-display-inline-block" class="gl-display-inline-block"
:is-loading="isLoadingPipeline(pipeline.id)" :is-loading="isLoadingPipeline(pipeline.id)"
:is-multi-project-viz-available="isMultiProjectVizAvailable"
:pipeline="pipeline" :pipeline="pipeline"
:column-title="columnTitle" :column-title="columnTitle"
:type="type" :type="type"

View File

@ -60,6 +60,15 @@ export default {
iid: this.pipelineIid, iid: this.pipelineIid,
}; };
}, },
loading() {
return this.$apollo.queries.jobs.loading;
},
showSkeletonLoader() {
return this.firstLoad && this.loading;
},
showLoadingSpinner() {
return !this.firstLoad && this.loading;
},
}, },
mounted() { mounted() {
eventHub.$on('jobActionPerformed', this.handleJobAction); eventHub.$on('jobActionPerformed', this.handleJobAction);
@ -69,7 +78,7 @@ export default {
}, },
methods: { methods: {
handleJobAction() { handleJobAction() {
this.firstLoad = true; this.firstLoad = false;
this.$apollo.queries.jobs.refetch(); this.$apollo.queries.jobs.refetch();
}, },
@ -98,7 +107,7 @@ export default {
<template> <template>
<div> <div>
<div v-if="$apollo.loading && firstLoad" class="gl-mt-5"> <div v-if="showSkeletonLoader" class="gl-mt-5">
<gl-skeleton-loader :width="1248" :height="73"> <gl-skeleton-loader :width="1248" :height="73">
<circle cx="748.031" cy="37.7193" r="15.0307" /> <circle cx="748.031" cy="37.7193" r="15.0307" />
<circle cx="787.241" cy="37.7193" r="15.0307" /> <circle cx="787.241" cy="37.7193" r="15.0307" />
@ -118,7 +127,7 @@ export default {
<jobs-table v-else :jobs="jobs" :table-fields="$options.fields" data-testid="jobs-tab-table" /> <jobs-table v-else :jobs="jobs" :table-fields="$options.fields" data-testid="jobs-tab-table" />
<gl-intersection-observer v-if="jobsPageInfo.hasNextPage" @appear="fetchMoreJobs"> <gl-intersection-observer v-if="jobsPageInfo.hasNextPage" @appear="fetchMoreJobs">
<gl-loading-icon v-if="$apollo.loading" size="md" /> <gl-loading-icon v-if="showLoadingSpinner" size="md" />
</gl-intersection-observer> </gl-intersection-observer>
</div> </div>
</template> </template>

View File

@ -1,8 +1,7 @@
<script> <script>
import { GlIcon, GlLink, GlPopover, GlSprintf, GlTooltipDirective, GlBadge } from '@gitlab/ui'; import { GlIcon, GlLink, GlPopover, GlSprintf, GlTooltipDirective, GlBadge } from '@gitlab/ui';
import { __, sprintf } from '~/locale'; import { __ } from '~/locale';
import { helpPagePath } from '~/helpers/help_page_helper'; import { helpPagePath } from '~/helpers/help_page_helper';
import glFeatureFlagMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
import TooltipOnTruncate from '~/vue_shared/components/tooltip_on_truncate/tooltip_on_truncate.vue'; import TooltipOnTruncate from '~/vue_shared/components/tooltip_on_truncate/tooltip_on_truncate.vue';
import { SCHEDULE_ORIGIN, ICONS } from '../../constants'; import { SCHEDULE_ORIGIN, ICONS } from '../../constants';
@ -18,7 +17,6 @@ export default {
directives: { directives: {
GlTooltip: GlTooltipDirective, GlTooltip: GlTooltipDirective,
}, },
mixins: [glFeatureFlagMixin()],
inject: { inject: {
targetProjectFullPath: { targetProjectFullPath: {
default: '', default: '',
@ -139,91 +137,67 @@ export default {
commitTitle() { commitTitle() {
return this.pipeline?.commit?.title; return this.pipeline?.commit?.title;
}, },
hasAuthor() {
return (
this.commitAuthor?.avatar_url && this.commitAuthor?.path && this.commitAuthor?.username
);
},
userImageAltDescription() {
return this.commitAuthor?.username
? sprintf(__("%{username}'s avatar"), { username: this.commitAuthor.username })
: null;
},
rearrangePipelinesTable() {
return this.glFeatures?.rearrangePipelinesTable;
},
}, },
}; };
</script> </script>
<template> <template>
<div class="pipeline-tags" data-testid="pipeline-url-table-cell"> <div class="pipeline-tags" data-testid="pipeline-url-table-cell">
<template v-if="rearrangePipelinesTable"> <div class="commit-title gl-mb-2" data-testid="commit-title-container">
<div class="commit-title gl-mb-2" data-testid="commit-title-container"> <span v-if="commitTitle" class="gl-display-flex">
<span v-if="commitTitle" class="gl-display-flex"> <tooltip-on-truncate :title="commitTitle" class="gl-flex-grow-1 gl-text-truncate">
<tooltip-on-truncate :title="commitTitle" class="flex-truncate-child gl-flex-grow-1">
<gl-link
:href="commitUrl"
class="commit-row-message gl-text-gray-900"
data-testid="commit-title"
>{{ commitTitle }}</gl-link
>
</tooltip-on-truncate>
</span>
<span v-else>{{ __("Can't find HEAD commit for this branch") }}</span>
</div>
<div class="gl-mb-2">
<gl-link
:href="pipeline.path"
class="gl-text-decoration-underline gl-text-blue-600! gl-mr-3"
data-testid="pipeline-url-link"
data-qa-selector="pipeline_url_link"
>
#{{ pipeline[pipelineKey] }}
</gl-link>
<!--Commit row-->
<div class="icon-container gl-display-inline-block gl-mr-1">
<gl-icon
v-gl-tooltip
:name="commitIcon"
:title="commitIconTooltipTitle"
data-testid="commit-icon-type"
/>
</div>
<tooltip-on-truncate :title="tooltipTitle" truncate-target="child" placement="top">
<gl-link <gl-link
v-if="mergeRequestRef" :href="commitUrl"
:href="mergeRequestRef.path" class="commit-row-message gl-text-gray-900"
class="ref-name gl-mr-3" data-testid="commit-title"
data-testid="merge-request-ref" >{{ commitTitle }}</gl-link
>{{ mergeRequestRef.iid }}</gl-link
> >
<gl-link v-else :href="refUrl" class="ref-name gl-mr-3" data-testid="commit-ref-name">{{
commitRef.name
}}</gl-link>
</tooltip-on-truncate> </tooltip-on-truncate>
</span>
<span v-else>{{ __("Can't find HEAD commit for this branch") }}</span>
</div>
<div class="gl-mb-2">
<gl-link
:href="pipeline.path"
class="gl-text-decoration-underline gl-text-blue-600! gl-mr-3"
data-testid="pipeline-url-link"
data-qa-selector="pipeline_url_link"
>
#{{ pipeline[pipelineKey] }}
</gl-link>
<!--Commit row-->
<div class="icon-container gl-display-inline-block gl-mr-1">
<gl-icon <gl-icon
v-gl-tooltip v-gl-tooltip
name="commit" :name="commitIcon"
class="commit-icon gl-mr-1" :title="commitIconTooltipTitle"
:title="__('Commit')" data-testid="commit-icon-type"
data-testid="commit-icon"
/> />
<gl-link :href="commitUrl" class="commit-sha mr-0" data-testid="commit-short-sha">{{
commitShortSha
}}</gl-link>
<!--End of commit row-->
</div> </div>
</template> <tooltip-on-truncate :title="tooltipTitle" truncate-target="child" placement="top">
<gl-link <gl-link
v-if="!rearrangePipelinesTable" v-if="mergeRequestRef"
:href="pipeline.path" :href="mergeRequestRef.path"
class="gl-text-decoration-underline" class="ref-name gl-mr-3"
data-testid="pipeline-url-link" data-testid="merge-request-ref"
data-qa-selector="pipeline_url_link" >{{ mergeRequestRef.iid }}</gl-link
> >
#{{ pipeline[pipelineKey] }} <gl-link v-else :href="refUrl" class="ref-name gl-mr-3" data-testid="commit-ref-name">{{
</gl-link> commitRef.name
}}</gl-link>
</tooltip-on-truncate>
<gl-icon
v-gl-tooltip
name="commit"
class="commit-icon gl-mr-1"
:title="__('Commit')"
data-testid="commit-icon"
/>
<gl-link :href="commitUrl" class="commit-sha mr-0" data-testid="commit-short-sha">{{
commitShortSha
}}</gl-link>
<!--End of commit row-->
</div>
<div class="label-container gl-mt-1"> <div class="label-container gl-mt-1">
<gl-badge <gl-badge
v-if="isScheduled" v-if="isScheduled"

View File

@ -1,85 +0,0 @@
<script>
import { CHILD_VIEW } from '~/pipelines/constants';
import CommitComponent from '~/vue_shared/components/commit.vue';
export default {
components: {
CommitComponent,
},
props: {
pipeline: {
type: Object,
required: true,
},
viewType: {
type: String,
required: true,
},
},
computed: {
commitAuthor() {
let commitAuthorInformation;
if (!this.pipeline || !this.pipeline.commit) {
return null;
}
// 1. person who is an author of a commit might be a GitLab user
if (this.pipeline.commit.author) {
// 2. if person who is an author of a commit is a GitLab user
// they can have a GitLab avatar
if (this.pipeline.commit.author.avatar_url) {
commitAuthorInformation = this.pipeline.commit.author;
// 3. If GitLab user does not have avatar, they might have a Gravatar
} else if (this.pipeline.commit.author_gravatar_url) {
commitAuthorInformation = {
...this.pipeline.commit.author,
avatar_url: this.pipeline.commit.author_gravatar_url,
};
}
// 4. If committer is not a GitLab User, they can have a Gravatar
} else {
commitAuthorInformation = {
avatar_url: this.pipeline.commit.author_gravatar_url,
path: `mailto:${this.pipeline.commit.author_email}`,
username: this.pipeline.commit.author_name,
};
}
return commitAuthorInformation;
},
commitTag() {
return this.pipeline?.ref?.tag;
},
commitRef() {
return this.pipeline?.ref;
},
commitUrl() {
return this.pipeline?.commit?.commit_path;
},
commitShortSha() {
return this.pipeline?.commit?.short_id;
},
commitTitle() {
return this.pipeline?.commit?.title;
},
isChildView() {
return this.viewType === CHILD_VIEW;
},
},
};
</script>
<template>
<commit-component
:tag="commitTag"
:commit-ref="commitRef"
:commit-url="commitUrl"
:merge-request-ref="pipeline.merge_request"
:short-sha="commitShortSha"
:title="commitTitle"
:author="commitAuthor"
:show-ref-info="!isChildView"
/>
</template>

View File

@ -3,7 +3,6 @@ import CodeQualityWalkthrough from '~/code_quality_walkthrough/components/step.v
import { PIPELINE_STATUSES } from '~/code_quality_walkthrough/constants'; import { PIPELINE_STATUSES } from '~/code_quality_walkthrough/constants';
import { CHILD_VIEW } from '~/pipelines/constants'; import { CHILD_VIEW } from '~/pipelines/constants';
import CiBadge from '~/vue_shared/components/ci_badge_link.vue'; import CiBadge from '~/vue_shared/components/ci_badge_link.vue';
import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
import PipelinesTimeago from './time_ago.vue'; import PipelinesTimeago from './time_ago.vue';
export default { export default {
@ -12,7 +11,6 @@ export default {
CiBadge, CiBadge,
PipelinesTimeago, PipelinesTimeago,
}, },
mixins: [glFeatureFlagsMixin()],
props: { props: {
pipeline: { pipeline: {
type: Object, type: Object,
@ -44,9 +42,6 @@ export default {
codeQualityBuildPath() { codeQualityBuildPath() {
return this.pipeline?.details?.code_quality_build_path; return this.pipeline?.details?.code_quality_build_path;
}, },
rearrangePipelinesTable() {
return this.glFeatures?.rearrangePipelinesTable;
},
}, },
}; };
</script> </script>
@ -61,7 +56,7 @@ export default {
:icon-classes="'gl-vertical-align-middle!'" :icon-classes="'gl-vertical-align-middle!'"
data-qa-selector="pipeline_commit_status" data-qa-selector="pipeline_commit_status"
/> />
<pipelines-timeago v-if="rearrangePipelinesTable" class="gl-mt-3" :pipeline="pipeline" /> <pipelines-timeago class="gl-mt-3" :pipeline="pipeline" />
<code-quality-walkthrough <code-quality-walkthrough
v-if="shouldRenderCodeQualityWalkthrough" v-if="shouldRenderCodeQualityWalkthrough"
:step="codeQualityStep" :step="codeQualityStep"

View File

@ -1,16 +1,13 @@
<script> <script>
import { GlTableLite, GlTooltipDirective } from '@gitlab/ui'; import { GlTableLite, GlTooltipDirective } from '@gitlab/ui';
import { s__, __ } from '~/locale'; import { s__, __ } from '~/locale';
import glFeatureFlagMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
import eventHub from '../../event_hub'; import eventHub from '../../event_hub';
import PipelineMiniGraph from './pipeline_mini_graph.vue'; import PipelineMiniGraph from './pipeline_mini_graph.vue';
import PipelineOperations from './pipeline_operations.vue'; import PipelineOperations from './pipeline_operations.vue';
import PipelineStopModal from './pipeline_stop_modal.vue'; import PipelineStopModal from './pipeline_stop_modal.vue';
import PipelineTriggerer from './pipeline_triggerer.vue'; import PipelineTriggerer from './pipeline_triggerer.vue';
import PipelineUrl from './pipeline_url.vue'; import PipelineUrl from './pipeline_url.vue';
import PipelinesCommit from './pipelines_commit.vue';
import PipelinesStatusBadge from './pipelines_status_badge.vue'; import PipelinesStatusBadge from './pipelines_status_badge.vue';
import PipelinesTimeago from './time_ago.vue';
const DEFAULT_TD_CLASS = 'gl-p-5!'; const DEFAULT_TD_CLASS = 'gl-p-5!';
const HIDE_TD_ON_MOBILE = 'gl-display-none! gl-lg-display-table-cell!'; const HIDE_TD_ON_MOBILE = 'gl-display-none! gl-lg-display-table-cell!';
@ -22,19 +19,16 @@ export default {
GlTableLite, GlTableLite,
LinkedPipelinesMiniList: () => LinkedPipelinesMiniList: () =>
import('ee_component/vue_shared/components/linked_pipelines_mini_list.vue'), import('ee_component/vue_shared/components/linked_pipelines_mini_list.vue'),
PipelinesCommit,
PipelineMiniGraph, PipelineMiniGraph,
PipelineOperations, PipelineOperations,
PipelinesStatusBadge, PipelinesStatusBadge,
PipelineStopModal, PipelineStopModal,
PipelinesTimeago,
PipelineTriggerer, PipelineTriggerer,
PipelineUrl, PipelineUrl,
}, },
directives: { directives: {
GlTooltip: GlTooltipDirective, GlTooltip: GlTooltipDirective,
}, },
mixins: [glFeatureFlagMixin()],
props: { props: {
pipelines: { pipelines: {
type: Array, type: Array,
@ -74,18 +68,16 @@ export default {
key: 'status', key: 'status',
label: s__('Pipeline|Status'), label: s__('Pipeline|Status'),
thClass: DEFAULT_TH_CLASSES, thClass: DEFAULT_TH_CLASSES,
columnClass: this.rearrangePipelinesTable ? 'gl-w-15p' : 'gl-w-10p', columnClass: 'gl-w-15p',
tdClass: DEFAULT_TD_CLASS, tdClass: DEFAULT_TD_CLASS,
thAttr: { 'data-testid': 'status-th' }, thAttr: { 'data-testid': 'status-th' },
}, },
{ {
key: 'pipeline', key: 'pipeline',
label: this.rearrangePipelinesTable ? __('Pipeline') : this.pipelineKeyOption.label, label: __('Pipeline'),
thClass: DEFAULT_TH_CLASSES, thClass: DEFAULT_TH_CLASSES,
tdClass: this.rearrangePipelinesTable tdClass: `${DEFAULT_TD_CLASS}`,
? `${DEFAULT_TD_CLASS}` columnClass: 'gl-w-30p',
: `${DEFAULT_TD_CLASS} ${HIDE_TD_ON_MOBILE}`,
columnClass: this.rearrangePipelinesTable ? 'gl-w-30p' : 'gl-w-10p',
thAttr: { 'data-testid': 'pipeline-th' }, thAttr: { 'data-testid': 'pipeline-th' },
}, },
{ {
@ -96,14 +88,6 @@ export default {
columnClass: 'gl-w-10p', columnClass: 'gl-w-10p',
thAttr: { 'data-testid': 'triggerer-th' }, thAttr: { 'data-testid': 'triggerer-th' },
}, },
{
key: 'commit',
label: s__('Pipeline|Commit'),
thClass: DEFAULT_TH_CLASSES,
tdClass: DEFAULT_TD_CLASS,
columnClass: 'gl-w-20p',
thAttr: { 'data-testid': 'commit-th' },
},
{ {
key: 'stages', key: 'stages',
label: s__('Pipeline|Stages'), label: s__('Pipeline|Stages'),
@ -112,14 +96,6 @@ export default {
columnClass: 'gl-w-quarter', columnClass: 'gl-w-quarter',
thAttr: { 'data-testid': 'stages-th' }, thAttr: { 'data-testid': 'stages-th' },
}, },
{
key: 'timeago',
label: s__('Pipeline|Duration'),
thClass: DEFAULT_TH_CLASSES,
tdClass: DEFAULT_TD_CLASS,
columnClass: this.rearrangePipelinesTable ? 'gl-w-5p' : 'gl-w-15p',
thAttr: { 'data-testid': 'timeago-th' },
},
{ {
key: 'actions', key: 'actions',
thClass: DEFAULT_TH_CLASSES, thClass: DEFAULT_TH_CLASSES,
@ -129,12 +105,7 @@ export default {
}, },
]; ];
return !this.rearrangePipelinesTable return fields;
? fields
: fields.filter((field) => !['commit', 'timeago'].includes(field.key));
},
rearrangePipelinesTable() {
return this.glFeatures?.rearrangePipelinesTable;
}, },
}, },
watch: { watch: {
@ -200,10 +171,6 @@ export default {
<pipeline-triggerer :pipeline="item" /> <pipeline-triggerer :pipeline="item" />
</template> </template>
<template #cell(commit)="{ item }">
<pipelines-commit :pipeline="item" :view-type="viewType" />
</template>
<template #cell(stages)="{ item }"> <template #cell(stages)="{ item }">
<div class="stage-cell"> <div class="stage-cell">
<!-- This empty div should be removed, see https://gitlab.com/gitlab-org/gitlab/-/issues/323488 --> <!-- This empty div should be removed, see https://gitlab.com/gitlab-org/gitlab/-/issues/323488 -->
@ -229,10 +196,6 @@ export default {
</div> </div>
</template> </template>
<template #cell(timeago)="{ item }">
<pipelines-timeago :pipeline="item" />
</template>
<template #cell(actions)="{ item }"> <template #cell(actions)="{ item }">
<pipeline-operations :pipeline="item" :canceling-pipeline="cancelingPipeline" /> <pipeline-operations :pipeline="item" :canceling-pipeline="cancelingPipeline" />
</template> </template>

View File

@ -1,6 +1,5 @@
<script> <script>
import { GlIcon, GlTooltipDirective } from '@gitlab/ui'; import { GlIcon, GlTooltipDirective } from '@gitlab/ui';
import glFeatureFlagMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
import timeagoMixin from '~/vue_shared/mixins/timeago'; import timeagoMixin from '~/vue_shared/mixins/timeago';
export default { export default {
@ -8,7 +7,7 @@ export default {
GlTooltip: GlTooltipDirective, GlTooltip: GlTooltipDirective,
}, },
components: { GlIcon }, components: { GlIcon },
mixins: [timeagoMixin, glFeatureFlagMixin()], mixins: [timeagoMixin],
props: { props: {
pipeline: { pipeline: {
type: Object, type: Object,
@ -54,14 +53,11 @@ export default {
showSkipped() { showSkipped() {
return !this.duration && !this.finishedTime && this.skipped; return !this.duration && !this.finishedTime && this.skipped;
}, },
shouldDisplayAsBlock() {
return this.glFeatures?.rearrangePipelinesTable;
},
}, },
}; };
</script> </script>
<template> <template>
<div class="{ 'gl-display-block': shouldDisplayAsBlock }"> <div class="gl-display-block">
<span v-if="showInProgress" data-testid="pipeline-in-progress"> <span v-if="showInProgress" data-testid="pipeline-in-progress">
<gl-icon v-if="stuck" name="warning" class="gl-mr-2" :size="12" data-testid="warning-icon" /> <gl-icon v-if="stuck" name="warning" class="gl-mr-2" :size="12" data-testid="warning-icon" />
<gl-icon <gl-icon

View File

@ -8,7 +8,7 @@ Vue.use(VueApollo);
const createPipelinesDetailApp = ( const createPipelinesDetailApp = (
selector, selector,
apolloProvider, apolloProvider,
{ pipelineProjectPath, pipelineIid, metricsPath, graphqlResourceEtag } = {}, { pipelineProjectPath, pipelineIid, metricsPath, graphqlResourceEtag, multiProjectHelpPath } = {},
) => { ) => {
// eslint-disable-next-line no-new // eslint-disable-next-line no-new
new Vue({ new Vue({
@ -22,6 +22,7 @@ const createPipelinesDetailApp = (
pipelineProjectPath, pipelineProjectPath,
pipelineIid, pipelineIid,
graphqlResourceEtag, graphqlResourceEtag,
multiProjectHelpPath,
}, },
errorCaptured(err, _vm, info) { errorCaptured(err, _vm, info) {
reportToSentry('pipeline_details_graph', `error: ${err}, info: ${info}`); reportToSentry('pipeline_details_graph', `error: ${err}, info: ${info}`);

View File

@ -1,12 +1,7 @@
<script> <script>
import { GlLink, GlIcon } from '@gitlab/ui'; import { GlLink, GlIcon, GlSprintf } from '@gitlab/ui';
import { escape } from 'lodash';
import { __, sprintf } from '~/locale'; import { __, sprintf } from '~/locale';
function buildDocsLinkStart(path) {
return `<a href="${escape(path)}" target="_blank" rel="noopener noreferrer">`;
}
const NoteableTypeText = { const NoteableTypeText = {
Issue: __('issue'), Issue: __('issue'),
Epic: __('epic'), Epic: __('epic'),
@ -17,6 +12,7 @@ export default {
components: { components: {
GlIcon, GlIcon,
GlLink, GlLink,
GlSprintf,
}, },
props: { props: {
isLocked: { isLocked: {
@ -59,20 +55,6 @@ export default {
noteableTypeText() { noteableTypeText() {
return NoteableTypeText[this.noteableType]; return NoteableTypeText[this.noteableType];
}, },
confidentialAndLockedDiscussionText() {
return sprintf(
__(
'This %{noteableTypeText} is %{confidentialLinkStart}confidential%{linkEnd} and %{lockedLinkStart}locked%{linkEnd}.',
),
{
noteableTypeText: this.noteableTypeText,
confidentialLinkStart: buildDocsLinkStart(this.confidentialNoteableDocsPath),
lockedLinkStart: buildDocsLinkStart(this.lockedNoteableDocsPath),
linkEnd: '</a>',
},
false,
);
},
confidentialContextText() { confidentialContextText() {
return sprintf(__('This is a confidential %{noteableTypeText}.'), { return sprintf(__('This is a confidential %{noteableTypeText}.'), {
noteableTypeText: this.noteableTypeText, noteableTypeText: this.noteableTypeText,
@ -91,9 +73,23 @@ export default {
<gl-icon v-if="!isLockedAndConfidential" :name="warningIcon" :size="16" class="icon inline" /> <gl-icon v-if="!isLockedAndConfidential" :name="warningIcon" :size="16" class="icon inline" />
<span v-if="isLockedAndConfidential" ref="lockedAndConfidential"> <span v-if="isLockedAndConfidential" ref="lockedAndConfidential">
<span <span>
v-html="confidentialAndLockedDiscussionText /* eslint-disable-line vue/no-v-html */" <gl-sprintf
></span> :message="
__(
'This %{noteableTypeText} is %{confidentialLinkStart}confidential%{confidentialLinkEnd} and %{lockedLinkStart}locked%{lockedLinkEnd}.',
)
"
>
<template #noteableTypeText>{{ noteableTypeText }}</template>
<template #confidentialLink="{ content }">
<gl-link :href="confidentialNoteableDocsPath" target="_blank">{{ content }}</gl-link>
</template>
<template #lockedLink="{ content }">
<gl-link :href="lockedNoteableDocsPath" target="_blank">{{ content }}</gl-link>
</template>
</gl-sprintf>
</span>
{{ {{
__("People without permission will never get a notification and won't be able to comment.") __("People without permission will never get a notification and won't be able to comment.")
}} }}

View File

@ -0,0 +1,40 @@
<script>
import { GlBadge, GlIcon } from '@gitlab/ui';
import { s__ } from '~/locale';
const gitlabTiers = {
free: s__('GitlabTiers|Free'),
premium: s__('GitlabTiers|Premium'),
ultimate: s__('GitlabTiers|Ultimate'),
};
export default {
components: {
GlBadge,
GlIcon,
},
props: {
tier: {
type: String,
required: true,
validator: (value) => Object.keys(gitlabTiers).includes(value),
},
size: {
type: String,
required: false,
default: 'md',
},
},
computed: {
tierName() {
return gitlabTiers[this.tier];
},
},
};
</script>
<template>
<gl-badge :size="size" class="gl-text-purple-600! gl-font-weight-bold gl-bg-purple-50!">
<gl-icon name="license" /> {{ tierName }}
</gl-badge>
</template>

View File

@ -5,6 +5,8 @@ class Admin::CohortsController < Admin::ApplicationController
feature_category :devops_reports feature_category :devops_reports
urgency :low
def index def index
@cohorts = load_cohorts @cohorts = load_cohorts
track_cohorts_visit track_cohorts_visit

View File

@ -9,6 +9,8 @@ class Admin::DevOpsReportController < Admin::ApplicationController
feature_category :devops_reports feature_category :devops_reports
urgency :low
# rubocop: disable CodeReuse/ActiveRecord # rubocop: disable CodeReuse/ActiveRecord
def show def show
@metric = DevOpsReport::Metric.order(:created_at).last&.present @metric = DevOpsReport::Metric.order(:created_at).last&.present

View File

@ -2,6 +2,8 @@
class Admin::InstanceReviewController < Admin::ApplicationController class Admin::InstanceReviewController < Admin::ApplicationController
feature_category :devops_reports feature_category :devops_reports
urgency :low
def index def index
redirect_to("#{Gitlab::SubscriptionPortal.subscriptions_instance_review_url}?#{instance_review_params}") redirect_to("#{Gitlab::SubscriptionPortal.subscriptions_instance_review_url}?#{instance_review_params}")
end end

View File

@ -7,6 +7,8 @@ class Admin::UsageTrendsController < Admin::ApplicationController
feature_category :devops_reports feature_category :devops_reports
urgency :low
def index def index
end end
end end

View File

@ -45,7 +45,6 @@ class Projects::MergeRequestsController < Projects::MergeRequests::ApplicationCo
push_frontend_feature_flag(:restructured_mr_widget, project, default_enabled: :yaml) push_frontend_feature_flag(:restructured_mr_widget, project, default_enabled: :yaml)
push_frontend_feature_flag(:refactor_mr_widgets_extensions, project, default_enabled: :yaml) push_frontend_feature_flag(:refactor_mr_widgets_extensions, project, default_enabled: :yaml)
push_frontend_feature_flag(:rebase_without_ci_ui, project, default_enabled: :yaml) push_frontend_feature_flag(:rebase_without_ci_ui, project, default_enabled: :yaml)
push_frontend_feature_flag(:rearrange_pipelines_table, project, default_enabled: :yaml)
push_frontend_feature_flag(:markdown_continue_lists, project, default_enabled: :yaml) push_frontend_feature_flag(:markdown_continue_lists, project, default_enabled: :yaml)
# Usage data feature flags # Usage data feature flags
push_frontend_feature_flag(:users_expanding_widgets_usage_data, project, default_enabled: :yaml) push_frontend_feature_flag(:users_expanding_widgets_usage_data, project, default_enabled: :yaml)

View File

@ -16,9 +16,6 @@ class Projects::PipelinesController < Projects::ApplicationController
before_action :authorize_create_pipeline!, only: [:new, :create, :config_variables] before_action :authorize_create_pipeline!, only: [:new, :create, :config_variables]
before_action :authorize_update_pipeline!, only: [:retry, :cancel] before_action :authorize_update_pipeline!, only: [:retry, :cancel]
before_action :ensure_pipeline, only: [:show, :downloadable_artifacts] before_action :ensure_pipeline, only: [:show, :downloadable_artifacts]
before_action do
push_frontend_feature_flag(:rearrange_pipelines_table, project, default_enabled: :yaml)
end
# Will be removed with https://gitlab.com/gitlab-org/gitlab/-/issues/225596 # Will be removed with https://gitlab.com/gitlab-org/gitlab/-/issues/225596
before_action :redirect_for_legacy_scope_filter, only: [:index], if: -> { request.format.html? } before_action :redirect_for_legacy_scope_filter, only: [:index], if: -> { request.format.html? }

View File

@ -47,6 +47,15 @@ query getPipelineDetails($projectPath: ID!, $iid: ID!) {
id id
iid iid
complete complete
user {
__typename
id
namespace {
__typename
id
crossProjectPipelineAvailable
}
}
usesNeeds usesNeeds
userPermissions { userPermissions {
updatePipeline updatePipeline

View File

@ -38,7 +38,7 @@ module Types
description(enum_mod.description) if use_description description(enum_mod.description) if use_description
enum_mod.definition.each do |key, content| enum_mod.definition.each do |key, content|
value(key.to_s.upcase, **content) value(key.to_s.upcase, value: key.to_s, description: content[:description])
end end
end end
# rubocop: enable Graphql/Descriptions # rubocop: enable Graphql/Descriptions

View File

@ -0,0 +1,15 @@
# frozen_string_literal: true
module Projects
module PipelineHelper
def js_pipeline_details_data(project, pipeline)
{
graphql_resource_etag: graphql_etag_pipeline_path(pipeline),
metrics_path: namespace_project_ci_prometheus_metrics_histograms_path(namespace_id: project.namespace, project_id: project, format: :json),
multi_project_help_path: help_page_path('ci/pipelines/multi_project_pipelines.md', anchor: 'multi-project-pipeline-visualization'),
pipeline_iid: pipeline.iid,
pipeline_project_path: project.full_path
}
end
end
end

View File

@ -12,21 +12,32 @@ module Boards
end end
# rubocop: disable CodeReuse/ActiveRecord # rubocop: disable CodeReuse/ActiveRecord
def metadata def metadata(required_fields = [:issue_count, :total_issue_weight])
issuables = item_model.arel_table fields = metadata_fields(required_fields)
keys = metadata_fields.keys keys = fields.keys
# TODO: eliminate need for SQL literal fragment # TODO: eliminate need for SQL literal fragment
columns = Arel.sql(metadata_fields.values_at(*keys).join(', ')) columns = Arel.sql(fields.values_at(*keys).join(', '))
results = item_model.where(id: init_collection.select(issuables[:id])).pluck(columns) results = item_model.where(id: collection_ids)
results = query_additions(results, required_fields)
results = results.select(columns)
Hash[keys.zip(results.flatten)] Hash[keys.zip(results.pluck(columns).flatten)]
end end
# rubocop: enable CodeReuse/ActiveRecord # rubocop: enable CodeReuse/ActiveRecord
private private
def metadata_fields # override if needed
{ size: 'COUNT(*)' } def query_additions(items, required_fields)
items
end
def collection_ids
@collection_ids ||= init_collection.select(item_model.arel_table[:id])
end
def metadata_fields(required_fields)
required_fields&.include?(:issue_count) ? { size: 'COUNT(*)' } : {}
end end
def order(items) def order(items)

View File

@ -4,11 +4,13 @@ module IssuableLinks
class DestroyService < BaseService class DestroyService < BaseService
include IncidentManagement::UsageData include IncidentManagement::UsageData
attr_reader :link, :current_user attr_reader :link, :current_user, :source, :target
def initialize(link, user) def initialize(link, user)
@link = link @link = link
@current_user = user @current_user = user
@source = link.source
@target = link.target
end end
def execute def execute
@ -22,6 +24,11 @@ module IssuableLinks
private private
def create_notes
SystemNoteService.unrelate_issuable(source, target, current_user)
SystemNoteService.unrelate_issuable(target, source, current_user)
end
def after_destroy def after_destroy
create_notes create_notes
track_event track_event

View File

@ -4,23 +4,10 @@ module IssueLinks
class DestroyService < IssuableLinks::DestroyService class DestroyService < IssuableLinks::DestroyService
private private
def source
@source ||= link.source
end
def target
@target ||= link.target
end
def permission_to_remove_relation? def permission_to_remove_relation?
can?(current_user, :admin_issue_link, source) && can?(current_user, :admin_issue_link, target) can?(current_user, :admin_issue_link, source) && can?(current_user, :admin_issue_link, target)
end end
def create_notes
SystemNoteService.unrelate_issue(source, target, current_user)
SystemNoteService.unrelate_issue(target, source, current_user)
end
def track_event def track_event
track_incident_action(current_user, target, :incident_unrelate) track_incident_action(current_user, target, :incident_unrelate)
end end

View File

@ -53,8 +53,8 @@ module SystemNoteService
::SystemNotes::IssuablesService.new(noteable: noteable, project: noteable.project, author: user).relate_issue(noteable_ref) ::SystemNotes::IssuablesService.new(noteable: noteable, project: noteable.project, author: user).relate_issue(noteable_ref)
end end
def unrelate_issue(noteable, noteable_ref, user) def unrelate_issuable(noteable, noteable_ref, user)
::SystemNotes::IssuablesService.new(noteable: noteable, project: noteable.project, author: user).unrelate_issue(noteable_ref) ::SystemNotes::IssuablesService.new(noteable: noteable, project: noteable.project, author: user).unrelate_issuable(noteable_ref)
end end
# Called when the due_date of a Noteable is changed # Called when the due_date of a Noteable is changed

View File

@ -26,8 +26,8 @@ module SystemNotes
# "removed the relation with gitlab-foss#9001" # "removed the relation with gitlab-foss#9001"
# #
# Returns the created Note object # Returns the created Note object
def unrelate_issue(noteable_ref) def unrelate_issuable(noteable_ref)
body = "removed the relation with #{noteable_ref.to_reference(noteable.project)}" body = "removed the relation with #{noteable_ref.to_reference(noteable.resource_parent)}"
issue_activity_counter.track_issue_unrelated_action(author: author) if noteable.is_a?(Issue) issue_activity_counter.track_issue_unrelated_action(author: author) if noteable.is_a?(Issue)

View File

@ -42,10 +42,20 @@ module WebHooks
hook.failed! hook.failed!
end end
end end
rescue Gitlab::ExclusiveLeaseHelpers::FailedToObtainLockError
raise if raise_lock_error?
end end
def lock_name def lock_name
"web_hooks:update_hook_failure_state:#{hook.id}" "web_hooks:update_hook_failure_state:#{hook.id}"
end end
# Allow an error to be raised after failing to obtain a lease only if the hook
# is not already in the correct failure state.
def raise_lock_error?
hook.reset # Reload so properties are guaranteed to be current.
hook.executable? != (response_category == :ok)
end
end end
end end

View File

@ -29,4 +29,4 @@
#js-pipeline-notification{ data: { deprecated_keywords_doc_path: help_page_path('ci/yaml/index.md', anchor: 'deprecated-keywords'), full_path: @project.full_path, pipeline_iid: @pipeline.iid } } #js-pipeline-notification{ data: { deprecated_keywords_doc_path: help_page_path('ci/yaml/index.md', anchor: 'deprecated-keywords'), full_path: @project.full_path, pipeline_iid: @pipeline.iid } }
= render "projects/pipelines/with_tabs", pipeline: @pipeline, stages: @stages, pipeline_has_errors: pipeline_has_errors = render "projects/pipelines/with_tabs", pipeline: @pipeline, stages: @stages, pipeline_has_errors: pipeline_has_errors
.js-pipeline-details-vue{ data: { metrics_path: namespace_project_ci_prometheus_metrics_histograms_path(namespace_id: @project.namespace, project_id: @project, format: :json), pipeline_project_path: @project.full_path, pipeline_iid: @pipeline.iid, graphql_resource_etag: graphql_etag_pipeline_path(@pipeline) } } .js-pipeline-details-vue{ data: js_pipeline_details_data(@project, @pipeline) }

View File

@ -31,6 +31,7 @@
- continuous_delivery - continuous_delivery
- continuous_integration - continuous_integration
- continuous_integration_scaling - continuous_integration_scaling
- continuous_verification
- database - database
- dataops - dataops
- delivery - delivery
@ -74,7 +75,6 @@
- kubernetes_management - kubernetes_management
- license - license
- license_compliance - license_compliance
- live_preview
- logging - logging
- memory - memory
- merge_trains - merge_trains
@ -110,7 +110,6 @@
- secrets_management - secrets_management
- security_benchmarking - security_benchmarking
- security_orchestration - security_orchestration
- self_monitoring
- service_desk - service_desk
- service_ping - service_ping
- sharding - sharding
@ -119,7 +118,6 @@
- static_application_security_testing - static_application_security_testing
- static_site_editor - static_site_editor
- subgroups - subgroups
- synthetic_monitoring
- team_planning - team_planning
- tracing - tracing
- usage_ping - usage_ping

View File

@ -1,7 +1,7 @@
--- ---
name: ci_pending_builds_maintain_denormalized_data name: ci_pending_builds_maintain_denormalized_data
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/75425 introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/75425
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/332951 rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/354496
milestone: '14.6' milestone: '14.6'
type: development type: development
group: group::pipeline execution group: group::pipeline execution

View File

@ -1,7 +1,7 @@
--- ---
name: ci_pending_builds_queue_source name: ci_pending_builds_queue_source
introduced_by_url: introduced_by_url:
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/350884 rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/354496
milestone: '14.0' milestone: '14.0'
type: development type: development
group: group::pipeline execution group: group::pipeline execution

View File

@ -1,7 +1,7 @@
--- ---
name: ci_queuing_use_denormalized_data_strategy name: ci_queuing_use_denormalized_data_strategy
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/76543 introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/76543
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/332951 rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/354496
milestone: '14.6' milestone: '14.6'
type: development type: development
group: group::pipeline execution group: group::pipeline execution

View File

@ -1,8 +1,8 @@
--- ---
name: rearrange_pipelines_table name: container_registry_follow_redirects_middleware
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/72545 introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/81056
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/343286 rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/353291
milestone: '14.8' milestone: '14.9'
type: development type: development
group: group::pipeline execution group: group::package
default_enabled: true default_enabled: false

View File

@ -62,3 +62,27 @@
- 'i_testing_group_code_coverage_visit_total' - 'i_testing_group_code_coverage_visit_total'
- 'i_testing_load_performance_widget_total' - 'i_testing_load_performance_widget_total'
- 'i_testing_metrics_report_widget_total' - 'i_testing_metrics_report_widget_total'
- name: xmau_plan
operator: OR
source: redis
time_frame: [7d, 28d]
events:
- users_creating_work_items
- users_updating_work_item_title
feature_flag: track_work_items_activity
- name: xmau_project_management
operator: OR
source: redis
time_frame: [7d, 28d]
events:
- users_creating_work_items
- users_updating_work_item_title
feature_flag: track_work_items_activity
- name: users_work_items
operator: OR
source: redis
time_frame: [7d, 28d]
events:
- users_creating_work_items
- users_updating_work_item_title
feature_flag: track_work_items_activity

View File

@ -0,0 +1,21 @@
---
key_path: counts_monthly.aggregated_metrics.xmau_plan
description: Unique users interacting with Plan features
product_category: team planning
product_section: dev
product_stage: plan
product_group: group::project management
value_type: number
status: active
milestone: '14.9'
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/81336
time_frame: 28d
data_source: redis_hll
data_category: optional
distribution:
- ce
- ee
tier:
- free
- premium
- ultimate

View File

@ -0,0 +1,21 @@
---
key_path: counts_monthly.aggregated_metrics.xmau_project_management
description: Unique users interacting with Project Management features
product_category: team planning
product_section: dev
product_stage: plan
product_group: group::project management
value_type: number
status: active
milestone: '14.9'
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/81336
time_frame: 28d
data_source: redis_hll
data_category: optional
distribution:
- ce
- ee
tier:
- free
- premium
- ultimate

View File

@ -0,0 +1,21 @@
---
key_path: counts_monthly.aggregated_metrics.users_work_items
description: Unique users interacting with work items
product_category: team planning
product_section: dev
product_stage: plan
product_group: group::product planning
value_type: number
status: active
milestone: '14.9'
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/81336
time_frame: 28d
data_source: redis_hll
data_category: optional
distribution:
- ce
- ee
tier:
- free
- premium
- ultimate

View File

@ -0,0 +1,21 @@
---
key_path: counts_weekly.aggregated_metrics.xmau_plan
description: Unique users interacting with Plan features
product_category: team planning
product_section: dev
product_stage: plan
product_group: group::project management
value_type: number
status: active
milestone: '14.9'
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/81336
time_frame: 7d
data_source: redis_hll
data_category: optional
distribution:
- ce
- ee
tier:
- free
- premium
- ultimate

View File

@ -0,0 +1,21 @@
---
key_path: counts_weekly.aggregated_metrics.xmau_project_management
description: Unique users interacting with Project Management features
product_category: team planning
product_section: dev
product_stage: plan
product_group: group::project management
value_type: number
status: active
milestone: '14.9'
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/81336
time_frame: 7d
data_source: redis_hll
data_category: optional
distribution:
- ce
- ee
tier:
- free
- premium
- ultimate

View File

@ -0,0 +1,21 @@
---
key_path: counts_weekly.aggregated_metrics.users_work_items
description: Unique users interacting with work items
product_category: team planning
product_section: dev
product_stage: plan
product_group: group::product planning
value_type: number
status: active
milestone: '14.9'
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/81336
time_frame: 7d
data_source: redis_hll
data_category: optional
distribution:
- ce
- ee
tier:
- free
- premium
- ultimate

View File

@ -8,8 +8,8 @@
We are changing how the date filter works in Value Stream Analytics. Instead of filtering by the time that the issue or merge request was created, the date filter will filter by the end event time of the given stage. This will result in completely different figures after this change has rolled out. We are changing how the date filter works in Value Stream Analytics. Instead of filtering by the time that the issue or merge request was created, the date filter will filter by the end event time of the given stage. This will result in completely different figures after this change has rolled out.
If you monitor Value Stream Analytics metrics and rely on the date filter, to avoid losing data, you must save the data prior to this change. If you monitor Value Stream Analytics metrics and rely on the date filter, to avoid losing data, you must save the data prior to this change.
stage: manage # (optional - may be required in the future) String value of the stage that the feature was created in. e.g., Growth stage: manage # (optional - may be required in the future) String value of the stage that the feature was created in. e.g., Growth
tiers: # (optional - may be required in the future) An array of tiers that the feature is available in currently. e.g., [Free, Silver, Gold, Core, Premium, Ultimate] tiers: # (optional - may be required in the future) An array of tiers that the feature is available in currently. e.g., [Free, Silver, Gold, Core, Premium, Ultimate]
issue_url: 'https://gitlab.com/gitlab-org/gitlab/-/issues/343210' # (optional) This is a link to the deprecation issue in GitLab issue_url: 'https://gitlab.com/gitlab-org/gitlab/-/issues/343210' # (optional) This is a link to the deprecation issue in GitLab
documentation_url: "https://docs.gitlab.com/ee/user/analytics/value_stream_analytics.html#filter-value-stream-analytics-data" # (optional) This is a link to the current documentation page documentation_url: "https://docs.gitlab.com/ee/user/analytics/value_stream_analytics.html#filter-value-stream-analytics-data" # (optional) This is a link to the current documentation page
image_url: "vsa_warning.png" # (optional) This is a link to a thumbnail image depicting the feature image_url: "vsa_warning.png" # (optional) This is a link to a thumbnail image depicting the feature

View File

@ -18,9 +18,9 @@
[warning](https://gitlab.com/gitlab-org/gitlab/-/issues/335789#note_672853791) [warning](https://gitlab.com/gitlab-org/gitlab/-/issues/335789#note_672853791)
in the Vulnerability Report. in the Vulnerability Report.
# The following items are not published on the docs page, but may be used in the future. # The following items are not published on the docs page, but may be used in the future.
stage: Secure # (optional - may be required in the future) String value of the stage that the feature was created in. e.g., Growth stage: Secure # (optional - may be required in the future) String value of the stage that the feature was created in. e.g., Growth
tiers: [Core, Premium, Ultimate] # (optional - may be required in the future) An array of tiers that the feature is available in currently. e.g., [Free, Silver, Gold, Core, Premium, Ultimate] tiers: [Core, Premium, Ultimate] # (optional - may be required in the future) An array of tiers that the feature is available in currently. e.g., [Free, Silver, Gold, Core, Premium, Ultimate]
issue_url: https://gitlab.com/groups/gitlab-org/-/epics/6968 # (optional) This is a link to the deprecation issue in GitLab issue_url: https://gitlab.com/groups/gitlab-org/-/epics/6968 # (optional) This is a link to the deprecation issue in GitLab
documentation_url: # (optional) This is a link to the current documentation page documentation_url: # (optional) This is a link to the current documentation page
image_url: # (optional) This is a link to a thumbnail image depicting the feature image_url: # (optional) This is a link to a thumbnail image depicting the feature
video_url: # (optional) Use the youtube thumbnail URL with the structure of https://img.youtube.com/vi/UNIQUEID/hqdefault.jpg video_url: # (optional) Use the youtube thumbnail URL with the structure of https://img.youtube.com/vi/UNIQUEID/hqdefault.jpg

View File

@ -8,9 +8,9 @@
If you are using our License Compliance API you should stop using the `approved` and `blacklisted` query parameters, they are now `allowed` and `denied`. In 15.0 the responses will also stop using `approved` and `blacklisted` so you need to adjust any of your custom tools to use the old and new values so they do not break with the 15.0 release. If you are using our License Compliance API you should stop using the `approved` and `blacklisted` query parameters, they are now `allowed` and `denied`. In 15.0 the responses will also stop using `approved` and `blacklisted` so you need to adjust any of your custom tools to use the old and new values so they do not break with the 15.0 release.
# The following items are not published on the docs page, but may be used in the future. # The following items are not published on the docs page, but may be used in the future.
stage: secure # (optional - may be required in the future) String value of the stage that the feature was created in. e.g., Growth stage: secure # (optional - may be required in the future) String value of the stage that the feature was created in. e.g., Growth
tiers: ultimate # (optional - may be required in the future) An array of tiers that the feature is available in currently. e.g., [Free, Silver, Gold, Core, Premium, Ultimate] tiers: ultimate # (optional - may be required in the future) An array of tiers that the feature is available in currently. e.g., [Free, Silver, Gold, Core, Premium, Ultimate]
issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/335707 # (optional) This is a link to the deprecation issue in GitLab issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/335707 # (optional) This is a link to the deprecation issue in GitLab
documentation_url: # (optional) This is a link to the current documentation page documentation_url: # (optional) This is a link to the current documentation page
image_url: # (optional) This is a link to a thumbnail image depicting the feature image_url: # (optional) This is a link to a thumbnail image depicting the feature
video_url: # (optional) Use the youtube thumbnail URL with the structure of https://img.youtube.com/vi/UNIQUEID/hqdefault.jpg video_url: # (optional) Use the youtube thumbnail URL with the structure of https://img.youtube.com/vi/UNIQUEID/hqdefault.jpg

View File

@ -8,10 +8,10 @@
If you have explicitly excluded bundler-audit using DS_EXCLUDED_ANALYZERS you will need to clean up (remove the reference) in 15.0. If you have customized your pipeline's Dependency Scanning configuration, for example to edit the `bundler-audit-dependency_scanning` job, you will want to switch to gemnasium-dependency_scanning before removal in 15.0, to prevent your pipeline from failing. If you have not used the DS_EXCLUDED_ANALYZERS to reference bundler-audit, or customized your template specifically for bundler-audit, you will not need to take action. If you have explicitly excluded bundler-audit using DS_EXCLUDED_ANALYZERS you will need to clean up (remove the reference) in 15.0. If you have customized your pipeline's Dependency Scanning configuration, for example to edit the `bundler-audit-dependency_scanning` job, you will want to switch to gemnasium-dependency_scanning before removal in 15.0, to prevent your pipeline from failing. If you have not used the DS_EXCLUDED_ANALYZERS to reference bundler-audit, or customized your template specifically for bundler-audit, you will not need to take action.
# The following items are not published on the docs page, but may be used in the future. # The following items are not published on the docs page, but may be used in the future.
stage: secure # (optional - may be required in the future) String value of the stage that the feature was created in. e.g., Growth stage: secure # (optional - may be required in the future) String value of the stage that the feature was created in. e.g., Growth
tiers: ultimate # (optional - may be required in the future) An array of tiers that the feature is available in currently. e.g., [Free, Silver, Gold, Core, Premium, Ultimate] tiers: ultimate # (optional - may be required in the future) An array of tiers that the feature is available in currently. e.g., [Free, Silver, Gold, Core, Premium, Ultimate]
issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/289832 # (optional) This is a link to the deprecation issue in GitLab issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/289832 # (optional) This is a link to the deprecation issue in GitLab
documentation_url: https://docs.gitlab.com/ee/user/application_security/dependency_scanning/analyzers.html # (optional) This is a link to the current documentation page documentation_url: https://docs.gitlab.com/ee/user/application_security/dependency_scanning/analyzers.html # (optional) This is a link to the current documentation page
image_url: # (optional) This is a link to a thumbnail image depicting the feature image_url: # (optional) This is a link to a thumbnail image depicting the feature
video_url: # (optional) Use the youtube thumbnail URL with the structure of https://img.youtube.com/vi/UNIQUEID/hqdefault.jpg video_url: # (optional) Use the youtube thumbnail URL with the structure of https://img.youtube.com/vi/UNIQUEID/hqdefault.jpg
removal_date: "2022-05-22" # (optional - may be required in the future) YYYY-MM-DD format. This should almost always be the 22nd of a month (YYYY-MM-22), the date of the milestone release when this feature is planned to be removed removal_date: "2022-05-22" # (optional - may be required in the future) YYYY-MM-DD format. This should almost always be the 22nd of a month (YYYY-MM-22), the date of the milestone release when this feature is planned to be removed

View File

@ -9,7 +9,7 @@
# The following items are not published on the docs page, but may be used in the future. # The following items are not published on the docs page, but may be used in the future.
stage: # (optional - may be required in the future) String value of the stage that the feature was created in. e.g., Growth stage: # (optional - may be required in the future) String value of the stage that the feature was created in. e.g., Growth
tiers: # (optional - may be required in the future) An array of tiers that the feature is available in currently. e.g., [Free, Silver, Gold, Core, Premium, Ultimate] tiers: # (optional - may be required in the future) An array of tiers that the feature is available in currently. e.g., [Free, Silver, Gold, Core, Premium, Ultimate]
issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/342800 # (optional) This is a link to the deprecation issue in GitLab issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/342800 # (optional) This is a link to the deprecation issue in GitLab
documentation_url: # (optional) This is a link to the current documentation page documentation_url: # (optional) This is a link to the current documentation page
image_url: # (optional) This is a link to a thumbnail image depicting the feature image_url: # (optional) This is a link to a thumbnail image depicting the feature
video_url: # (optional) Use the youtube thumbnail URL with the structure of https://img.youtube.com/vi/UNIQUEID/hqdefault.jpg video_url: # (optional) Use the youtube thumbnail URL with the structure of https://img.youtube.com/vi/UNIQUEID/hqdefault.jpg

View File

@ -15,13 +15,13 @@
announcement_date: "2022-01-22" # The date of the milestone release when this feature was first announced as deprecated. This should almost always be the 22nd of a month (YYYY-MM-22), unless you did an out of band blog post. announcement_date: "2022-01-22" # The date of the milestone release when this feature was first announced as deprecated. This should almost always be the 22nd of a month (YYYY-MM-22), unless you did an out of band blog post.
removal_milestone: "15.0" # The milestone when this feature is planned to be removed removal_milestone: "15.0" # The milestone when this feature is planned to be removed
removal_date: "2022-05-22" # the date of the milestone release when this feature is planned to be removed removal_date: "2022-05-22" # the date of the milestone release when this feature is planned to be removed
breaking_change: true # If this deprecation is a breaking change, set this value to true breaking_change: true # If this deprecation is a breaking change, set this value to true
body: | # Do not modify this line, instead modify the lines below. body: | # Do not modify this line, instead modify the lines below.
The `merged_by` field in the [merge request API](https://docs.gitlab.com/ee/api/merge_requests.html#list-merge-requests) is being deprecated and will be removed in GitLab 15.0. This field is being replaced with the `merge_user` field (already present in GraphQL) which more correctly identifies who merged a merge request when performing actions (merge when pipeline succeeds, add to merge train) other than a simple merge. The `merged_by` field in the [merge request API](https://docs.gitlab.com/ee/api/merge_requests.html#list-merge-requests) is being deprecated and will be removed in GitLab 15.0. This field is being replaced with the `merge_user` field (already present in GraphQL) which more correctly identifies who merged a merge request when performing actions (merge when pipeline succeeds, add to merge train) other than a simple merge.
# The following items are not published on the docs page, but may be used in the future. # The following items are not published on the docs page, but may be used in the future.
stage: create # (optional - may be required in the future) String value of the stage that the feature was created in. e.g., Growth stage: create # (optional - may be required in the future) String value of the stage that the feature was created in. e.g., Growth
tiers: # (optional - may be required in the future) An array of tiers that the feature is available in currently. e.g., [Free, Silver, Gold, Core, Premium, Ultimate] tiers: # (optional - may be required in the future) An array of tiers that the feature is available in currently. e.g., [Free, Silver, Gold, Core, Premium, Ultimate]
issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/350534 # (optional) This is a link to the deprecation issue in GitLab issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/350534 # (optional) This is a link to the deprecation issue in GitLab
documentation_url: # (optional) This is a link to the current documentation page documentation_url: # (optional) This is a link to the current documentation page
image_url: # (optional) This is a link to a thumbnail image depicting the feature image_url: # (optional) This is a link to a thumbnail image depicting the feature
video_url: # (optional) Use the youtube thumbnail URL with the structure of https://img.youtube.com/vi/UNIQUEID/hqdefault.jpg video_url: # (optional) Use the youtube thumbnail URL with the structure of https://img.youtube.com/vi/UNIQUEID/hqdefault.jpg

View File

@ -6,9 +6,9 @@
body: | # Do not modify this line, instead modify the lines below. body: | # Do not modify this line, instead modify the lines below.
The Static Site Editor will no longer be available starting in GitLab 15.0. Improvements to the Markdown editing experience across GitLab will deliver smiliar benefit but with a wider reach. Incoming requests to the Static Site Editor will be redirected to the Web IDE. Current users of the Static Site Editor can view the [documentation](https://docs.gitlab.com/ee/user/project/static_site_editor/) for more information, including how to remove the configuration files from existing projects. The Static Site Editor will no longer be available starting in GitLab 15.0. Improvements to the Markdown editing experience across GitLab will deliver smiliar benefit but with a wider reach. Incoming requests to the Static Site Editor will be redirected to the Web IDE. Current users of the Static Site Editor can view the [documentation](https://docs.gitlab.com/ee/user/project/static_site_editor/) for more information, including how to remove the configuration files from existing projects.
# The following items are not published on the docs page, but may be used in the future. # The following items are not published on the docs page, but may be used in the future.
stage: Create # (optional - may be required in the future) String value of the stage that the feature was created in. e.g., Growth stage: Create # (optional - may be required in the future) String value of the stage that the feature was created in. e.g., Growth
tiers: [Free, Premium, Ultimate] # (optional - may be required in the future) An array of tiers that the feature is available in currently. e.g., [Free, Silver, Gold, Core, Premium, Ultimate] tiers: [Free, Premium, Ultimate] # (optional - may be required in the future) An array of tiers that the feature is available in currently. e.g., [Free, Silver, Gold, Core, Premium, Ultimate]
issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/347137 # (optional) This is a link to the deprecation issue in GitLab issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/347137 # (optional) This is a link to the deprecation issue in GitLab
documentation_url: https://docs.gitlab.com/ee/user/project/static_site_editor/ # (optional) This is a link to the current documentation page documentation_url: https://docs.gitlab.com/ee/user/project/static_site_editor/ # (optional) This is a link to the current documentation page
image_url: # (optional) This is a link to a thumbnail image depicting the feature image_url: # (optional) This is a link to a thumbnail image depicting the feature
video_url: # (optional) Use the youtube thumbnail URL with the structure of https://img.youtube.com/vi/UNIQUEID/hqdefault.jpg video_url: # (optional) Use the youtube thumbnail URL with the structure of https://img.youtube.com/vi/UNIQUEID/hqdefault.jpg

View File

@ -8,10 +8,10 @@
If you have explicitly excluded retire.js using DS_EXCLUDED_ANALYZERS you will need to clean up (remove the reference) in 15.0. If you have customized your pipeline's Dependency Scanning configuration related to the `retire-js-dependency_scanning` job you will want to switch to gemnasium-dependency_scanning before the removal in 15.0, to prevent your pipeline from failing. If you have not used the DS_EXCLUDED_ANALYZERS to reference retire.js, or customized your template specifically for retire.js, you will not need to take action. If you have explicitly excluded retire.js using DS_EXCLUDED_ANALYZERS you will need to clean up (remove the reference) in 15.0. If you have customized your pipeline's Dependency Scanning configuration related to the `retire-js-dependency_scanning` job you will want to switch to gemnasium-dependency_scanning before the removal in 15.0, to prevent your pipeline from failing. If you have not used the DS_EXCLUDED_ANALYZERS to reference retire.js, or customized your template specifically for retire.js, you will not need to take action.
# The following items are not published on the docs page, but may be used in the future. # The following items are not published on the docs page, but may be used in the future.
stage: secure # (optional - may be required in the future) String value of the stage that the feature was created in. e.g., Growth stage: secure # (optional - may be required in the future) String value of the stage that the feature was created in. e.g., Growth
tiers: ultimate # (optional - may be required in the future) An array of tiers that the feature is available in currently. e.g., [Free, Silver, Gold, Core, Premium, Ultimate] tiers: ultimate # (optional - may be required in the future) An array of tiers that the feature is available in currently. e.g., [Free, Silver, Gold, Core, Premium, Ultimate]
issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/350510 # (optional) This is a link to the deprecation issue in GitLab issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/350510 # (optional) This is a link to the deprecation issue in GitLab
documentation_url: https://docs.gitlab.com/ee/user/application_security/dependency_scanning/analyzers.html # (optional) This is a link to the current documentation page documentation_url: https://docs.gitlab.com/ee/user/application_security/dependency_scanning/analyzers.html # (optional) This is a link to the current documentation page
image_url: # (optional) This is a link to a thumbnail image depicting the feature image_url: # (optional) This is a link to a thumbnail image depicting the feature
video_url: # (optional) Use the youtube thumbnail URL with the structure of https://img.youtube.com/vi/UNIQUEID/hqdefault.jpg video_url: # (optional) Use the youtube thumbnail URL with the structure of https://img.youtube.com/vi/UNIQUEID/hqdefault.jpg
removal_date: "2022-05-22" # (optional - may be required in the future) YYYY-MM-DD format. This should almost always be the 22nd of a month (YYYY-MM-22), the date of the milestone release when this feature is planned to be removed removal_date: "2022-05-22" # (optional - may be required in the future) YYYY-MM-DD format. This should almost always be the 22nd of a month (YYYY-MM-22), the date of the milestone release when this feature is planned to be removed

View File

@ -3,8 +3,8 @@
announcement_date: "2022-02-22" # The date of the milestone release when this feature was first announced as deprecated. This should almost always be the 22nd of a month (YYYY-MM-22), unless you did an out of band blog post. announcement_date: "2022-02-22" # The date of the milestone release when this feature was first announced as deprecated. This should almost always be the 22nd of a month (YYYY-MM-22), unless you did an out of band blog post.
removal_milestone: "15.0" # The milestone when this feature is planned to be removed removal_milestone: "15.0" # The milestone when this feature is planned to be removed
removal_date: "2022-05-22" # The date of the milestone release when this feature is planned to be removed. This should almost always be the 22nd of a month (YYYY-MM-22), unless you did an out of band blog post. removal_date: "2022-05-22" # The date of the milestone release when this feature is planned to be removed. This should almost always be the 22nd of a month (YYYY-MM-22), unless you did an out of band blog post.
breaking_change: true # If this deprecation is a breaking change, set this value to true breaking_change: true # If this deprecation is a breaking change, set this value to true
reporter: djensen # GitLab username of the person reporting the deprecation reporter: djensen # GitLab username of the person reporting the deprecation
body: | # Do not modify this line, instead modify the lines below. body: | # Do not modify this line, instead modify the lines below.
The feature to disable enforcement of PAT expiration is unusual from a security perspective. The feature to disable enforcement of PAT expiration is unusual from a security perspective.
We have become concerned that this unusual feature could create unexpected behavior for users. We have become concerned that this unusual feature could create unexpected behavior for users.

View File

@ -3,8 +3,8 @@
announcement_date: "2022-02-22" # The date of the milestone release when this feature was first announced as deprecated. This should almost always be the 22nd of a month (YYYY-MM-22), unless you did an out of band blog post. announcement_date: "2022-02-22" # The date of the milestone release when this feature was first announced as deprecated. This should almost always be the 22nd of a month (YYYY-MM-22), unless you did an out of band blog post.
removal_milestone: "15.0" # The milestone when this feature is planned to be removed removal_milestone: "15.0" # The milestone when this feature is planned to be removed
removal_date: "2022-05-22" # The date of the milestone release when this feature is planned to be removed. This should almost always be the 22nd of a month (YYYY-MM-22), unless you did an out of band blog post. removal_date: "2022-05-22" # The date of the milestone release when this feature is planned to be removed. This should almost always be the 22nd of a month (YYYY-MM-22), unless you did an out of band blog post.
breaking_change: true # If this deprecation is a breaking change, set this value to true breaking_change: true # If this deprecation is a breaking change, set this value to true
reporter: djensen # GitLab username of the person reporting the deprecation reporter: djensen # GitLab username of the person reporting the deprecation
body: | # Do not modify this line, instead modify the lines below. body: | # Do not modify this line, instead modify the lines below.
The feature to disable enforcement of SSH expiration is unusual from a security perspective. The feature to disable enforcement of SSH expiration is unusual from a security perspective.
We have become concerned that this unusual feature could create unexpected behavior for users. We have become concerned that this unusual feature could create unexpected behavior for users.

View File

@ -2,7 +2,7 @@
announcement_milestone: "14.8" # The milestone when this feature was first announced as deprecated. announcement_milestone: "14.8" # The milestone when this feature was first announced as deprecated.
announcement_date: "2022-02-22" # The date of the milestone release when this feature was first announced as deprecated. This should almost always be the 22nd of a month (YYYY-MM-22), unless you did an out of band blog post. announcement_date: "2022-02-22" # The date of the milestone release when this feature was first announced as deprecated. This should almost always be the 22nd of a month (YYYY-MM-22), unless you did an out of band blog post.
removal_milestone: "15.0" # The milestone when this feature is planned to be removed removal_milestone: "15.0" # The milestone when this feature is planned to be removed
removal_date: 2022-05-22 # The date of the milestone release when this feature is planned to be removed. This should almost always be the 22nd of a month (YYYY-MM-22), unless you did an out of band blog post. removal_date: "2022-05-22" # The date of the milestone release when this feature is planned to be removed. This should almost always be the 22nd of a month (YYYY-MM-22), unless you did an out of band blog post.
breaking_change: true # If this deprecation is a breaking change, set this value to true breaking_change: true # If this deprecation is a breaking change, set this value to true
reporter: jacobvosmaer-gitlab # GitLab username of the person reporting the deprecation reporter: jacobvosmaer-gitlab # GitLab username of the person reporting the deprecation
body: | # Do not modify this line, instead modify the lines below. body: | # Do not modify this line, instead modify the lines below.

View File

@ -3,7 +3,7 @@
announcement_date: "2022-02-22" # The date of the milestone release when this feature was first announced as deprecated. This should almost always be the 22nd of a month (YYYY-MM-22), unless you did an out of band blog post. announcement_date: "2022-02-22" # The date of the milestone release when this feature was first announced as deprecated. This should almost always be the 22nd of a month (YYYY-MM-22), unless you did an out of band blog post.
removal_milestone: "15.0" # The milestone when this feature is planned to be removed removal_milestone: "15.0" # The milestone when this feature is planned to be removed
removal_date: "2022-05-22" # The date of the milestone release when this feature was first announced as deprecated. This should almost always be the 22nd of a month (YYYY-MM-22), unless you did an out of band blog post. removal_date: "2022-05-22" # The date of the milestone release when this feature was first announced as deprecated. This should almost always be the 22nd of a month (YYYY-MM-22), unless you did an out of band blog post.
breaking_change: true # If this deprecation is a breaking change, set this value to true breaking_change: true # If this deprecation is a breaking change, set this value to true
body: | # Do not modify this line, instead modify the lines below. body: | # Do not modify this line, instead modify the lines below.
The `started` field in the [iterations API](https://docs.gitlab.com/ee/api/iterations.html#list-project-iterations) is being deprecated and will be removed in GitLab 15.0. This field is being replaced with the `current` field (already available) which aligns with the naming for other time-based entities, such as milestones. The `started` field in the [iterations API](https://docs.gitlab.com/ee/api/iterations.html#list-project-iterations) is being deprecated and will be removed in GitLab 15.0. This field is being replaced with the `current` field (already available) which aligns with the naming for other time-based entities, such as milestones.
# The following items are not published on the docs page, but may be used in the future. # The following items are not published on the docs page, but may be used in the future.

View File

@ -20,7 +20,7 @@
- [Distributed read capabilities](https://docs.gitlab.com/ee/administration/gitaly/#distributed-reads) - [Distributed read capabilities](https://docs.gitlab.com/ee/administration/gitaly/#distributed-reads)
# The following items are not published on the docs page, but may be used in the future. # The following items are not published on the docs page, but may be used in the future.
stage: Gitaly # (optional - may be required in the future) String value of the stage that the feature was created in. e.g., Growth stage: Gitaly # (optional - may be required in the future) String value of the stage that the feature was created in. e.g., Growth
tiers: # (optional - may be required in the future) An array of tiers that the feature is available in currently. e.g., [Free, Silver, Gold, Core, Premium, Ultimate] tiers: # (optional - may be required in the future) An array of tiers that the feature is available in currently. e.g., [Free, Silver, Gold, Core, Premium, Ultimate]
issue_url: # (optional) This is a link to the deprecation issue in GitLab issue_url: # (optional) This is a link to the deprecation issue in GitLab
documentation_url: # (optional) This is a link to the current documentation page documentation_url: # (optional) This is a link to the current documentation page

View File

@ -3,14 +3,14 @@
announcement_date: "2022-02-22" # The date of the milestone release when this feature was first announced as deprecated. This should almost always be the 22nd of a month (YYYY-MM-22), unless you did an out of band blog post. announcement_date: "2022-02-22" # The date of the milestone release when this feature was first announced as deprecated. This should almost always be the 22nd of a month (YYYY-MM-22), unless you did an out of band blog post.
removal_milestone: "15.0" # The milestone when this feature is planned to be removed removal_milestone: "15.0" # The milestone when this feature is planned to be removed
removal_date: "2022-05-22" # The date of the milestone release when this feature is planned to be removed. This should almost always be the 22nd of a month (YYYY-MM-22), unless you did an out of band blog post. removal_date: "2022-05-22" # The date of the milestone release when this feature is planned to be removed. This should almost always be the 22nd of a month (YYYY-MM-22), unless you did an out of band blog post.
breaking_change: true # If this deprecation is a breaking change, set this value to true breaking_change: true # If this deprecation is a breaking change, set this value to true
reporter: sarahwaldner # GitLab username of the person reporting the deprecation reporter: sarahwaldner # GitLab username of the person reporting the deprecation
body: | # Do not modify this line, instead modify the lines below. body: | # Do not modify this line, instead modify the lines below.
The feature flag `PUSH_RULES_SUPERSEDE_CODE_OWNERS` is being removed in GitLab 15.0. Upon its removal, push rules will supersede CODEOWNERS. The CODEOWNERS feature will no longer be available for access control. The feature flag `PUSH_RULES_SUPERSEDE_CODE_OWNERS` is being removed in GitLab 15.0. Upon its removal, push rules will supersede CODEOWNERS. The CODEOWNERS feature will no longer be available for access control.
# The following items are not published on the docs page, but may be used in the future. # The following items are not published on the docs page, but may be used in the future.
stage: create # (optional - may be required in the future) String value of the stage that the feature was created in. e.g., Growth stage: create # (optional - may be required in the future) String value of the stage that the feature was created in. e.g., Growth
tiers: # (optional - may be required in the future) An array of tiers that the feature is available in currently. e.g., [Free, Silver, Gold, Core, Premium, Ultimate] tiers: # (optional - may be required in the future) An array of tiers that the feature is available in currently. e.g., [Free, Silver, Gold, Core, Premium, Ultimate]
issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/262019 # (optional) This is a link to the deprecation issue in GitLab issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/262019 # (optional) This is a link to the deprecation issue in GitLab
documentation_url: # (optional) This is a link to the current documentation page documentation_url: # (optional) This is a link to the current documentation page
image_url: # (optional) This is a link to a thumbnail image depicting the feature image_url: # (optional) This is a link to a thumbnail image depicting the feature
video_url: # (optional) Use the youtube thumbnail URL with the structure of https://img.youtube.com/vi/UNIQUEID/hqdefault.jpg video_url: # (optional) Use the youtube thumbnail URL with the structure of https://img.youtube.com/vi/UNIQUEID/hqdefault.jpg

View File

@ -39,7 +39,7 @@
- `sobelow`: version 2 - `sobelow`: version 2
- `spotbugs`: version 2 - `spotbugs`: version 2
# The following items are not published on the docs page, but may be used in the future. # The following items are not published on the docs page, but may be used in the future.
stage: secure, protect # (optional - may be required in the future) String value of the stage that the feature was created in. e.g., Growth stage: secure, protect # (optional - may be required in the future) String value of the stage that the feature was created in. e.g., Growth
tiers: Free, Silver, Gold, Core, Premium, Ultimate # (optional - may be required in the future) An array of tiers that the feature is available in currently. e.g., [Free, Silver, Gold, Core, Premium, Ultimate] tiers: Free, Silver, Gold, Core, Premium, Ultimate # (optional - may be required in the future) An array of tiers that the feature is available in currently. e.g., [Free, Silver, Gold, Core, Premium, Ultimate]
issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/350936 # (optional) This is a link to the deprecation issue in GitLab issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/350936 # (optional) This is a link to the deprecation issue in GitLab
documentation_url: # (optional) This is a link to the current documentation page documentation_url: # (optional) This is a link to the current documentation page

View File

@ -2,8 +2,8 @@
announcement_milestone: "14.8" # The milestone when this feature was first announced as deprecated. announcement_milestone: "14.8" # The milestone when this feature was first announced as deprecated.
announcement_date: "2021-02-22" # The date of the milestone release when this feature was first announced as deprecated. This should almost always be the 22nd of a month (YYYY-MM-22), unless you did an out of band blog post. announcement_date: "2021-02-22" # The date of the milestone release when this feature was first announced as deprecated. This should almost always be the 22nd of a month (YYYY-MM-22), unless you did an out of band blog post.
removal_milestone: "15.0" # The milestone when this feature is planned to be removed removal_milestone: "15.0" # The milestone when this feature is planned to be removed
removal_date: 2021-05-22 # The date of the milestone release when this feature was first announced as deprecated. This should almost always be the 22nd of a month (YYYY-MM-22), unless you did an out of band blog post. removal_date: "2021-05-22" # The date of the milestone release when this feature was first announced as deprecated. This should almost always be the 22nd of a month (YYYY-MM-22), unless you did an out of band blog post.
breaking_change: true # If this deprecation is a breaking change, set this value to true breaking_change: true # If this deprecation is a breaking change, set this value to true
body: | # Do not modify this line, instead modify the lines below. body: | # Do not modify this line, instead modify the lines below.
For those using Dependency Scanning for Python projects, we are deprecating the default `gemnasium-python:2` image which uses Python 3.6 as well as the custom `gemnasium-python:2-python-3.9` image which uses Python 3.9. The new default image as of GitLab 15.0 will be for Python 3.9 as it is a [supported version](https://endoflife.date/python) and 3.6 [is no longer supported](https://endoflife.date/python). For those using Dependency Scanning for Python projects, we are deprecating the default `gemnasium-python:2` image which uses Python 3.6 as well as the custom `gemnasium-python:2-python-3.9` image which uses Python 3.9. The new default image as of GitLab 15.0 will be for Python 3.9 as it is a [supported version](https://endoflife.date/python) and 3.6 [is no longer supported](https://endoflife.date/python).
@ -25,9 +25,9 @@
name: registry.gitlab.com/gitlab-org/security-products/analyzers/gemnasium-python:2-python-3.9 name: registry.gitlab.com/gitlab-org/security-products/analyzers/gemnasium-python:2-python-3.9
``` ```
# The following items are not published on the docs page, but may be used in the future. # The following items are not published on the docs page, but may be used in the future.
stage: secure # (optional - may be required in the future) String value of the stage that the feature was created in. e.g., Growth stage: secure # (optional - may be required in the future) String value of the stage that the feature was created in. e.g., Growth
tiers: ultimate # (optional - may be required in the future) An array of tiers that the feature is available in currently. e.g., [Free, Silver, Gold, Core, Premium, Ultimate] tiers: ultimate # (optional - may be required in the future) An array of tiers that the feature is available in currently. e.g., [Free, Silver, Gold, Core, Premium, Ultimate]
issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/334060 # (optional) This is a link to the deprecation issue in GitLab issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/334060 # (optional) This is a link to the deprecation issue in GitLab
documentation_url: # (optional) This is a link to the current documentation page documentation_url: # (optional) This is a link to the current documentation page
image_url: # (optional) This is a link to a thumbnail image depicting the feature image_url: # (optional) This is a link to a thumbnail image depicting the feature
video_url: # (optional) Use the youtube thumbnail URL with the structure of https://img.youtube.com/vi/UNIQUEID/hqdefault.jpg video_url: # (optional) Use the youtube thumbnail URL with the structure of https://img.youtube.com/vi/UNIQUEID/hqdefault.jpg

View File

@ -3,13 +3,13 @@
announcement_date: "2022-01-22" # The date of the milestone release when this feature was first announced as deprecated. This should almost always be the 22nd of a month (YYYY-MM-22), unless you did an out of band blog post. announcement_date: "2022-01-22" # The date of the milestone release when this feature was first announced as deprecated. This should almost always be the 22nd of a month (YYYY-MM-22), unless you did an out of band blog post.
removal_milestone: "15.0" # The milestone when this feature is planned to be removed removal_milestone: "15.0" # The milestone when this feature is planned to be removed
removal_date: "2022-05-22" # The date of the milestone release when this feature was first announced as deprecated. This should almost always be the 22nd of a month (YYYY-MM-22), unless you did an out of band blog post. removal_date: "2022-05-22" # The date of the milestone release when this feature was first announced as deprecated. This should almost always be the 22nd of a month (YYYY-MM-22), unless you did an out of band blog post.
breaking_change: true # If this deprecation is a breaking change, set this value to true breaking_change: true # If this deprecation is a breaking change, set this value to true
body: | # Do not modify this line, instead modify the lines below. body: | # Do not modify this line, instead modify the lines below.
The logging features in GitLab allow users to install the ELK stack (Elasticsearch, Logstash, and Kibana) to aggregate and manage application logs. Users can search for relevant logs in GitLab. However, since deprecating certificate-based integration with Kubernetes clusters and GitLab Managed Apps, we don't have a recommended solution for logging within GitLab. For more information, you can follow the issue for [integrating Opstrace with GitLab](https://gitlab.com/groups/gitlab-org/-/epics/6976). The logging features in GitLab allow users to install the ELK stack (Elasticsearch, Logstash, and Kibana) to aggregate and manage application logs. Users can search for relevant logs in GitLab. However, since deprecating certificate-based integration with Kubernetes clusters and GitLab Managed Apps, we don't have a recommended solution for logging within GitLab. For more information, you can follow the issue for [integrating Opstrace with GitLab](https://gitlab.com/groups/gitlab-org/-/epics/6976).
# The following items are not published on the docs page, but may be used in the future. # The following items are not published on the docs page, but may be used in the future.
stage: Monitor # (optional - may be required in the future) String value of the stage that the feature was created in. e.g., Growth stage: Monitor # (optional - may be required in the future) String value of the stage that the feature was created in. e.g., Growth
tiers: [Free] # (optional - may be required in the future) An array of tiers that the feature is available in currently. e.g., [Free, Silver, Gold, Core, Premium, Ultimate] tiers: [Free] # (optional - may be required in the future) An array of tiers that the feature is available in currently. e.g., [Free, Silver, Gold, Core, Premium, Ultimate]
issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/346485 # (optional) This is a link to the deprecation issue in GitLab issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/346485 # (optional) This is a link to the deprecation issue in GitLab
documentation_url: https://docs.gitlab.com/ee/operations/#aggregate-and-store-logs-deprecated # (optional) This is a link to the current documentation page documentation_url: https://docs.gitlab.com/ee/operations/#aggregate-and-store-logs-deprecated # (optional) This is a link to the current documentation page
image_url: # (optional) This is a link to a thumbnail image depicting the feature image_url: # (optional) This is a link to a thumbnail image depicting the feature
video_url: # (optional) Use the youtube thumbnail URL with the structure of https://img.youtube.com/vi/UNIQUEID/hqdefault.jpg video_url: # (optional) Use the youtube thumbnail URL with the structure of https://img.youtube.com/vi/UNIQUEID/hqdefault.jpg

View File

@ -3,14 +3,14 @@
announcement_date: "2022-01-22" # The date of the milestone release when this feature was first announced as deprecated. This should almost always be the 22nd of a month (YYYY-MM-22), unless you did an out of band blog post. announcement_date: "2022-01-22" # The date of the milestone release when this feature was first announced as deprecated. This should almost always be the 22nd of a month (YYYY-MM-22), unless you did an out of band blog post.
removal_milestone: "15.0" # The milestone when this feature is planned to be removed removal_milestone: "15.0" # The milestone when this feature is planned to be removed
removal_date: "2022-05-22" # The date of the milestone release when this feature was first announced as deprecated. This should almost always be the 22nd of a month (YYYY-MM-22), unless you did an out of band blog post. removal_date: "2022-05-22" # The date of the milestone release when this feature was first announced as deprecated. This should almost always be the 22nd of a month (YYYY-MM-22), unless you did an out of band blog post.
breaking_change: true # If this deprecation is a breaking change, set this value to true breaking_change: true # If this deprecation is a breaking change, set this value to true
body: | # Do not modify this line, instead modify the lines below. body: | # Do not modify this line, instead modify the lines below.
By displaying data stored in a Prometheus instance, GitLab allows users to view performance metrics. GitLab also displays visualizations of these metrics in dashboards. The user can connect to a previously-configured external Prometheus instance, or set up Prometheus as a GitLab Managed App. By displaying data stored in a Prometheus instance, GitLab allows users to view performance metrics. GitLab also displays visualizations of these metrics in dashboards. The user can connect to a previously-configured external Prometheus instance, or set up Prometheus as a GitLab Managed App.
However, since certificate-based integration with Kubernetes clusters is deprecated in GitLab, the metrics functionality in GitLab that relies on Prometheus is also deprecated. This includes the metrics visualizations in dashboards. GitLab is working to develop a single user experience based on [Opstrace](https://about.gitlab.com/press/releases/2021-12-14-gitlab-acquires-opstrace-to-expand-its-devops-platform-with-open-source-observability-solution.html). An [issue exists](https://gitlab.com/groups/gitlab-org/-/epics/6976) for you to follow work on the Opstrace integration. However, since certificate-based integration with Kubernetes clusters is deprecated in GitLab, the metrics functionality in GitLab that relies on Prometheus is also deprecated. This includes the metrics visualizations in dashboards. GitLab is working to develop a single user experience based on [Opstrace](https://about.gitlab.com/press/releases/2021-12-14-gitlab-acquires-opstrace-to-expand-its-devops-platform-with-open-source-observability-solution.html). An [issue exists](https://gitlab.com/groups/gitlab-org/-/epics/6976) for you to follow work on the Opstrace integration.
# The following items are not published on the docs page, but may be used in the future. # The following items are not published on the docs page, but may be used in the future.
stage: Monitor # (optional - may be required in the future) String value of the stage that the feature was created in. e.g., Growth stage: Monitor # (optional - may be required in the future) String value of the stage that the feature was created in. e.g., Growth
tiers: [Free] # (optional - may be required in the future) An array of tiers that the feature is available in currently. e.g., [Free, Silver, Gold, Core, Premium, Ultimate] tiers: [Free] # (optional - may be required in the future) An array of tiers that the feature is available in currently. e.g., [Free, Silver, Gold, Core, Premium, Ultimate]
issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/346541 # (optional) This is a link to the deprecation issue in GitLab issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/346541 # (optional) This is a link to the deprecation issue in GitLab
documentation_url: https://docs.gitlab.com/ee/operations/metrics/dashboards/ # (optional) This is a link to the current documentation page documentation_url: https://docs.gitlab.com/ee/operations/metrics/dashboards/ # (optional) This is a link to the current documentation page
image_url: # (optional) This is a link to a thumbnail image depicting the feature image_url: # (optional) This is a link to a thumbnail image depicting the feature
video_url: # (optional) Use the youtube thumbnail URL with the structure of https://img.youtube.com/vi/UNIQUEID/hqdefault.jpg video_url: # (optional) Use the youtube thumbnail URL with the structure of https://img.youtube.com/vi/UNIQUEID/hqdefault.jpg

View File

@ -3,13 +3,13 @@
announcement_date: "2022-01-22" # The date of the milestone release when this feature was first announced as deprecated. This should almost always be the 22nd of a month (YYYY-MM-22), unless you did an out of band blog post. announcement_date: "2022-01-22" # The date of the milestone release when this feature was first announced as deprecated. This should almost always be the 22nd of a month (YYYY-MM-22), unless you did an out of band blog post.
removal_milestone: "15.0" # The milestone when this feature is planned to be removed removal_milestone: "15.0" # The milestone when this feature is planned to be removed
removal_date: "2022-05-22" # The date of the milestone release when this feature was first announced as deprecated. This should almost always be the 22nd of a month (YYYY-MM-22), unless you did an out of band blog post. removal_date: "2022-05-22" # The date of the milestone release when this feature was first announced as deprecated. This should almost always be the 22nd of a month (YYYY-MM-22), unless you did an out of band blog post.
breaking_change: true # If this deprecation is a breaking change, set this value to true breaking_change: true # If this deprecation is a breaking change, set this value to true
body: | # Do not modify this line, instead modify the lines below. body: | # Do not modify this line, instead modify the lines below.
Tracing in GitLab is an integration with Jaeger, an open-source end-to-end distributed tracing system. GitLab users can navigate to their Jaeger instance to gain insight into the performance of a deployed application, tracking each function or microservice that handles a given request. Tracing in GitLab is deprecated in GitLab 14.7, and scheduled for removal in 15.0. To track work on a possible replacement, see the issue for [Opstrace integration with GitLab](https://gitlab.com/groups/gitlab-org/-/epics/6976). Tracing in GitLab is an integration with Jaeger, an open-source end-to-end distributed tracing system. GitLab users can navigate to their Jaeger instance to gain insight into the performance of a deployed application, tracking each function or microservice that handles a given request. Tracing in GitLab is deprecated in GitLab 14.7, and scheduled for removal in 15.0. To track work on a possible replacement, see the issue for [Opstrace integration with GitLab](https://gitlab.com/groups/gitlab-org/-/epics/6976).
# The following items are not published on the docs page, but may be used in the future. # The following items are not published on the docs page, but may be used in the future.
stage: Monitor # (optional - may be required in the future) String value of the stage that the feature was created in. e.g., Growth stage: Monitor # (optional - may be required in the future) String value of the stage that the feature was created in. e.g., Growth
tiers: [Free] # (optional - may be required in the future) An array of tiers that the feature is available in currently. e.g., [Free, Silver, Gold, Core, Premium, Ultimate] tiers: [Free] # (optional - may be required in the future) An array of tiers that the feature is available in currently. e.g., [Free, Silver, Gold, Core, Premium, Ultimate]
issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/346540 # (optional) This is a link to the deprecation issue in GitLab issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/346540 # (optional) This is a link to the deprecation issue in GitLab
documentation_url: https://docs.gitlab.com/ee/operations/tracing.html#tracing # (optional) This is a link to the current documentation page documentation_url: https://docs.gitlab.com/ee/operations/tracing.html#tracing # (optional) This is a link to the current documentation page
image_url: # (optional) This is a link to a thumbnail image depicting the feature image_url: # (optional) This is a link to a thumbnail image depicting the feature
video_url: # (optional) Use the youtube thumbnail URL with the structure of https://img.youtube.com/vi/UNIQUEID/hqdefault.jpg video_url: # (optional) Use the youtube thumbnail URL with the structure of https://img.youtube.com/vi/UNIQUEID/hqdefault.jpg

View File

@ -2,8 +2,8 @@
announcement_milestone: "14.8" # The milestone when this feature was first announced as deprecated. announcement_milestone: "14.8" # The milestone when this feature was first announced as deprecated.
announcement_date: "2022-02-22" # The date of the milestone release when this feature was first announced as deprecated. This should almost always be the 22nd of a month (YYYY-MM-22), unless you did an out of band blog post. announcement_date: "2022-02-22" # The date of the milestone release when this feature was first announced as deprecated. This should almost always be the 22nd of a month (YYYY-MM-22), unless you did an out of band blog post.
removal_milestone: "15.0" # The milestone when this feature is planned to be removed removal_milestone: "15.0" # The milestone when this feature is planned to be removed
removal_date: 2022-05-22 # The date of the milestone release when this feature was first announced as deprecated. This should almost always be the 22nd of a month (YYYY-MM-22), unless you did an out of band blog post. removal_date: "2022-05-22" # The date of the milestone release when this feature was first announced as deprecated. This should almost always be the 22nd of a month (YYYY-MM-22), unless you did an out of band blog post.
breaking_change: true # If this deprecation is a breaking change, set this value to true breaking_change: true # If this deprecation is a breaking change, set this value to true
body: | # Do not modify this line, instead modify the lines below. body: | # Do not modify this line, instead modify the lines below.
By default, all new applications expire access tokens after 2 hours. In GitLab 14.2 and earlier, OAuth access tokens By default, all new applications expire access tokens after 2 hours. In GitLab 14.2 and earlier, OAuth access tokens
had no expiration. In GitLab 15.0, an expiry will be automatically generated for any existing token that does not had no expiration. In GitLab 15.0, an expiry will be automatically generated for any existing token that does not

View File

@ -2,7 +2,7 @@
announcement_milestone: "14.0" # The milestone when this feature was first announced as deprecated. announcement_milestone: "14.0" # The milestone when this feature was first announced as deprecated.
announcement_date: "2021-06-22" # The date of the milestone release when this feature was first announced as deprecated. This should almost always be the 22nd of a month (YYYY-MM-22), unless you did an out of band blog post. announcement_date: "2021-06-22" # The date of the milestone release when this feature was first announced as deprecated. This should almost always be the 22nd of a month (YYYY-MM-22), unless you did an out of band blog post.
removal_milestone: "15.0" # The milestone when this feature is planned to be removed removal_milestone: "15.0" # The milestone when this feature is planned to be removed
removal_date: 2022-05-22 # The date of the milestone release when this feature was first announced as deprecated. This should almost always be the 22nd of a month (YYYY-MM-22), unless you did an out of band blog post. removal_date: "2022-05-22" # The date of the milestone release when this feature was first announced as deprecated. This should almost always be the 22nd of a month (YYYY-MM-22), unless you did an out of band blog post.
breaking_change: yes # If this deprecation is a breaking change, set this value to true breaking_change: yes # If this deprecation is a breaking change, set this value to true
body: | # Do not modify this line, instead modify the lines below. body: | # Do not modify this line, instead modify the lines below.
The OAuth implicit grant authorization flow will be removed in our next major release, GitLab 15.0. Any applications that use OAuth implicit grant should switch to alternative [supported OAuth flows](https://docs.gitlab.com/ee/api/oauth2.html). The OAuth implicit grant authorization flow will be removed in our next major release, GitLab 15.0. Any applications that use OAuth implicit grant should switch to alternative [supported OAuth flows](https://docs.gitlab.com/ee/api/oauth2.html).

View File

@ -1,7 +1,7 @@
- name: "Max job log file size of 100 MB" - name: "Max job log file size of 100 MB"
removal_date: August 22, 2021 # day the removal was released removal_date: August 22, 2021 # day the removal was released
removal_milestone: "14.2" removal_milestone: "14.2"
reporter: jreporter # GitLab username of the person reporting the removal reporter: jreporter # GitLab username of the person reporting the removal
breaking_change: false breaking_change: false
body: | body: |
GitLab values efficiency for all users in our wider community of contributors, so we're always working hard to make sure the application performs at a high level with a lovable UX. GitLab values efficiency for all users in our wider community of contributors, so we're always working hard to make sure the application performs at a high level with a lovable UX.

View File

@ -5,5 +5,5 @@
breaking_change: false breaking_change: false
body: | # example (supports markdown) body: | # example (supports markdown)
The support for [`gitlab_pages['use_legacy_storage']` setting](https://docs.gitlab.com/ee/administration/pages/index.html#domain-source-configuration-before-140) in Omnibus installations has been removed. The support for [`gitlab_pages['use_legacy_storage']` setting](https://docs.gitlab.com/ee/administration/pages/index.html#domain-source-configuration-before-140) in Omnibus installations has been removed.
In 14.0 we removed [`domain_config_source`](https://docs.gitlab.com/ee/administration/pages/index.html#domain-source-configuration-before-140) which had been previously deprecated, and allowed users to specify disk storage. In 14.0 we added `use_legacy_storage` as a **temporary** flag to unblock upgrades, and allow us to debug issues with our users and it was deprecated and communicated for removal in 14.3. In 14.0 we removed [`domain_config_source`](https://docs.gitlab.com/ee/administration/pages/index.html#domain-source-configuration-before-140) which had been previously deprecated, and allowed users to specify disk storage. In 14.0 we added `use_legacy_storage` as a **temporary** flag to unblock upgrades, and allow us to debug issues with our users and it was deprecated and communicated for removal in 14.3.

View File

@ -1,6 +1,6 @@
- name: "Limit the number of triggered pipeline to 25K in free tier" - name: "Limit the number of triggered pipeline to 25K in free tier"
removal_date: Dec 22, 2021 # day the removal was released removal_date: Dec 22, 2021 # day the removal was released
removal_milestone: "14.6" removal_milestone: "14.6"
reporter: dhershkovitch # GitLab username of the person reporting the removal reporter: dhershkovitch # GitLab username of the person reporting the removal
body: | body: |
A large amount of triggered pipelines in a single project impacts the performance of GitLab.com. In GitLab 14.6, we are limiting the number of triggered pipelines in a single project on GitLab.com at any given moment to 25,000. This change applies to projects in the free tier only, Premium and Ultimate are not affected by this change. A large amount of triggered pipelines in a single project impacts the performance of GitLab.com. In GitLab 14.6, we are limiting the number of triggered pipelines in a single project on GitLab.com at any given moment to 25,000. This change applies to projects in the free tier only, Premium and Ultimate are not affected by this change.

View File

@ -1,6 +1,6 @@
- name: "Release CLI distributed as a generic package" - name: "Release CLI distributed as a generic package"
removal_date: Dec 22, 2021 # day the removal was released removal_date: Dec 22, 2021 # day the removal was released
removal_milestone: "14.6" removal_milestone: "14.6"
reporter: kbychu # GitLab username of the person reporting the removal reporter: kbychu # GitLab username of the person reporting the removal
body: | body: |
The [release-cli](https://gitlab.com/gitlab-org/release-cli) will be released as a [generic package](https://gitlab.com/gitlab-org/release-cli/-/packages) starting in GitLab 14.2. We will continue to deploy it as a binary to S3 until GitLab 14.5 and stop distributing it in S3 in GitLab 14.6. The [release-cli](https://gitlab.com/gitlab-org/release-cli) will be released as a [generic package](https://gitlab.com/gitlab-org/release-cli/-/packages) starting in GitLab 14.2. We will continue to deploy it as a binary to S3 until GitLab 14.5 and stop distributing it in S3 in GitLab 14.6.

View File

@ -0,0 +1,17 @@
# frozen_string_literal: true
class AddIndexToIssues < Gitlab::Database::Migration[1.0]
DOWNTIME = false
disable_ddl_transaction!
INDEX_NAME = 'index_issues_on_id_and_weight'
def up
add_concurrent_index :issues, [:id, :weight], name: INDEX_NAME
end
def down
remove_concurrent_index_by_name :issues, INDEX_NAME
end
end

View File

@ -0,0 +1,25 @@
# frozen_string_literal: true
class ScheduleMigratePersonalNamespaceProjectMaintainerToOwner < Gitlab::Database::Migration[1.0]
MIGRATION = 'MigratePersonalNamespaceProjectMaintainerToOwner'
INTERVAL = 2.minutes
BATCH_SIZE = 1_000
SUB_BATCH_SIZE = 200
disable_ddl_transaction!
def up
queue_batched_background_migration(
MIGRATION,
:members,
:id,
job_interval: INTERVAL,
batch_size: BATCH_SIZE,
sub_batch_size: SUB_BATCH_SIZE
)
end
def down
# no-op
end
end

View File

@ -0,0 +1 @@
688232dde01ea4e8574dca73459094264bde405d799ecaf1a5867adb72576b98

View File

@ -0,0 +1 @@
84346c2f608792f259ab91dbc2c8aac8397a2997f890f8e077aad809276bb7cd

View File

@ -27884,6 +27884,8 @@ CREATE INDEX index_issues_on_description_trigram ON issues USING gin (descriptio
CREATE INDEX index_issues_on_duplicated_to_id ON issues USING btree (duplicated_to_id) WHERE (duplicated_to_id IS NOT NULL); CREATE INDEX index_issues_on_duplicated_to_id ON issues USING btree (duplicated_to_id) WHERE (duplicated_to_id IS NOT NULL);
CREATE INDEX index_issues_on_id_and_weight ON issues USING btree (id, weight);
CREATE INDEX index_issues_on_incident_issue_type ON issues USING btree (issue_type) WHERE (issue_type = 1); CREATE INDEX index_issues_on_incident_issue_type ON issues USING btree (issue_type) WHERE (issue_type = 1);
CREATE INDEX index_issues_on_last_edited_by_id ON issues USING btree (last_edited_by_id); CREATE INDEX index_issues_on_last_edited_by_id ON issues USING btree (last_edited_by_id);

View File

@ -208,13 +208,18 @@ When the number exceeds the limit the page displays an alert and links to a pagi
> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/51401) in GitLab 11.10. > [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/51401) in GitLab 11.10.
The number of pipelines that can be created in a single push is 4. When pushing multiple changes with a single Git push, like multiple tags or branches,
This limit prevents the accidental creation of pipelines when `git push --all` only four tag or branch pipelines can be triggered. This limit prevents the accidental
or `git push --mirror` is used. creation of a large number of pipelines when using `git push --all` or `git push --mirror`.
This limit does not affect any of the updated merge request pipelines. [Merge request pipelines](../ci/pipelines/merge_request_pipelines.md) are not limited.
All updated merge requests have a pipeline created when using If the Git push updates multiple merge requests at the same time, a merge request pipeline
[merge request pipelines](../ci/pipelines/merge_request_pipelines.md). can trigger for every updated merge request.
To remove the limit so that any number of pipelines can trigger for a single Git push event,
administrators can enable the `git_push_create_all_pipelines` [feature flag](feature_flags.md).
Enabling this feature flag is not recommended, as it can cause excessive load on the GitLab
instance if too many changes are pushed at once and a flood of pipelines are created accidentally.
## Retention of activity history ## Retention of activity history

View File

@ -10759,10 +10759,11 @@ Represents an epic board list.
| Name | Type | Description | | Name | Type | Description |
| ---- | ---- | ----------- | | ---- | ---- | ----------- |
| <a id="epiclistcollapsed"></a>`collapsed` | [`Boolean`](#boolean) | Indicates if this list is collapsed for this user. | | <a id="epiclistcollapsed"></a>`collapsed` | [`Boolean`](#boolean) | Indicates if this list is collapsed for this user. |
| <a id="epiclistepicscount"></a>`epicsCount` | [`Int`](#int) | Count of epics in the list. | | <a id="epiclistepicscount"></a>`epicsCount` **{warning-solid}** | [`Int`](#int) | **Deprecated** in 14.9. This was renamed. Use: `metadata`. |
| <a id="epiclistid"></a>`id` | [`BoardsEpicListID!`](#boardsepiclistid) | Global ID of the board list. | | <a id="epiclistid"></a>`id` | [`BoardsEpicListID!`](#boardsepiclistid) | Global ID of the board list. |
| <a id="epiclistlabel"></a>`label` | [`Label`](#label) | Label of the list. | | <a id="epiclistlabel"></a>`label` | [`Label`](#label) | Label of the list. |
| <a id="epiclistlisttype"></a>`listType` | [`String!`](#string) | Type of the list. | | <a id="epiclistlisttype"></a>`listType` | [`String!`](#string) | Type of the list. |
| <a id="epiclistmetadata"></a>`metadata` | [`EpicListMetadata`](#epiclistmetadata) | Epic list metatada. |
| <a id="epiclistposition"></a>`position` | [`Int`](#int) | Position of the list within the board. | | <a id="epiclistposition"></a>`position` | [`Int`](#int) | Position of the list within the board. |
| <a id="epiclisttitle"></a>`title` | [`String!`](#string) | Title of the list. | | <a id="epiclisttitle"></a>`title` | [`String!`](#string) | Title of the list. |
@ -10784,6 +10785,17 @@ four standard [pagination arguments](#connection-pagination-arguments):
| ---- | ---- | ----------- | | ---- | ---- | ----------- |
| <a id="epiclistepicsfilters"></a>`filters` | [`EpicFilters`](#epicfilters) | Filters applied when selecting epics in the board list. | | <a id="epiclistepicsfilters"></a>`filters` | [`EpicFilters`](#epicfilters) | Filters applied when selecting epics in the board list. |
### `EpicListMetadata`
Represents epic board list metadata.
#### Fields
| Name | Type | Description |
| ---- | ---- | ----------- |
| <a id="epiclistmetadataepicscount"></a>`epicsCount` | [`Int`](#int) | Count of epics in the list. |
| <a id="epiclistmetadatatotalweight"></a>`totalWeight` | [`Int`](#int) | Total weight of all issues in the list. Available only when feature flag `epic_board_total_weight` is enabled. This flag is disabled by default, because the feature is experimental and is subject to change without notice. |
### `EpicPermissions` ### `EpicPermissions`
Check permissions for the current user on an epic. Check permissions for the current user on an epic.
@ -15271,6 +15283,7 @@ Represents the security scan information.
| ---- | ---- | ----------- | | ---- | ---- | ----------- |
| <a id="scanerrors"></a>`errors` | [`[String!]!`](#string) | List of errors. | | <a id="scanerrors"></a>`errors` | [`[String!]!`](#string) | List of errors. |
| <a id="scanname"></a>`name` | [`String!`](#string) | Name of the scan. | | <a id="scanname"></a>`name` | [`String!`](#string) | Name of the scan. |
| <a id="scanstatus"></a>`status` | [`ScanStatus!`](#scanstatus) | Indicates the status of the scan. |
| <a id="scanwarnings"></a>`warnings` | [`[String!]!`](#string) | List of warnings. | | <a id="scanwarnings"></a>`warnings` | [`[String!]!`](#string) | List of warnings. |
### `ScanExecutionPolicy` ### `ScanExecutionPolicy`
@ -18142,6 +18155,20 @@ Size of UI component in SAST configuration page.
| <a id="sastuicomponentsizemedium"></a>`MEDIUM` | Size of UI component in SAST configuration page is medium. | | <a id="sastuicomponentsizemedium"></a>`MEDIUM` | Size of UI component in SAST configuration page is medium. |
| <a id="sastuicomponentsizesmall"></a>`SMALL` | Size of UI component in SAST configuration page is small. | | <a id="sastuicomponentsizesmall"></a>`SMALL` | Size of UI component in SAST configuration page is small. |
### `ScanStatus`
The status of the security scan.
| Value | Description |
| ----- | ----------- |
| <a id="scanstatuscreated"></a>`CREATED` | The scan has been created. |
| <a id="scanstatusjob_failed"></a>`JOB_FAILED` | The related CI build failed. |
| <a id="scanstatuspreparation_failed"></a>`PREPARATION_FAILED` | Report couldn't be prepared. |
| <a id="scanstatuspreparing"></a>`PREPARING` | Preparing the report for the scan. |
| <a id="scanstatuspurged"></a>`PURGED` | Report for the scan has been removed from the database. |
| <a id="scanstatusreport_error"></a>`REPORT_ERROR` | The report artifact provided by the CI build couldn't be parsed. |
| <a id="scanstatussucceeded"></a>`SUCCEEDED` | The report has been successfully prepared. |
### `SecurityReportTypeEnum` ### `SecurityReportTypeEnum`
| Value | Description | | Value | Description |

View File

@ -12,9 +12,6 @@ info: To determine the technical writer assigned to the Stage/Group associated w
> - It's enabled on GitLab.com. > - It's enabled on GitLab.com.
> - It's recommended for production use. > - It's recommended for production use.
WARNING:
This feature might not be available to you. Check the **version history** note above for details.
Usage Trends gives you an overview of how much data your instance contains, and how quickly this volume is changing over time. Usage Trends gives you an overview of how much data your instance contains, and how quickly this volume is changing over time.
Usage Trends data refreshes daily. Usage Trends data refreshes daily.

View File

@ -219,7 +219,7 @@ security issues:
WARNING: WARNING:
This feature is in its end-of-life process. It is [deprecated](../../update/deprecations.md#vulnerability-check) This feature is in its end-of-life process. It is [deprecated](../../update/deprecations.md#vulnerability-check)
for use in GitLab 14.8, and is planned for removal in GitLab 15.0. Users should migrate to the new for use in GitLab 14.8, and is planned for removal in GitLab 15.0. Users should migrate to the new
[Security Approval Policies](policies/#scan-result-policy-editor). [Security Approval Policies](policies/scan-result-policies.md).
To prevent a merge request introducing a security vulnerability in a project, enable the To prevent a merge request introducing a security vulnerability in a project, enable the
Vulnerability-Check rule. While this rule is enabled, additional merge request approval by Vulnerability-Check rule. While this rule is enabled, additional merge request approval by

View File

@ -12,16 +12,15 @@ info: To determine the technical writer assigned to the Stage/Group associated w
> - [Moved](https://gitlab.com/groups/gitlab-org/-/epics/6290) to GitLab Free in 14.5. > - [Moved](https://gitlab.com/groups/gitlab-org/-/epics/6290) to GitLab Free in 14.5.
> - Support for Omnibus installations was [introduced](https://gitlab.com/gitlab-org/omnibus-gitlab/-/merge_requests/5686) in GitLab 14.5. > - Support for Omnibus installations was [introduced](https://gitlab.com/gitlab-org/omnibus-gitlab/-/merge_requests/5686) in GitLab 14.5.
You can use GitLab CI/CD to safely deploy to and update your Kubernetes clusters. You can use a GitLab CI/CD workflow to safely deploy to and update your Kubernetes clusters.
To do so, you install a GitLab agent in your cluster. Then in your GitLab CI/CD pipelines, To do so, you must first [install an agent in your cluster](install/index.md). When done, you have a Kubernetes context and can
you can refer to the cluster connection as a Kubernetes context. run Kubernetes API commands in your GitLab CI/CD pipeline.
Then you can run Kubernetes API commands as part of your GitLab CI/CD pipeline.
To ensure access to your cluster is safe: To ensure access to your cluster is safe:
- Each agent has a separate context (`kubecontext`). - Each agent has a separate context (`kubecontext`).
- Only the project where the agent is, and any additional projects you authorize can access the agent in your cluster. - Only the project where the agent is configured, and any additional projects you authorize, can access the agent in your cluster.
You do not need to have a runner in the cluster with the agent. You do not need to have a runner in the cluster with the agent.

View File

@ -14,7 +14,22 @@ info: To determine the technical writer assigned to the Stage/Group associated w
> - [Renamed](https://gitlab.com/groups/gitlab-org/-/epics/7167) from "GitLab Kubernetes Agent" to "GitLab agent for Kubernetes" in GitLab 14.6. > - [Renamed](https://gitlab.com/groups/gitlab-org/-/epics/7167) from "GitLab Kubernetes Agent" to "GitLab agent for Kubernetes" in GitLab 14.6.
You can connect your Kubernetes cluster with GitLab to deploy, manage, You can connect your Kubernetes cluster with GitLab to deploy, manage,
and monitor your cloud-native solutions. You can choose from two primary workflows. and monitor your cloud-native solutions.
To connect a Kubernetes cluster to GitLab, you must first [install an agent in your cluster](install/index.md).
The agent runs in the cluster, and you can use it to:
- Communicate with a cluster, which is behind a firewall or NAT.
- Access API endpoints in a cluster in real time.
- Push information about events happening in the cluster.
- Enable a cache of Kubernetes objects, which are kept up-to-date with very low latency.
For more details about the agent's purpose and architecture, see the [architecture documentation](https://gitlab.com/gitlab-org/cluster-integration/gitlab-agent/-/blob/master/doc/architecture.md).
## Workflows
You can choose from two primary workflows.
In a [**GitOps** workflow](gitops.md), you keep your Kubernetes manifests in GitLab. You install a GitLab agent in your cluster, and In a [**GitOps** workflow](gitops.md), you keep your Kubernetes manifests in GitLab. You install a GitLab agent in your cluster, and
any time you update your manifests, the agent updates the cluster. This workflow is fully driven with Git and is considered pull-based, any time you update your manifests, the agent updates the cluster. This workflow is fully driven with Git and is considered pull-based,
@ -23,8 +38,6 @@ because the cluster is pulling updates from your GitLab repository.
In a [**CI/CD** workflow](ci_cd_tunnel.md), you use GitLab CI/CD to query and update your cluster by using the Kubernetes API. In a [**CI/CD** workflow](ci_cd_tunnel.md), you use GitLab CI/CD to query and update your cluster by using the Kubernetes API.
This workflow is considered push-based, because GitLab is pushing requests from GitLab CI/CD to your cluster. This workflow is considered push-based, because GitLab is pushing requests from GitLab CI/CD to your cluster.
Both of these workflows require you to [install an agent in your cluster](install/index.md).
## Supported cluster versions ## Supported cluster versions
GitLab supports the following Kubernetes versions. You can upgrade your GitLab supports the following Kubernetes versions. You can upgrade your

View File

@ -12,7 +12,7 @@ module API
desc 'Get the current application statistics' do desc 'Get the current application statistics' do
success Entities::ApplicationStatistics success Entities::ApplicationStatistics
end end
get "application/statistics" do get "application/statistics", urgency: :low do
counts = Gitlab::Database::Count.approximate_counts(COUNTED_ITEMS) counts = Gitlab::Database::Count.approximate_counts(COUNTED_ITEMS)
present counts, with: Entities::ApplicationStatistics present counts, with: Entities::ApplicationStatistics
end end

View File

@ -10,6 +10,21 @@ module ContainerRegistry
REGISTRY_FEATURES_HEADER = 'gitlab-container-registry-features' REGISTRY_FEATURES_HEADER = 'gitlab-container-registry-features'
REGISTRY_TAG_DELETE_FEATURE = 'tag_delete' REGISTRY_TAG_DELETE_FEATURE = 'tag_delete'
ALLOWED_REDIRECT_SCHEMES = %w[http https].freeze
REDIRECT_OPTIONS = {
clear_authorization_header: true,
limit: 3,
cookies: [],
callback: -> (response_env, request_env) do
request_env.request_headers.delete(::FaradayMiddleware::FollowRedirects::AUTH_HEADER)
redirect_to = request_env.url
unless redirect_to.scheme.in?(ALLOWED_REDIRECT_SCHEMES)
raise ArgumentError, "Invalid scheme for #{redirect_to}"
end
end
}.freeze
def self.supports_tag_delete? def self.supports_tag_delete?
with_dummy_client(return_value_if_disabled: false) do |client| with_dummy_client(return_value_if_disabled: false) do |client|
client.supports_tag_delete? client.supports_tag_delete?
@ -136,6 +151,10 @@ module ContainerRegistry
def faraday_blob def faraday_blob
@faraday_blob ||= faraday_base do |conn| @faraday_blob ||= faraday_base do |conn|
initialize_connection(conn, @options) initialize_connection(conn, @options)
if Feature.enabled?(:container_registry_follow_redirects_middleware)
conn.use ::FaradayMiddleware::FollowRedirects, REDIRECT_OPTIONS
end
end end
end end
end end

View File

@ -0,0 +1,45 @@
# frozen_string_literal: true
module Gitlab
module BackgroundMigration
# Migrates personal namespace project `maintainer` memberships (for the associated user only) to OWNER
# Does not create any missing records, simply migrates existing ones
class MigratePersonalNamespaceProjectMaintainerToOwner
include Gitlab::Database::DynamicModelHelpers
def perform(start_id, end_id, batch_table, batch_column, sub_batch_size, pause_ms)
parent_batch_relation = relation_scoped_to_range(batch_table, batch_column, start_id, end_id)
parent_batch_relation.each_batch(column: batch_column, of: sub_batch_size) do |sub_batch|
batch_metrics.time_operation(:update_all) do
sub_batch.update_all('access_level = 50')
end
pause_ms = 0 if pause_ms < 0
sleep(pause_ms * 0.001)
end
end
def batch_metrics
@batch_metrics ||= Gitlab::Database::BackgroundMigration::BatchMetrics.new
end
private
def relation_scoped_to_range(source_table, source_key_column, start_id, stop_id)
# members of projects within their own personal namespace
# rubocop: disable CodeReuse/ActiveRecord
define_batchable_model(:members, connection: ApplicationRecord.connection)
.where(source_key_column => start_id..stop_id)
.joins("INNER JOIN projects ON members.source_id = projects.id")
.joins("INNER JOIN namespaces ON projects.namespace_id = namespaces.id")
.where(type: 'ProjectMember')
.where("namespaces.type = 'User'")
.where('members.access_level < 50')
.where('namespaces.owner_id = members.user_id')
end
end
# rubocop: enable CodeReuse/ActiveRecord
end
end

View File

@ -16777,6 +16777,15 @@ msgstr ""
msgid "GithubIntegration|This requires mirroring your GitHub repository to this project. %{docs_link}" msgid "GithubIntegration|This requires mirroring your GitHub repository to this project. %{docs_link}"
msgstr "" msgstr ""
msgid "GitlabTiers|Free"
msgstr ""
msgid "GitlabTiers|Premium"
msgstr ""
msgid "GitlabTiers|Ultimate"
msgstr ""
msgid "Gitpod" msgid "Gitpod"
msgstr "" msgstr ""
@ -26990,6 +26999,9 @@ msgstr ""
msgid "Pipelines|GitLab Runner is an application that works with GitLab CI/CD to run jobs in a pipeline. There are active runners available to run your jobs right now. If you prefer, you can %{settingsLinkStart}configure your runners%{settingsLinkEnd} or %{docsLinkStart}learn more%{docsLinkEnd} about runners." msgid "Pipelines|GitLab Runner is an application that works with GitLab CI/CD to run jobs in a pipeline. There are active runners available to run your jobs right now. If you prefer, you can %{settingsLinkStart}configure your runners%{settingsLinkEnd} or %{docsLinkStart}learn more%{docsLinkEnd} about runners."
msgstr "" msgstr ""
msgid "Pipelines|Gitlab Premium users have access to the multi-project pipeline graph to improve the visualization of these pipelines. %{linkStart}Learn More%{linkEnd}"
msgstr ""
msgid "Pipelines|If you are unsure, please ask a project maintainer to review it for you." msgid "Pipelines|If you are unsure, please ask a project maintainer to review it for you."
msgstr "" msgstr ""
@ -27029,6 +27041,9 @@ msgstr ""
msgid "Pipelines|More Information" msgid "Pipelines|More Information"
msgstr "" msgstr ""
msgid "Pipelines|Multi-project pipeline graphs"
msgstr ""
msgid "Pipelines|No runners detected" msgid "Pipelines|No runners detected"
msgstr "" msgstr ""
@ -27179,9 +27194,6 @@ msgstr ""
msgid "Pipeline|Checking pipeline status." msgid "Pipeline|Checking pipeline status."
msgstr "" msgstr ""
msgid "Pipeline|Commit"
msgstr ""
msgid "Pipeline|Could not retrieve the pipeline status. For troubleshooting steps, read the %{linkStart}documentation%{linkEnd}." msgid "Pipeline|Could not retrieve the pipeline status. For troubleshooting steps, read the %{linkStart}documentation%{linkEnd}."
msgstr "" msgstr ""
@ -27197,9 +27209,6 @@ msgstr ""
msgid "Pipeline|Detached merge request pipeline" msgid "Pipeline|Detached merge request pipeline"
msgstr "" msgstr ""
msgid "Pipeline|Duration"
msgstr ""
msgid "Pipeline|Failed" msgid "Pipeline|Failed"
msgstr "" msgstr ""
@ -27743,6 +27752,9 @@ msgstr ""
msgid "Preferences|When you type in a description or comment box, selected text is surrounded by the corresponding character after typing one of the following characters: %{supported_characters}." msgid "Preferences|When you type in a description or comment box, selected text is surrounded by the corresponding character after typing one of the following characters: %{supported_characters}."
msgstr "" msgstr ""
msgid "Preparing the report for the scan."
msgstr ""
msgid "Prev" msgid "Prev"
msgstr "" msgstr ""
@ -30798,6 +30810,12 @@ msgstr ""
msgid "Report abuse to admin" msgid "Report abuse to admin"
msgstr "" msgstr ""
msgid "Report couldn't be prepared."
msgstr ""
msgid "Report for the scan has been removed from the database."
msgstr ""
msgid "Reported %{timeAgo} by %{reportedBy}" msgid "Reported %{timeAgo} by %{reportedBy}"
msgstr "" msgstr ""
@ -36831,6 +36849,9 @@ msgstr ""
msgid "The regular expression used to find test coverage output in the job log. For example, use %{regex} for Simplecov (Ruby). Leave blank to disable." msgid "The regular expression used to find test coverage output in the job log. For example, use %{regex} for Simplecov (Ruby). Leave blank to disable."
msgstr "" msgstr ""
msgid "The related CI build failed."
msgstr ""
msgid "The remote mirror URL is invalid." msgid "The remote mirror URL is invalid."
msgstr "" msgstr ""
@ -36840,6 +36861,12 @@ msgstr ""
msgid "The remote repository is being updated..." msgid "The remote repository is being updated..."
msgstr "" msgstr ""
msgid "The report artifact provided by the CI build couldn't be parsed."
msgstr ""
msgid "The report has been successfully prepared."
msgstr ""
msgid "The repository can be committed to, and issues, comments and other entities can be created." msgid "The repository can be committed to, and issues, comments and other entities can be created."
msgstr "" msgstr ""
@ -36861,6 +36888,9 @@ msgstr ""
msgid "The same shared runner executes code from multiple projects, unless you configure autoscaling with %{link} set to 1 (which it is on GitLab.com)." msgid "The same shared runner executes code from multiple projects, unless you configure autoscaling with %{link} set to 1 (which it is on GitLab.com)."
msgstr "" msgstr ""
msgid "The scan has been created."
msgstr ""
msgid "The snippet can be accessed without any authentication." msgid "The snippet can be accessed without any authentication."
msgstr "" msgstr ""
@ -37314,7 +37344,7 @@ msgstr ""
msgid "This %{issuable} is locked. Only %{strong_open}project members%{strong_close} can comment." msgid "This %{issuable} is locked. Only %{strong_open}project members%{strong_close} can comment."
msgstr "" msgstr ""
msgid "This %{noteableTypeText} is %{confidentialLinkStart}confidential%{linkEnd} and %{lockedLinkStart}locked%{linkEnd}." msgid "This %{noteableTypeText} is %{confidentialLinkStart}confidential%{confidentialLinkEnd} and %{lockedLinkStart}locked%{lockedLinkEnd}."
msgstr "" msgstr ""
msgid "This %{noteableTypeText} is locked." msgid "This %{noteableTypeText} is locked."

View File

@ -24,6 +24,7 @@ module QA
view 'app/assets/javascripts/pipelines/components/graph/linked_pipeline.vue' do view 'app/assets/javascripts/pipelines/components/graph/linked_pipeline.vue' do
element :expand_pipeline_button element :expand_pipeline_button
element :child_pipeline element :child_pipeline
element :linked_pipeline_body
end end
view 'app/assets/javascripts/reports/components/report_section.vue' do view 'app/assets/javascripts/reports/components/report_section.vue' do
@ -93,7 +94,7 @@ module QA
end end
def find_child_pipeline_by_title(title) def find_child_pipeline_by_title(title)
child_pipelines.find { |pipeline| pipeline[:title].include?(title) } find_element(:child_pipeline, text: title)
end end
def expand_child_pipeline(title: nil) def expand_child_pipeline(title: nil)

View File

@ -1,104 +0,0 @@
# frozen_string_literal: true
module QA
RSpec.describe 'Verify', :runner do
describe 'Pass dotenv variables to downstream via bridge' do
let(:executor) { "qa-runner-#{Faker::Alphanumeric.alphanumeric(8)}" }
let(:upstream_var) { Faker::Alphanumeric.alphanumeric(8) }
let(:group) { Resource::Group.fabricate_via_api! }
let(:upstream_project) do
Resource::Project.fabricate_via_api! do |project|
project.group = group
project.name = 'upstream-project-with-bridge'
end
end
let(:downstream_project) do
Resource::Project.fabricate_via_api! do |project|
project.group = group
project.name = 'downstream-project-with-bridge'
end
end
let!(:runner) do
Resource::Runner.fabricate! do |runner|
runner.name = executor
runner.tags = [executor]
runner.token = group.reload!.runners_token
end
end
before do
Flow::Login.sign_in
add_ci_file(downstream_project, downstream_ci_file)
add_ci_file(upstream_project, upstream_ci_file)
upstream_project.visit!
Flow::Pipeline.visit_latest_pipeline(pipeline_condition: 'succeeded')
end
after do
runner.remove_via_api!
[upstream_project, downstream_project].each(&:remove_via_api!)
end
it 'runs the pipeline with composed config', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/348088' do
Page::Project::Pipeline::Show.perform do |parent_pipeline|
Support::Waiter.wait_until { parent_pipeline.has_child_pipeline? }
parent_pipeline.expand_child_pipeline
parent_pipeline.click_job('downstream_test')
end
Page::Project::Job::Show.perform do |show|
expect(show).to have_passed(timeout: 360)
expect(show.output).to have_content(upstream_var)
end
end
private
def add_ci_file(project, file)
Resource::Repository::Commit.fabricate_via_api! do |commit|
commit.project = project
commit.commit_message = 'Add config file'
commit.add_files([file])
end
end
def upstream_ci_file
{
file_path: '.gitlab-ci.yml',
content: <<~YAML
build:
stage: build
tags: ["#{executor}"]
script:
- echo "DYNAMIC_ENVIRONMENT_VAR=#{upstream_var}" >> variables.env
artifacts:
reports:
dotenv: variables.env
trigger:
stage: deploy
variables:
PASSED_MY_VAR: $DYNAMIC_ENVIRONMENT_VAR
trigger: #{downstream_project.full_path}
YAML
}
end
def downstream_ci_file
{
file_path: '.gitlab-ci.yml',
content: <<~YAML
downstream_test:
stage: test
tags: ["#{executor}"]
script:
- echo $PASSED_MY_VAR
YAML
}
end
end
end
end

View File

@ -56,7 +56,7 @@ module QA
end end
Page::Project::Job::Show.perform do |show| Page::Project::Job::Show.perform do |show|
expect(show).to have_passed(timeout: 360) expect(show).to have_passed(timeout: 800)
end end
end end
end end

View File

@ -125,7 +125,6 @@ RSpec.describe 'Merge request > User sees pipelines', :js do
before do before do
stub_feature_flags(ci_disallow_to_create_merge_request_pipelines_in_target_project: false) stub_feature_flags(ci_disallow_to_create_merge_request_pipelines_in_target_project: false)
stub_feature_flags(rearrange_pipelines_table: false)
end end
it 'creates a pipeline in the parent project when user proceeds with the warning' do it 'creates a pipeline in the parent project when user proceeds with the warning' do

View File

@ -161,51 +161,7 @@ RSpec.describe 'Pipelines', :js do
end end
end end
context 'when pipeline is detached merge request pipeline, with rearrange_pipelines_table feature flag turned off' do context 'when pipeline is detached merge request pipeline' do
let(:merge_request) do
create(:merge_request,
:with_detached_merge_request_pipeline,
source_project: source_project,
target_project: target_project)
end
let!(:pipeline) { merge_request.all_pipelines.first }
let(:source_project) { project }
let(:target_project) { project }
before do
stub_feature_flags(rearrange_pipelines_table: false)
visit project_pipelines_path(source_project)
end
shared_examples_for 'detached merge request pipeline' do
it 'shows pipeline information without pipeline ref', :sidekiq_might_not_need_inline do
within '.pipeline-tags' do
expect(page).to have_content(expected_detached_mr_tag)
end
within '.branch-commit' do
expect(page).to have_link(merge_request.iid,
href: project_merge_request_path(project, merge_request))
end
within '.branch-commit' do
expect(page).not_to have_link(pipeline.ref)
end
end
end
it_behaves_like 'detached merge request pipeline'
context 'when source project is a forked project' do
let(:source_project) { fork_project(project, user, repository: true) }
it_behaves_like 'detached merge request pipeline'
end
end
context 'when pipeline is detached merge request pipeline, with rearrange_pipelines_table feature flag turned on' do
let(:merge_request) do let(:merge_request) do
create(:merge_request, create(:merge_request,
:with_detached_merge_request_pipeline, :with_detached_merge_request_pipeline,
@ -218,8 +174,6 @@ RSpec.describe 'Pipelines', :js do
let(:target_project) { project } let(:target_project) { project }
before do before do
stub_feature_flags(rearrange_pipelines_table: true)
visit project_pipelines_path(source_project) visit project_pipelines_path(source_project)
end end
@ -245,52 +199,7 @@ RSpec.describe 'Pipelines', :js do
end end
end end
context 'when pipeline is merge request pipeline, with rearrange_pipelines_table feature flag turned off' do context 'when pipeline is merge request pipeline' do
let(:merge_request) do
create(:merge_request,
:with_merge_request_pipeline,
source_project: source_project,
target_project: target_project,
merge_sha: target_project.commit.sha)
end
let!(:pipeline) { merge_request.all_pipelines.first }
let(:source_project) { project }
let(:target_project) { project }
before do
stub_feature_flags(rearrange_pipelines_table: false)
visit project_pipelines_path(source_project)
end
shared_examples_for 'Correct merge request pipeline information' do
it 'does not show detached tag for the pipeline, and shows the link of the merge request, and does not show the ref of the pipeline', :sidekiq_might_not_need_inline do
within '.pipeline-tags' do
expect(page).not_to have_content(expected_detached_mr_tag)
end
within '.branch-commit' do
expect(page).to have_link(merge_request.iid,
href: project_merge_request_path(project, merge_request))
end
within '.branch-commit' do
expect(page).not_to have_link(pipeline.ref)
end
end
end
it_behaves_like 'Correct merge request pipeline information'
context 'when source project is a forked project' do
let(:source_project) { fork_project(project, user, repository: true) }
it_behaves_like 'Correct merge request pipeline information'
end
end
context 'when pipeline is merge request pipeline, with rearrange_pipelines_table feature flag turned on' do
let(:merge_request) do let(:merge_request) do
create(:merge_request, create(:merge_request,
:with_merge_request_pipeline, :with_merge_request_pipeline,
@ -304,8 +213,6 @@ RSpec.describe 'Pipelines', :js do
let(:target_project) { project } let(:target_project) { project }
before do before do
stub_feature_flags(rearrange_pipelines_table: true)
visit project_pipelines_path(source_project) visit project_pipelines_path(source_project)
end end
@ -676,28 +583,6 @@ RSpec.describe 'Pipelines', :js do
context 'with pipeline key selection' do context 'with pipeline key selection' do
before do before do
stub_feature_flags(rearrange_pipelines_table: false)
visit project_pipelines_path(project)
wait_for_requests
end
it 'changes the Pipeline ID column for Pipeline IID' do
page.find('[data-testid="pipeline-key-dropdown"]').click
within '.gl-new-dropdown-contents' do
dropdown_options = page.find_all '.gl-new-dropdown-item'
dropdown_options[1].click
end
expect(page.find('[data-testid="pipeline-th"]')).to have_content 'Pipeline IID'
expect(page.find('[data-testid="pipeline-url-link"]')).to have_content "##{pipeline.iid}"
end
end
context 'with pipeline key selection and rearrange_pipelines_table ff on' do
before do
stub_feature_flags(rearrange_pipelines_table: true)
visit project_pipelines_path(project) visit project_pipelines_path(project)
wait_for_requests wait_for_requests
end end

View File

@ -93,5 +93,38 @@ describe('DirtySubmitForm', () => {
expect(updateDirtyInputSpy).toHaveBeenCalledTimes(range.length); expect(updateDirtyInputSpy).toHaveBeenCalledTimes(range.length);
}); });
describe('when inputs listener is added', () => {
it('calls listener when changes are made to an input', () => {
const { form, input } = createForm();
const inputsListener = jest.fn();
const dirtySubmitForm = new DirtySubmitForm(form);
dirtySubmitForm.addInputsListener(inputsListener);
setInputValue(input, 'new value');
jest.runOnlyPendingTimers();
expect(inputsListener).toHaveBeenCalledTimes(1);
});
describe('when inputs listener is removed', () => {
it('does not call listener when changes are made to an input', () => {
const { form, input } = createForm();
const inputsListener = jest.fn();
const dirtySubmitForm = new DirtySubmitForm(form);
dirtySubmitForm.addInputsListener(inputsListener);
dirtySubmitForm.removeInputsListener(inputsListener);
setInputValue(input, 'new value');
jest.runOnlyPendingTimers();
expect(inputsListener).not.toHaveBeenCalled();
});
});
});
}); });
}); });

View File

@ -1,4 +1,4 @@
import { GlIntersectionObserver, GlSkeletonLoader } from '@gitlab/ui'; import { GlIntersectionObserver, GlSkeletonLoader, GlLoadingIcon } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils'; import { shallowMount } from '@vue/test-utils';
import Vue from 'vue'; import Vue from 'vue';
import VueApollo from 'vue-apollo'; import VueApollo from 'vue-apollo';
@ -19,6 +19,7 @@ describe('Jobs app', () => {
let resolverSpy; let resolverSpy;
const findSkeletonLoader = () => wrapper.findComponent(GlSkeletonLoader); const findSkeletonLoader = () => wrapper.findComponent(GlSkeletonLoader);
const findLoadingSpinner = () => wrapper.findComponent(GlLoadingIcon);
const findJobsTable = () => wrapper.findComponent(JobsTable); const findJobsTable = () => wrapper.findComponent(JobsTable);
const triggerInfiniteScroll = () => const triggerInfiniteScroll = () =>
@ -48,7 +49,29 @@ describe('Jobs app', () => {
wrapper.destroy(); wrapper.destroy();
}); });
it('displays the loading state', () => { describe('loading spinner', () => {
beforeEach(async () => {
createComponent(resolverSpy);
await waitForPromises();
triggerInfiniteScroll();
});
it('displays loading spinner when fetching more jobs', () => {
expect(findLoadingSpinner().exists()).toBe(true);
expect(findSkeletonLoader().exists()).toBe(false);
});
it('hides loading spinner after jobs have been fetched', async () => {
await waitForPromises();
expect(findLoadingSpinner().exists()).toBe(false);
expect(findSkeletonLoader().exists()).toBe(false);
});
});
it('displays the skeleton loader', () => {
createComponent(resolverSpy); createComponent(resolverSpy);
expect(findSkeletonLoader().exists()).toBe(true); expect(findSkeletonLoader().exists()).toBe(true);
@ -91,7 +114,7 @@ describe('Jobs app', () => {
}); });
}); });
it('does not display main loading state again after fetchMore', async () => { it('does not display skeleton loader again after fetchMore', async () => {
createComponent(resolverSpy); createComponent(resolverSpy);
expect(findSkeletonLoader().exists()).toBe(true); expect(findSkeletonLoader().exists()).toBe(true);

View File

@ -66,7 +66,6 @@ describe('graph component', () => {
afterEach(() => { afterEach(() => {
wrapper.destroy(); wrapper.destroy();
wrapper = null;
}); });
describe('with data', () => { describe('with data', () => {

View File

@ -1,5 +1,5 @@
import { GlButton, GlLoadingIcon } from '@gitlab/ui'; import { GlButton, GlLoadingIcon, GlPopover } from '@gitlab/ui';
import { mount } from '@vue/test-utils'; import { mountExtended } from 'helpers/vue_test_utils_helper';
import { BV_HIDE_TOOLTIP } from '~/lib/utils/constants'; import { BV_HIDE_TOOLTIP } from '~/lib/utils/constants';
import { UPSTREAM, DOWNSTREAM } from '~/pipelines/components/graph/constants'; import { UPSTREAM, DOWNSTREAM } from '~/pipelines/components/graph/constants';
import LinkedPipelineComponent from '~/pipelines/components/graph/linked_pipeline.vue'; import LinkedPipelineComponent from '~/pipelines/components/graph/linked_pipeline.vue';
@ -9,15 +9,20 @@ import mockPipeline from './linked_pipelines_mock_data';
describe('Linked pipeline', () => { describe('Linked pipeline', () => {
let wrapper; let wrapper;
const defaultProps = {
pipeline: mockPipeline,
columnTitle: 'Downstream',
type: DOWNSTREAM,
expanded: false,
isLoading: false,
isMultiProjectVizAvailable: true,
};
const downstreamProps = { const downstreamProps = {
pipeline: { pipeline: {
...mockPipeline, ...mockPipeline,
multiproject: false, multiproject: false,
}, },
columnTitle: 'Downstream',
type: DOWNSTREAM,
expanded: false,
isLoading: false,
}; };
const upstreamProps = { const upstreamProps = {
@ -27,21 +32,29 @@ describe('Linked pipeline', () => {
}; };
const findButton = () => wrapper.find(GlButton); const findButton = () => wrapper.find(GlButton);
const findDownstreamPipelineTitle = () => wrapper.find('[data-testid="downstream-title"]'); const findDownstreamPipelineTitle = () => wrapper.findByTestId('downstream-title');
const findPipelineLabel = () => wrapper.find('[data-testid="downstream-pipeline-label"]'); const findPipelineLabel = () => wrapper.findByTestId('downstream-pipeline-label');
const findLinkedPipeline = () => wrapper.find({ ref: 'linkedPipeline' }); const findLinkedPipeline = () => wrapper.findByTestId('linkedPipeline');
const findLinkedPipelineBody = () => wrapper.findByTestId('linkedPipelineBody');
const findLoadingIcon = () => wrapper.find(GlLoadingIcon); const findLoadingIcon = () => wrapper.find(GlLoadingIcon);
const findPipelineLink = () => wrapper.find('[data-testid="pipelineLink"]'); const findPipelineLink = () => wrapper.findByTestId('pipelineLink');
const findExpandButton = () => wrapper.find('[data-testid="expand-pipeline-button"]'); const findExpandButton = () => wrapper.findByTestId('expand-pipeline-button');
const findPopover = () => wrapper.find(GlPopover);
const createWrapper = (propsData, data = []) => { const createWrapper = (propsData, data = []) => {
wrapper = mount(LinkedPipelineComponent, { wrapper = mountExtended(LinkedPipelineComponent, {
propsData, propsData: {
...defaultProps,
...propsData,
},
data() { data() {
return { return {
...data, ...data,
}; };
}, },
provide: {
multiProjectHelpPath: '/ci/pipelines/multi-project-pipelines',
},
}); });
}; };
@ -92,7 +105,7 @@ describe('Linked pipeline', () => {
}); });
it('should render the tooltip text as the title attribute', () => { it('should render the tooltip text as the title attribute', () => {
const titleAttr = findLinkedPipeline().attributes('title'); const titleAttr = findLinkedPipelineBody().attributes('title');
expect(titleAttr).toContain(mockPipeline.project.name); expect(titleAttr).toContain(mockPipeline.project.name);
expect(titleAttr).toContain(mockPipeline.status.label); expect(titleAttr).toContain(mockPipeline.status.label);
@ -168,10 +181,6 @@ describe('Linked pipeline', () => {
describe('when isLoading is true', () => { describe('when isLoading is true', () => {
const props = { const props = {
pipeline: mockPipeline,
columnTitle: 'Downstream',
type: DOWNSTREAM,
expanded: false,
isLoading: true, isLoading: true,
}; };
@ -184,19 +193,43 @@ describe('Linked pipeline', () => {
}); });
}); });
describe('on click/hover', () => { describe('when the user does not have access to the multi-project pipeline viz feature', () => {
const props = {
pipeline: mockPipeline,
columnTitle: 'Downstream',
type: DOWNSTREAM,
expanded: false,
isLoading: false,
};
beforeEach(() => { beforeEach(() => {
const props = { isMultiProjectVizAvailable: false };
createWrapper(props); createWrapper(props);
}); });
it('the multi-project expand button is disabled', () => {
expect(findExpandButton().props('disabled')).toBe(true);
});
it('it adds the popover text inside the DOM', () => {
expect(findPopover().exists()).toBe(true);
expect(findPopover().text()).toContain(
'Gitlab Premium users have access to the multi-project pipeline graph to improve the visualization of these pipelines.',
);
});
});
describe('when the user has access to the multi-project pipeline viz feature', () => {
beforeEach(() => {
createWrapper();
});
it('the multi-project expand button is enabled', () => {
expect(findExpandButton().props('disabled')).toBe(false);
});
it('does not add the popover text inside the DOM', () => {
expect(findPopover().exists()).toBe(false);
});
});
describe('on click/hover', () => {
beforeEach(() => {
createWrapper();
});
it('emits `pipelineClicked` event', () => { it('emits `pipelineClicked` event', () => {
jest.spyOn(wrapper.vm, '$emit'); jest.spyOn(wrapper.vm, '$emit');
findButton().trigger('click'); findButton().trigger('click');

View File

@ -26,6 +26,7 @@ const processedPipeline = pipelineWithUpstreamDownstream(mockPipelineResponse);
describe('Linked Pipelines Column', () => { describe('Linked Pipelines Column', () => {
const defaultProps = { const defaultProps = {
columnTitle: 'Downstream', columnTitle: 'Downstream',
isMultiProjectVizAvailable: true,
linkedPipelines: processedPipeline.downstream, linkedPipelines: processedPipeline.downstream,
showLinks: false, showLinks: false,
type: DOWNSTREAM, type: DOWNSTREAM,
@ -51,6 +52,9 @@ describe('Linked Pipelines Column', () => {
...defaultProps, ...defaultProps,
...props, ...props,
}, },
provide: {
multiProjectHelpPath: 'ci/pipelines/multi-project-pipeline',
},
}); });
}; };
@ -67,7 +71,6 @@ describe('Linked Pipelines Column', () => {
afterEach(() => { afterEach(() => {
wrapper.destroy(); wrapper.destroy();
wrapper = null;
}); });
describe('it renders correctly', () => { describe('it renders correctly', () => {

View File

@ -13,6 +13,15 @@ export const mockPipelineResponse = {
usesNeeds: true, usesNeeds: true,
downstream: null, downstream: null,
upstream: null, upstream: null,
user: {
__typename: 'UserCore',
id: 'gid://gitlab/User/1',
namespace: {
__typename: 'Namespace',
id: 'gid://gitlab/Namespaces::UserNamespace/1',
crossProjectPipelineAvailable: true,
},
},
userPermissions: { userPermissions: {
__typename: 'PipelinePermissions', __typename: 'PipelinePermissions',
updatePipeline: true, updatePipeline: true,
@ -780,6 +789,15 @@ export const wrappedPipelineReturn = {
id: 'gid://gitlab/Ci::Pipeline/175', id: 'gid://gitlab/Ci::Pipeline/175',
iid: '38', iid: '38',
complete: true, complete: true,
user: {
__typename: 'UserCore',
id: 'gid://gitlab/User/1',
namespace: {
__typename: 'Namespace',
id: 'gid://gitlab/Namespaces::UserNamespace/1',
crossProjectPipelineAvailable: true,
},
},
usesNeeds: true, usesNeeds: true,
userPermissions: { userPermissions: {
__typename: 'PipelinePermissions', __typename: 'PipelinePermissions',

View File

@ -30,14 +30,11 @@ describe('Pipeline Url Component', () => {
const defaultProps = mockPipeline(projectPath); const defaultProps = mockPipeline(projectPath);
const createComponent = (props, rearrangePipelinesTable = false) => { const createComponent = (props) => {
wrapper = shallowMountExtended(PipelineUrlComponent, { wrapper = shallowMountExtended(PipelineUrlComponent, {
propsData: { ...defaultProps, ...props }, propsData: { ...defaultProps, ...props },
provide: { provide: {
targetProjectFullPath: projectPath, targetProjectFullPath: projectPath,
glFeatures: {
rearrangePipelinesTable,
},
}, },
}); });
}; };
@ -47,190 +44,176 @@ describe('Pipeline Url Component', () => {
wrapper = null; wrapper = null;
}); });
describe('with the rearrangePipelinesTable feature flag turned off', () => { it('should render pipeline url table cell', () => {
it('should render pipeline url table cell', () => { createComponent();
createComponent();
expect(findTableCell().exists()).toBe(true); expect(findTableCell().exists()).toBe(true);
});
it('should render a link the provided path and id', () => {
createComponent();
expect(findPipelineUrlLink().attributes('href')).toBe('foo');
expect(findPipelineUrlLink().text()).toBe('#1');
});
it('should not render tags when flags are not set', () => {
createComponent();
expect(findStuckTag().exists()).toBe(false);
expect(findLatestTag().exists()).toBe(false);
expect(findYamlTag().exists()).toBe(false);
expect(findAutoDevopsTag().exists()).toBe(false);
expect(findFailureTag().exists()).toBe(false);
expect(findScheduledTag().exists()).toBe(false);
expect(findForkTag().exists()).toBe(false);
expect(findTrainTag().exists()).toBe(false);
});
it('should render the stuck tag when flag is provided', () => {
const stuckPipeline = defaultProps.pipeline;
stuckPipeline.flags.stuck = true;
createComponent({
...stuckPipeline.pipeline,
}); });
it('should render a link the provided path and id', () => { expect(findStuckTag().text()).toContain('stuck');
createComponent(); });
expect(findPipelineUrlLink().attributes('href')).toBe('foo'); it('should render latest tag when flag is provided', () => {
const latestPipeline = defaultProps.pipeline;
latestPipeline.flags.latest = true;
expect(findPipelineUrlLink().text()).toBe('#1'); createComponent({
...latestPipeline,
}); });
it('should not render tags when flags are not set', () => { expect(findLatestTag().text()).toContain('latest');
createComponent(); });
expect(findStuckTag().exists()).toBe(false); it('should render a yaml badge when it is invalid', () => {
expect(findLatestTag().exists()).toBe(false); const yamlPipeline = defaultProps.pipeline;
expect(findYamlTag().exists()).toBe(false); yamlPipeline.flags.yaml_errors = true;
expect(findAutoDevopsTag().exists()).toBe(false);
expect(findFailureTag().exists()).toBe(false); createComponent({
expect(findScheduledTag().exists()).toBe(false); ...yamlPipeline,
expect(findForkTag().exists()).toBe(false);
expect(findTrainTag().exists()).toBe(false);
}); });
it('should render the stuck tag when flag is provided', () => { expect(findYamlTag().text()).toContain('yaml invalid');
const stuckPipeline = defaultProps.pipeline; });
stuckPipeline.flags.stuck = true;
createComponent({ it('should render an autodevops badge when flag is provided', () => {
...stuckPipeline.pipeline, const autoDevopsPipeline = defaultProps.pipeline;
}); autoDevopsPipeline.flags.auto_devops = true;
expect(findStuckTag().text()).toContain('stuck'); createComponent({
...autoDevopsPipeline,
}); });
it('should render latest tag when flag is provided', () => { expect(trimText(findAutoDevopsTag().text())).toBe('Auto DevOps');
const latestPipeline = defaultProps.pipeline;
latestPipeline.flags.latest = true;
createComponent({ expect(findAutoDevopsTagLink().attributes()).toMatchObject({
...latestPipeline, href: '/help/topics/autodevops/index.md',
}); target: '_blank',
expect(findLatestTag().text()).toContain('latest');
});
it('should render a yaml badge when it is invalid', () => {
const yamlPipeline = defaultProps.pipeline;
yamlPipeline.flags.yaml_errors = true;
createComponent({
...yamlPipeline,
});
expect(findYamlTag().text()).toContain('yaml invalid');
});
it('should render an autodevops badge when flag is provided', () => {
const autoDevopsPipeline = defaultProps.pipeline;
autoDevopsPipeline.flags.auto_devops = true;
createComponent({
...autoDevopsPipeline,
});
expect(trimText(findAutoDevopsTag().text())).toBe('Auto DevOps');
expect(findAutoDevopsTagLink().attributes()).toMatchObject({
href: '/help/topics/autodevops/index.md',
target: '_blank',
});
});
it('should render a detached badge when flag is provided', () => {
const detachedMRPipeline = defaultProps.pipeline;
detachedMRPipeline.flags.detached_merge_request_pipeline = true;
createComponent({
...detachedMRPipeline,
});
expect(findDetachedTag().text()).toBe('merge request');
});
it('should render error badge when pipeline has a failure reason set', () => {
const failedPipeline = defaultProps.pipeline;
failedPipeline.flags.failure_reason = true;
failedPipeline.failure_reason = 'some reason';
createComponent({
...failedPipeline,
});
expect(findFailureTag().text()).toContain('error');
expect(findFailureTag().attributes('title')).toContain('some reason');
});
it('should render scheduled badge when pipeline was triggered by a schedule', () => {
const scheduledPipeline = defaultProps.pipeline;
scheduledPipeline.source = 'schedule';
createComponent({
...scheduledPipeline,
});
expect(findScheduledTag().exists()).toBe(true);
expect(findScheduledTag().text()).toContain('Scheduled');
});
it('should render the fork badge when the pipeline was run in a fork', () => {
const forkedPipeline = defaultProps.pipeline;
forkedPipeline.project.full_path = '/test/forked';
createComponent({
...forkedPipeline,
});
expect(findForkTag().exists()).toBe(true);
expect(findForkTag().text()).toBe('fork');
});
it('should render the train badge when the pipeline is a merge train pipeline', () => {
const mergeTrainPipeline = defaultProps.pipeline;
mergeTrainPipeline.flags.merge_train_pipeline = true;
createComponent({
...mergeTrainPipeline,
});
expect(findTrainTag().text()).toBe('merge train');
});
it('should not render the train badge when the pipeline is not a merge train pipeline', () => {
const mergeTrainPipeline = defaultProps.pipeline;
mergeTrainPipeline.flags.merge_train_pipeline = false;
createComponent({
...mergeTrainPipeline,
});
expect(findTrainTag().exists()).toBe(false);
});
it('should not render the commit wrapper and commit-short-sha', () => {
createComponent();
expect(findCommitTitleContainer().exists()).toBe(false);
expect(findCommitShortSha().exists()).toBe(false);
}); });
}); });
describe('with the rearrangePipelinesTable feature flag turned on', () => { it('should render a detached badge when flag is provided', () => {
it('should render the commit title, commit reference and commit-short-sha', () => { const detachedMRPipeline = defaultProps.pipeline;
createComponent({}, true); detachedMRPipeline.flags.detached_merge_request_pipeline = true;
const commitWrapper = findCommitTitleContainer(); createComponent({
...detachedMRPipeline,
expect(findCommitTitle(commitWrapper).exists()).toBe(true);
expect(findRefName().exists()).toBe(true);
expect(findCommitShortSha().exists()).toBe(true);
}); });
it('should render commit icon tooltip', () => { expect(findDetachedTag().text()).toBe('merge request');
createComponent({}, true); });
expect(findCommitIcon().attributes('title')).toBe('Commit'); it('should render error badge when pipeline has a failure reason set', () => {
const failedPipeline = defaultProps.pipeline;
failedPipeline.flags.failure_reason = true;
failedPipeline.failure_reason = 'some reason';
createComponent({
...failedPipeline,
}); });
it.each` expect(findFailureTag().text()).toContain('error');
pipeline | expectedTitle expect(findFailureTag().attributes('title')).toContain('some reason');
${mockPipelineTag()} | ${'Tag'} });
${mockPipelineBranch()} | ${'Branch'}
${mockPipeline()} | ${'Merge Request'}
`(
'should render tooltip $expectedTitle for commit icon type',
({ pipeline, expectedTitle }) => {
createComponent(pipeline, true);
expect(findCommitIconType().attributes('title')).toBe(expectedTitle); it('should render scheduled badge when pipeline was triggered by a schedule', () => {
}, const scheduledPipeline = defaultProps.pipeline;
); scheduledPipeline.source = 'schedule';
createComponent({
...scheduledPipeline,
});
expect(findScheduledTag().exists()).toBe(true);
expect(findScheduledTag().text()).toContain('Scheduled');
});
it('should render the fork badge when the pipeline was run in a fork', () => {
const forkedPipeline = defaultProps.pipeline;
forkedPipeline.project.full_path = '/test/forked';
createComponent({
...forkedPipeline,
});
expect(findForkTag().exists()).toBe(true);
expect(findForkTag().text()).toBe('fork');
});
it('should render the train badge when the pipeline is a merge train pipeline', () => {
const mergeTrainPipeline = defaultProps.pipeline;
mergeTrainPipeline.flags.merge_train_pipeline = true;
createComponent({
...mergeTrainPipeline,
});
expect(findTrainTag().text()).toBe('merge train');
});
it('should not render the train badge when the pipeline is not a merge train pipeline', () => {
const mergeTrainPipeline = defaultProps.pipeline;
mergeTrainPipeline.flags.merge_train_pipeline = false;
createComponent({
...mergeTrainPipeline,
});
expect(findTrainTag().exists()).toBe(false);
});
it('should render the commit title, commit reference and commit-short-sha', () => {
createComponent({}, true);
const commitWrapper = findCommitTitleContainer();
expect(findCommitTitle(commitWrapper).exists()).toBe(true);
expect(findRefName().exists()).toBe(true);
expect(findCommitShortSha().exists()).toBe(true);
});
it('should render commit icon tooltip', () => {
createComponent({}, true);
expect(findCommitIcon().attributes('title')).toBe('Commit');
});
it.each`
pipeline | expectedTitle
${mockPipelineTag()} | ${'Tag'}
${mockPipelineBranch()} | ${'Branch'}
${mockPipeline()} | ${'Merge Request'}
`('should render tooltip $expectedTitle for commit icon type', ({ pipeline, expectedTitle }) => {
createComponent(pipeline, true);
expect(findCommitIconType().attributes('title')).toBe(expectedTitle);
}); });
}); });

View File

@ -17,7 +17,6 @@ import {
import eventHub from '~/pipelines/event_hub'; import eventHub from '~/pipelines/event_hub';
import CiBadge from '~/vue_shared/components/ci_badge_link.vue'; import CiBadge from '~/vue_shared/components/ci_badge_link.vue';
import CommitComponent from '~/vue_shared/components/commit.vue';
jest.mock('~/pipelines/event_hub'); jest.mock('~/pipelines/event_hub');
@ -37,18 +36,13 @@ describe('Pipelines Table', () => {
return pipelines.find((p) => p.user !== null && p.commit !== null); return pipelines.find((p) => p.user !== null && p.commit !== null);
}; };
const createComponent = (props = {}, rearrangePipelinesTable = false) => { const createComponent = (props = {}) => {
wrapper = extendedWrapper( wrapper = extendedWrapper(
mount(PipelinesTable, { mount(PipelinesTable, {
propsData: { propsData: {
...defaultProps, ...defaultProps,
...props, ...props,
}, },
provide: {
glFeatures: {
rearrangePipelinesTable,
},
},
}), }),
); );
}; };
@ -57,7 +51,6 @@ describe('Pipelines Table', () => {
const findStatusBadge = () => wrapper.findComponent(CiBadge); const findStatusBadge = () => wrapper.findComponent(CiBadge);
const findPipelineInfo = () => wrapper.findComponent(PipelineUrl); const findPipelineInfo = () => wrapper.findComponent(PipelineUrl);
const findTriggerer = () => wrapper.findComponent(PipelineTriggerer); const findTriggerer = () => wrapper.findComponent(PipelineTriggerer);
const findCommit = () => wrapper.findComponent(CommitComponent);
const findPipelineMiniGraph = () => wrapper.findComponent(PipelineMiniGraph); const findPipelineMiniGraph = () => wrapper.findComponent(PipelineMiniGraph);
const findTimeAgo = () => wrapper.findComponent(PipelinesTimeago); const findTimeAgo = () => wrapper.findComponent(PipelinesTimeago);
const findActions = () => wrapper.findComponent(PipelineOperations); const findActions = () => wrapper.findComponent(PipelineOperations);
@ -65,10 +58,7 @@ describe('Pipelines Table', () => {
const findTableRows = () => wrapper.findAllByTestId('pipeline-table-row'); const findTableRows = () => wrapper.findAllByTestId('pipeline-table-row');
const findStatusTh = () => wrapper.findByTestId('status-th'); const findStatusTh = () => wrapper.findByTestId('status-th');
const findPipelineTh = () => wrapper.findByTestId('pipeline-th'); const findPipelineTh = () => wrapper.findByTestId('pipeline-th');
const findTriggererTh = () => wrapper.findByTestId('triggerer-th');
const findCommitTh = () => wrapper.findByTestId('commit-th');
const findStagesTh = () => wrapper.findByTestId('stages-th'); const findStagesTh = () => wrapper.findByTestId('stages-th');
const findTimeAgoTh = () => wrapper.findByTestId('timeago-th');
const findActionsTh = () => wrapper.findByTestId('actions-th'); const findActionsTh = () => wrapper.findByTestId('actions-th');
const findRetryBtn = () => wrapper.findByTestId('pipelines-retry-button'); const findRetryBtn = () => wrapper.findByTestId('pipelines-retry-button');
const findCancelBtn = () => wrapper.findByTestId('pipelines-cancel-button'); const findCancelBtn = () => wrapper.findByTestId('pipelines-cancel-button');
@ -82,7 +72,7 @@ describe('Pipelines Table', () => {
wrapper = null; wrapper = null;
}); });
describe('Pipelines Table with rearrangePipelinesTable feature flag turned off', () => { describe('Pipelines Table', () => {
beforeEach(() => { beforeEach(() => {
createComponent({ pipelines: [pipeline], viewType: 'root' }); createComponent({ pipelines: [pipeline], viewType: 'root' });
}); });
@ -93,11 +83,8 @@ describe('Pipelines Table', () => {
it('should render table head with correct columns', () => { it('should render table head with correct columns', () => {
expect(findStatusTh().text()).toBe('Status'); expect(findStatusTh().text()).toBe('Status');
expect(findPipelineTh().text()).toBe('Pipeline ID'); expect(findPipelineTh().text()).toBe('Pipeline');
expect(findTriggererTh().text()).toBe('Triggerer');
expect(findCommitTh().text()).toBe('Commit');
expect(findStagesTh().text()).toBe('Stages'); expect(findStagesTh().text()).toBe('Stages');
expect(findTimeAgoTh().text()).toBe('Duration');
expect(findActionsTh().text()).toBe('Actions'); expect(findActionsTh().text()).toBe('Actions');
}); });
@ -125,27 +112,6 @@ describe('Pipelines Table', () => {
}); });
}); });
describe('triggerer cell', () => {
it('should render the pipeline triggerer', () => {
expect(findTriggerer().exists()).toBe(true);
});
});
describe('commit cell', () => {
it('should render commit information', () => {
expect(findCommit().exists()).toBe(true);
});
it('should display and link to commit', () => {
expect(findCommit().text()).toContain(pipeline.commit.short_id);
expect(findCommit().props('commitUrl')).toBe(pipeline.commit.commit_path);
});
it('should display the commit author', () => {
expect(findCommit().props('author')).toEqual(pipeline.commit.author);
});
});
describe('stages cell', () => { describe('stages cell', () => {
it('should render a pipeline mini graph', () => { it('should render a pipeline mini graph', () => {
expect(findPipelineMiniGraph().exists()).toBe(true); expect(findPipelineMiniGraph().exists()).toBe(true);
@ -163,7 +129,7 @@ describe('Pipelines Table', () => {
pipeline = createMockPipeline(); pipeline = createMockPipeline();
pipeline.details.stages = null; pipeline.details.stages = null;
createComponent({ pipelines: [pipeline] }, true); createComponent({ pipelines: [pipeline] });
}); });
it('stages are not rendered', () => { it('stages are not rendered', () => {
@ -176,7 +142,7 @@ describe('Pipelines Table', () => {
}); });
it('when update graph dropdown is set, should update graph dropdown', () => { it('when update graph dropdown is set, should update graph dropdown', () => {
createComponent({ pipelines: [pipeline], updateGraphDropdown: true }, true); createComponent({ pipelines: [pipeline], updateGraphDropdown: true });
expect(findPipelineMiniGraph().props('updateDropdown')).toBe(true); expect(findPipelineMiniGraph().props('updateDropdown')).toBe(true);
}); });
@ -207,30 +173,11 @@ describe('Pipelines Table', () => {
expect(findCancelBtn().attributes('title')).toBe(BUTTON_TOOLTIP_CANCEL); expect(findCancelBtn().attributes('title')).toBe(BUTTON_TOOLTIP_CANCEL);
}); });
}); });
});
describe('Pipelines Table with rearrangePipelinesTable feature flag turned on', () => {
beforeEach(() => {
createComponent({ pipelines: [pipeline], viewType: 'root' }, true);
});
it('should render table head with correct columns', () => {
expect(findStatusTh().text()).toBe('Status');
expect(findPipelineTh().text()).toBe('Pipeline');
expect(findStagesTh().text()).toBe('Stages');
expect(findActionsTh().text()).toBe('Actions');
});
describe('triggerer cell', () => { describe('triggerer cell', () => {
it('should render the pipeline triggerer', () => { it('should render the pipeline triggerer', () => {
expect(findTriggerer().exists()).toBe(true); expect(findTriggerer().exists()).toBe(true);
}); });
}); });
describe('commit cell', () => {
it('should not render commit information', () => {
expect(findCommit().exists()).toBe(false);
});
});
}); });
}); });

View File

@ -34,21 +34,19 @@ exports[`Issue Warning Component when noteable is locked and confidential render
<span> <span>
<span> <span>
This issue is This issue is
<a <gl-link-stub
href="" href=""
rel="noopener noreferrer"
target="_blank" target="_blank"
> >
confidential confidential
</a> </gl-link-stub>
and and
<a <gl-link-stub
href="" href=""
rel="noopener noreferrer"
target="_blank" target="_blank"
> >
locked locked
</a> </gl-link-stub>
. .
</span> </span>

View File

@ -1,4 +1,4 @@
import { GlIcon } from '@gitlab/ui'; import { GlIcon, GlSprintf } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils'; import { shallowMount } from '@vue/test-utils';
import { nextTick } from 'vue'; import { nextTick } from 'vue';
import NoteableWarning from '~/vue_shared/components/notes/noteable_warning.vue'; import NoteableWarning from '~/vue_shared/components/notes/noteable_warning.vue';
@ -16,6 +16,9 @@ describe('Issue Warning Component', () => {
propsData: { propsData: {
...props, ...props,
}, },
stubs: {
GlSprintf,
},
}); });
afterEach(() => { afterEach(() => {

View File

@ -0,0 +1,51 @@
import { shallowMount } from '@vue/test-utils';
import { GlBadge, GlIcon } from '@gitlab/ui';
import TierBadge from '~/vue_shared/components/tier_badge.vue';
describe('Tier badge component', () => {
let wrapper;
const createComponent = (props) =>
shallowMount(TierBadge, {
propsData: {
...props,
},
});
const findBadge = () => wrapper.findComponent(GlBadge);
const findTierText = () => findBadge().text();
const findIcon = () => wrapper.findComponent(GlIcon);
afterEach(() => {
wrapper.destroy();
});
describe('tiers name', () => {
it.each`
tier | tierText
${'free'} | ${'Free'}
${'premium'} | ${'Premium'}
${'ultimate'} | ${'Ultimate'}
`(
'shows $tierText text in the badge and the license icon when $tier prop is passed',
({ tier, tierText }) => {
wrapper = createComponent({ tier });
expect(findTierText()).toBe(tierText);
expect(findIcon().exists()).toBe(true);
expect(findIcon().props().name).toBe('license');
},
);
});
describe('badge size', () => {
const newSize = 'lg';
beforeEach(() => {
wrapper = createComponent({ tier: 'free', size: newSize });
});
it('passes down the size prop to the GlBadge component', () => {
expect(findBadge().props().size).toBe(newSize);
});
});
});

View File

@ -102,9 +102,9 @@ RSpec.describe Types::BaseEnum do
it 'sets the values defined by the declarative enum' do it 'sets the values defined by the declarative enum' do
set_declarative_enum set_declarative_enum
expect(enum_type.values.keys).to eq(['FOO']) expect(enum_type.values.keys).to contain_exactly('FOO')
expect(enum_type.values.values.map(&:description)).to eq(['description of foo']) expect(enum_type.values.values.map(&:description)).to contain_exactly('description of foo')
expect(enum_type.values.values.map(&:value)).to eq([0]) expect(enum_type.values.values.map(&:value)).to contain_exactly('foo')
end end
end end
end end

View File

@ -0,0 +1,22 @@
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe Projects::PipelineHelper do
describe '#js_pipeline_details_data' do
let_it_be(:project) { create(:project, :repository) }
let_it_be(:pipeline) { create(:ci_pipeline, project: project, ref: 'master', sha: project.commit.id) }
subject(:pipeline_details_data) { helper.js_pipeline_details_data(project, pipeline) }
it 'returns pipeline details data' do
expect(pipeline_details_data).to eq({
graphql_resource_etag: graphql_etag_pipeline_path(pipeline),
metrics_path: namespace_project_ci_prometheus_metrics_histograms_path(namespace_id: project.namespace, project_id: project, format: :json),
multi_project_help_path: help_page_path('ci/pipelines/multi_project_pipelines.md', anchor: 'multi-project-pipeline-visualization'),
pipeline_iid: pipeline.iid,
pipeline_project_path: project.full_path
})
end
end
end

View File

@ -168,24 +168,100 @@ RSpec.describe ContainerRegistry::Client do
expect(subject).to eq('Blob') expect(subject).to eq('Blob')
end end
it 'follows 307 redirect for GET /v2/:name/blobs/:digest' do context 'with a 307 redirect' do
stub_request(method, url) let(:redirect_location) { 'http://redirected' }
.with(headers: blob_headers)
.to_return(status: 307, body: '', headers: { Location: 'http://redirected' }) before do
# We should probably use hash_excluding here, but that requires an update to WebMock: stub_request(method, url)
# https://github.com/bblimke/webmock/blob/master/lib/webmock/matchers/hash_excluding_matcher.rb .with(headers: blob_headers)
stub_request(:get, "http://redirected/") .to_return(status: 307, body: '', headers: { Location: redirect_location })
.with(headers: redirect_header) do |request|
!request.headers.include?('Authorization') # We should probably use hash_excluding here, but that requires an update to WebMock:
# https://github.com/bblimke/webmock/blob/master/lib/webmock/matchers/hash_excluding_matcher.rb
stub_request(:get, redirect_location)
.with(headers: redirect_header) do |request|
!request.headers.include?('Authorization')
end
.to_return(status: 200, body: "Successfully redirected")
end
shared_examples 'handling redirects' do
it 'follows the redirect' do
expect(Faraday::Utils).not_to receive(:escape).with('signature=')
expect_new_faraday
expect(subject).to eq('Successfully redirected')
end end
.to_return(status: 200, body: "Successfully redirected") end
expect_new_faraday(times: 2) it_behaves_like 'handling redirects'
expect(subject).to eq('Successfully redirected') context 'with a redirect location with params ending with =' do
let(:redirect_location) { 'http://redirect?foo=bar&test=signature=' }
it_behaves_like 'handling redirects'
context 'with container_registry_follow_redirects_middleware disabled' do
before do
stub_feature_flags(container_registry_follow_redirects_middleware: false)
end
it 'follows the redirect' do
expect(Faraday::Utils).to receive(:escape).with('foo').and_call_original
expect(Faraday::Utils).to receive(:escape).with('bar').and_call_original
expect(Faraday::Utils).to receive(:escape).with('test').and_call_original
expect(Faraday::Utils).to receive(:escape).with('signature=').and_call_original
expect_new_faraday(times: 2)
expect(subject).to eq('Successfully redirected')
end
end
end
context 'with a redirect location with params ending with %3D' do
let(:redirect_location) { 'http://redirect?foo=bar&test=signature%3D' }
it_behaves_like 'handling redirects'
context 'with container_registry_follow_redirects_middleware disabled' do
before do
stub_feature_flags(container_registry_follow_redirects_middleware: false)
end
it 'follows the redirect' do
expect(Faraday::Utils).to receive(:escape).with('foo').and_call_original
expect(Faraday::Utils).to receive(:escape).with('bar').and_call_original
expect(Faraday::Utils).to receive(:escape).with('test').and_call_original
expect(Faraday::Utils).to receive(:escape).with('signature=').and_call_original
expect_new_faraday(times: 2)
expect(subject).to eq('Successfully redirected')
end
end
end
end end
it_behaves_like 'handling timeouts' it_behaves_like 'handling timeouts'
# TODO Remove this context along with the
# container_registry_follow_redirects_middleware feature flag
# See https://gitlab.com/gitlab-org/gitlab/-/issues/353291
context 'faraday blob' do
subject { client.send(:faraday_blob) }
it 'has a follow redirects middleware' do
expect(subject.builder.handlers).to include(::FaradayMiddleware::FollowRedirects)
end
context 'with container_registry_follow_redirects_middleware is disabled' do
before do
stub_feature_flags(container_registry_follow_redirects_middleware: false)
end
it 'has not a follow redirects middleware' do
expect(subject.builder.handlers).not_to include(::FaradayMiddleware::FollowRedirects)
end
end
end
end end
describe '#upload_blob' do describe '#upload_blob' do

Some files were not shown because too many files have changed in this diff Show More