Add latest changes from gitlab-org/gitlab@master
This commit is contained in:
parent
383ec6808b
commit
7aa988fed2
58 changed files with 595 additions and 312 deletions
|
@ -491,10 +491,6 @@ RSpec/EmptyLineAfterFinalLetItBe:
|
||||||
- ee/spec/graphql/mutations/issues/set_epic_spec.rb
|
- ee/spec/graphql/mutations/issues/set_epic_spec.rb
|
||||||
- ee/spec/graphql/mutations/requirements_management/export_requirements_spec.rb
|
- ee/spec/graphql/mutations/requirements_management/export_requirements_spec.rb
|
||||||
- ee/spec/graphql/mutations/vulnerabilities/create_external_issue_link_spec.rb
|
- ee/spec/graphql/mutations/vulnerabilities/create_external_issue_link_spec.rb
|
||||||
- ee/spec/graphql/resolvers/ci/code_coverage_activities_resolver_spec.rb
|
|
||||||
- ee/spec/graphql/resolvers/epics_resolver_spec.rb
|
|
||||||
- ee/spec/graphql/resolvers/geo/geo_node_resolver_spec.rb
|
|
||||||
- ee/spec/graphql/resolvers/incident_management/oncall_shifts_resolver_spec.rb
|
|
||||||
- ee/spec/graphql/types/issue_type_spec.rb
|
- ee/spec/graphql/types/issue_type_spec.rb
|
||||||
- ee/spec/helpers/ee/graph_helper_spec.rb
|
- ee/spec/helpers/ee/graph_helper_spec.rb
|
||||||
- ee/spec/helpers/ee/issues_helper_spec.rb
|
- ee/spec/helpers/ee/issues_helper_spec.rb
|
||||||
|
@ -801,8 +797,6 @@ RSpec/EmptyLineAfterFinalLetItBe:
|
||||||
- spec/lib/gitlab/auth/otp/strategies/forti_token_cloud_spec.rb
|
- spec/lib/gitlab/auth/otp/strategies/forti_token_cloud_spec.rb
|
||||||
- spec/lib/gitlab/auth_spec.rb
|
- spec/lib/gitlab/auth_spec.rb
|
||||||
- spec/lib/gitlab/cache/ci/project_pipeline_status_spec.rb
|
- spec/lib/gitlab/cache/ci/project_pipeline_status_spec.rb
|
||||||
- spec/lib/gitlab/checks/project_created_spec.rb
|
|
||||||
- spec/lib/gitlab/checks/project_moved_spec.rb
|
|
||||||
- spec/lib/gitlab/ci/build/policy/changes_spec.rb
|
- spec/lib/gitlab/ci/build/policy/changes_spec.rb
|
||||||
- spec/lib/gitlab/ci/config/external/file/local_spec.rb
|
- spec/lib/gitlab/ci/config/external/file/local_spec.rb
|
||||||
- spec/lib/gitlab/ci/config/external/file/project_spec.rb
|
- spec/lib/gitlab/ci/config/external/file/project_spec.rb
|
||||||
|
@ -840,12 +834,6 @@ RSpec/EmptyLineAfterFinalLetItBe:
|
||||||
- spec/lib/gitlab/github_import/importer/pull_request_review_importer_spec.rb
|
- spec/lib/gitlab/github_import/importer/pull_request_review_importer_spec.rb
|
||||||
- spec/lib/gitlab/github_import/milestone_finder_spec.rb
|
- spec/lib/gitlab/github_import/milestone_finder_spec.rb
|
||||||
- spec/lib/gitlab/gl_repository/repo_type_spec.rb
|
- spec/lib/gitlab/gl_repository/repo_type_spec.rb
|
||||||
- spec/lib/gitlab/graphql/batch_key_spec.rb
|
|
||||||
- spec/lib/gitlab/graphql/docs/renderer_spec.rb
|
|
||||||
- spec/lib/gitlab/graphql/loaders/batch_lfs_oid_loader_spec.rb
|
|
||||||
- spec/lib/gitlab/graphql/markdown_field_spec.rb
|
|
||||||
- spec/lib/gitlab/graphql/pagination/keyset/connection_spec.rb
|
|
||||||
- spec/lib/gitlab/graphql/pagination/keyset/last_items_spec.rb
|
|
||||||
- spec/lib/gitlab/group_search_results_spec.rb
|
- spec/lib/gitlab/group_search_results_spec.rb
|
||||||
- spec/lib/gitlab/hook_data/issue_builder_spec.rb
|
- spec/lib/gitlab/hook_data/issue_builder_spec.rb
|
||||||
- spec/lib/gitlab/hook_data/merge_request_builder_spec.rb
|
- spec/lib/gitlab/hook_data/merge_request_builder_spec.rb
|
||||||
|
|
|
@ -129,7 +129,7 @@ export default {
|
||||||
<template #help>
|
<template #help>
|
||||||
{{
|
{{
|
||||||
s__(
|
s__(
|
||||||
'JiraService|Warning: All GitLab users that have access to this GitLab project will be able to view all issues from the Jira project specified below.',
|
'JiraService|Warning: All GitLab users that have access to this GitLab project are able to view all issues from the Jira project specified below.',
|
||||||
)
|
)
|
||||||
}}
|
}}
|
||||||
</template>
|
</template>
|
||||||
|
@ -169,7 +169,7 @@ export default {
|
||||||
id="service_project_key"
|
id="service_project_key"
|
||||||
v-model="projectKey"
|
v-model="projectKey"
|
||||||
name="service[project_key]"
|
name="service[project_key]"
|
||||||
:placeholder="s__('JiraService|e.g. AB')"
|
:placeholder="s__('JiraService|For example, AB')"
|
||||||
:required="enableJiraIssues"
|
:required="enableJiraIssues"
|
||||||
:state="validProjectKey"
|
:state="validProjectKey"
|
||||||
:disabled="!enableJiraIssues"
|
:disabled="!enableJiraIssues"
|
||||||
|
|
|
@ -144,7 +144,7 @@ export default {
|
||||||
label-for="service[trigger]"
|
label-for="service[trigger]"
|
||||||
:description="
|
:description="
|
||||||
s__(
|
s__(
|
||||||
'Integrations|When a Jira issue is mentioned in a commit or merge request a remote link and comment (if enabled) will be created.',
|
'Integrations|When a Jira issue is mentioned in a commit or merge request a remote link and comment (if enabled) is created.',
|
||||||
)
|
)
|
||||||
"
|
"
|
||||||
>
|
>
|
||||||
|
|
|
@ -121,6 +121,7 @@ export default {
|
||||||
:is="componentName(firstNote)"
|
:is="componentName(firstNote)"
|
||||||
:note="componentData(firstNote)"
|
:note="componentData(firstNote)"
|
||||||
:line="line || diffLine"
|
:line="line || diffLine"
|
||||||
|
:discussion-file="discussion.diff_file"
|
||||||
:commit="commit"
|
:commit="commit"
|
||||||
:help-page-path="helpPagePath"
|
:help-page-path="helpPagePath"
|
||||||
:show-reply-button="userCanReply"
|
:show-reply-button="userCanReply"
|
||||||
|
@ -167,6 +168,7 @@ export default {
|
||||||
v-for="(note, index) in discussion.notes"
|
v-for="(note, index) in discussion.notes"
|
||||||
:key="note.id"
|
:key="note.id"
|
||||||
:note="componentData(note)"
|
:note="componentData(note)"
|
||||||
|
:discussion-file="discussion.diff_file"
|
||||||
:help-page-path="helpPagePath"
|
:help-page-path="helpPagePath"
|
||||||
:line="diffLine"
|
:line="diffLine"
|
||||||
:discussion-root="index === 0"
|
:discussion-root="index === 0"
|
||||||
|
|
|
@ -48,6 +48,11 @@ export default {
|
||||||
required: false,
|
required: false,
|
||||||
default: null,
|
default: null,
|
||||||
},
|
},
|
||||||
|
discussionFile: {
|
||||||
|
type: Object,
|
||||||
|
required: false,
|
||||||
|
default: null,
|
||||||
|
},
|
||||||
helpPagePath: {
|
helpPagePath: {
|
||||||
type: String,
|
type: String,
|
||||||
required: false,
|
required: false,
|
||||||
|
@ -167,12 +172,18 @@ export default {
|
||||||
return commentLineOptions(lines, this.commentLineStart, this.line.line_code);
|
return commentLineOptions(lines, this.commentLineStart, this.line.line_code);
|
||||||
},
|
},
|
||||||
diffFile() {
|
diffFile() {
|
||||||
|
let fileResolvedFromAvailableSource;
|
||||||
|
|
||||||
if (this.commentLineStart.line_code) {
|
if (this.commentLineStart.line_code) {
|
||||||
const lineCode = this.commentLineStart.line_code.split('_')[0];
|
const lineCode = this.commentLineStart.line_code.split('_')[0];
|
||||||
return this.getDiffFileByHash(lineCode);
|
fileResolvedFromAvailableSource = this.getDiffFileByHash(lineCode);
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
if (!fileResolvedFromAvailableSource && this.discussionFile) {
|
||||||
|
fileResolvedFromAvailableSource = this.discussionFile;
|
||||||
|
}
|
||||||
|
|
||||||
|
return fileResolvedFromAvailableSource || null;
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
created() {
|
created() {
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
import { reportToSentry } from '../../utils';
|
import { reportToSentry } from '../../utils';
|
||||||
import LinkedGraphWrapper from '../graph_shared/linked_graph_wrapper.vue';
|
import LinkedGraphWrapper from '../graph_shared/linked_graph_wrapper.vue';
|
||||||
import LinksLayer from '../graph_shared/links_layer.vue';
|
import LinksLayer from '../graph_shared/links_layer.vue';
|
||||||
import { DOWNSTREAM, MAIN, UPSTREAM, ONE_COL_WIDTH } from './constants';
|
import { DOWNSTREAM, MAIN, UPSTREAM, ONE_COL_WIDTH, STAGE_VIEW } from './constants';
|
||||||
import LinkedPipelinesColumn from './linked_pipelines_column.vue';
|
import LinkedPipelinesColumn from './linked_pipelines_column.vue';
|
||||||
import StageColumnComponent from './stage_column_component.vue';
|
import StageColumnComponent from './stage_column_component.vue';
|
||||||
import { validateConfigPaths } from './utils';
|
import { validateConfigPaths } from './utils';
|
||||||
|
@ -25,11 +25,20 @@ export default {
|
||||||
type: Object,
|
type: Object,
|
||||||
required: true,
|
required: true,
|
||||||
},
|
},
|
||||||
|
viewType: {
|
||||||
|
type: String,
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
isLinkedPipeline: {
|
isLinkedPipeline: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
required: false,
|
required: false,
|
||||||
default: false,
|
default: false,
|
||||||
},
|
},
|
||||||
|
pipelineLayers: {
|
||||||
|
type: Array,
|
||||||
|
required: false,
|
||||||
|
default: () => [],
|
||||||
|
},
|
||||||
type: {
|
type: {
|
||||||
type: String,
|
type: String,
|
||||||
required: false,
|
required: false,
|
||||||
|
@ -63,8 +72,8 @@ export default {
|
||||||
downstreamPipelines() {
|
downstreamPipelines() {
|
||||||
return this.hasDownstreamPipelines ? this.pipeline.downstream : [];
|
return this.hasDownstreamPipelines ? this.pipeline.downstream : [];
|
||||||
},
|
},
|
||||||
graph() {
|
layout() {
|
||||||
return this.pipeline.stages;
|
return this.isStageView ? this.pipeline.stages : this.generateColumnsFromLayersList();
|
||||||
},
|
},
|
||||||
hasDownstreamPipelines() {
|
hasDownstreamPipelines() {
|
||||||
return Boolean(this.pipeline?.downstream?.length > 0);
|
return Boolean(this.pipeline?.downstream?.length > 0);
|
||||||
|
@ -72,12 +81,18 @@ export default {
|
||||||
hasUpstreamPipelines() {
|
hasUpstreamPipelines() {
|
||||||
return Boolean(this.pipeline?.upstream?.length > 0);
|
return Boolean(this.pipeline?.upstream?.length > 0);
|
||||||
},
|
},
|
||||||
|
isStageView() {
|
||||||
|
return this.viewType === STAGE_VIEW;
|
||||||
|
},
|
||||||
metricsConfig() {
|
metricsConfig() {
|
||||||
return {
|
return {
|
||||||
path: this.configPaths.metricsPath,
|
path: this.configPaths.metricsPath,
|
||||||
collectMetrics: true,
|
collectMetrics: true,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
shouldHideLinks() {
|
||||||
|
return this.isStageView;
|
||||||
|
},
|
||||||
// The show downstream check prevents showing redundant linked columns
|
// The show downstream check prevents showing redundant linked columns
|
||||||
showDownstreamPipelines() {
|
showDownstreamPipelines() {
|
||||||
return (
|
return (
|
||||||
|
@ -101,6 +116,26 @@ export default {
|
||||||
this.getMeasurements();
|
this.getMeasurements();
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
generateColumnsFromLayersList() {
|
||||||
|
return this.pipelineLayers.map((layers, idx) => {
|
||||||
|
/*
|
||||||
|
look up the groups in each layer,
|
||||||
|
then add each set of layer groups to a stage-like object
|
||||||
|
*/
|
||||||
|
|
||||||
|
const groups = layers.map((id) => {
|
||||||
|
const { stageIdx, groupIdx } = this.pipeline.stagesLookup[id];
|
||||||
|
return this.pipeline.stages?.[stageIdx]?.groups?.[groupIdx];
|
||||||
|
});
|
||||||
|
|
||||||
|
return {
|
||||||
|
name: '',
|
||||||
|
id: `layer-${idx}`,
|
||||||
|
status: { action: null },
|
||||||
|
groups: groups.filter(Boolean),
|
||||||
|
};
|
||||||
|
});
|
||||||
|
},
|
||||||
getMeasurements() {
|
getMeasurements() {
|
||||||
this.measurements = {
|
this.measurements = {
|
||||||
width: this.$refs[this.containerId].scrollWidth,
|
width: this.$refs[this.containerId].scrollWidth,
|
||||||
|
@ -147,29 +182,31 @@ export default {
|
||||||
:linked-pipelines="upstreamPipelines"
|
:linked-pipelines="upstreamPipelines"
|
||||||
:column-title="__('Upstream')"
|
:column-title="__('Upstream')"
|
||||||
:type="$options.pipelineTypeConstants.UPSTREAM"
|
:type="$options.pipelineTypeConstants.UPSTREAM"
|
||||||
|
:view-type="viewType"
|
||||||
@error="onError"
|
@error="onError"
|
||||||
/>
|
/>
|
||||||
</template>
|
</template>
|
||||||
<template #main>
|
<template #main>
|
||||||
<div :id="containerId" :ref="containerId">
|
<div :id="containerId" :ref="containerId">
|
||||||
<links-layer
|
<links-layer
|
||||||
:pipeline-data="graph"
|
:pipeline-data="layout"
|
||||||
:pipeline-id="pipeline.id"
|
:pipeline-id="pipeline.id"
|
||||||
:container-id="containerId"
|
:container-id="containerId"
|
||||||
:container-measurements="measurements"
|
:container-measurements="measurements"
|
||||||
:highlighted-job="hoveredJobName"
|
:highlighted-job="hoveredJobName"
|
||||||
:metrics-config="metricsConfig"
|
:metrics-config="metricsConfig"
|
||||||
:never-show-links="true"
|
:never-show-links="shouldHideLinks"
|
||||||
|
:view-type="viewType"
|
||||||
default-link-color="gl-stroke-transparent"
|
default-link-color="gl-stroke-transparent"
|
||||||
@error="onError"
|
@error="onError"
|
||||||
@highlightedJobsChange="updateHighlightedJobs"
|
@highlightedJobsChange="updateHighlightedJobs"
|
||||||
>
|
>
|
||||||
<stage-column-component
|
<stage-column-component
|
||||||
v-for="stage in graph"
|
v-for="column in layout"
|
||||||
:key="stage.name"
|
:key="column.id || column.name"
|
||||||
:title="stage.name"
|
:title="column.name"
|
||||||
:groups="stage.groups"
|
:groups="column.groups"
|
||||||
:action="stage.status.action"
|
:action="column.status.action"
|
||||||
:highlighted-jobs="highlightedJobs"
|
:highlighted-jobs="highlightedJobs"
|
||||||
:job-hovered="hoveredJobName"
|
:job-hovered="hoveredJobName"
|
||||||
:pipeline-expanded="pipelineExpanded"
|
:pipeline-expanded="pipelineExpanded"
|
||||||
|
@ -189,6 +226,7 @@ export default {
|
||||||
:linked-pipelines="downstreamPipelines"
|
:linked-pipelines="downstreamPipelines"
|
||||||
:column-title="__('Downstream')"
|
:column-title="__('Downstream')"
|
||||||
:type="$options.pipelineTypeConstants.DOWNSTREAM"
|
:type="$options.pipelineTypeConstants.DOWNSTREAM"
|
||||||
|
:view-type="viewType"
|
||||||
@downstreamHovered="setJob"
|
@downstreamHovered="setJob"
|
||||||
@pipelineExpandToggle="togglePipelineExpanded"
|
@pipelineExpandToggle="togglePipelineExpanded"
|
||||||
@scrollContainer="slidePipelineContainer"
|
@scrollContainer="slidePipelineContainer"
|
||||||
|
|
|
@ -5,7 +5,8 @@ import { __ } from '~/locale';
|
||||||
import glFeatureFlagMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
|
import glFeatureFlagMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
|
||||||
import { DEFAULT, DRAW_FAILURE, LOAD_FAILURE } from '../../constants';
|
import { DEFAULT, DRAW_FAILURE, LOAD_FAILURE } from '../../constants';
|
||||||
import { reportToSentry } from '../../utils';
|
import { reportToSentry } from '../../utils';
|
||||||
import { IID_FAILURE, STAGE_VIEW } from './constants';
|
import { listByLayers } from '../parsing_utils';
|
||||||
|
import { IID_FAILURE, LAYER_VIEW, STAGE_VIEW } from './constants';
|
||||||
import PipelineGraph from './graph_component.vue';
|
import PipelineGraph from './graph_component.vue';
|
||||||
import GraphViewSelector from './graph_view_selector.vue';
|
import GraphViewSelector from './graph_view_selector.vue';
|
||||||
import {
|
import {
|
||||||
|
@ -43,6 +44,7 @@ export default {
|
||||||
alertType: null,
|
alertType: null,
|
||||||
currentViewType: STAGE_VIEW,
|
currentViewType: STAGE_VIEW,
|
||||||
pipeline: null,
|
pipeline: null,
|
||||||
|
pipelineLayers: null,
|
||||||
showAlert: false,
|
showAlert: false,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
@ -155,6 +157,13 @@ export default {
|
||||||
reportToSentry(this.$options.name, `error: ${err}, info: ${info}`);
|
reportToSentry(this.$options.name, `error: ${err}, info: ${info}`);
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
getPipelineLayers() {
|
||||||
|
if (this.currentViewType === LAYER_VIEW && !this.pipelineLayers) {
|
||||||
|
this.pipelineLayers = listByLayers(this.pipeline);
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.pipelineLayers;
|
||||||
|
},
|
||||||
hideAlert() {
|
hideAlert() {
|
||||||
this.showAlert = false;
|
this.showAlert = false;
|
||||||
this.alertType = null;
|
this.alertType = null;
|
||||||
|
@ -192,6 +201,8 @@ export default {
|
||||||
v-if="pipeline"
|
v-if="pipeline"
|
||||||
:config-paths="configPaths"
|
:config-paths="configPaths"
|
||||||
:pipeline="pipeline"
|
:pipeline="pipeline"
|
||||||
|
:pipeline-layers="getPipelineLayers()"
|
||||||
|
:view-type="currentViewType"
|
||||||
@error="reportFailure"
|
@error="reportFailure"
|
||||||
@refreshPipelineGraph="refreshPipelineGraph"
|
@refreshPipelineGraph="refreshPipelineGraph"
|
||||||
/>
|
/>
|
||||||
|
|
|
@ -55,16 +55,16 @@ export default {
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="gl-display-flex gl-justify-content-end gl-align-items-center gl-my-4">
|
<div class="gl-display-flex gl-align-items-center gl-my-4">
|
||||||
<span>{{ $options.i18n.labelText }}</span>
|
<span>{{ $options.i18n.labelText }}</span>
|
||||||
<gl-dropdown class="gl-ml-4" :right="true">
|
<gl-dropdown class="gl-ml-4">
|
||||||
<template #button-content>
|
<template #button-content>
|
||||||
<gl-sprintf :message="currentDropdownText">
|
<gl-sprintf :message="currentDropdownText">
|
||||||
<template #code="{ content }">
|
<template #code="{ content }">
|
||||||
<code> {{ content }} </code>
|
<code> {{ content }} </code>
|
||||||
</template>
|
</template>
|
||||||
</gl-sprintf>
|
</gl-sprintf>
|
||||||
<gl-icon class="gl-px-2" name="angle-down" :size="18" />
|
<gl-icon class="gl-px-2" name="angle-down" :size="16" />
|
||||||
</template>
|
</template>
|
||||||
<gl-dropdown-item
|
<gl-dropdown-item
|
||||||
v-for="view in $options.views"
|
v-for="view in $options.views"
|
||||||
|
|
|
@ -2,7 +2,8 @@
|
||||||
import getPipelineDetails from 'shared_queries/pipelines/get_pipeline_details.query.graphql';
|
import getPipelineDetails from 'shared_queries/pipelines/get_pipeline_details.query.graphql';
|
||||||
import { LOAD_FAILURE } from '../../constants';
|
import { LOAD_FAILURE } from '../../constants';
|
||||||
import { reportToSentry } from '../../utils';
|
import { reportToSentry } from '../../utils';
|
||||||
import { ONE_COL_WIDTH, UPSTREAM } from './constants';
|
import { listByLayers } from '../parsing_utils';
|
||||||
|
import { ONE_COL_WIDTH, UPSTREAM, LAYER_VIEW } from './constants';
|
||||||
import LinkedPipeline from './linked_pipeline.vue';
|
import LinkedPipeline from './linked_pipeline.vue';
|
||||||
import {
|
import {
|
||||||
getQueryHeaders,
|
getQueryHeaders,
|
||||||
|
@ -35,11 +36,16 @@ export default {
|
||||||
type: String,
|
type: String,
|
||||||
required: true,
|
required: true,
|
||||||
},
|
},
|
||||||
|
viewType: {
|
||||||
|
type: String,
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
currentPipeline: null,
|
currentPipeline: null,
|
||||||
loadingPipelineId: null,
|
loadingPipelineId: null,
|
||||||
|
pipelineLayers: {},
|
||||||
pipelineExpanded: false,
|
pipelineExpanded: false,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
@ -123,6 +129,13 @@ export default {
|
||||||
|
|
||||||
toggleQueryPollingByVisibility(this.$apollo.queries.currentPipeline);
|
toggleQueryPollingByVisibility(this.$apollo.queries.currentPipeline);
|
||||||
},
|
},
|
||||||
|
getPipelineLayers(id) {
|
||||||
|
if (this.viewType === LAYER_VIEW && !this.pipelineLayers[id]) {
|
||||||
|
this.pipelineLayers[id] = listByLayers(this.currentPipeline);
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.pipelineLayers[id];
|
||||||
|
},
|
||||||
isExpanded(id) {
|
isExpanded(id) {
|
||||||
return Boolean(this.currentPipeline?.id && id === this.currentPipeline.id);
|
return Boolean(this.currentPipeline?.id && id === this.currentPipeline.id);
|
||||||
},
|
},
|
||||||
|
@ -203,7 +216,9 @@ export default {
|
||||||
class="d-inline-block gl-mt-n2"
|
class="d-inline-block gl-mt-n2"
|
||||||
:config-paths="configPaths"
|
:config-paths="configPaths"
|
||||||
:pipeline="currentPipeline"
|
:pipeline="currentPipeline"
|
||||||
|
:pipeline-layers="getPipelineLayers(pipeline.id)"
|
||||||
:is-linked-pipeline="true"
|
:is-linked-pipeline="true"
|
||||||
|
:view-type="viewType"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</li>
|
</li>
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import Visibility from 'visibilityjs';
|
import Visibility from 'visibilityjs';
|
||||||
import { getIdFromGraphQLId } from '~/graphql_shared/utils';
|
import { getIdFromGraphQLId } from '~/graphql_shared/utils';
|
||||||
import { unwrapStagesWithNeeds } from '../unwrapping_utils';
|
import { unwrapStagesWithNeedsAndLookup } from '../unwrapping_utils';
|
||||||
|
|
||||||
const addMulti = (mainPipelineProjectPath, linkedPipeline) => {
|
const addMulti = (mainPipelineProjectPath, linkedPipeline) => {
|
||||||
return {
|
return {
|
||||||
|
@ -86,12 +86,13 @@ const unwrapPipelineData = (mainPipelineProjectPath, data) => {
|
||||||
stages: { nodes: stages },
|
stages: { nodes: stages },
|
||||||
} = pipeline;
|
} = pipeline;
|
||||||
|
|
||||||
const nodes = unwrapStagesWithNeeds(stages);
|
const { stages: updatedStages, lookup } = unwrapStagesWithNeedsAndLookup(stages);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
...pipeline,
|
...pipeline,
|
||||||
id: getIdFromGraphQLId(pipeline.id),
|
id: getIdFromGraphQLId(pipeline.id),
|
||||||
stages: nodes,
|
stages: updatedStages,
|
||||||
|
stagesLookup: lookup,
|
||||||
upstream: upstream
|
upstream: upstream
|
||||||
? [upstream].map(addMulti.bind(null, mainPipelineProjectPath)).map(transformId)
|
? [upstream].map(addMulti.bind(null, mainPipelineProjectPath)).map(transformId)
|
||||||
: [],
|
: [],
|
||||||
|
|
|
@ -11,6 +11,7 @@ import {
|
||||||
import { performanceMarkAndMeasure } from '~/performance/utils';
|
import { performanceMarkAndMeasure } from '~/performance/utils';
|
||||||
import { DRAW_FAILURE } from '../../constants';
|
import { DRAW_FAILURE } from '../../constants';
|
||||||
import { createJobsHash, generateJobNeedsDict, reportToSentry } from '../../utils';
|
import { createJobsHash, generateJobNeedsDict, reportToSentry } from '../../utils';
|
||||||
|
import { STAGE_VIEW } from '../graph/constants';
|
||||||
import { parseData } from '../parsing_utils';
|
import { parseData } from '../parsing_utils';
|
||||||
import { reportPerformance } from './api';
|
import { reportPerformance } from './api';
|
||||||
import { generateLinksData } from './drawing_utils';
|
import { generateLinksData } from './drawing_utils';
|
||||||
|
@ -54,11 +55,17 @@ export default {
|
||||||
required: false,
|
required: false,
|
||||||
default: '',
|
default: '',
|
||||||
},
|
},
|
||||||
|
viewType: {
|
||||||
|
type: String,
|
||||||
|
required: false,
|
||||||
|
default: STAGE_VIEW,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
links: [],
|
links: [],
|
||||||
needsObject: null,
|
needsObject: null,
|
||||||
|
parsedData: {},
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
|
@ -108,6 +115,15 @@ export default {
|
||||||
highlightedJobs(jobs) {
|
highlightedJobs(jobs) {
|
||||||
this.$emit('highlightedJobsChange', jobs);
|
this.$emit('highlightedJobsChange', jobs);
|
||||||
},
|
},
|
||||||
|
viewType() {
|
||||||
|
/*
|
||||||
|
We need to wait a tick so that the layout reflows
|
||||||
|
before the links refresh.
|
||||||
|
*/
|
||||||
|
this.$nextTick(() => {
|
||||||
|
this.refreshLinks();
|
||||||
|
});
|
||||||
|
},
|
||||||
},
|
},
|
||||||
errorCaptured(err, _vm, info) {
|
errorCaptured(err, _vm, info) {
|
||||||
reportToSentry(this.$options.name, `error: ${err}, info: ${info}`);
|
reportToSentry(this.$options.name, `error: ${err}, info: ${info}`);
|
||||||
|
@ -166,14 +182,17 @@ export default {
|
||||||
this.beginPerfMeasure();
|
this.beginPerfMeasure();
|
||||||
try {
|
try {
|
||||||
const arrayOfJobs = this.pipelineData.flatMap(({ groups }) => groups);
|
const arrayOfJobs = this.pipelineData.flatMap(({ groups }) => groups);
|
||||||
const parsedData = parseData(arrayOfJobs);
|
this.parsedData = parseData(arrayOfJobs);
|
||||||
this.links = generateLinksData(parsedData, this.containerId, `-${this.pipelineId}`);
|
this.refreshLinks();
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
this.$emit('error', { type: DRAW_FAILURE, reportToSentry: false });
|
this.$emit('error', { type: DRAW_FAILURE, reportToSentry: false });
|
||||||
reportToSentry(this.$options.name, err);
|
reportToSentry(this.$options.name, err);
|
||||||
}
|
}
|
||||||
this.finishPerfMeasureAndSend();
|
this.finishPerfMeasureAndSend();
|
||||||
},
|
},
|
||||||
|
refreshLinks() {
|
||||||
|
this.links = generateLinksData(this.parsedData, this.containerId, `-${this.pipelineId}`);
|
||||||
|
},
|
||||||
getLinkClasses(link) {
|
getLinkClasses(link) {
|
||||||
return [
|
return [
|
||||||
this.isLinkHighlighted(link.ref) ? 'gl-stroke-blue-400' : this.defaultLinkColor,
|
this.isLinkHighlighted(link.ref) ? 'gl-stroke-blue-400' : this.defaultLinkColor,
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
import { uniqWith, isEqual } from 'lodash';
|
import { uniqWith, isEqual } from 'lodash';
|
||||||
|
import { createSankey } from './dag/drawing_utils';
|
||||||
|
|
||||||
/*
|
/*
|
||||||
The following functions are the main engine in transforming the data as
|
The following functions are the main engine in transforming the data as
|
||||||
|
@ -144,3 +145,28 @@ export const getMaxNodes = (nodes) => {
|
||||||
export const removeOrphanNodes = (sankeyfiedNodes) => {
|
export const removeOrphanNodes = (sankeyfiedNodes) => {
|
||||||
return sankeyfiedNodes.filter((node) => node.sourceLinks.length || node.targetLinks.length);
|
return sankeyfiedNodes.filter((node) => node.sourceLinks.length || node.targetLinks.length);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
This utility accepts unwrapped pipeline data in the format returned from
|
||||||
|
our standard pipeline GraphQL query and returns a list of names by layer
|
||||||
|
for the layer view. It can be combined with the stageLookup on the pipeline
|
||||||
|
to generate columns by layer.
|
||||||
|
*/
|
||||||
|
|
||||||
|
export const listByLayers = ({ stages }) => {
|
||||||
|
const arrayOfJobs = stages.flatMap(({ groups }) => groups);
|
||||||
|
const parsedData = parseData(arrayOfJobs);
|
||||||
|
const dataWithLayers = createSankey()(parsedData);
|
||||||
|
|
||||||
|
return dataWithLayers.nodes.reduce((acc, { layer, name }) => {
|
||||||
|
/* sort groups by layer */
|
||||||
|
|
||||||
|
if (!acc[layer]) {
|
||||||
|
acc[layer] = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
acc[layer].push(name);
|
||||||
|
|
||||||
|
return acc;
|
||||||
|
}, []);
|
||||||
|
};
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
import { reportToSentry } from '../utils';
|
import { reportToSentry } from '../utils';
|
||||||
|
|
||||||
const unwrapGroups = (stages) => {
|
const unwrapGroups = (stages) => {
|
||||||
return stages.map((stage) => {
|
return stages.map((stage, idx) => {
|
||||||
const {
|
const {
|
||||||
groups: { nodes: groups },
|
groups: { nodes: groups },
|
||||||
} = stage;
|
} = stage;
|
||||||
return { ...stage, groups };
|
return { node: { ...stage, groups }, lookup: { stageIdx: idx } };
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -23,20 +23,34 @@ const unwrapJobWithNeeds = (denodedJobArray) => {
|
||||||
return unwrapNodesWithName(denodedJobArray, 'needs');
|
return unwrapNodesWithName(denodedJobArray, 'needs');
|
||||||
};
|
};
|
||||||
|
|
||||||
const unwrapStagesWithNeeds = (denodedStages) => {
|
const unwrapStagesWithNeedsAndLookup = (denodedStages) => {
|
||||||
const unwrappedNestedGroups = unwrapGroups(denodedStages);
|
const unwrappedNestedGroups = unwrapGroups(denodedStages);
|
||||||
|
|
||||||
const nodes = unwrappedNestedGroups.map((node) => {
|
const lookupMap = {};
|
||||||
|
|
||||||
|
const nodes = unwrappedNestedGroups.map(({ node, lookup }) => {
|
||||||
const { groups } = node;
|
const { groups } = node;
|
||||||
const groupsWithJobs = groups.map((group) => {
|
const groupsWithJobs = groups.map((group, idx) => {
|
||||||
const jobs = unwrapJobWithNeeds(group.jobs.nodes);
|
const jobs = unwrapJobWithNeeds(group.jobs.nodes);
|
||||||
|
|
||||||
|
lookupMap[group.name] = { ...lookup, groupIdx: idx };
|
||||||
return { ...group, jobs };
|
return { ...group, jobs };
|
||||||
});
|
});
|
||||||
|
|
||||||
return { ...node, groups: groupsWithJobs };
|
return { ...node, groups: groupsWithJobs };
|
||||||
});
|
});
|
||||||
|
|
||||||
return nodes;
|
return { stages: nodes, lookup: lookupMap };
|
||||||
};
|
};
|
||||||
|
|
||||||
export { unwrapGroups, unwrapNodesWithName, unwrapJobWithNeeds, unwrapStagesWithNeeds };
|
const unwrapStagesWithNeeds = (denodedStages) => {
|
||||||
|
return unwrapStagesWithNeedsAndLookup(denodedStages).stages;
|
||||||
|
};
|
||||||
|
|
||||||
|
export {
|
||||||
|
unwrapGroups,
|
||||||
|
unwrapJobWithNeeds,
|
||||||
|
unwrapNodesWithName,
|
||||||
|
unwrapStagesWithNeeds,
|
||||||
|
unwrapStagesWithNeedsAndLookup,
|
||||||
|
};
|
||||||
|
|
|
@ -25,32 +25,3 @@
|
||||||
background-color: $red-500;
|
background-color: $red-500;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.runner {
|
|
||||||
.btn {
|
|
||||||
padding: 1px 6px;
|
|
||||||
}
|
|
||||||
|
|
||||||
h4 {
|
|
||||||
font-weight: $gl-font-weight-normal;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.admin-runner-btn-group-cell {
|
|
||||||
min-width: 150px;
|
|
||||||
|
|
||||||
.btn-sm {
|
|
||||||
padding: 4px 9px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.btn-default {
|
|
||||||
color: $gl-text-color-secondary;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@include media-breakpoint-down(md) {
|
|
||||||
.runners-content {
|
|
||||||
width: 100%;
|
|
||||||
overflow: auto;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -116,7 +116,7 @@ class JiraService < IssueTrackerService
|
||||||
end
|
end
|
||||||
|
|
||||||
def description
|
def description
|
||||||
s_('JiraService|Jira issue tracker')
|
s_('JiraService|Track issues in Jira')
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.to_param
|
def self.to_param
|
||||||
|
@ -130,19 +130,20 @@ class JiraService < IssueTrackerService
|
||||||
name: 'url',
|
name: 'url',
|
||||||
title: s_('JiraService|Web URL'),
|
title: s_('JiraService|Web URL'),
|
||||||
placeholder: 'https://jira.example.com',
|
placeholder: 'https://jira.example.com',
|
||||||
|
help: s_('JiraService|Base URL of the Jira instance.'),
|
||||||
required: true
|
required: true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
type: 'text',
|
type: 'text',
|
||||||
name: 'api_url',
|
name: 'api_url',
|
||||||
title: s_('JiraService|Jira API URL'),
|
title: s_('JiraService|Jira API URL'),
|
||||||
placeholder: s_('JiraService|If different from Web URL')
|
help: s_('JiraService|If different from Web URL.')
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
type: 'text',
|
type: 'text',
|
||||||
name: 'username',
|
name: 'username',
|
||||||
title: s_('JiraService|Username or Email'),
|
title: s_('JiraService|Username or Email'),
|
||||||
placeholder: s_('JiraService|Use a username for server version and an email for cloud version'),
|
help: s_('JiraService|Use a username for server version and an email for cloud version.'),
|
||||||
required: true
|
required: true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -150,8 +151,8 @@ class JiraService < IssueTrackerService
|
||||||
name: 'password',
|
name: 'password',
|
||||||
title: s_('JiraService|Password or API token'),
|
title: s_('JiraService|Password or API token'),
|
||||||
non_empty_password_title: s_('JiraService|Enter new password or API token'),
|
non_empty_password_title: s_('JiraService|Enter new password or API token'),
|
||||||
non_empty_password_help: s_('JiraService|Leave blank to use your current password or API token'),
|
non_empty_password_help: s_('JiraService|Leave blank to use your current password or API token.'),
|
||||||
placeholder: s_('JiraService|Use a password for server version and an API token for cloud version'),
|
help: s_('JiraService|Use a password for server version and an API token for cloud version.'),
|
||||||
required: true
|
required: true
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
.form-check
|
.form-check
|
||||||
= f.check_box :authorized_keys_enabled, class: 'form-check-input'
|
= f.check_box :authorized_keys_enabled, class: 'form-check-input'
|
||||||
= f.label :authorized_keys_enabled, class: 'form-check-label' do
|
= f.label :authorized_keys_enabled, class: 'form-check-label' do
|
||||||
Write to "authorized_keys" file
|
= _('Write to "authorized_keys" file')
|
||||||
.form-text.text-muted
|
.form-text.text-muted
|
||||||
By default, we write to the "authorized_keys" file to support Git
|
By default, we write to the "authorized_keys" file to support Git
|
||||||
over SSH without additional configuration. GitLab can be optimized
|
over SSH without additional configuration. GitLab can be optimized
|
||||||
|
@ -31,4 +31,4 @@
|
||||||
.form-text.text-muted
|
.form-text.text-muted
|
||||||
= _('Number of changes (branches or tags) in a single push to determine whether individual push events or bulk push event will be created. Bulk push event will be created if it surpasses that value.')
|
= _('Number of changes (branches or tags) in a single push to determine whether individual push events or bulk push event will be created. Bulk push event will be created if it surpasses that value.')
|
||||||
|
|
||||||
= f.submit 'Save changes', class: "gl-button btn btn-confirm"
|
= f.submit _('Save changes'), class: "gl-button btn btn-confirm"
|
||||||
|
|
|
@ -118,7 +118,7 @@
|
||||||
= _('Runners currently online: %{active_runners_count}') % { active_runners_count: @active_runners_count }
|
= _('Runners currently online: %{active_runners_count}') % { active_runners_count: @active_runners_count }
|
||||||
|
|
||||||
- if @runners.any?
|
- if @runners.any?
|
||||||
.runners-content.content-list
|
.content-list{ data: { testid: 'runners-table' } }
|
||||||
.table-holder
|
.table-holder
|
||||||
.gl-responsive-table-row.table-row-header{ role: 'row' }
|
.gl-responsive-table-row.table-row-header{ role: 'row' }
|
||||||
.table-section.section-10{ role: 'rowheader' }= _('Type/State')
|
.table-section.section-10{ role: 'rowheader' }= _('Type/State')
|
||||||
|
|
|
@ -82,7 +82,7 @@
|
||||||
|
|
||||||
|
|
||||||
- if @group_runners.any?
|
- if @group_runners.any?
|
||||||
.runners-content.content-list
|
.content-list{ data: { testid: 'runners-table' } }
|
||||||
.table-holder
|
.table-holder
|
||||||
.gl-responsive-table-row.table-row-header{ role: 'row' }
|
.gl-responsive-table-row.table-row-header{ role: 'row' }
|
||||||
.table-section.section-10{ role: 'rowheader' }= _('Type/State')
|
.table-section.section-10{ role: 'rowheader' }= _('Type/State')
|
||||||
|
|
|
@ -1,3 +1,3 @@
|
||||||
.file-content.code
|
.file-content.code
|
||||||
.nothing-here-block
|
.nothing-here-block
|
||||||
Empty file
|
= _("Empty file")
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
%li.runner{ id: dom_id(runner) }
|
%li.runner{ id: dom_id(runner) }
|
||||||
%h4
|
%h4.gl-font-weight-normal
|
||||||
= runner_status_icon(runner)
|
= runner_status_icon(runner)
|
||||||
|
|
||||||
- if @project_runners.include?(runner)
|
- if @project_runners.include?(runner)
|
||||||
|
@ -9,9 +9,9 @@
|
||||||
%span.has-tooltip{ title: _('Locked to current projects') }
|
%span.has-tooltip{ title: _('Locked to current projects') }
|
||||||
= sprite_icon('lock')
|
= sprite_icon('lock')
|
||||||
|
|
||||||
%small.edit-runner
|
= link_to edit_project_runner_path(@project, runner), class: 'btn gl-button btn-sm btn-icon', data: { testid: 'edit-runner-link' } do
|
||||||
= link_to edit_project_runner_path(@project, runner), class: 'btn gl-button btn-edit' do
|
= sprite_icon('pencil')
|
||||||
= sprite_icon('pencil', css_class: 'gl-my-2')
|
|
||||||
- else
|
- else
|
||||||
%span.commit-sha
|
%span.commit-sha
|
||||||
= runner.short_sha
|
= runner.short_sha
|
||||||
|
|
|
@ -0,0 +1,5 @@
|
||||||
|
---
|
||||||
|
title: Externalize strings in _performance.html.haml
|
||||||
|
merge_request: 58016
|
||||||
|
author: nuwe1
|
||||||
|
type: other
|
|
@ -0,0 +1,5 @@
|
||||||
|
---
|
||||||
|
title: Externalizes strings in viewers/_empty.html.haml
|
||||||
|
merge_request: 58451
|
||||||
|
author: nuwe1
|
||||||
|
type: other
|
|
@ -0,0 +1,5 @@
|
||||||
|
---
|
||||||
|
title: Fix EmptyLineAfterFinalLetItBe offenses in spec/lib/gitlab/checks
|
||||||
|
merge_request: 58248
|
||||||
|
author: Huzaifa Iftikhar @huzaifaiftikhar
|
||||||
|
type: fixed
|
|
@ -0,0 +1,5 @@
|
||||||
|
---
|
||||||
|
title: Fix EmptyLineAfterFinalLetItBe offenses in spec/lib/gitlab/graphql
|
||||||
|
merge_request: 58261
|
||||||
|
author: Huzaifa Iftikhar @huzaifaiftikhar
|
||||||
|
type: fixed
|
|
@ -0,0 +1,5 @@
|
||||||
|
---
|
||||||
|
title: Update Jira plugin UI copy
|
||||||
|
merge_request: 57793
|
||||||
|
author: Russell Dickenson rdickenson@gitlab.com
|
||||||
|
type: other
|
|
@ -0,0 +1,6 @@
|
||||||
|
---
|
||||||
|
title: Fill in all placeholder values in the apply suggestion commit message placeholder
|
||||||
|
text
|
||||||
|
merge_request: 58136
|
||||||
|
author:
|
||||||
|
type: other
|
|
@ -57,7 +57,7 @@ functions available. Consider these best practices when creating ChatOps jobs:
|
||||||
in the project, the job runs. The job itself can use existing
|
in the project, the job runs. The job itself can use existing
|
||||||
[CI/CD variables](../variables/README.md#predefined-cicd-variables) like
|
[CI/CD variables](../variables/README.md#predefined-cicd-variables) like
|
||||||
`GITLAB_USER_ID` to perform additional rights validation, but
|
`GITLAB_USER_ID` to perform additional rights validation, but
|
||||||
these variables can be [overridden](../variables/README.md#priority-of-cicd-variables).
|
these variables can be [overridden](../variables/README.md#cicd-variable-precedence).
|
||||||
|
|
||||||
### Controlling the ChatOps reply
|
### Controlling the ChatOps reply
|
||||||
|
|
||||||
|
|
|
@ -690,7 +690,7 @@ with `review/` would have that variable available.
|
||||||
|
|
||||||
Some GitLab features can behave differently for each environment.
|
Some GitLab features can behave differently for each environment.
|
||||||
For example, you can
|
For example, you can
|
||||||
[create a secret variable to be injected only into a production environment](../variables/README.md#limit-the-environment-scopes-of-cicd-variables).
|
[create a project CI/CD variable to be injected only into a production environment](../variables/README.md#limit-the-environment-scope-of-a-cicd-variable).
|
||||||
|
|
||||||
In most cases, these features use the _environment specs_ mechanism, which offers
|
In most cases, these features use the _environment specs_ mechanism, which offers
|
||||||
an efficient way to implement scoping in each environment group.
|
an efficient way to implement scoping in each environment group.
|
||||||
|
|
|
@ -220,7 +220,7 @@ the ones defined in the upstream project take precedence.
|
||||||
|
|
||||||
#### With variable inheritance
|
#### With variable inheritance
|
||||||
|
|
||||||
You can pass variables to a downstream pipeline with [`dotenv` variable inheritance](variables/README.md#inherit-cicd-variables) and [cross project artifact downloads](yaml/README.md#cross-project-artifact-downloads-with-needs).
|
You can pass variables to a downstream pipeline with [`dotenv` variable inheritance](variables/README.md#pass-an-environment-variable-to-another-job) and [cross project artifact downloads](yaml/README.md#cross-project-artifact-downloads-with-needs).
|
||||||
|
|
||||||
In the upstream pipeline:
|
In the upstream pipeline:
|
||||||
|
|
||||||
|
|
|
@ -255,7 +255,7 @@ curl --request POST \
|
||||||
"https://gitlab.example.com/api/v4/projects/9/trigger/pipeline"
|
"https://gitlab.example.com/api/v4/projects/9/trigger/pipeline"
|
||||||
```
|
```
|
||||||
|
|
||||||
Trigger variables have the [highest priority](../variables/README.md#priority-of-cicd-variables)
|
Trigger variables have the [highest priority](../variables/README.md#cicd-variable-precedence)
|
||||||
of all types of variables.
|
of all types of variables.
|
||||||
|
|
||||||
## Using cron to trigger nightly pipelines
|
## Using cron to trigger nightly pipelines
|
||||||
|
|
|
@ -66,6 +66,11 @@ or have them [prefilled in manual pipelines](../pipelines/index.md#prefill-varia
|
||||||
|
|
||||||
There are two types of variables: [`File` or `Variable`](#cicd-variable-types).
|
There are two types of variables: [`File` or `Variable`](#cicd-variable-types).
|
||||||
|
|
||||||
|
Variable names are limited by the [shell the runner uses](https://docs.gitlab.com/runner/shells/index.html)
|
||||||
|
to execute scripts. Each shell has its own set of reserved variable names.
|
||||||
|
|
||||||
|
Make sure each variable is defined for the [scope you want to use it in](where_variables_can_be_used.md).
|
||||||
|
|
||||||
### Create a custom CI/CD variable in the `.gitlab-ci.yml` file
|
### Create a custom CI/CD variable in the `.gitlab-ci.yml` file
|
||||||
|
|
||||||
To create a custom variable in the [`.gitlab-ci.yml`](../yaml/README.md#variables) file,
|
To create a custom variable in the [`.gitlab-ci.yml`](../yaml/README.md#variables) file,
|
||||||
|
@ -467,16 +472,23 @@ export GITLAB_USER_ID="42"
|
||||||
...
|
...
|
||||||
```
|
```
|
||||||
|
|
||||||
## Inherit CI/CD variables
|
## Pass an environment variable to another job
|
||||||
|
|
||||||
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/22638) in GitLab 13.0 behind a disabled [feature flag](../../administration/feature_flags.md): `ci_dependency_variables`.
|
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/22638) in GitLab 13.0.
|
||||||
> - [Feature flag removed](https://gitlab.com/gitlab-org/gitlab/-/issues/217834) in GitLab 13.1.
|
> - [Feature flag removed](https://gitlab.com/gitlab-org/gitlab/-/issues/217834) in GitLab 13.1.
|
||||||
|
|
||||||
You can inherit CI/CD variables from dependent jobs.
|
You can pass environment variables from one job to another job in a later stage.
|
||||||
|
These variables cannot be used as CI/CD variables to configure a pipeline, but
|
||||||
|
they can be used in job scripts.
|
||||||
|
|
||||||
This feature makes use of the [`artifacts:reports:dotenv`](../pipelines/job_artifacts.md#artifactsreportsdotenv) report feature.
|
1. In the job script, save the variable as a `.env` file.
|
||||||
|
1. Save the `.env` file as an [`artifacts:reports:dotenv`](../pipelines/job_artifacts.md#artifactsreportsdotenv)
|
||||||
|
artifact.
|
||||||
|
1. Set a job in a later stage to receive the artifact by using the [`dependencies`](../yaml/README.md#dependencies)
|
||||||
|
or the [`needs`](../yaml/README.md#artifact-downloads-with-needs) keywords.
|
||||||
|
1. The later job can then [use the variable in scripts](#use-cicd-variables-in-job-scripts).
|
||||||
|
|
||||||
Example with [`dependencies`](../yaml/README.md#dependencies) keyword.
|
For example, with the [`dependencies`](../yaml/README.md#dependencies) keyword:
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
build:
|
build:
|
||||||
|
@ -490,12 +502,12 @@ build:
|
||||||
deploy:
|
deploy:
|
||||||
stage: deploy
|
stage: deploy
|
||||||
script:
|
script:
|
||||||
- echo $BUILD_VERSION # => hello
|
- echo $BUILD_VERSION # Output is: 'hello'
|
||||||
dependencies:
|
dependencies:
|
||||||
- build
|
- build
|
||||||
```
|
```
|
||||||
|
|
||||||
Example with the [`needs`](../yaml/README.md#artifact-downloads-with-needs) keyword:
|
For example, with the [`needs`](../yaml/README.md#artifact-downloads-with-needs) keyword:
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
build:
|
build:
|
||||||
|
@ -509,131 +521,113 @@ build:
|
||||||
deploy:
|
deploy:
|
||||||
stage: deploy
|
stage: deploy
|
||||||
script:
|
script:
|
||||||
- echo $BUILD_VERSION # => hello
|
- echo $BUILD_VERSION # Output is: 'hello'
|
||||||
needs:
|
needs:
|
||||||
- job: build
|
- job: build
|
||||||
artifacts: true
|
artifacts: true
|
||||||
```
|
```
|
||||||
|
|
||||||
## Priority of CI/CD variables
|
## CI/CD variable precedence
|
||||||
|
|
||||||
Variables of different types can take precedence over other
|
You can use CI/CD variables with the same name in different places, but the values
|
||||||
variables, depending on where they are defined.
|
can overwrite each other. The type of variable and where they are defined determines
|
||||||
|
which variables take precedence.
|
||||||
|
|
||||||
The order of precedence for variables is (from highest to lowest):
|
The order of precedence for variables is (from highest to lowest):
|
||||||
|
|
||||||
1. [Trigger variables](../triggers/README.md#making-use-of-trigger-variables), [scheduled pipeline variables](../pipelines/schedules.md#using-variables),
|
1. [Trigger variables](../triggers/README.md#making-use-of-trigger-variables),
|
||||||
and [manual pipeline run variables](#override-a-variable-by-manually-running-a-pipeline).
|
[scheduled pipeline variables](../pipelines/schedules.md#using-variables),
|
||||||
1. Project-level [variables](#custom-cicd-variables) or [protected variables](#protect-a-cicd-variable).
|
and [manual pipeline run variables](#override-a-variable-when-running-a-pipeline-manually).
|
||||||
1. Group-level [variables](#group-cicd-variables) or [protected variables](#protect-a-cicd-variable).
|
1. Project [variables](#custom-cicd-variables).
|
||||||
1. Instance-level [variables](#instance-cicd-variables) or [protected variables](#protect-a-cicd-variable).
|
1. Group [variables](#group-cicd-variables).
|
||||||
1. [Inherited CI/CD variables](#inherit-cicd-variables).
|
1. Instance [variables](#instance-cicd-variables).
|
||||||
1. YAML-defined [job-level variables](../yaml/README.md#variables).
|
1. [Inherited variables](#pass-an-environment-variable-to-another-job).
|
||||||
1. YAML-defined [global variables](../yaml/README.md#variables).
|
1. Variables defined in jobs in the `.gitlab-ci.yml` file.
|
||||||
|
1. Variables defined outside of jobs (globally) in the `.gitlab-ci.yml` file.
|
||||||
1. [Deployment variables](#deployment-variables).
|
1. [Deployment variables](#deployment-variables).
|
||||||
1. [Predefined CI/CD variables](predefined_variables.md).
|
1. [Predefined variables](predefined_variables.md).
|
||||||
|
|
||||||
For example, if you define:
|
In the following example, when the script in `job1` executes, the value of `API_TOKEN` is `secure`.
|
||||||
|
Variables defined in jobs have a higher precedence than variables defined globally.
|
||||||
|
|
||||||
- `API_TOKEN=secure` as a project variable.
|
```yaml
|
||||||
- `API_TOKEN=yaml` in your `.gitlab-ci.yml`.
|
variables:
|
||||||
|
API_TOKEN: "default"
|
||||||
|
|
||||||
`API_TOKEN` takes the value `secure` as the project
|
job1:
|
||||||
variables take precedence over those defined in `.gitlab-ci.yml`.
|
variables:
|
||||||
|
API_TOKEN: "secure"
|
||||||
|
script:
|
||||||
|
- echo "The variable value is $API_TOKEN"
|
||||||
|
```
|
||||||
|
|
||||||
## Unsupported variables
|
## Override a defined CI/CD variable
|
||||||
|
|
||||||
Variable names are limited by the underlying shell used to execute scripts (see [available shells](https://docs.gitlab.com/runner/shells/index.html).
|
You can override the value of a variable when you:
|
||||||
Each shell has its own unique set of reserved variable names.
|
|
||||||
Keep in mind the [scope of CI/CD variables](where_variables_can_be_used.md) to ensure a variable is defined in the scope in which you wish to use it.
|
|
||||||
|
|
||||||
## Where variables can be used
|
1. [Run a pipeline manually](#override-a-variable-when-running-a-pipeline-manually) in the UI.
|
||||||
|
1. Create a pipeline by using [the API](../../api/pipelines.md#create-a-new-pipeline).
|
||||||
|
1. Run a job manually in the UI.
|
||||||
|
1. Use [push options](../../user/project/push_options.md#push-options-for-gitlab-cicd).
|
||||||
|
1. Trigger a pipeline by using [the API](../triggers/README.md#making-use-of-trigger-variables).
|
||||||
|
1. Pass variables to a [downstream pipeline](../multi_project_pipelines.md#passing-cicd-variables-to-a-downstream-pipeline).
|
||||||
|
|
||||||
[This section](where_variables_can_be_used.md) describes where and how the different types of variables can be used.
|
The pipeline variables declared in these events take [priority over other variables](#cicd-variable-precedence).
|
||||||
|
|
||||||
## Advanced use
|
### Override a variable when running a pipeline manually
|
||||||
|
|
||||||
### Limit the environment scopes of CI/CD variables
|
You can override the value of a CI/CD variable when you
|
||||||
|
[run a pipeline manually](../pipelines/index.md#run-a-pipeline-manually).
|
||||||
|
|
||||||
|
1. Go to your project's **CI/CD > Pipelines** and select **Run pipeline**.
|
||||||
|
1. Choose the branch you want to run the pipeline for.
|
||||||
|
1. Input the variable and its value in the UI.
|
||||||
|
|
||||||
|
### Restrict who can override variables
|
||||||
|
|
||||||
|
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/295234) in GitLab 13.8.
|
||||||
|
|
||||||
|
You can grant permission to override variables to [maintainers](../../user/permissions.md#project-features) only. When other users try to run a pipeline
|
||||||
|
with overridden variables, they receive the `Insufficient permissions to set pipeline variables`
|
||||||
|
error message.
|
||||||
|
|
||||||
|
If you [store your CI/CD configurations in a different repository](../../ci/pipelines/settings.md#custom-cicd-configuration-path),
|
||||||
|
use this setting for control over the environment the pipeline runs in.
|
||||||
|
|
||||||
|
You can enable this feature by using [the projects API](../../api/projects.md#edit-project)
|
||||||
|
to enable the `restrict_user_defined_variables` setting. The setting is `disabled` by default.
|
||||||
|
|
||||||
|
## Limit the environment scope of a CI/CD variable
|
||||||
|
|
||||||
You can limit the environment scope of a variable by
|
You can limit the environment scope of a variable by
|
||||||
[defining which environments](../environments/index.md) it can be available for.
|
[defining which environments](../environments/index.md) it can be available for.
|
||||||
|
|
||||||
To learn more about scoping environments, see [Scoping environments with specs](../environments/index.md#scoping-environments-with-specs).
|
To learn more about scoping environments, see [Scoping environments with specs](../environments/index.md#scoping-environments-with-specs).
|
||||||
|
|
||||||
### Deployment variables
|
## Deployment variables
|
||||||
|
|
||||||
[Integrations](../../user/project/integrations/overview.md) that are
|
Integrations that are responsible for deployment configuration can define their own
|
||||||
responsible for deployment configuration may define their own variables that
|
variables that are set in the build environment. These variables are only defined
|
||||||
are set in the build environment. These variables are only defined for
|
for [deployment jobs](../environments/index.md).
|
||||||
[deployment jobs](../environments/index.md). Please consult the documentation of
|
|
||||||
the integrations that you are using to learn which variables they define.
|
|
||||||
|
|
||||||
An example integration that defines deployment variables is the
|
For example, the [Kubernetes integration](../../user/project/clusters/index.md#deployment-variables)
|
||||||
[Kubernetes integration](../../user/project/clusters/index.md#deployment-variables).
|
defines deployment variables that you can use with the integration.
|
||||||
|
|
||||||
### Auto DevOps environment variables
|
The [documentation for each integration](../../user/project/integrations/overview.md)
|
||||||
|
explains if the integration has any deployment variables available.
|
||||||
|
|
||||||
|
## Auto DevOps environment variables
|
||||||
|
|
||||||
> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/49056) in GitLab 11.7.
|
> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/49056) in GitLab 11.7.
|
||||||
|
|
||||||
You can configure [Auto DevOps](../../topics/autodevops/index.md) to
|
You can configure [Auto DevOps](../../topics/autodevops/index.md) to pass CI/CD variables
|
||||||
pass CI/CD variables to the running application by prefixing the key of the
|
to a running application.
|
||||||
variable with `K8S_SECRET_`.
|
|
||||||
|
|
||||||
These [prefixed variables](../../topics/autodevops/customize.md#application-secret-variables) are
|
To make a CI/CD variable available as an environment variable in the running application's container,
|
||||||
then available as environment variables on the running application
|
[prefix the variable key](../../topics/autodevops/customize.md#application-secret-variables)
|
||||||
container.
|
with `K8S_SECRET_`.
|
||||||
|
|
||||||
WARNING:
|
CI/CD variables with multi-line values are not supported.
|
||||||
Variables with multi-line values are not supported due to
|
|
||||||
limitations with the Auto DevOps scripting environment.
|
|
||||||
|
|
||||||
### When you can override variables
|
|
||||||
|
|
||||||
You can override the value of a variable when:
|
|
||||||
|
|
||||||
1. [Manually running](#override-a-variable-by-manually-running-a-pipeline) pipelines in the UI.
|
|
||||||
1. Manually creating pipelines [via API](../../api/pipelines.md#create-a-new-pipeline).
|
|
||||||
1. Manually playing a job via the UI.
|
|
||||||
1. Using [push options](../../user/project/push_options.md#push-options-for-gitlab-cicd).
|
|
||||||
1. Manually triggering pipelines with [the API](../triggers/README.md#making-use-of-trigger-variables).
|
|
||||||
1. Passing variables to a [downstream pipeline](../multi_project_pipelines.md#passing-cicd-variables-to-a-downstream-pipeline).
|
|
||||||
|
|
||||||
These pipeline variables declared in these events take [priority over other variables](#priority-of-cicd-variables).
|
|
||||||
|
|
||||||
#### Restrict who can override variables
|
|
||||||
|
|
||||||
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/295234) in GitLab 13.8.
|
|
||||||
|
|
||||||
To allow only users with Maintainer role to set these variables, you can use
|
|
||||||
[the API](../../api/projects.md#edit-project) to enable the project setting `restrict_user_defined_variables`.
|
|
||||||
When a user without Maintainer role tries to run a pipeline with overridden
|
|
||||||
variables, an `Insufficient permissions to set pipeline variables` error occurs.
|
|
||||||
|
|
||||||
The setting is `disabled` by default.
|
|
||||||
|
|
||||||
If you [store your CI/CD configurations in a different repository](../../ci/pipelines/settings.md#custom-cicd-configuration-path),
|
|
||||||
use this setting for strict control over all aspects of the environment
|
|
||||||
the pipeline runs in.
|
|
||||||
|
|
||||||
#### Override a variable by manually running a pipeline
|
|
||||||
|
|
||||||
> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/44059) in GitLab 10.8.
|
|
||||||
|
|
||||||
You can override the value of a current variable by
|
|
||||||
[running a pipeline manually](../pipelines/index.md#run-a-pipeline-manually).
|
|
||||||
|
|
||||||
For instance, suppose you added a custom variable named `$TEST`
|
|
||||||
and you want to override it in a manual pipeline.
|
|
||||||
|
|
||||||
Go to your project's **CI/CD > Pipelines** and select **Run pipeline**.
|
|
||||||
Choose the branch you want to run the pipeline for, then add a variable and its value in the UI:
|
|
||||||
|
|
||||||
![Override variable value](img/override_variable_manual_pipeline.png)
|
|
||||||
|
|
||||||
The runner overrides the value previously set and uses the custom
|
|
||||||
value for this specific pipeline.
|
|
||||||
|
|
||||||
![Manually overridden variable output](img/override_value_via_manual_pipeline_output.png)
|
|
||||||
|
|
||||||
## CI/CD variable expressions
|
## CI/CD variable expressions
|
||||||
|
|
||||||
|
@ -828,44 +822,22 @@ testvariable:
|
||||||
> Introduced in GitLab Runner 1.7.
|
> Introduced in GitLab Runner 1.7.
|
||||||
|
|
||||||
WARNING:
|
WARNING:
|
||||||
Enabling debug tracing can have severe security implications. The
|
Debug logging can be a serious security risk. The output contains the content of
|
||||||
output **will** contain the content of all your variables and any other
|
all variables and other secrets available to the job. The output is uploaded to the
|
||||||
secrets! The output **will** be uploaded to the GitLab server and made visible
|
GitLab server and visible in job logs.
|
||||||
in job logs!
|
|
||||||
|
|
||||||
By default, the runner hides most of the details of what it is doing when
|
You can use debug logging to help troubleshoot problems with pipeline configuration
|
||||||
processing a job. This behavior keeps job logs short, and prevents secrets
|
or job scripts. Debug logging exposes job execution details that are usually hidden
|
||||||
from being leaked into the log unless your script writes them to the screen.
|
by the runner and makes job logs more verbose. It also exposes all variables and secrets
|
||||||
|
available to the job.
|
||||||
|
|
||||||
If a job isn't working as expected, this can make the problem difficult to
|
Before you enable debug logging, make sure only [team members](../../user/permissions.md#project-features)
|
||||||
investigate; in these cases, you can enable debug tracing in `.gitlab-ci.yml`.
|
can view job logs. You should also [delete job logs](../jobs/index.md#view-jobs-in-a-pipeline)
|
||||||
Available on GitLab Runner v1.7+, this feature enables the shell's execution log. This results in a verbose job log listing all commands that were run, variables that were set, and so on.
|
with debug output before you make logs public again.
|
||||||
|
|
||||||
Before enabling this, you should ensure jobs are visible to
|
|
||||||
[team members only](../../user/permissions.md#project-features). You should
|
|
||||||
also [erase](../jobs/index.md#view-jobs-in-a-pipeline) all generated job logs
|
|
||||||
before making them visible again.
|
|
||||||
|
|
||||||
### Restricted access to debug logging
|
|
||||||
|
|
||||||
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/213159) in GitLab 13.7.
|
|
||||||
> - [Feature flag removed](https://gitlab.com/gitlab-org/gitlab/-/issues/292661) in GitLab 13.8.
|
|
||||||
|
|
||||||
With restricted access to debug logging, only users with
|
|
||||||
[developer or higher permissions](../../user/permissions.md#project-members-permissions)
|
|
||||||
can view job logs when debug logging is enabled with a variable in:
|
|
||||||
|
|
||||||
- The [`.gitlab-ci.yml` file](#create-a-custom-cicd-variable-in-the-gitlab-ciyml-file).
|
|
||||||
- The CI/CD variables set in the GitLab UI.
|
|
||||||
|
|
||||||
WARNING:
|
|
||||||
If you add `CI_DEBUG_TRACE` as a local variable to your runners, debug logs are visible
|
|
||||||
to all users with access to job logs. The permission levels are not checked by Runner,
|
|
||||||
so you should make use of the variable in GitLab only.
|
|
||||||
|
|
||||||
### Enable Debug logging
|
### Enable Debug logging
|
||||||
|
|
||||||
To enable debug logs (traces), set the `CI_DEBUG_TRACE` variable to `true`:
|
To enable debug logging (tracing), set the `CI_DEBUG_TRACE` variable to `true`:
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
job_name:
|
job_name:
|
||||||
|
@ -873,11 +845,10 @@ job_name:
|
||||||
CI_DEBUG_TRACE: "true"
|
CI_DEBUG_TRACE: "true"
|
||||||
```
|
```
|
||||||
|
|
||||||
Example truncated output with `CI_DEBUG_TRACE` set to `true`:
|
Example output (truncated):
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
...
|
...
|
||||||
|
|
||||||
export CI_SERVER_TLS_CA_FILE="/builds/gitlab-examples/ci-debug-trace.tmp/CI_SERVER_TLS_CA_FILE"
|
export CI_SERVER_TLS_CA_FILE="/builds/gitlab-examples/ci-debug-trace.tmp/CI_SERVER_TLS_CA_FILE"
|
||||||
if [[ -d "/builds/gitlab-examples/ci-debug-trace/.git" ]]; then
|
if [[ -d "/builds/gitlab-examples/ci-debug-trace/.git" ]]; then
|
||||||
echo $'\''\x1b[32;1mFetching changes...\x1b[0;m'\''
|
echo $'\''\x1b[32;1mFetching changes...\x1b[0;m'\''
|
||||||
|
@ -982,10 +953,26 @@ if [[ -d "/builds/gitlab-examples/ci-debug-trace/.git" ]]; then
|
||||||
++ CI_COMMIT_REF_NAME=master
|
++ CI_COMMIT_REF_NAME=master
|
||||||
++ export CI_COMMIT_REF_SLUG=master
|
++ export CI_COMMIT_REF_SLUG=master
|
||||||
++ CI_COMMIT_REF_SLUG=master
|
++ CI_COMMIT_REF_SLUG=master
|
||||||
|
|
||||||
...
|
...
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### Restrict access to debug logging
|
||||||
|
|
||||||
|
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/213159) in GitLab 13.7.
|
||||||
|
> - [Feature flag removed](https://gitlab.com/gitlab-org/gitlab/-/issues/292661) in GitLab 13.8.
|
||||||
|
|
||||||
|
You can restrict access to debug logging. When restricted, only users with
|
||||||
|
[developer or higher permissions](../../user/permissions.md#project-members-permissions)
|
||||||
|
can view job logs when debug logging is enabled with a variable in:
|
||||||
|
|
||||||
|
- The [`.gitlab-ci.yml` file](#create-a-custom-cicd-variable-in-the-gitlab-ciyml-file).
|
||||||
|
- The CI/CD variables set in the GitLab UI.
|
||||||
|
|
||||||
|
WARNING:
|
||||||
|
If you add `CI_DEBUG_TRACE` as a local variable to runners, debug logs generate and are visible
|
||||||
|
to all users with access to job logs. The permission levels are not checked by the runner,
|
||||||
|
so you should only use the variable in GitLab itself.
|
||||||
|
|
||||||
## Video walkthrough of a working example
|
## Video walkthrough of a working example
|
||||||
|
|
||||||
The [Managing the Complex Configuration Data Management Monster Using GitLab](https://www.youtube.com/watch?v=v4ZOJ96hAck)
|
The [Managing the Complex Configuration Data Management Monster Using GitLab](https://www.youtube.com/watch?v=v4ZOJ96hAck)
|
||||||
|
|
Binary file not shown.
Before Width: | Height: | Size: 108 KiB |
Binary file not shown.
Before Width: | Height: | Size: 18 KiB |
|
@ -4636,7 +4636,7 @@ meaning it applies to all jobs. If you define a variable in a job, it's availabl
|
||||||
to that job only.
|
to that job only.
|
||||||
|
|
||||||
If a variable of the same name is defined globally and for a specific job, the
|
If a variable of the same name is defined globally and for a specific job, the
|
||||||
[job-specific variable overrides the global variable](../variables/README.md#priority-of-cicd-variables).
|
[job-specific variable overrides the global variable](../variables/README.md#cicd-variable-precedence).
|
||||||
|
|
||||||
All YAML-defined variables are also set to any linked
|
All YAML-defined variables are also set to any linked
|
||||||
[Docker service containers](../services/index.md).
|
[Docker service containers](../services/index.md).
|
||||||
|
|
|
@ -408,8 +408,19 @@ When ready to merge:
|
||||||
circling back with the author about that. Otherwise, if the MR only has a few commits, we'll
|
circling back with the author about that. Otherwise, if the MR only has a few commits, we'll
|
||||||
be respecting the author's setting by not squashing them.
|
be respecting the author's setting by not squashing them.
|
||||||
|
|
||||||
- **Start a new merge request pipeline with the `Run Pipeline` button in the merge
|
WARNING:
|
||||||
request's "Pipelines" tab, and enable "Merge When Pipeline Succeeds" (MWPS).** Note that:
|
**If the merge request is from a fork, review all changes thoroughly for malicious code before
|
||||||
|
starting a [Pipeline for Merged Results](../ci/merge_request_pipelines/index.md#run-pipelines-in-the-parent-project-for-merge-requests-from-a-forked-project).**
|
||||||
|
Pay particular attention to new dependencies and dependency updates, such as Ruby gems and Node packages.
|
||||||
|
While changes to files like `Gemfile.lock` or `yarn.lock` might appear trivial, they could lead to the
|
||||||
|
fetching of malicious packages.
|
||||||
|
If the MR source branch is more than 100 commits behind the target branch, ask the author to rebase it.
|
||||||
|
Review links and images, especially in documentation MRs.
|
||||||
|
When in doubt, ask someone from `@gitlab-com/gl-security/appsec` to review the merge request **before starting any merge request pipeline**.
|
||||||
|
|
||||||
|
- Start a new merge request pipeline with the `Run Pipeline` button in the merge
|
||||||
|
request's "Pipelines" tab, and enable "Merge When Pipeline Succeeds" (MWPS).
|
||||||
|
Note that:
|
||||||
- If **[master is broken](https://about.gitlab.com/handbook/engineering/workflow/#broken-master),
|
- If **[master is broken](https://about.gitlab.com/handbook/engineering/workflow/#broken-master),
|
||||||
do not merge the merge request** except for
|
do not merge the merge request** except for
|
||||||
[very specific cases](https://about.gitlab.com/handbook/engineering/workflow/#criteria-for-merging-during-broken-master).
|
[very specific cases](https://about.gitlab.com/handbook/engineering/workflow/#criteria-for-merging-during-broken-master).
|
||||||
|
@ -417,10 +428,6 @@ When ready to merge:
|
||||||
- If the **latest [Pipeline for Merged Results](../ci/merge_request_pipelines/pipelines_for_merged_results/#pipelines-for-merged-results)** finished less than 2 hours ago, you
|
- If the **latest [Pipeline for Merged Results](../ci/merge_request_pipelines/pipelines_for_merged_results/#pipelines-for-merged-results)** finished less than 2 hours ago, you
|
||||||
might merge without starting a new pipeline as the merge request is close
|
might merge without starting a new pipeline as the merge request is close
|
||||||
enough to `master`.
|
enough to `master`.
|
||||||
- If the **merge request is from a fork**, we can use [Pipelines for Merged Results from a forked project](../ci/merge_request_pipelines/index.md#run-pipelines-in-the-parent-project-for-merge-requests-from-a-forked-project) with caution.
|
|
||||||
Before triggering the pipeline, review all changes for **malicious code**.
|
|
||||||
If you cannot trigger the pipeline, review the status of the fork relative to `master`.
|
|
||||||
If it's more than 100 commits behind, ask the author to rebase it before merging.
|
|
||||||
- When you set the MR to "Merge When Pipeline Succeeds", you should take over
|
- When you set the MR to "Merge When Pipeline Succeeds", you should take over
|
||||||
subsequent revisions for anything that would be spotted after that.
|
subsequent revisions for anything that would be spotted after that.
|
||||||
|
|
||||||
|
|
|
@ -171,7 +171,7 @@ list of options.
|
||||||
## Custom Helm chart per environment
|
## Custom Helm chart per environment
|
||||||
|
|
||||||
You can specify the use of a custom Helm chart per environment by scoping the CI/CD variable
|
You can specify the use of a custom Helm chart per environment by scoping the CI/CD variable
|
||||||
to the desired environment. See [Limiting environment scopes of variables](../../ci/variables/README.md#limit-the-environment-scopes-of-cicd-variables).
|
to the desired environment. See [Limit environment scope of CI/CD variables](../../ci/variables/README.md#limit-the-environment-scope-of-a-cicd-variable).
|
||||||
|
|
||||||
## Customizing `.gitlab-ci.yml`
|
## Customizing `.gitlab-ci.yml`
|
||||||
|
|
||||||
|
|
|
@ -231,7 +231,7 @@ any of the following places:
|
||||||
**Continuous Integration and Delivery** section
|
**Continuous Integration and Delivery** section
|
||||||
|
|
||||||
The base domain variable `KUBE_INGRESS_BASE_DOMAIN` follows the same order of precedence
|
The base domain variable `KUBE_INGRESS_BASE_DOMAIN` follows the same order of precedence
|
||||||
as other environment [variables](../../ci/variables/README.md#priority-of-cicd-variables).
|
as other environment [variables](../../ci/variables/README.md#cicd-variable-precedence).
|
||||||
If the CI/CD variable is not set and the cluster setting is left blank, the instance-wide **Auto DevOps domain**
|
If the CI/CD variable is not set and the cluster setting is left blank, the instance-wide **Auto DevOps domain**
|
||||||
setting is used if set.
|
setting is used if set.
|
||||||
|
|
||||||
|
@ -274,7 +274,7 @@ used by Auto DevOps currently defines 3 environment names:
|
||||||
Those environments are tied to jobs using [Auto Deploy](stages.md#auto-deploy), so
|
Those environments are tied to jobs using [Auto Deploy](stages.md#auto-deploy), so
|
||||||
except for the environment scope, they must have a different deployment domain.
|
except for the environment scope, they must have a different deployment domain.
|
||||||
You must define a separate `KUBE_INGRESS_BASE_DOMAIN` variable for each of the above
|
You must define a separate `KUBE_INGRESS_BASE_DOMAIN` variable for each of the above
|
||||||
[based on the environment](../../ci/variables/README.md#limit-the-environment-scopes-of-cicd-variables).
|
[based on the environment](../../ci/variables/README.md#limit-the-environment-scope-of-a-cicd-variable).
|
||||||
|
|
||||||
The following table is an example of how to configure the three different clusters:
|
The following table is an example of how to configure the three different clusters:
|
||||||
|
|
||||||
|
|
|
@ -107,7 +107,7 @@ The domain should have a wildcard DNS configured to the Ingress IP address.
|
||||||
When adding more than one Kubernetes cluster to your project, you need to differentiate
|
When adding more than one Kubernetes cluster to your project, you need to differentiate
|
||||||
them with an environment scope. The environment scope associates clusters with
|
them with an environment scope. The environment scope associates clusters with
|
||||||
[environments](../../../ci/environments/index.md) similar to how the
|
[environments](../../../ci/environments/index.md) similar to how the
|
||||||
[environment-specific variables](../../../ci/variables/README.md#limit-the-environment-scopes-of-cicd-variables)
|
[environment-specific CI/CD variables](../../../ci/variables/README.md#limit-the-environment-scope-of-a-cicd-variable)
|
||||||
work.
|
work.
|
||||||
|
|
||||||
While evaluating which environment matches the environment scope of a
|
While evaluating which environment matches the environment scope of a
|
||||||
|
|
|
@ -86,7 +86,7 @@ differentiates the new cluster from the rest.
|
||||||
|
|
||||||
When adding more than one Kubernetes cluster to your project, you need to differentiate
|
When adding more than one Kubernetes cluster to your project, you need to differentiate
|
||||||
them with an environment scope. The environment scope associates clusters with [environments](../../../ci/environments/index.md) similar to how the
|
them with an environment scope. The environment scope associates clusters with [environments](../../../ci/environments/index.md) similar to how the
|
||||||
[environment-specific CI/CD variables](../../../ci/variables/README.md#limit-the-environment-scopes-of-cicd-variables) work.
|
[environment-specific CI/CD variables](../../../ci/variables/README.md#limit-the-environment-scope-of-a-cicd-variable) work.
|
||||||
|
|
||||||
The default environment scope is `*`, which means all jobs, regardless of their
|
The default environment scope is `*`, which means all jobs, regardless of their
|
||||||
environment, use that cluster. Each scope can be used only by a single cluster
|
environment, use that cluster. Each scope can be used only by a single cluster
|
||||||
|
|
|
@ -16961,7 +16961,7 @@ msgstr ""
|
||||||
msgid "Integrations|Use the GitLab Slack application"
|
msgid "Integrations|Use the GitLab Slack application"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
msgid "Integrations|When a Jira issue is mentioned in a commit or merge request a remote link and comment (if enabled) will be created."
|
msgid "Integrations|When a Jira issue is mentioned in a commit or merge request a remote link and comment (if enabled) is created."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
msgid "Integrations|You can now close this window and return to the GitLab for Jira application."
|
msgid "Integrations|You can now close this window and return to the GitLab for Jira application."
|
||||||
|
@ -17678,6 +17678,9 @@ msgstr ""
|
||||||
msgid "JiraService|Automatically transitions Jira issues to the \"Done\" category. %{linkStart}Learn more%{linkEnd}"
|
msgid "JiraService|Automatically transitions Jira issues to the \"Done\" category. %{linkStart}Learn more%{linkEnd}"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "JiraService|Base URL of the Jira instance."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "JiraService|Define the type of Jira issue to create from a vulnerability."
|
msgid "JiraService|Define the type of Jira issue to create from a vulnerability."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -17708,10 +17711,13 @@ msgstr ""
|
||||||
msgid "JiraService|For example, 12, 24"
|
msgid "JiraService|For example, 12, 24"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "JiraService|For example, AB"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "JiraService|GitLab for Jira Configuration"
|
msgid "JiraService|GitLab for Jira Configuration"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
msgid "JiraService|If different from Web URL"
|
msgid "JiraService|If different from Web URL."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
msgid "JiraService|Issue List"
|
msgid "JiraService|Issue List"
|
||||||
|
@ -17732,16 +17738,13 @@ msgstr ""
|
||||||
msgid "JiraService|Jira comments will be created when an issue gets referenced in a merge request."
|
msgid "JiraService|Jira comments will be created when an issue gets referenced in a merge request."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
msgid "JiraService|Jira issue tracker"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
msgid "JiraService|Jira issue type"
|
msgid "JiraService|Jira issue type"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
msgid "JiraService|Jira project key"
|
msgid "JiraService|Jira project key"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
msgid "JiraService|Leave blank to use your current password or API token"
|
msgid "JiraService|Leave blank to use your current password or API token."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
msgid "JiraService|Move to Done"
|
msgid "JiraService|Move to Done"
|
||||||
|
@ -17777,13 +17780,16 @@ msgstr ""
|
||||||
msgid "JiraService|This issue is synchronized with Jira"
|
msgid "JiraService|This issue is synchronized with Jira"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "JiraService|Track issues in Jira"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "JiraService|Transition Jira issues to their final state:"
|
msgid "JiraService|Transition Jira issues to their final state:"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
msgid "JiraService|Use a password for server version and an API token for cloud version"
|
msgid "JiraService|Use a password for server version and an API token for cloud version."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
msgid "JiraService|Use a username for server version and an email for cloud version"
|
msgid "JiraService|Use a username for server version and an email for cloud version."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
msgid "JiraService|Use custom transitions"
|
msgid "JiraService|Use custom transitions"
|
||||||
|
@ -17798,7 +17804,7 @@ msgstr ""
|
||||||
msgid "JiraService|View Jira issues in GitLab"
|
msgid "JiraService|View Jira issues in GitLab"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
msgid "JiraService|Warning: All GitLab users that have access to this GitLab project will be able to view all issues from the Jira project specified below."
|
msgid "JiraService|Warning: All GitLab users that have access to this GitLab project are able to view all issues from the Jira project specified below."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
msgid "JiraService|Web URL"
|
msgid "JiraService|Web URL"
|
||||||
|
@ -17807,9 +17813,6 @@ msgstr ""
|
||||||
msgid "JiraService|Work on Jira issues without leaving GitLab. Adds a Jira menu to access your list of Jira issues and view any issue as read-only."
|
msgid "JiraService|Work on Jira issues without leaving GitLab. Adds a Jira menu to access your list of Jira issues and view any issue as read-only."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
msgid "JiraService|e.g. AB"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
msgid "JiraService|transition ids can have only numbers which can be split with , or ;"
|
msgid "JiraService|transition ids can have only numbers which can be split with , or ;"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -18975,9 +18978,6 @@ msgstr ""
|
||||||
msgid "Manage projects."
|
msgid "Manage projects."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
msgid "Manage storage usage"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
msgid "Manage two-factor authentication"
|
msgid "Manage two-factor authentication"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -20535,17 +20535,15 @@ msgstr ""
|
||||||
msgid "NamespaceStorageSize|You have reached %{usage_in_percent} of %{namespace_name}'s storage capacity (%{used_storage} of %{storage_limit})"
|
msgid "NamespaceStorageSize|You have reached %{usage_in_percent} of %{namespace_name}'s storage capacity (%{used_storage} of %{storage_limit})"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
msgid "NamespaceStorageSize|You have reached the free storage limit of %{free_size_limit} on %{locked_project_count} project. To unlock it, please purchase additional storage"
|
msgid "NamespaceStorageSize|You have reached the free storage limit of %{free_size_limit} on one or more projects."
|
||||||
msgid_plural "NamespaceStorageSize|You have reached the free storage limit of %{free_size_limit} on %{locked_project_count} projects. To unlock them, please purchase additional storage"
|
|
||||||
msgstr[0] ""
|
|
||||||
msgstr[1] ""
|
|
||||||
|
|
||||||
msgid "NamespaceStorageSize|push to your repository, create pipelines, create issues or add comments. To learn more about reducing storage capacity please visit our docs."
|
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
msgid "NamespaceStorageSize|push to your repository, create pipelines, create issues or add comments. To reduce storage capacity, delete unused repositories, artifacts, wikis, issues, and pipelines."
|
msgid "NamespaceStorageSize|push to your repository, create pipelines, create issues or add comments. To reduce storage capacity, delete unused repositories, artifacts, wikis, issues, and pipelines."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "NamespaceStorageSize|push to your repository, create pipelines, create issues or add comments. To reduce storage capacity, delete unused repositories, artifacts, wikis, issues, and pipelines. To learn more about reducing storage capacity please visit our docs."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "Namespaces"
|
msgid "Namespaces"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -34201,6 +34199,9 @@ msgstr ""
|
||||||
msgid "View the performance dashboard at"
|
msgid "View the performance dashboard at"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "View usage details"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "View users statistics"
|
msgid "View users statistics"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -35115,6 +35116,9 @@ msgstr ""
|
||||||
msgid "Write milestone description..."
|
msgid "Write milestone description..."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Write to \"authorized_keys\" file"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "Write your release notes or drag your files here…"
|
msgid "Write your release notes or drag your files here…"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
|
|
@ -51,7 +51,7 @@
|
||||||
"@gitlab/favicon-overlay": "2.0.0",
|
"@gitlab/favicon-overlay": "2.0.0",
|
||||||
"@gitlab/svgs": "1.188.0",
|
"@gitlab/svgs": "1.188.0",
|
||||||
"@gitlab/tributejs": "1.0.0",
|
"@gitlab/tributejs": "1.0.0",
|
||||||
"@gitlab/ui": "29.1.0",
|
"@gitlab/ui": "29.2.1",
|
||||||
"@gitlab/visual-review-tools": "1.6.1",
|
"@gitlab/visual-review-tools": "1.6.1",
|
||||||
"@rails/actioncable": "^6.0.3-4",
|
"@rails/actioncable": "^6.0.3-4",
|
||||||
"@rails/ujs": "^6.0.3-4",
|
"@rails/ujs": "^6.0.3-4",
|
||||||
|
|
|
@ -201,21 +201,21 @@ RSpec.describe "Admin Runners" do
|
||||||
|
|
||||||
visit admin_runners_path
|
visit admin_runners_path
|
||||||
|
|
||||||
within '.runners-content .gl-responsive-table-row:nth-child(2)' do
|
within '[data-testid="runners-table"] .gl-responsive-table-row:nth-child(2)' do
|
||||||
expect(page).to have_content 'runner-2'
|
expect(page).to have_content 'runner-2'
|
||||||
end
|
end
|
||||||
|
|
||||||
within '.runners-content .gl-responsive-table-row:nth-child(3)' do
|
within '[data-testid="runners-table"] .gl-responsive-table-row:nth-child(3)' do
|
||||||
expect(page).to have_content 'runner-1'
|
expect(page).to have_content 'runner-1'
|
||||||
end
|
end
|
||||||
|
|
||||||
sorting_by 'Last Contact'
|
sorting_by 'Last Contact'
|
||||||
|
|
||||||
within '.runners-content .gl-responsive-table-row:nth-child(2)' do
|
within '[data-testid="runners-table"] .gl-responsive-table-row:nth-child(2)' do
|
||||||
expect(page).to have_content 'runner-1'
|
expect(page).to have_content 'runner-1'
|
||||||
end
|
end
|
||||||
|
|
||||||
within '.runners-content .gl-responsive-table-row:nth-child(3)' do
|
within '[data-testid="runners-table"] .gl-responsive-table-row:nth-child(3)' do
|
||||||
expect(page).to have_content 'runner-2'
|
expect(page).to have_content 'runner-2'
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -79,7 +79,7 @@ RSpec.describe 'Runners' do
|
||||||
visit project_runners_path(project)
|
visit project_runners_path(project)
|
||||||
|
|
||||||
within '.activated-specific-runners' do
|
within '.activated-specific-runners' do
|
||||||
first('.edit-runner > a').click
|
first('[data-testid="edit-runner-link"]').click
|
||||||
end
|
end
|
||||||
|
|
||||||
expect(page.find_field('runner[access_level]')).not_to be_checked
|
expect(page.find_field('runner[access_level]')).not_to be_checked
|
||||||
|
@ -99,7 +99,7 @@ RSpec.describe 'Runners' do
|
||||||
visit project_runners_path(project)
|
visit project_runners_path(project)
|
||||||
|
|
||||||
within '.activated-specific-runners' do
|
within '.activated-specific-runners' do
|
||||||
first('.edit-runner > a').click
|
first('[data-testid="edit-runner-link"]').click
|
||||||
end
|
end
|
||||||
|
|
||||||
expect(page.find_field('runner[run_untagged]')).to be_checked
|
expect(page.find_field('runner[run_untagged]')).to be_checked
|
||||||
|
|
|
@ -1,32 +1,65 @@
|
||||||
import { mount, createLocalVue } from '@vue/test-utils';
|
import { mount } from '@vue/test-utils';
|
||||||
import { escape } from 'lodash';
|
import { escape } from 'lodash';
|
||||||
|
import Vue from 'vue';
|
||||||
|
import Vuex from 'vuex';
|
||||||
|
|
||||||
import waitForPromises from 'helpers/wait_for_promises';
|
import waitForPromises from 'helpers/wait_for_promises';
|
||||||
|
|
||||||
|
import DiffsModule from '~/diffs/store/modules';
|
||||||
|
|
||||||
import NoteActions from '~/notes/components/note_actions.vue';
|
import NoteActions from '~/notes/components/note_actions.vue';
|
||||||
import NoteBody from '~/notes/components/note_body.vue';
|
import NoteBody from '~/notes/components/note_body.vue';
|
||||||
import NoteHeader from '~/notes/components/note_header.vue';
|
import NoteHeader from '~/notes/components/note_header.vue';
|
||||||
import issueNote from '~/notes/components/noteable_note.vue';
|
import issueNote from '~/notes/components/noteable_note.vue';
|
||||||
import createStore from '~/notes/stores';
|
import NotesModule from '~/notes/stores/modules';
|
||||||
|
|
||||||
import UserAvatarLink from '~/vue_shared/components/user_avatar/user_avatar_link.vue';
|
import UserAvatarLink from '~/vue_shared/components/user_avatar/user_avatar_link.vue';
|
||||||
|
|
||||||
import { noteableDataMock, notesDataMock, note } from '../mock_data';
|
import { noteableDataMock, notesDataMock, note } from '../mock_data';
|
||||||
|
|
||||||
|
Vue.use(Vuex);
|
||||||
|
|
||||||
|
const singleLineNotePosition = {
|
||||||
|
line_range: {
|
||||||
|
start: {
|
||||||
|
line_code: 'abc_1_1',
|
||||||
|
type: null,
|
||||||
|
old_line: '1',
|
||||||
|
new_line: '1',
|
||||||
|
},
|
||||||
|
end: {
|
||||||
|
line_code: 'abc_1_1',
|
||||||
|
type: null,
|
||||||
|
old_line: '1',
|
||||||
|
new_line: '1',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
describe('issue_note', () => {
|
describe('issue_note', () => {
|
||||||
let store;
|
let store;
|
||||||
let wrapper;
|
let wrapper;
|
||||||
const findMultilineComment = () => wrapper.find('[data-testid="multiline-comment"]');
|
const findMultilineComment = () => wrapper.find('[data-testid="multiline-comment"]');
|
||||||
|
|
||||||
const createWrapper = (props = {}) => {
|
const createWrapper = (props = {}, storeUpdater = (s) => s) => {
|
||||||
store = createStore();
|
store = new Vuex.Store(
|
||||||
|
storeUpdater({
|
||||||
|
modules: {
|
||||||
|
notes: NotesModule(),
|
||||||
|
diffs: DiffsModule(),
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
|
||||||
store.dispatch('setNoteableData', noteableDataMock);
|
store.dispatch('setNoteableData', noteableDataMock);
|
||||||
store.dispatch('setNotesData', notesDataMock);
|
store.dispatch('setNotesData', notesDataMock);
|
||||||
|
|
||||||
const localVue = createLocalVue();
|
wrapper = mount(issueNote, {
|
||||||
wrapper = mount(localVue.extend(issueNote), {
|
|
||||||
store,
|
store,
|
||||||
propsData: {
|
propsData: {
|
||||||
note,
|
note,
|
||||||
...props,
|
...props,
|
||||||
},
|
},
|
||||||
localVue,
|
|
||||||
stubs: [
|
stubs: [
|
||||||
'note-header',
|
'note-header',
|
||||||
'user-avatar-link',
|
'user-avatar-link',
|
||||||
|
@ -216,10 +249,14 @@ describe('issue_note', () => {
|
||||||
const noteBodyComponent = wrapper.findComponent(NoteBody);
|
const noteBodyComponent = wrapper.findComponent(NoteBody);
|
||||||
|
|
||||||
store.hotUpdate({
|
store.hotUpdate({
|
||||||
|
modules: {
|
||||||
|
notes: {
|
||||||
actions: {
|
actions: {
|
||||||
updateNote() {},
|
updateNote() {},
|
||||||
setSelectedCommentPositionHover() {},
|
setSelectedCommentPositionHover() {},
|
||||||
},
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
noteBodyComponent.vm.$emit('handleFormUpdate', noteBody, null, () => {});
|
noteBodyComponent.vm.$emit('handleFormUpdate', noteBody, null, () => {});
|
||||||
|
@ -238,9 +275,13 @@ describe('issue_note', () => {
|
||||||
it('restores content of updated note', async () => {
|
it('restores content of updated note', async () => {
|
||||||
const updatedText = 'updated note text';
|
const updatedText = 'updated note text';
|
||||||
store.hotUpdate({
|
store.hotUpdate({
|
||||||
|
modules: {
|
||||||
|
notes: {
|
||||||
actions: {
|
actions: {
|
||||||
updateNote() {},
|
updateNote() {},
|
||||||
},
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
});
|
});
|
||||||
const noteBody = wrapper.findComponent(NoteBody);
|
const noteBody = wrapper.findComponent(NoteBody);
|
||||||
noteBody.vm.resetAutoSave = () => {};
|
noteBody.vm.resetAutoSave = () => {};
|
||||||
|
@ -267,10 +308,14 @@ describe('issue_note', () => {
|
||||||
|
|
||||||
const updateActions = () => {
|
const updateActions = () => {
|
||||||
store.hotUpdate({
|
store.hotUpdate({
|
||||||
|
modules: {
|
||||||
|
notes: {
|
||||||
actions: {
|
actions: {
|
||||||
updateNote,
|
updateNote,
|
||||||
setSelectedCommentPositionHover() {},
|
setSelectedCommentPositionHover() {},
|
||||||
},
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -299,4 +344,62 @@ describe('issue_note', () => {
|
||||||
expect(updateNote.mock.calls[0][1].note.note.position).toBe(expectation);
|
expect(updateNote.mock.calls[0][1].note.note.position).toBe(expectation);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('diffFile', () => {
|
||||||
|
it.each`
|
||||||
|
scenario | files | noteDef
|
||||||
|
${'the note has no position'} | ${undefined} | ${note}
|
||||||
|
${'the Diffs store has no data'} | ${[]} | ${{ ...note, position: singleLineNotePosition }}
|
||||||
|
`(
|
||||||
|
'returns `null` when $scenario and no diff file is provided as a prop',
|
||||||
|
({ noteDef, diffs }) => {
|
||||||
|
const storeUpdater = (rawStore) => {
|
||||||
|
const updatedStore = { ...rawStore };
|
||||||
|
|
||||||
|
if (diffs) {
|
||||||
|
updatedStore.modules.diffs.state.diffFiles = diffs;
|
||||||
|
}
|
||||||
|
|
||||||
|
return updatedStore;
|
||||||
|
};
|
||||||
|
|
||||||
|
createWrapper({ note: noteDef, discussionFile: null }, storeUpdater);
|
||||||
|
|
||||||
|
expect(wrapper.vm.diffFile).toBe(null);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
it("returns the correct diff file from the Diffs store if it's available", () => {
|
||||||
|
createWrapper(
|
||||||
|
{
|
||||||
|
note: { ...note, position: singleLineNotePosition },
|
||||||
|
},
|
||||||
|
(rawStore) => {
|
||||||
|
const updatedStore = { ...rawStore };
|
||||||
|
updatedStore.modules.diffs.state.diffFiles = [
|
||||||
|
{ file_hash: 'abc', testId: 'diffFileTest' },
|
||||||
|
];
|
||||||
|
return updatedStore;
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(wrapper.vm.diffFile.testId).toBe('diffFileTest');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('returns the provided diff file if the more robust getters fail', () => {
|
||||||
|
createWrapper(
|
||||||
|
{
|
||||||
|
note: { ...note, position: singleLineNotePosition },
|
||||||
|
discussionFile: { testId: 'diffFileTest' },
|
||||||
|
},
|
||||||
|
(rawStore) => {
|
||||||
|
const updatedStore = { ...rawStore };
|
||||||
|
updatedStore.modules.diffs.state.diffFiles = [];
|
||||||
|
return updatedStore;
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(wrapper.vm.diffFile.testId).toBe('diffFileTest');
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import { mount, shallowMount } from '@vue/test-utils';
|
import { mount, shallowMount } from '@vue/test-utils';
|
||||||
import { GRAPHQL } from '~/pipelines/components/graph/constants';
|
import { GRAPHQL, STAGE_VIEW } from '~/pipelines/components/graph/constants';
|
||||||
import PipelineGraph from '~/pipelines/components/graph/graph_component.vue';
|
import PipelineGraph from '~/pipelines/components/graph/graph_component.vue';
|
||||||
import JobItem from '~/pipelines/components/graph/job_item.vue';
|
import JobItem from '~/pipelines/components/graph/job_item.vue';
|
||||||
import LinkedPipelinesColumn from '~/pipelines/components/graph/linked_pipelines_column.vue';
|
import LinkedPipelinesColumn from '~/pipelines/components/graph/linked_pipelines_column.vue';
|
||||||
|
@ -20,6 +20,7 @@ describe('graph component', () => {
|
||||||
|
|
||||||
const defaultProps = {
|
const defaultProps = {
|
||||||
pipeline: generateResponse(mockPipelineResponse, 'root/fungi-xoxo'),
|
pipeline: generateResponse(mockPipelineResponse, 'root/fungi-xoxo'),
|
||||||
|
viewType: STAGE_VIEW,
|
||||||
configPaths: {
|
configPaths: {
|
||||||
metricsPath: '',
|
metricsPath: '',
|
||||||
graphqlResourceEtag: 'this/is/a/path',
|
graphqlResourceEtag: 'this/is/a/path',
|
||||||
|
|
|
@ -1,13 +1,15 @@
|
||||||
import { GlAlert, GlLoadingIcon } from '@gitlab/ui';
|
import { GlAlert, GlLoadingIcon } from '@gitlab/ui';
|
||||||
import { shallowMount } from '@vue/test-utils';
|
import { mount, shallowMount } from '@vue/test-utils';
|
||||||
import Vue from 'vue';
|
import Vue from 'vue';
|
||||||
import VueApollo from 'vue-apollo';
|
import VueApollo from 'vue-apollo';
|
||||||
import createMockApollo from 'helpers/mock_apollo_helper';
|
import createMockApollo from 'helpers/mock_apollo_helper';
|
||||||
import getPipelineDetails from 'shared_queries/pipelines/get_pipeline_details.query.graphql';
|
import getPipelineDetails from 'shared_queries/pipelines/get_pipeline_details.query.graphql';
|
||||||
import { IID_FAILURE } from '~/pipelines/components/graph/constants';
|
import { IID_FAILURE, LAYER_VIEW, STAGE_VIEW } from '~/pipelines/components/graph/constants';
|
||||||
import PipelineGraph from '~/pipelines/components/graph/graph_component.vue';
|
import PipelineGraph from '~/pipelines/components/graph/graph_component.vue';
|
||||||
import PipelineGraphWrapper from '~/pipelines/components/graph/graph_component_wrapper.vue';
|
import PipelineGraphWrapper from '~/pipelines/components/graph/graph_component_wrapper.vue';
|
||||||
import GraphViewSelector from '~/pipelines/components/graph/graph_view_selector.vue';
|
import GraphViewSelector from '~/pipelines/components/graph/graph_view_selector.vue';
|
||||||
|
import StageColumnComponent from '~/pipelines/components/graph/stage_column_component.vue';
|
||||||
|
import * as parsingUtils from '~/pipelines/components/parsing_utils';
|
||||||
import { mockPipelineResponse } from './mock_data';
|
import { mockPipelineResponse } from './mock_data';
|
||||||
|
|
||||||
const defaultProvide = {
|
const defaultProvide = {
|
||||||
|
@ -24,6 +26,9 @@ describe('Pipeline graph wrapper', () => {
|
||||||
const getAlert = () => wrapper.find(GlAlert);
|
const getAlert = () => wrapper.find(GlAlert);
|
||||||
const getLoadingIcon = () => wrapper.find(GlLoadingIcon);
|
const getLoadingIcon = () => wrapper.find(GlLoadingIcon);
|
||||||
const getGraph = () => wrapper.find(PipelineGraph);
|
const getGraph = () => wrapper.find(PipelineGraph);
|
||||||
|
const getStageColumnTitle = () => wrapper.find('[data-testid="stage-column-title"]');
|
||||||
|
const getAllStageColumnGroupsInColumn = () =>
|
||||||
|
wrapper.find(StageColumnComponent).findAll('[data-testid="stage-column-group"]');
|
||||||
const getViewSelector = () => wrapper.find(GraphViewSelector);
|
const getViewSelector = () => wrapper.find(GraphViewSelector);
|
||||||
|
|
||||||
const createComponent = ({
|
const createComponent = ({
|
||||||
|
@ -48,12 +53,13 @@ describe('Pipeline graph wrapper', () => {
|
||||||
|
|
||||||
const createComponentWithApollo = ({
|
const createComponentWithApollo = ({
|
||||||
getPipelineDetailsHandler = jest.fn().mockResolvedValue(mockPipelineResponse),
|
getPipelineDetailsHandler = jest.fn().mockResolvedValue(mockPipelineResponse),
|
||||||
|
mountFn = shallowMount,
|
||||||
provide = {},
|
provide = {},
|
||||||
} = {}) => {
|
} = {}) => {
|
||||||
const requestHandlers = [[getPipelineDetails, getPipelineDetailsHandler]];
|
const requestHandlers = [[getPipelineDetails, getPipelineDetailsHandler]];
|
||||||
|
|
||||||
const apolloProvider = createMockApollo(requestHandlers);
|
const apolloProvider = createMockApollo(requestHandlers);
|
||||||
createComponent({ apolloProvider, provide });
|
createComponent({ apolloProvider, provide, mountFn });
|
||||||
};
|
};
|
||||||
|
|
||||||
afterEach(() => {
|
afterEach(() => {
|
||||||
|
@ -223,13 +229,16 @@ describe('Pipeline graph wrapper', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('when feature flag is on', () => {
|
describe('when feature flag is on', () => {
|
||||||
|
let layersFn;
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
|
layersFn = jest.spyOn(parsingUtils, 'listByLayers');
|
||||||
createComponentWithApollo({
|
createComponentWithApollo({
|
||||||
provide: {
|
provide: {
|
||||||
glFeatures: {
|
glFeatures: {
|
||||||
pipelineGraphLayersView: true,
|
pipelineGraphLayersView: true,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
mountFn: mount,
|
||||||
});
|
});
|
||||||
|
|
||||||
jest.runOnlyPendingTimers();
|
jest.runOnlyPendingTimers();
|
||||||
|
@ -239,6 +248,26 @@ describe('Pipeline graph wrapper', () => {
|
||||||
it('appears', () => {
|
it('appears', () => {
|
||||||
expect(getViewSelector().exists()).toBe(true);
|
expect(getViewSelector().exists()).toBe(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('switches between views', async () => {
|
||||||
|
const groupsInFirstColumn =
|
||||||
|
mockPipelineResponse.data.project.pipeline.stages.nodes[0].groups.nodes.length;
|
||||||
|
expect(getAllStageColumnGroupsInColumn()).toHaveLength(groupsInFirstColumn);
|
||||||
|
expect(getStageColumnTitle().text()).toBe('Build');
|
||||||
|
await getViewSelector().vm.$emit('updateViewType', LAYER_VIEW);
|
||||||
|
expect(getAllStageColumnGroupsInColumn()).toHaveLength(groupsInFirstColumn + 1);
|
||||||
|
expect(getStageColumnTitle().text()).toBe('');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('calls listByLayers only once no matter how many times view is switched', async () => {
|
||||||
|
expect(layersFn).not.toHaveBeenCalled();
|
||||||
|
await getViewSelector().vm.$emit('updateViewType', LAYER_VIEW);
|
||||||
|
expect(layersFn).toHaveBeenCalledTimes(1);
|
||||||
|
await getViewSelector().vm.$emit('updateViewType', STAGE_VIEW);
|
||||||
|
await getViewSelector().vm.$emit('updateViewType', LAYER_VIEW);
|
||||||
|
await getViewSelector().vm.$emit('updateViewType', STAGE_VIEW);
|
||||||
|
expect(layersFn).toHaveBeenCalledTimes(1);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -2,10 +2,17 @@ import { mount, shallowMount, createLocalVue } from '@vue/test-utils';
|
||||||
import VueApollo from 'vue-apollo';
|
import VueApollo from 'vue-apollo';
|
||||||
import createMockApollo from 'helpers/mock_apollo_helper';
|
import createMockApollo from 'helpers/mock_apollo_helper';
|
||||||
import getPipelineDetails from 'shared_queries/pipelines/get_pipeline_details.query.graphql';
|
import getPipelineDetails from 'shared_queries/pipelines/get_pipeline_details.query.graphql';
|
||||||
import { DOWNSTREAM, GRAPHQL, UPSTREAM } from '~/pipelines/components/graph/constants';
|
import {
|
||||||
|
DOWNSTREAM,
|
||||||
|
GRAPHQL,
|
||||||
|
UPSTREAM,
|
||||||
|
LAYER_VIEW,
|
||||||
|
STAGE_VIEW,
|
||||||
|
} from '~/pipelines/components/graph/constants';
|
||||||
import PipelineGraph from '~/pipelines/components/graph/graph_component.vue';
|
import PipelineGraph from '~/pipelines/components/graph/graph_component.vue';
|
||||||
import LinkedPipeline from '~/pipelines/components/graph/linked_pipeline.vue';
|
import LinkedPipeline from '~/pipelines/components/graph/linked_pipeline.vue';
|
||||||
import LinkedPipelinesColumn from '~/pipelines/components/graph/linked_pipelines_column.vue';
|
import LinkedPipelinesColumn from '~/pipelines/components/graph/linked_pipelines_column.vue';
|
||||||
|
import * as parsingUtils from '~/pipelines/components/parsing_utils';
|
||||||
import { LOAD_FAILURE } from '~/pipelines/constants';
|
import { LOAD_FAILURE } from '~/pipelines/constants';
|
||||||
import {
|
import {
|
||||||
mockPipelineResponse,
|
mockPipelineResponse,
|
||||||
|
@ -20,6 +27,7 @@ describe('Linked Pipelines Column', () => {
|
||||||
columnTitle: 'Downstream',
|
columnTitle: 'Downstream',
|
||||||
linkedPipelines: processedPipeline.downstream,
|
linkedPipelines: processedPipeline.downstream,
|
||||||
type: DOWNSTREAM,
|
type: DOWNSTREAM,
|
||||||
|
viewType: STAGE_VIEW,
|
||||||
configPaths: {
|
configPaths: {
|
||||||
metricsPath: '',
|
metricsPath: '',
|
||||||
graphqlResourceEtag: 'this/is/a/path',
|
graphqlResourceEtag: 'this/is/a/path',
|
||||||
|
@ -67,7 +75,7 @@ describe('Linked Pipelines Column', () => {
|
||||||
|
|
||||||
describe('it renders correctly', () => {
|
describe('it renders correctly', () => {
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
createComponent();
|
createComponentWithApollo();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('renders the pipeline title', () => {
|
it('renders the pipeline title', () => {
|
||||||
|
@ -91,6 +99,27 @@ describe('Linked Pipelines Column', () => {
|
||||||
await wrapper.vm.$nextTick();
|
await wrapper.vm.$nextTick();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
describe('layer type rendering', () => {
|
||||||
|
let layersFn;
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
layersFn = jest.spyOn(parsingUtils, 'listByLayers');
|
||||||
|
createComponentWithApollo({ mountFn: mount });
|
||||||
|
});
|
||||||
|
|
||||||
|
it('calls listByLayers only once no matter how many times view is switched', async () => {
|
||||||
|
expect(layersFn).not.toHaveBeenCalled();
|
||||||
|
await clickExpandButtonAndAwaitTimers();
|
||||||
|
await wrapper.setProps({ viewType: LAYER_VIEW });
|
||||||
|
await wrapper.vm.$nextTick();
|
||||||
|
expect(layersFn).toHaveBeenCalledTimes(1);
|
||||||
|
await wrapper.setProps({ viewType: STAGE_VIEW });
|
||||||
|
await wrapper.setProps({ viewType: LAYER_VIEW });
|
||||||
|
await wrapper.setProps({ viewType: STAGE_VIEW });
|
||||||
|
expect(layersFn).toHaveBeenCalledTimes(1);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
describe('downstream', () => {
|
describe('downstream', () => {
|
||||||
describe('when successful', () => {
|
describe('when successful', () => {
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
|
|
|
@ -434,21 +434,7 @@ export const mockPipelineResponse = {
|
||||||
},
|
},
|
||||||
needs: {
|
needs: {
|
||||||
__typename: 'CiBuildNeedConnection',
|
__typename: 'CiBuildNeedConnection',
|
||||||
nodes: [
|
nodes: [],
|
||||||
{
|
|
||||||
__typename: 'CiBuildNeed',
|
|
||||||
name: 'build_c',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
__typename: 'CiBuildNeed',
|
|
||||||
name: 'build_b',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
__typename: 'CiBuildNeed',
|
|
||||||
name:
|
|
||||||
'build_a_nlfjkdnlvskfnksvjknlfdjvlvnjdkjdf_nvjkenjkrlngjeknjkl',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
|
|
@ -96,11 +96,11 @@ const completeMock = [
|
||||||
describe('Shared pipeline unwrapping utils', () => {
|
describe('Shared pipeline unwrapping utils', () => {
|
||||||
describe('unwrapGroups', () => {
|
describe('unwrapGroups', () => {
|
||||||
it('takes stages without nodes and returns the unwrapped groups', () => {
|
it('takes stages without nodes and returns the unwrapped groups', () => {
|
||||||
expect(unwrapGroups(stagesAndGroups)[0].groups).toEqual(groupsArray);
|
expect(unwrapGroups(stagesAndGroups)[0].node.groups).toEqual(groupsArray);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('keeps other stage properties intact', () => {
|
it('keeps other stage properties intact', () => {
|
||||||
expect(unwrapGroups(stagesAndGroups)[0]).toMatchObject(basicStageInfo);
|
expect(unwrapGroups(stagesAndGroups)[0].node).toMatchObject(basicStageInfo);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -5,6 +5,7 @@ require 'spec_helper'
|
||||||
RSpec.describe Gitlab::Checks::ProjectCreated, :clean_gitlab_redis_shared_state do
|
RSpec.describe Gitlab::Checks::ProjectCreated, :clean_gitlab_redis_shared_state do
|
||||||
let_it_be(:user) { create(:user) }
|
let_it_be(:user) { create(:user) }
|
||||||
let_it_be(:project) { create(:project, :repository, namespace: user.namespace) }
|
let_it_be(:project) { create(:project, :repository, namespace: user.namespace) }
|
||||||
|
|
||||||
let(:protocol) { 'http' }
|
let(:protocol) { 'http' }
|
||||||
let(:git_user) { user }
|
let(:git_user) { user }
|
||||||
let(:repository) { project.repository }
|
let(:repository) { project.repository }
|
||||||
|
|
|
@ -5,6 +5,7 @@ require 'spec_helper'
|
||||||
RSpec.describe Gitlab::Checks::ProjectMoved, :clean_gitlab_redis_shared_state do
|
RSpec.describe Gitlab::Checks::ProjectMoved, :clean_gitlab_redis_shared_state do
|
||||||
let_it_be(:user) { create(:user) }
|
let_it_be(:user) { create(:user) }
|
||||||
let_it_be(:project) { create(:project, :repository, :wiki_repo, namespace: user.namespace) }
|
let_it_be(:project) { create(:project, :repository, :wiki_repo, namespace: user.namespace) }
|
||||||
|
|
||||||
let(:repository) { project.repository }
|
let(:repository) { project.repository }
|
||||||
let(:protocol) { 'http' }
|
let(:protocol) { 'http' }
|
||||||
let(:git_user) { user }
|
let(:git_user) { user }
|
||||||
|
@ -101,6 +102,7 @@ RSpec.describe Gitlab::Checks::ProjectMoved, :clean_gitlab_redis_shared_state do
|
||||||
|
|
||||||
context 'with project snippet' do
|
context 'with project snippet' do
|
||||||
let_it_be(:snippet) { create(:project_snippet, :repository, project: project, author: user) }
|
let_it_be(:snippet) { create(:project_snippet, :repository, project: project, author: user) }
|
||||||
|
|
||||||
let(:repository) { snippet.repository }
|
let(:repository) { snippet.repository }
|
||||||
|
|
||||||
it_behaves_like 'errors per protocol' do
|
it_behaves_like 'errors per protocol' do
|
||||||
|
@ -111,6 +113,7 @@ RSpec.describe Gitlab::Checks::ProjectMoved, :clean_gitlab_redis_shared_state do
|
||||||
|
|
||||||
context 'with personal snippet' do
|
context 'with personal snippet' do
|
||||||
let_it_be(:snippet) { create(:personal_snippet, :repository, author: user) }
|
let_it_be(:snippet) { create(:personal_snippet, :repository, author: user) }
|
||||||
|
|
||||||
let(:repository) { snippet.repository }
|
let(:repository) { snippet.repository }
|
||||||
|
|
||||||
it 'returns nil' do
|
it 'returns nil' do
|
||||||
|
|
|
@ -6,6 +6,7 @@ require 'test_prof/recipes/rspec/let_it_be'
|
||||||
RSpec.describe ::Gitlab::Graphql::BatchKey do
|
RSpec.describe ::Gitlab::Graphql::BatchKey do
|
||||||
let_it_be(:rect) { Struct.new(:len, :width) }
|
let_it_be(:rect) { Struct.new(:len, :width) }
|
||||||
let_it_be(:circle) { Struct.new(:radius) }
|
let_it_be(:circle) { Struct.new(:radius) }
|
||||||
|
|
||||||
let(:lookahead) { nil }
|
let(:lookahead) { nil }
|
||||||
let(:object) { rect.new(2, 3) }
|
let(:object) { rect.new(2, 3) }
|
||||||
|
|
||||||
|
|
|
@ -6,6 +6,7 @@ RSpec.describe Gitlab::Graphql::Loaders::BatchLfsOidLoader do
|
||||||
include GraphqlHelpers
|
include GraphqlHelpers
|
||||||
|
|
||||||
let_it_be(:project) { create(:project, :repository) }
|
let_it_be(:project) { create(:project, :repository) }
|
||||||
|
|
||||||
let(:repository) { project.repository }
|
let(:repository) { project.repository }
|
||||||
let(:blob) { Gitlab::Graphql::Representation::TreeEntry.new(repository.blob_at('master', 'files/lfs/lfs_object.iso'), repository) }
|
let(:blob) { Gitlab::Graphql::Representation::TreeEntry.new(repository.blob_at('master', 'files/lfs/lfs_object.iso'), repository) }
|
||||||
let(:otherblob) { Gitlab::Graphql::Representation::TreeEntry.new(repository.blob_at('master', 'README'), repository) }
|
let(:otherblob) { Gitlab::Graphql::Representation::TreeEntry.new(repository.blob_at('master', 'README'), repository) }
|
||||||
|
|
|
@ -57,6 +57,7 @@ RSpec.describe Gitlab::Graphql::MarkdownField do
|
||||||
|
|
||||||
describe 'basic verification that references work' do
|
describe 'basic verification that references work' do
|
||||||
let_it_be(:project) { create(:project, :public) }
|
let_it_be(:project) { create(:project, :public) }
|
||||||
|
|
||||||
let(:issue) { create(:issue, project: project) }
|
let(:issue) { create(:issue, project: project) }
|
||||||
let(:note) { build(:note, note: "Referencing #{issue.to_reference(full: true)}") }
|
let(:note) { build(:note, note: "Referencing #{issue.to_reference(full: true)}") }
|
||||||
|
|
||||||
|
|
|
@ -337,6 +337,7 @@ RSpec.describe Gitlab::Graphql::Pagination::Keyset::Connection do
|
||||||
|
|
||||||
describe '#nodes' do
|
describe '#nodes' do
|
||||||
let_it_be(:all_nodes) { create_list(:project, 5) }
|
let_it_be(:all_nodes) { create_list(:project, 5) }
|
||||||
|
|
||||||
let(:paged_nodes) { subject.nodes }
|
let(:paged_nodes) { subject.nodes }
|
||||||
|
|
||||||
it_behaves_like 'connection with paged nodes' do
|
it_behaves_like 'connection with paged nodes' do
|
||||||
|
|
|
@ -4,6 +4,7 @@ require 'spec_helper'
|
||||||
|
|
||||||
RSpec.describe Gitlab::Graphql::Pagination::Keyset::LastItems do
|
RSpec.describe Gitlab::Graphql::Pagination::Keyset::LastItems do
|
||||||
let_it_be(:merge_request) { create(:merge_request) }
|
let_it_be(:merge_request) { create(:merge_request) }
|
||||||
|
|
||||||
let(:scope) { MergeRequest.order_merged_at_asc }
|
let(:scope) { MergeRequest.order_merged_at_asc }
|
||||||
|
|
||||||
subject { described_class.take_items(*args) }
|
subject { described_class.take_items(*args) }
|
||||||
|
|
|
@ -23,10 +23,10 @@ RSpec.describe ServiceFieldEntity do
|
||||||
type: 'text',
|
type: 'text',
|
||||||
name: 'username',
|
name: 'username',
|
||||||
title: 'Username or Email',
|
title: 'Username or Email',
|
||||||
placeholder: 'Use a username for server version and an email for cloud version',
|
placeholder: nil,
|
||||||
|
help: 'Use a username for server version and an email for cloud version.',
|
||||||
required: true,
|
required: true,
|
||||||
choices: nil,
|
choices: nil,
|
||||||
help: nil,
|
|
||||||
value: 'jira_username'
|
value: 'jira_username'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -42,10 +42,10 @@ RSpec.describe ServiceFieldEntity do
|
||||||
type: 'password',
|
type: 'password',
|
||||||
name: 'password',
|
name: 'password',
|
||||||
title: 'Enter new password or API token',
|
title: 'Enter new password or API token',
|
||||||
placeholder: 'Use a password for server version and an API token for cloud version',
|
placeholder: nil,
|
||||||
|
help: 'Leave blank to use your current password or API token.',
|
||||||
required: true,
|
required: true,
|
||||||
choices: nil,
|
choices: nil,
|
||||||
help: 'Leave blank to use your current password or API token',
|
|
||||||
value: 'true'
|
value: 'true'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -907,10 +907,10 @@
|
||||||
resolved "https://registry.yarnpkg.com/@gitlab/tributejs/-/tributejs-1.0.0.tgz#672befa222aeffc83e7d799b0500a7a4418e59b8"
|
resolved "https://registry.yarnpkg.com/@gitlab/tributejs/-/tributejs-1.0.0.tgz#672befa222aeffc83e7d799b0500a7a4418e59b8"
|
||||||
integrity sha512-nmKw1+hB6MHvlmPz63yPwVs1qQkycHwsKgxpEbzmky16Y6mL4EJMk3w1b8QlOAF/AIAzjCERPhe/R4MJiohbZw==
|
integrity sha512-nmKw1+hB6MHvlmPz63yPwVs1qQkycHwsKgxpEbzmky16Y6mL4EJMk3w1b8QlOAF/AIAzjCERPhe/R4MJiohbZw==
|
||||||
|
|
||||||
"@gitlab/ui@29.1.0":
|
"@gitlab/ui@29.2.1":
|
||||||
version "29.1.0"
|
version "29.2.1"
|
||||||
resolved "https://registry.yarnpkg.com/@gitlab/ui/-/ui-29.1.0.tgz#0db1c12ca1ee9882613a73ddc964a81db2697c2f"
|
resolved "https://registry.yarnpkg.com/@gitlab/ui/-/ui-29.2.1.tgz#e6377131f3a22eebe07903198ec874ca5d26884c"
|
||||||
integrity sha512-jmsh67gmucdLxP7MBYt+SkLCXa62nYZy9/iRLZk4B+QdyEOzbpqj0ydAmPjMjFNfOV18KHKC6Lvpw4kUDE/GRA==
|
integrity sha512-vLzCMQsppGLpzWRaNxXpx86y6JjSOEnQXQxtLudnSJktWl0uHfglED2xe7vJQJo+qmzQf6T5m3gbVupj/pG4+A==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@babel/standalone" "^7.0.0"
|
"@babel/standalone" "^7.0.0"
|
||||||
"@gitlab/vue-toasted" "^1.3.0"
|
"@gitlab/vue-toasted" "^1.3.0"
|
||||||
|
|
Loading…
Reference in a new issue