summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2020-05-08 12:09:37 +0000
committerGitLab Bot <gitlab-bot@gitlab.com>2020-05-08 12:09:37 +0000
commit96897f83e965318f70032eea0196c4c0b807b1d4 (patch)
tree80cd64c9ad08215adffdc3be89497ad1fdab690e
parent5bdbc604c8a08f827c3833e2c28ec0c299bb41fc (diff)
downloadgitlab-ce-96897f83e965318f70032eea0196c4c0b807b1d4.tar.gz
Add latest changes from gitlab-org/gitlab@master
-rw-r--r--app/assets/javascripts/ide/components/commit_sidebar/list.vue18
-rw-r--r--app/assets/javascripts/ide/components/ide.vue10
-rw-r--r--app/assets/javascripts/ide/components/ide_tree.vue16
-rw-r--r--app/assets/javascripts/ide/components/new_dropdown/index.vue7
-rw-r--r--app/assets/javascripts/ide/components/new_dropdown/modal.vue84
-rw-r--r--app/assets/javascripts/ide/constants.js1
-rw-r--r--app/assets/javascripts/ide/stores/actions.js8
-rw-r--r--app/assets/javascripts/ide/stores/mutation_types.js1
-rw-r--r--app/assets/javascripts/ide/stores/mutations.js9
-rw-r--r--app/assets/javascripts/monitoring/constants.js18
-rw-r--r--app/assets/javascripts/monitoring/stores/variable_mapping.js125
-rw-r--r--app/assets/stylesheets/page_bundles/themes/_dark.scss6
-rw-r--r--app/models/ci/pipeline.rb5
-rw-r--r--app/models/ci/stage.rb3
-rw-r--r--app/services/ci/pipeline_processing/atomic_processing_service.rb2
-rw-r--r--app/services/ci/pipeline_processing/atomic_processing_service/status_collection.rb19
-rw-r--r--app/services/tags/destroy_service.rb14
-rw-r--r--app/views/projects/settings/ci_cd/_form.html.haml4
-rw-r--r--app/views/projects/settings/ci_cd/show.html.haml2
-rw-r--r--changelogs/unreleased/sk-fix-tag-deletion-duplicate-events.yml5
-rw-r--r--qa/qa.rb1
-rw-r--r--qa/qa/page/project/settings/ci_cd.rb7
-rw-r--r--qa/qa/page/project/settings/general_pipelines.rb23
-rw-r--r--qa/qa/specs/features/browser_ui/4_verify/testing/view_code_coverage_spec.rb62
-rw-r--r--spec/frontend/ide/components/new_dropdown/index_spec.js12
-rw-r--r--spec/frontend/ide/components/new_dropdown/modal_spec.js87
-rw-r--r--spec/frontend/ide/stores/mutations_spec.js17
-rw-r--r--spec/frontend/monitoring/store/variable_mapping_spec.js150
-rw-r--r--spec/frontend/reports/components/grouped_test_reports_app_spec.js (renamed from spec/javascripts/reports/components/grouped_test_reports_app_spec.js)42
-rw-r--r--spec/frontend/reports/components/modal_open_name_spec.js (renamed from spec/javascripts/reports/components/modal_open_name_spec.js)4
-rw-r--r--spec/frontend/reports/components/modal_spec.js (renamed from spec/javascripts/reports/components/modal_spec.js)0
-rw-r--r--spec/frontend/reports/components/summary_row_spec.js (renamed from spec/javascripts/reports/components/summary_row_spec.js)2
-rw-r--r--spec/frontend/reports/components/test_issue_body_spec.js (renamed from spec/javascripts/reports/components/test_issue_body_spec.js)2
-rw-r--r--spec/frontend/reports/mock_data/mock_data.js (renamed from spec/javascripts/reports/mock_data/mock_data.js)0
-rw-r--r--spec/frontend/reports/mock_data/new_and_fixed_failures_report.json (renamed from spec/javascripts/reports/mock_data/new_and_fixed_failures_report.json)0
-rw-r--r--spec/frontend/reports/mock_data/new_errors_report.json (renamed from spec/javascripts/reports/mock_data/new_errors_report.json)0
-rw-r--r--spec/frontend/reports/mock_data/new_failures_report.json (renamed from spec/javascripts/reports/mock_data/new_failures_report.json)0
-rw-r--r--spec/frontend/reports/mock_data/no_failures_report.json (renamed from spec/javascripts/reports/mock_data/no_failures_report.json)0
-rw-r--r--spec/frontend/reports/mock_data/resolved_failures.json (renamed from spec/javascripts/reports/mock_data/resolved_failures.json)0
-rw-r--r--spec/frontend/reports/store/actions_spec.js (renamed from spec/javascripts/reports/store/actions_spec.js)4
-rw-r--r--spec/frontend/reports/store/mutations_spec.js (renamed from spec/javascripts/reports/store/mutations_spec.js)0
-rw-r--r--spec/models/ci/pipeline_spec.rb23
-rw-r--r--spec/models/ci/stage_spec.rb26
-rw-r--r--spec/services/ci/pipeline_processing/atomic_processing_service/status_collection_spec.rb15
-rw-r--r--spec/services/ci/pipeline_processing/atomic_processing_service_spec.rb10
-rw-r--r--spec/services/ci/pipeline_processing/legacy_processing_service_spec.rb20
-rw-r--r--spec/services/ci/pipeline_processing/shared_processing_service.rb25
-rw-r--r--spec/services/ci/pipeline_processing/shared_processing_service_tests_with_yaml.rb40
-rw-r--r--spec/services/ci/pipeline_processing/test_cases/dag_test_manual_allow_failure_false.yml4
-rw-r--r--spec/services/ci/pipeline_processing/test_cases/dag_test_manual_allow_failure_true.yml2
-rw-r--r--spec/services/ci/pipeline_processing/test_cases/dag_test_manual_allow_failure_true_deploy_on_failure.yml2
-rw-r--r--spec/services/ci/pipeline_processing/test_cases/stage_test_manual_allow_failure_false.yml4
-rw-r--r--spec/services/ci/pipeline_processing/test_cases/stage_test_manual_allow_failure_true.yml2
-rw-r--r--spec/services/ci/pipeline_processing/test_cases/stage_test_manual_allow_failure_true_deploy_on_failure.yml2
54 files changed, 701 insertions, 244 deletions
diff --git a/app/assets/javascripts/ide/components/commit_sidebar/list.vue b/app/assets/javascripts/ide/components/commit_sidebar/list.vue
index a15e22d4742..e6a1a1ba73c 100644
--- a/app/assets/javascripts/ide/components/commit_sidebar/list.vue
+++ b/app/assets/javascripts/ide/components/commit_sidebar/list.vue
@@ -1,9 +1,8 @@
<script>
-import $ from 'jquery';
import { mapActions } from 'vuex';
import { __, sprintf } from '~/locale';
+import { GlModal } from '@gitlab/ui';
import Icon from '~/vue_shared/components/icon.vue';
-import DeprecatedModal2 from '~/vue_shared/components/deprecated_modal_2.vue';
import tooltip from '~/vue_shared/directives/tooltip';
import ListItem from './list_item.vue';
@@ -11,7 +10,7 @@ export default {
components: {
Icon,
ListItem,
- GlModal: DeprecatedModal2,
+ GlModal,
},
directives: {
tooltip,
@@ -58,7 +57,7 @@ export default {
methods: {
...mapActions(['stageAllChanges', 'unstageAllChanges', 'discardAllChanges']),
openDiscardModal() {
- $('#discard-all-changes').modal('show');
+ this.$refs.discardAllModal.show();
},
unstageAndDiscardAllChanges() {
this.unstageAllChanges();
@@ -114,11 +113,12 @@ export default {
</p>
<gl-modal
v-if="!stagedList"
- id="discard-all-changes"
- :footer-primary-button-text="__('Discard all changes')"
- :header-title-text="__('Discard all changes?')"
- footer-primary-button-variant="danger"
- @submit="unstageAndDiscardAllChanges"
+ ref="discardAllModal"
+ ok-variant="danger"
+ modal-id="discard-all-changes"
+ :ok-title="__('Discard all changes')"
+ :title="__('Discard all changes?')"
+ @ok="unstageAndDiscardAllChanges"
>
{{ $options.discardModalText }}
</gl-modal>
diff --git a/app/assets/javascripts/ide/components/ide.vue b/app/assets/javascripts/ide/components/ide.vue
index 998d3f2d8ea..36c8b18e205 100644
--- a/app/assets/javascripts/ide/components/ide.vue
+++ b/app/assets/javascripts/ide/components/ide.vue
@@ -3,6 +3,7 @@ import Vue from 'vue';
import { mapActions, mapGetters, mapState } from 'vuex';
import { GlDeprecatedButton, GlLoadingIcon } from '@gitlab/ui';
import { __ } from '~/locale';
+import { modalTypes } from '../constants';
import FindFile from '~/vue_shared/components/file_finder/index.vue';
import NewModal from './new_dropdown/modal.vue';
import IdeSidebar from './ide_side_bar.vue';
@@ -67,7 +68,7 @@ export default {
document.querySelector('.navbar-gitlab').classList.add(`theme-${this.themeName}`);
},
methods: {
- ...mapActions(['toggleFileFinder', 'openNewEntryModal']),
+ ...mapActions(['toggleFileFinder']),
onBeforeUnload(e = {}) {
const returnValue = __('Are you sure you want to lose unsaved changes?');
@@ -81,6 +82,9 @@ export default {
openFile(file) {
this.$router.push(`/project${file.url}`);
},
+ createNewFile() {
+ this.$refs.newModal.open(modalTypes.blob);
+ },
},
};
</script>
@@ -137,7 +141,7 @@ export default {
variant="success"
:title="__('New file')"
:aria-label="__('New file')"
- @click="openNewEntryModal({ type: 'blob' })"
+ @click="createNewFile()"
>
{{ __('New file') }}
</gl-deprecated-button>
@@ -159,6 +163,6 @@ export default {
<component :is="rightPaneComponent" v-if="currentProjectId" />
</div>
<ide-status-bar />
- <new-modal />
+ <new-modal ref="newModal" />
</article>
</template>
diff --git a/app/assets/javascripts/ide/components/ide_tree.vue b/app/assets/javascripts/ide/components/ide_tree.vue
index 598f3a1dac6..d78cddc0953 100644
--- a/app/assets/javascripts/ide/components/ide_tree.vue
+++ b/app/assets/javascripts/ide/components/ide_tree.vue
@@ -1,14 +1,17 @@
<script>
import { mapState, mapGetters, mapActions } from 'vuex';
+import { modalTypes } from '../constants';
import IdeTreeList from './ide_tree_list.vue';
import Upload from './new_dropdown/upload.vue';
import NewEntryButton from './new_dropdown/button.vue';
+import NewModal from './new_dropdown/modal.vue';
export default {
components: {
Upload,
IdeTreeList,
NewEntryButton,
+ NewModal,
},
computed: {
...mapState(['currentBranchId']),
@@ -26,7 +29,13 @@ export default {
}
},
methods: {
- ...mapActions(['updateViewer', 'openNewEntryModal', 'createTempEntry', 'resetOpenFiles']),
+ ...mapActions(['updateViewer', 'createTempEntry', 'resetOpenFiles']),
+ createNewFile() {
+ this.$refs.newModal.open(modalTypes.blob);
+ },
+ createNewFolder() {
+ this.$refs.newModal.open(modalTypes.tree);
+ },
},
};
</script>
@@ -41,7 +50,7 @@ export default {
:show-label="false"
class="d-flex border-0 p-0 mr-3 qa-new-file"
icon="doc-new"
- @click="openNewEntryModal({ type: 'blob' })"
+ @click="createNewFile()"
/>
<upload
:show-label="false"
@@ -54,9 +63,10 @@ export default {
:show-label="false"
class="d-flex border-0 p-0"
icon="folder-new"
- @click="openNewEntryModal({ type: 'tree' })"
+ @click="createNewFolder()"
/>
</div>
+ <new-modal ref="newModal" />
</template>
</ide-tree-list>
</template>
diff --git a/app/assets/javascripts/ide/components/new_dropdown/index.vue b/app/assets/javascripts/ide/components/new_dropdown/index.vue
index 9961c0df52e..9ad17d73716 100644
--- a/app/assets/javascripts/ide/components/new_dropdown/index.vue
+++ b/app/assets/javascripts/ide/components/new_dropdown/index.vue
@@ -4,12 +4,14 @@ import icon from '~/vue_shared/components/icon.vue';
import upload from './upload.vue';
import ItemButton from './button.vue';
import { modalTypes } from '../../constants';
+import NewModal from '../new_dropdown/modal.vue';
export default {
components: {
icon,
upload,
ItemButton,
+ NewModal,
},
props: {
type: {
@@ -37,9 +39,9 @@ export default {
},
},
methods: {
- ...mapActions(['createTempEntry', 'openNewEntryModal', 'deleteEntry']),
+ ...mapActions(['createTempEntry', 'deleteEntry']),
createNewItem(type) {
- this.openNewEntryModal({ type, path: this.path });
+ this.$refs.newModal.open(type, this.path);
this.$emit('toggle', false);
},
openDropdown() {
@@ -109,5 +111,6 @@ export default {
</li>
</ul>
</div>
+ <new-modal ref="newModal" />
</div>
</template>
diff --git a/app/assets/javascripts/ide/components/new_dropdown/modal.vue b/app/assets/javascripts/ide/components/new_dropdown/modal.vue
index bf3d736ddf3..f9a27d77498 100644
--- a/app/assets/javascripts/ide/components/new_dropdown/modal.vue
+++ b/app/assets/javascripts/ide/components/new_dropdown/modal.vue
@@ -1,61 +1,60 @@
<script>
-import $ from 'jquery';
import { mapActions, mapState, mapGetters } from 'vuex';
import flash from '~/flash';
import { __, sprintf, s__ } from '~/locale';
-import DeprecatedModal2 from '~/vue_shared/components/deprecated_modal_2.vue';
+import { GlModal } from '@gitlab/ui';
import { modalTypes } from '../../constants';
export default {
components: {
- GlModal: DeprecatedModal2,
+ GlModal,
},
data() {
return {
name: '',
+ type: modalTypes.blob,
+ path: '',
};
},
computed: {
- ...mapState(['entries', 'entryModal']),
+ ...mapState(['entries']),
...mapGetters('fileTemplates', ['templateTypes']),
entryName: {
get() {
- const entryPath = this.entryModal.entry.path;
-
- if (this.entryModal.type === modalTypes.rename) {
- return this.name || entryPath;
+ if (this.type === modalTypes.rename) {
+ return this.name || this.path;
}
- return this.name || (entryPath ? `${entryPath}/` : '');
+ return this.name || (this.path ? `${this.path}/` : '');
},
set(val) {
this.name = val.trim();
},
},
modalTitle() {
- if (this.entryModal.type === modalTypes.tree) {
+ const entry = this.entries[this.path];
+
+ if (this.type === modalTypes.tree) {
return __('Create new directory');
- } else if (this.entryModal.type === modalTypes.rename) {
- return this.entryModal.entry.type === modalTypes.tree
- ? __('Rename folder')
- : __('Rename file');
+ } else if (this.type === modalTypes.rename) {
+ return entry.type === modalTypes.tree ? __('Rename folder') : __('Rename file');
}
return __('Create new file');
},
buttonLabel() {
- if (this.entryModal.type === modalTypes.tree) {
+ const entry = this.entries[this.path];
+
+ if (this.type === modalTypes.tree) {
return __('Create directory');
- } else if (this.entryModal.type === modalTypes.rename) {
- return this.entryModal.entry.type === modalTypes.tree
- ? __('Rename folder')
- : __('Rename file');
+ } else if (this.type === modalTypes.rename) {
+ return entry.type === modalTypes.tree ? __('Rename folder') : __('Rename file');
}
return __('Create file');
},
isCreatingNewFile() {
- return this.entryModal.type === 'blob';
+ return this.type === modalTypes.blob;
},
placeholder() {
return this.isCreatingNewFile ? 'dir/file_name' : 'dir/';
@@ -64,7 +63,7 @@ export default {
methods: {
...mapActions(['createTempEntry', 'renameEntry']),
submitForm() {
- if (this.entryModal.type === modalTypes.rename) {
+ if (this.type === modalTypes.rename) {
if (this.entries[this.entryName] && !this.entries[this.entryName].deleted) {
flash(
sprintf(s__('The name "%{name}" is already taken in this directory.'), {
@@ -82,7 +81,7 @@ export default {
parentPath = parentPath.join('/');
this.renameEntry({
- path: this.entryModal.entry.path,
+ path: this.path,
name: entryName,
parentPath,
});
@@ -90,17 +89,17 @@ export default {
} else {
this.createTempEntry({
name: this.name,
- type: this.entryModal.type,
+ type: this.type,
});
}
},
createFromTemplate(template) {
this.createTempEntry({
name: template.name,
- type: this.entryModal.type,
+ type: this.type,
});
- $('#ide-new-entry').modal('toggle');
+ this.$refs.modal.toggle();
},
focusInput() {
const name = this.entries[this.entryName] ? this.entries[this.entryName].name : null;
@@ -112,8 +111,23 @@ export default {
this.$refs.fieldName.setSelectionRange(inputValue.indexOf(name), inputValue.length);
}
},
- closedModal() {
+ resetData() {
this.name = '';
+ this.path = '';
+ this.type = modalTypes.blob;
+ },
+ open(type = modalTypes.blob, path = '') {
+ this.type = type;
+ this.path = path;
+ this.$refs.modal.show();
+
+ // wait for modal to show first
+ this.$nextTick(() => {
+ this.focusInput();
+ });
+ },
+ close() {
+ this.$refs.modal.hide();
},
},
};
@@ -121,15 +135,15 @@ export default {
<template>
<gl-modal
- id="ide-new-entry"
- class="qa-new-file-modal"
- :header-title-text="modalTitle"
- :footer-primary-button-text="buttonLabel"
- footer-primary-button-variant="success"
- modal-size="lg"
- @submit="submitForm"
- @open="focusInput"
- @closed="closedModal"
+ ref="modal"
+ modal-id="ide-new-entry"
+ modal-class="qa-new-file-modal"
+ :title="modalTitle"
+ :ok-title="buttonLabel"
+ ok-variant="success"
+ size="lg"
+ @ok="submitForm"
+ @hide="resetData"
>
<div class="form-group row">
<label class="label-bold col-form-label col-sm-2"> {{ __('Name') }} </label>
diff --git a/app/assets/javascripts/ide/constants.js b/app/assets/javascripts/ide/constants.js
index fa2672aaece..ae8550cba76 100644
--- a/app/assets/javascripts/ide/constants.js
+++ b/app/assets/javascripts/ide/constants.js
@@ -78,6 +78,7 @@ export const commitItemIconMap = {
export const modalTypes = {
rename: 'rename',
tree: 'tree',
+ blob: 'blob',
};
export const commitActionTypes = {
diff --git a/app/assets/javascripts/ide/stores/actions.js b/app/assets/javascripts/ide/stores/actions.js
index 1856a84359f..89422c8a526 100644
--- a/app/assets/javascripts/ide/stores/actions.js
+++ b/app/assets/javascripts/ide/stores/actions.js
@@ -1,4 +1,3 @@
-import $ from 'jquery';
import Vue from 'vue';
import { escape } from 'lodash';
import { __, sprintf } from '~/locale';
@@ -176,13 +175,6 @@ export const setLinks = ({ commit }, links) => commit(types.SET_LINKS, links);
export const setErrorMessage = ({ commit }, errorMessage) =>
commit(types.SET_ERROR_MESSAGE, errorMessage);
-export const openNewEntryModal = ({ commit }, { type, path = '' }) => {
- commit(types.OPEN_NEW_ENTRY_MODAL, { type, path });
-
- // open the modal manually so we don't mess around with dropdown/rows
- $('#ide-new-entry').modal('show');
-};
-
export const deleteEntry = ({ commit, dispatch, state }, path) => {
const entry = state.entries[path];
const { prevPath, prevName, prevParentPath } = entry;
diff --git a/app/assets/javascripts/ide/stores/mutation_types.js b/app/assets/javascripts/ide/stores/mutation_types.js
index 78831bdf022..d088d6d5cba 100644
--- a/app/assets/javascripts/ide/stores/mutation_types.js
+++ b/app/assets/javascripts/ide/stores/mutation_types.js
@@ -73,7 +73,6 @@ export const RESET_OPEN_FILES = 'RESET_OPEN_FILES';
export const SET_ERROR_MESSAGE = 'SET_ERROR_MESSAGE';
-export const OPEN_NEW_ENTRY_MODAL = 'OPEN_NEW_ENTRY_MODAL';
export const DELETE_ENTRY = 'DELETE_ENTRY';
export const RENAME_ENTRY = 'RENAME_ENTRY';
export const REVERT_RENAME_ENTRY = 'REVERT_RENAME_ENTRY';
diff --git a/app/assets/javascripts/ide/stores/mutations.js b/app/assets/javascripts/ide/stores/mutations.js
index 5d567d9b169..8372c4c4de0 100644
--- a/app/assets/javascripts/ide/stores/mutations.js
+++ b/app/assets/javascripts/ide/stores/mutations.js
@@ -192,15 +192,6 @@ export default {
[types.SET_ERROR_MESSAGE](state, errorMessage) {
Object.assign(state, { errorMessage });
},
- [types.OPEN_NEW_ENTRY_MODAL](state, { type, path }) {
- Object.assign(state, {
- entryModal: {
- type,
- path,
- entry: { ...state.entries[path] },
- },
- });
- },
[types.DELETE_ENTRY](state, path) {
const entry = state.entries[path];
const { tempFile = false } = entry;
diff --git a/app/assets/javascripts/monitoring/constants.js b/app/assets/javascripts/monitoring/constants.js
index f2f0a0eac7b..dbd374f1e1c 100644
--- a/app/assets/javascripts/monitoring/constants.js
+++ b/app/assets/javascripts/monitoring/constants.js
@@ -198,3 +198,21 @@ export const OPERATORS = {
equalTo: '==',
lessThan: '<',
};
+
+/**
+ * Dashboard yml files support custom user-defined variables that
+ * are rendered as input elements in the monitoring dashboard.
+ * These values can be edited by the user and are passed on to the
+ * the backend and eventually to Prometheus API proxy.
+ *
+ * As of 13.0, the supported types are:
+ * simple custom -> dropdown elements
+ * advanced custom -> dropdown elements
+ * text -> text input elements
+ *
+ * Custom variables have a simple and a advanced variant.
+ */
+export const VARIABLE_TYPES = {
+ custom: 'custom',
+ text: 'text',
+};
diff --git a/app/assets/javascripts/monitoring/stores/variable_mapping.js b/app/assets/javascripts/monitoring/stores/variable_mapping.js
new file mode 100644
index 00000000000..b8abcac5e09
--- /dev/null
+++ b/app/assets/javascripts/monitoring/stores/variable_mapping.js
@@ -0,0 +1,125 @@
+import { VARIABLE_TYPES } from '../constants';
+
+/**
+ * This file exclusively deals with parsing user-defined variables
+ * in dashboard yml file.
+ *
+ * As of 13.0, simple custom and advanced custom variables are supported.
+ *
+ * In the future iterations, text and query variables will be
+ * supported
+ *
+ */
+
+/**
+ * Utility method to determine if a custom variable is
+ * simple or not. If its not simple, it is advanced.
+ *
+ * @param {Array|Object} customVar Array if simple, object if advanced
+ * @returns {Boolean} true if simple, false if advanced
+ */
+const isSimpleCustomVariable = customVar => Array.isArray(customVar);
+
+/**
+ * Normalize simple and advanced custom variable options to a standard
+ * format
+ * @param {Object} custom variable option
+ * @returns {Object} normalized custom variable options
+ */
+const normalizeDropdownOptions = ({ default: defaultOpt = false, text, value }) => ({
+ default: defaultOpt,
+ text,
+ value,
+});
+
+/**
+ * Simple custom variables have an array of values.
+ * This method parses such variables options to a standard format.
+ *
+ * @param {String} opt option from simple custom variable
+ */
+const parseSimpleDropdownOptions = opt => ({ text: opt, value: opt });
+
+/**
+ * Custom advanced variables are rendered as dropdown elements in the dashboard
+ * header. This method parses advanced custom variables.
+ *
+ * @param {Object} advVariable advance custom variable
+ * @returns {Object}
+ */
+const customAdvancedVariableParser = advVariable => {
+ const options = advVariable?.options?.values ?? [];
+ return {
+ type: VARIABLE_TYPES.custom,
+ label: advVariable.label,
+ options: options.map(normalizeDropdownOptions),
+ };
+};
+
+/**
+ * Custom simple variables are rendered as dropdown elements in the dashboard
+ * header. This method parses simple custom variables.
+ *
+ * Simple custom variables do not have labels so its set to null here.
+ *
+ * @param {Array} customVariable array of options
+ * @returns {Object}
+ */
+const customSimpleVariableParser = simpleVar => {
+ const options = (simpleVar || []).map(parseSimpleDropdownOptions);
+ return {
+ type: VARIABLE_TYPES.custom,
+ label: null,
+ options: options.map(normalizeDropdownOptions),
+ };
+};
+
+/**
+ * This method returns a parser based on the type of the variable.
+ * Currently, the supported variables are simple custom and
+ * advanced custom only. In the future, this method will support
+ * text and query variables.
+ *
+ * @param {Array|Object} variable
+ * @return {Function} parser method
+ */
+const getVariableParser = variable => {
+ if (isSimpleCustomVariable(variable)) {
+ return customSimpleVariableParser;
+ } else if (variable.type === VARIABLE_TYPES.custom) {
+ return customAdvancedVariableParser;
+ }
+ return () => null;
+};
+
+/**
+ * This method parses the templating property in the dashboard yml file.
+ * The templating property has variables that are rendered as input elements
+ * for the user to edit. The values from input elements are relayed to
+ * backend and eventually Prometheus API.
+ *
+ * This method currently is not used anywhere. Once the issue
+ * https://gitlab.com/gitlab-org/gitlab/-/issues/214536 is completed,
+ * this method will have been used by the monitoring dashboard.
+ *
+ * @param {Object} templating templating variables from the dashboard yml file
+ * @returns {Object} a map of processed templating variables
+ */
+export const parseTemplatingVariables = ({ variables = {} } = {}) =>
+ Object.entries(variables).reduce((acc, [key, variable]) => {
+ // get the parser
+ const parser = getVariableParser(variable);
+ // parse the variable
+ const parsedVar = parser(variable);
+ // for simple custom variable label is null and it should be
+ // replace with key instead
+ if (parsedVar) {
+ acc[key] = {
+ ...parsedVar,
+ label: parsedVar.label || key,
+ };
+ }
+ return acc;
+ }, {});
+
+export default {};
diff --git a/app/assets/stylesheets/page_bundles/themes/_dark.scss b/app/assets/stylesheets/page_bundles/themes/_dark.scss
index 30822eb7de4..1d316ca2e3f 100644
--- a/app/assets/stylesheets/page_bundles/themes/_dark.scss
+++ b/app/assets/stylesheets/page_bundles/themes/_dark.scss
@@ -40,7 +40,7 @@
h1,
h2,
h3,
- h4:not(.modal-title),
+ h4,
h5,
h6,
code,
@@ -80,10 +80,6 @@
background-color: $dropdown-hover-background;
}
- .modal-body {
- color: $gl-text-color;
- }
-
.dropdown-menu-toggle svg,
.dropdown-menu-toggle svg:hover,
.ide-tree-header:not(.ide-pipeline-header) svg,
diff --git a/app/models/ci/pipeline.rb b/app/models/ci/pipeline.rb
index 656a567c0a7..214ff2d61d9 100644
--- a/app/models/ci/pipeline.rb
+++ b/app/models/ci/pipeline.rb
@@ -115,8 +115,11 @@ module Ci
state_machine :status, initial: :created do
event :enqueue do
- transition [:created, :waiting_for_resource, :preparing, :skipped, :scheduled] => :pending
+ transition [:created, :manual, :waiting_for_resource, :preparing, :skipped, :scheduled] => :pending
transition [:success, :failed, :canceled] => :running
+
+ # this is needed to ensure tests to be covered
+ transition [:running] => :running
end
event :request_resource do
diff --git a/app/models/ci/stage.rb b/app/models/ci/stage.rb
index 93bd42f8734..d3325a47053 100644
--- a/app/models/ci/stage.rb
+++ b/app/models/ci/stage.rb
@@ -42,8 +42,7 @@ module Ci
state_machine :status, initial: :created do
event :enqueue do
- transition [:created, :waiting_for_resource, :preparing] => :pending
- transition [:success, :failed, :canceled, :skipped] => :running
+ transition any - [:pending] => :pending
end
event :request_resource do
diff --git a/app/services/ci/pipeline_processing/atomic_processing_service.rb b/app/services/ci/pipeline_processing/atomic_processing_service.rb
index 2a1bf15b9a3..b01a9d2e3b8 100644
--- a/app/services/ci/pipeline_processing/atomic_processing_service.rb
+++ b/app/services/ci/pipeline_processing/atomic_processing_service.rb
@@ -95,7 +95,7 @@ module Ci
def processable_status(processable)
if processable.scheduling_type_dag?
# Processable uses DAG, get status of all dependent needs
- @collection.status_for_names(processable.aggregated_needs_names.to_a)
+ @collection.status_for_names(processable.aggregated_needs_names.to_a, dag: true)
else
# Processable uses Stages, get status of prior stage
@collection.status_for_prior_stage_position(processable.stage_idx.to_i)
diff --git a/app/services/ci/pipeline_processing/atomic_processing_service/status_collection.rb b/app/services/ci/pipeline_processing/atomic_processing_service/status_collection.rb
index 42e38a5c80f..2228328882d 100644
--- a/app/services/ci/pipeline_processing/atomic_processing_service/status_collection.rb
+++ b/app/services/ci/pipeline_processing/atomic_processing_service/status_collection.rb
@@ -32,14 +32,14 @@ module Ci
# This methods gets composite status of all processables
def status_of_all
- status_for_array(all_statuses)
+ status_for_array(all_statuses, dag: false)
end
# This methods gets composite status for processables with given names
- def status_for_names(names)
+ def status_for_names(names, dag:)
name_statuses = all_statuses_by_name.slice(*names)
- status_for_array(name_statuses.values)
+ status_for_array(name_statuses.values, dag: dag)
end
# This methods gets composite status for processables before given stage
@@ -48,7 +48,7 @@ module Ci
stage_statuses = all_statuses_grouped_by_stage_position
.select { |stage_position, _| stage_position < position }
- status_for_array(stage_statuses.values.flatten)
+ status_for_array(stage_statuses.values.flatten, dag: false)
end
end
@@ -65,7 +65,7 @@ module Ci
strong_memoize("status_for_stage_position_#{current_position}") do
stage_statuses = all_statuses_grouped_by_stage_position[current_position].to_a
- status_for_array(stage_statuses.flatten)
+ status_for_array(stage_statuses.flatten, dag: false)
end
end
@@ -76,7 +76,14 @@ module Ci
private
- def status_for_array(statuses)
+ def status_for_array(statuses, dag:)
+ # TODO: This is hack to support
+ # the same exact behaviour for Atomic and Legacy processing
+ # that DAG is blocked from executing if dependent is not "complete"
+ if dag && statuses.any? { |status| HasStatus::COMPLETED_STATUSES.exclude?(status[:status]) }
+ return 'pending'
+ end
+
result = Gitlab::Ci::Status::Composite
.new(statuses)
.status
diff --git a/app/services/tags/destroy_service.rb b/app/services/tags/destroy_service.rb
index 4f6ae07be7d..3a01192487d 100644
--- a/app/services/tags/destroy_service.rb
+++ b/app/services/tags/destroy_service.rb
@@ -18,11 +18,6 @@ module Tags
.new(project, current_user, tag: tag_name)
.execute
- push_data = build_push_data(tag)
- EventCreateService.new.push(project, current_user, push_data)
- project.execute_hooks(push_data.dup, :tag_push_hooks)
- project.execute_services(push_data.dup, :tag_push_hooks)
-
success('Tag was removed')
else
error('Failed to remove tag')
@@ -38,14 +33,5 @@ module Tags
def success(message)
super().merge(message: message)
end
-
- def build_push_data(tag)
- Gitlab::DataBuilder::Push.build(
- project: project,
- user: current_user,
- oldrev: tag.dereferenced_target.sha,
- newrev: Gitlab::Git::BLANK_SHA,
- ref: "#{Gitlab::Git::TAG_REF_PREFIX}#{tag.name}")
- end
end
end
diff --git a/app/views/projects/settings/ci_cd/_form.html.haml b/app/views/projects/settings/ci_cd/_form.html.haml
index 4040b1094aa..b50f712922f 100644
--- a/app/views/projects/settings/ci_cd/_form.html.haml
+++ b/app/views/projects/settings/ci_cd/_form.html.haml
@@ -103,7 +103,7 @@
.input-group
%span.input-group-prepend
.input-group-text /
- = f.text_field :build_coverage_regex, class: 'form-control', placeholder: 'Regular expression'
+ = f.text_field :build_coverage_regex, class: 'form-control', placeholder: 'Regular expression', data: { qa_selector: 'build_coverage_regex_field' }
%span.input-group-append
.input-group-text /
%p.form-text.text-muted
@@ -143,7 +143,7 @@
go test -cover (Go)
%code coverage: \d+.\d+% of statements
- = f.submit _('Save changes'), class: "btn btn-success"
+ = f.submit _('Save changes'), class: "btn btn-success", data: { qa_selector: 'save_general_pipelines_changes_button' }
%hr
diff --git a/app/views/projects/settings/ci_cd/show.html.haml b/app/views/projects/settings/ci_cd/show.html.haml
index 1358077f2b2..4e14426a069 100644
--- a/app/views/projects/settings/ci_cd/show.html.haml
+++ b/app/views/projects/settings/ci_cd/show.html.haml
@@ -5,7 +5,7 @@
- expanded = expanded_by_default?
- general_expanded = @project.errors.empty? ? expanded : true
-%section.settings#js-general-pipeline-settings.no-animate{ class: ('expanded' if general_expanded) }
+%section.settings#js-general-pipeline-settings.no-animate{ class: ('expanded' if general_expanded), data: { qa_selector: 'general_pipelines_settings_content' } }
.settings-header
%h4
= _("General pipelines")
diff --git a/changelogs/unreleased/sk-fix-tag-deletion-duplicate-events.yml b/changelogs/unreleased/sk-fix-tag-deletion-duplicate-events.yml
new file mode 100644
index 00000000000..8dc6dcb1317
--- /dev/null
+++ b/changelogs/unreleased/sk-fix-tag-deletion-duplicate-events.yml
@@ -0,0 +1,5 @@
+---
+title: Fix duplicated activity and events on deletion of tag
+merge_request: 28861
+author: Sashi Kumar
+type: fixed
diff --git a/qa/qa.rb b/qa/qa.rb
index 603e03b6752..a03492ce538 100644
--- a/qa/qa.rb
+++ b/qa/qa.rb
@@ -252,6 +252,7 @@ module QA
autoload :Main, 'qa/page/project/settings/main'
autoload :Repository, 'qa/page/project/settings/repository'
autoload :CICD, 'qa/page/project/settings/ci_cd'
+ autoload :GeneralPipelines, 'qa/page/project/settings/general_pipelines'
autoload :AutoDevops, 'qa/page/project/settings/auto_devops'
autoload :DeployKeys, 'qa/page/project/settings/deploy_keys'
autoload :DeployTokens, 'qa/page/project/settings/deploy_tokens'
diff --git a/qa/qa/page/project/settings/ci_cd.rb b/qa/qa/page/project/settings/ci_cd.rb
index 46f93fad61e..6d4f05f877a 100644
--- a/qa/qa/page/project/settings/ci_cd.rb
+++ b/qa/qa/page/project/settings/ci_cd.rb
@@ -11,6 +11,13 @@ module QA
element :autodevops_settings_content
element :runners_settings_content
element :variables_settings_content
+ element :general_pipelines_settings_content
+ end
+
+ def expand_general_pipelines(&block)
+ expand_section(:general_pipelines_settings_content) do
+ Settings::GeneralPipelines.perform(&block)
+ end
end
def expand_runners_settings(&block)
diff --git a/qa/qa/page/project/settings/general_pipelines.rb b/qa/qa/page/project/settings/general_pipelines.rb
new file mode 100644
index 00000000000..2265281a3f4
--- /dev/null
+++ b/qa/qa/page/project/settings/general_pipelines.rb
@@ -0,0 +1,23 @@
+# frozen_string_literal: true
+
+module QA
+ module Page
+ module Project
+ module Settings
+ class GeneralPipelines < Page::Base
+ include Common
+
+ view 'app/views/projects/settings/ci_cd/_form.html.haml' do
+ element :build_coverage_regex_field
+ element :save_general_pipelines_changes_button
+ end
+
+ def configure_coverage_regex(pattern)
+ fill_element :build_coverage_regex_field, pattern
+ click_element :save_general_pipelines_changes_button
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/qa/qa/specs/features/browser_ui/4_verify/testing/view_code_coverage_spec.rb b/qa/qa/specs/features/browser_ui/4_verify/testing/view_code_coverage_spec.rb
new file mode 100644
index 00000000000..bf20c4a70ea
--- /dev/null
+++ b/qa/qa/specs/features/browser_ui/4_verify/testing/view_code_coverage_spec.rb
@@ -0,0 +1,62 @@
+# frozen_string_literal: true
+
+module QA
+ context 'Verify', :docker, :runner do
+ describe 'Code coverage statistics' do
+ let(:simplecov) { '\(\d+.\d+\%\) covered' }
+ let(:executor) { "qa-runner-#{Time.now.to_i}" }
+ let(:runner) do
+ Resource::Runner.fabricate_via_api! do |runner|
+ runner.name = executor
+ end
+ end
+
+ let(:merge_request) do
+ Resource::MergeRequest.fabricate_via_api! do |mr|
+ mr.project = runner.project
+ mr.file_name = '.gitlab-ci.yml'
+ mr.file_content = <<~EOF
+ test:
+ tags:
+ - qa
+ - e2e
+ script:
+ - echo '(66.67%) covered'
+ EOF
+ end
+ end
+
+ before do
+ Flow::Login.sign_in
+ end
+
+ after do
+ runner.remove_via_api!
+ end
+
+ it 'creates an MR with code coverage statistics' do
+ runner.project.visit!
+ configure_code_coverage(simplecov)
+ merge_request.visit!
+
+ Page::MergeRequest::Show.perform do |mr_widget|
+ Support::Retrier.retry_until(max_attempts: 5, sleep_interval: 5) do
+ mr_widget.has_pipeline_status?(/Pipeline #\d+ passed/)
+ end
+ expect(mr_widget).to have_content('Coverage 66.67%')
+ end
+ end
+ end
+
+ private
+
+ def configure_code_coverage(coverage_tool_pattern)
+ Page::Project::Menu.perform(&:go_to_ci_cd_settings)
+ Page::Project::Settings::CICD.perform do |settings|
+ settings.expand_general_pipelines do |coverage|
+ coverage.configure_coverage_regex(coverage_tool_pattern)
+ end
+ end
+ end
+ end
+end
diff --git a/spec/frontend/ide/components/new_dropdown/index_spec.js b/spec/frontend/ide/components/new_dropdown/index_spec.js
index f4fecb68b64..00781c16609 100644
--- a/spec/frontend/ide/components/new_dropdown/index_spec.js
+++ b/spec/frontend/ide/components/new_dropdown/index_spec.js
@@ -23,9 +23,9 @@ describe('new dropdown component', () => {
tree: [],
};
- jest.spyOn(vm, 'openNewEntryModal').mockImplementation(() => {});
-
vm.$mount();
+
+ jest.spyOn(vm.$refs.newModal, 'open').mockImplementation(() => {});
});
afterEach(() => {
@@ -43,16 +43,16 @@ describe('new dropdown component', () => {
});
describe('createNewItem', () => {
- it('sets modalType to blob when new file is clicked', () => {
+ it('opens modal for a blob when new file is clicked', () => {
vm.$el.querySelectorAll('.dropdown-menu button')[0].click();
- expect(vm.openNewEntryModal).toHaveBeenCalledWith({ type: 'blob', path: '' });
+ expect(vm.$refs.newModal.open).toHaveBeenCalledWith('blob', '');
});
- it('sets modalType to tree when new directory is clicked', () => {
+ it('opens modal for a tree when new directory is clicked', () => {
vm.$el.querySelectorAll('.dropdown-menu button')[2].click();
- expect(vm.openNewEntryModal).toHaveBeenCalledWith({ type: 'tree', path: '' });
+ expect(vm.$refs.newModal.open).toHaveBeenCalledWith('tree', '');
});
});
diff --git a/spec/frontend/ide/components/new_dropdown/modal_spec.js b/spec/frontend/ide/components/new_dropdown/modal_spec.js
index 2f10bf787b3..23da4df188b 100644
--- a/spec/frontend/ide/components/new_dropdown/modal_spec.js
+++ b/spec/frontend/ide/components/new_dropdown/modal_spec.js
@@ -14,55 +14,48 @@ describe('new file modal component', () => {
vm.$destroy();
});
- describe.each(['tree', 'blob'])('%s', type => {
- beforeEach(() => {
+ describe.each`
+ entryType | modalTitle | btnTitle | showsFileTemplates
+ ${'tree'} | ${'Create new directory'} | ${'Create directory'} | ${false}
+ ${'blob'} | ${'Create new file'} | ${'Create file'} | ${true}
+ `('$entryType', ({ entryType, modalTitle, btnTitle, showsFileTemplates }) => {
+ beforeEach(done => {
const store = createStore();
- store.state.entryModal = {
- type,
- path: '',
- entry: {
- path: '',
- },
- };
vm = createComponentWithStore(Component, store).$mount();
-
+ vm.open(entryType);
vm.name = 'testing';
- });
- it(`sets modal title as ${type}`, () => {
- const title = type === 'tree' ? 'directory' : 'file';
+ vm.$nextTick(done);
+ });
- expect(vm.$el.querySelector('.modal-title').textContent.trim()).toBe(`Create new ${title}`);
+ afterEach(() => {
+ vm.close();
});
- it(`sets button label as ${type}`, () => {
- const title = type === 'tree' ? 'directory' : 'file';
+ it(`sets modal title as ${entryType}`, () => {
+ expect(document.querySelector('.modal-title').textContent.trim()).toBe(modalTitle);
+ });
- expect(vm.$el.querySelector('.btn-success').textContent.trim()).toBe(`Create ${title}`);
+ it(`sets button label as ${entryType}`, () => {
+ expect(document.querySelector('.btn-success').textContent.trim()).toBe(btnTitle);
});
- it(`sets form label as ${type}`, () => {
- expect(vm.$el.querySelector('.label-bold').textContent.trim()).toBe('Name');
+ it(`sets form label as ${entryType}`, () => {
+ expect(document.querySelector('.label-bold').textContent.trim()).toBe('Name');
});
- it(`${type === 'tree' ? 'does not show' : 'shows'} file templates`, () => {
- const templateFilesEl = vm.$el.querySelector('.file-templates');
- if (type === 'tree') {
- expect(templateFilesEl).toBeNull();
- } else {
- expect(templateFilesEl instanceof Element).toBeTruthy();
- }
+ it(`shows file templates: ${showsFileTemplates}`, () => {
+ const templateFilesEl = document.querySelector('.file-templates');
+ expect(Boolean(templateFilesEl)).toBe(showsFileTemplates);
});
});
describe('rename entry', () => {
beforeEach(() => {
const store = createStore();
- store.state.entryModal = {
- type: 'rename',
- path: '',
- entry: {
+ store.state.entries = {
+ 'test-path': {
name: 'test',
type: 'blob',
path: 'test-path',
@@ -72,23 +65,29 @@ describe('new file modal component', () => {
vm = createComponentWithStore(Component, store).$mount();
});
- ['tree', 'blob'].forEach(type => {
- it(`renders title and button for renaming ${type}`, done => {
- const text = type === 'tree' ? 'folder' : 'file';
-
- vm.$store.state.entryModal.entry.type = type;
+ it.each`
+ entryType | modalTitle | btnTitle
+ ${'tree'} | ${'Rename folder'} | ${'Rename folder'}
+ ${'blob'} | ${'Rename file'} | ${'Rename file'}
+ `(
+ 'renders title and button for renaming $entryType',
+ ({ entryType, modalTitle, btnTitle }, done) => {
+ vm.$store.state.entries['test-path'].type = entryType;
+ vm.open('rename', 'test-path');
vm.$nextTick(() => {
- expect(vm.$el.querySelector('.modal-title').textContent.trim()).toBe(`Rename ${text}`);
- expect(vm.$el.querySelector('.btn-success').textContent.trim()).toBe(`Rename ${text}`);
+ expect(document.querySelector('.modal-title').textContent.trim()).toBe(modalTitle);
+ expect(document.querySelector('.btn-success').textContent.trim()).toBe(btnTitle);
done();
});
- });
- });
+ },
+ );
describe('entryName', () => {
it('returns entries name', () => {
+ vm.open('rename', 'test-path');
+
expect(vm.entryName).toBe('test-path');
});
@@ -115,15 +114,6 @@ describe('new file modal component', () => {
describe('submitForm', () => {
it('throws an error when target entry exists', () => {
const store = createStore();
- store.state.entryModal = {
- type: 'rename',
- path: 'test-path/test',
- entry: {
- name: 'test',
- type: 'blob',
- path: 'test-path/test',
- },
- };
store.state.entries = {
'test-path/test': {
name: 'test',
@@ -132,6 +122,7 @@ describe('new file modal component', () => {
};
vm = createComponentWithStore(Component, store).$mount();
+ vm.open('rename', 'test-path/test');
expect(createFlash).not.toHaveBeenCalled();
diff --git a/spec/frontend/ide/stores/mutations_spec.js b/spec/frontend/ide/stores/mutations_spec.js
index 5d0fe35a10e..bca355b820a 100644
--- a/spec/frontend/ide/stores/mutations_spec.js
+++ b/spec/frontend/ide/stores/mutations_spec.js
@@ -339,23 +339,6 @@ describe('Multi-file store mutations', () => {
});
});
- describe('OPEN_NEW_ENTRY_MODAL', () => {
- it('sets entryModal', () => {
- localState.entries.testPath = file();
-
- mutations.OPEN_NEW_ENTRY_MODAL(localState, {
- type: 'test',
- path: 'testPath',
- });
-
- expect(localState.entryModal).toEqual({
- type: 'test',
- path: 'testPath',
- entry: localState.entries.testPath,
- });
- });
- });
-
describe('RENAME_ENTRY', () => {
beforeEach(() => {
localState.trees = {
diff --git a/spec/frontend/monitoring/store/variable_mapping_spec.js b/spec/frontend/monitoring/store/variable_mapping_spec.js
new file mode 100644
index 00000000000..5081092a519
--- /dev/null
+++ b/spec/frontend/monitoring/store/variable_mapping_spec.js
@@ -0,0 +1,150 @@
+import { parseTemplatingVariables } from '~/monitoring/stores/variable_mapping';
+
+describe('parseTemplatingVariables', () => {
+ const generateMockTemplatingData = data => {
+ const vars = data
+ ? {
+ variables: {
+ ...data,
+ },
+ }
+ : {};
+ return {
+ dashboard: {
+ templating: vars,
+ },
+ };
+ };
+
+ const simpleVar = ['value1', 'value2', 'value3'];
+ const advVar = {
+ label: 'Advanced Var',
+ type: 'custom',
+ options: {
+ values: [
+ { value: 'value1', text: 'Var 1 Option 1' },
+ {
+ value: 'value2',
+ text: 'Var 1 Option 2',
+ default: true,
+ },
+ ],
+ },
+ };
+ const advVarWithoutOptions = {
+ type: 'custom',
+ options: {},
+ };
+ const advVarWithoutLabel = {
+ type: 'custom',
+ options: {
+ values: [
+ { value: 'value1', text: 'Var 1 Option 1' },
+ {
+ value: 'value2',
+ text: 'Var 1 Option 2',
+ default: true,
+ },
+ ],
+ },
+ };
+ const advVarWithoutType = {
+ label: 'Variable 2',
+ options: {
+ values: [
+ { value: 'value1', text: 'Var 1 Option 1' },
+ {
+ value: 'value2',
+ text: 'Var 1 Option 2',
+ default: true,
+ },
+ ],
+ },
+ };
+
+ const responseForSimpleCustomVariable = {
+ simpleVar: {
+ label: 'simpleVar',
+ options: [
+ {
+ default: false,
+ text: 'value1',
+ value: 'value1',
+ },
+ {
+ default: false,
+ text: 'value2',
+ value: 'value2',
+ },
+ {
+ default: false,
+ text: 'value3',
+ value: 'value3',
+ },
+ ],
+ type: 'custom',
+ },
+ };
+
+ const responseForAdvancedCustomVariableWithoutOptions = {
+ advVarWithoutOptions: {
+ label: 'advVarWithoutOptions',
+ options: [],
+ type: 'custom',
+ },
+ };
+
+ const responseForAdvancedCustomVariableWithoutLabel = {
+ advVarWithoutLabel: {
+ label: 'advVarWithoutLabel',
+ options: [
+ {
+ default: false,
+ text: 'Var 1 Option 1',
+ value: 'value1',
+ },
+ {
+ default: true,
+ text: 'Var 1 Option 2',
+ value: 'value2',
+ },
+ ],
+ type: 'custom',
+ },
+ };
+
+ const responseForAdvancedCustomVariable = {
+ ...responseForSimpleCustomVariable,
+ advVar: {
+ label: 'Advanced Var',
+ options: [
+ {
+ default: false,
+ text: 'Var 1 Option 1',
+ value: 'value1',
+ },
+ {
+ default: true,
+ text: 'Var 1 Option 2',
+ value: 'value2',
+ },
+ ],
+ type: 'custom',
+ },
+ };
+
+ it.each`
+ case | input | expected
+ ${'Returns empty object for no dashboard input'} | ${{}} | ${{}}
+ ${'Returns empty object for empty dashboard input'} | ${{ dashboard: {} }} | ${{}}
+ ${'Returns empty object for empty templating prop'} | ${generateMockTemplatingData()} | ${{}}
+ ${'Returns empty object for empty variables prop'} | ${generateMockTemplatingData({})} | ${{}}
+ ${'Returns parsed object for simple variable'} | ${generateMockTemplatingData({ simpleVar })} | ${responseForSimpleCustomVariable}
+ ${'Returns parsed object for advanced variable without options'} | ${generateMockTemplatingData({ advVarWithoutOptions })} | ${responseForAdvancedCustomVariableWithoutOptions}
+ ${'Returns parsed object for advanced variable without type'} | ${generateMockTemplatingData({ advVarWithoutType })} | ${{}}
+ ${'Returns parsed object for advanced variable without label'} | ${generateMockTemplatingData({ advVarWithoutLabel })} | ${responseForAdvancedCustomVariableWithoutLabel}
+ ${'Returns parsed object for simple and advanced variables'} | ${generateMockTemplatingData({ simpleVar, advVar })} | ${responseForAdvancedCustomVariable}
+ `('$case', ({ input, expected }) => {
+ expect(parseTemplatingVariables(input?.dashboard?.templating)).toEqual(expected);
+ });
+});
diff --git a/spec/javascripts/reports/components/grouped_test_reports_app_spec.js b/spec/frontend/reports/components/grouped_test_reports_app_spec.js
index 9d7150d95cd..1a01db391da 100644
--- a/spec/javascripts/reports/components/grouped_test_reports_app_spec.js
+++ b/spec/frontend/reports/components/grouped_test_reports_app_spec.js
@@ -35,7 +35,7 @@ describe('Grouped Test Reports App', () => {
});
it('renders success summary text', done => {
- setTimeout(() => {
+ setImmediate(() => {
expect(vm.$el.querySelector('.gl-spinner')).toBeNull();
expect(vm.$el.querySelector('.js-code-text').textContent.trim()).toEqual(
'Test summary contained no changed test results out of 11 total tests',
@@ -49,7 +49,7 @@ describe('Grouped Test Reports App', () => {
'java ant found no changed test results out of 3 total tests',
);
done();
- }, 0);
+ });
});
});
@@ -62,14 +62,14 @@ describe('Grouped Test Reports App', () => {
});
it('renders success summary text', done => {
- setTimeout(() => {
+ setImmediate(() => {
expect(vm.$el.querySelector('.gl-spinner')).not.toBeNull();
expect(vm.$el.querySelector('.js-code-text').textContent.trim()).toEqual(
'Test summary results are being parsed',
);
done();
- }, 0);
+ });
});
});
@@ -82,7 +82,7 @@ describe('Grouped Test Reports App', () => {
});
it('renders failed summary text + new badge', done => {
- setTimeout(() => {
+ setImmediate(() => {
expect(vm.$el.querySelector('.gl-spinner')).toBeNull();
expect(vm.$el.querySelector('.js-code-text').textContent.trim()).toEqual(
'Test summary contained 2 failed out of 11 total tests',
@@ -95,7 +95,7 @@ describe('Grouped Test Reports App', () => {
'java ant found no changed test results out of 3 total tests',
);
done();
- }, 0);
+ });
});
});
@@ -108,7 +108,7 @@ describe('Grouped Test Reports App', () => {
});
it('renders error summary text + new badge', done => {
- setTimeout(() => {
+ setImmediate(() => {
expect(vm.$el.querySelector('.gl-spinner')).toBeNull();
expect(vm.$el.querySelector('.js-code-text').textContent.trim()).toEqual(
'Test summary contained 2 errors out of 11 total tests',
@@ -121,7 +121,7 @@ describe('Grouped Test Reports App', () => {
'rspec:pg found no changed test results out of 8 total tests',
);
done();
- }, 0);
+ });
});
});
@@ -134,7 +134,7 @@ describe('Grouped Test Reports App', () => {
});
it('renders summary text', done => {
- setTimeout(() => {
+ setImmediate(() => {
expect(vm.$el.querySelector('.gl-spinner')).toBeNull();
expect(vm.$el.querySelector('.js-code-text').textContent.trim()).toEqual(
'Test summary contained 2 failed and 2 fixed test results out of 11 total tests',
@@ -147,7 +147,7 @@ describe('Grouped Test Reports App', () => {
expect(vm.$el.textContent).toContain('New');
expect(vm.$el.textContent).toContain(' java ant found 1 failed out of 3 total tests');
done();
- }, 0);
+ });
});
});
@@ -160,7 +160,7 @@ describe('Grouped Test Reports App', () => {
});
it('renders summary text', done => {
- setTimeout(() => {
+ setImmediate(() => {
expect(vm.$el.querySelector('.gl-spinner')).toBeNull();
expect(vm.$el.querySelector('.js-code-text').textContent.trim()).toEqual(
'Test summary contained 4 fixed test results out of 11 total tests',
@@ -170,11 +170,11 @@ describe('Grouped Test Reports App', () => {
'rspec:pg found 4 fixed test results out of 8 total tests',
);
done();
- }, 0);
+ });
});
it('renders resolved failures', done => {
- setTimeout(() => {
+ setImmediate(() => {
expect(vm.$el.querySelector('.report-block-container').textContent).toContain(
resolvedFailures.suites[0].resolved_failures[0].name,
);
@@ -183,11 +183,11 @@ describe('Grouped Test Reports App', () => {
resolvedFailures.suites[0].resolved_failures[1].name,
);
done();
- }, 0);
+ });
});
it('renders resolved errors', done => {
- setTimeout(() => {
+ setImmediate(() => {
expect(vm.$el.querySelector('.report-block-container').textContent).toContain(
resolvedFailures.suites[0].resolved_errors[0].name,
);
@@ -196,7 +196,7 @@ describe('Grouped Test Reports App', () => {
resolvedFailures.suites[0].resolved_errors[1].name,
);
done();
- }, 0);
+ });
});
});
@@ -209,7 +209,7 @@ describe('Grouped Test Reports App', () => {
});
it('renders an error status for the report', done => {
- setTimeout(() => {
+ setImmediate(() => {
const { name } = failedReport.suites[0];
expect(vm.$el.querySelector('.report-block-list-issue').textContent).toContain(
@@ -229,12 +229,12 @@ describe('Grouped Test Reports App', () => {
});
it('renders loading summary text with loading icon', done => {
- setTimeout(() => {
+ setImmediate(() => {
expect(vm.$el.querySelector('.js-code-text').textContent.trim()).toEqual(
'Test summary failed loading results',
);
done();
- }, 0);
+ });
});
});
@@ -252,9 +252,9 @@ describe('Grouped Test Reports App', () => {
'Test summary results are being parsed',
);
- setTimeout(() => {
+ setImmediate(() => {
done();
- }, 0);
+ });
});
});
});
diff --git a/spec/javascripts/reports/components/modal_open_name_spec.js b/spec/frontend/reports/components/modal_open_name_spec.js
index ae1fb2bf187..d59f3571c4b 100644
--- a/spec/javascripts/reports/components/modal_open_name_spec.js
+++ b/spec/frontend/reports/components/modal_open_name_spec.js
@@ -1,6 +1,6 @@
import Vue from 'vue';
import Vuex from 'vuex';
-import { mountComponentWithStore } from 'spec/helpers/vue_mount_component_helper';
+import { mountComponentWithStore } from 'helpers/vue_mount_component_helper';
import component from '~/reports/components/modal_open_name.vue';
Vue.use(Vuex);
@@ -38,7 +38,7 @@ describe('Modal open name', () => {
});
it('calls openModal actions when button is clicked', () => {
- spyOn(vm, 'openModal');
+ jest.spyOn(vm, 'openModal').mockImplementation(() => {});
vm.$el.click();
diff --git a/spec/javascripts/reports/components/modal_spec.js b/spec/frontend/reports/components/modal_spec.js
index ff046e64b6e..ff046e64b6e 100644
--- a/spec/javascripts/reports/components/modal_spec.js
+++ b/spec/frontend/reports/components/modal_spec.js
diff --git a/spec/javascripts/reports/components/summary_row_spec.js b/spec/frontend/reports/components/summary_row_spec.js
index a19fbad403c..cb0cc025e80 100644
--- a/spec/javascripts/reports/components/summary_row_spec.js
+++ b/spec/frontend/reports/components/summary_row_spec.js
@@ -1,5 +1,5 @@
import Vue from 'vue';
-import mountComponent from 'spec/helpers/vue_mount_component_helper';
+import mountComponent from 'helpers/vue_mount_component_helper';
import component from '~/reports/components/summary_row.vue';
describe('Summary row', () => {
diff --git a/spec/javascripts/reports/components/test_issue_body_spec.js b/spec/frontend/reports/components/test_issue_body_spec.js
index a55719a9d36..ff81020a4eb 100644
--- a/spec/javascripts/reports/components/test_issue_body_spec.js
+++ b/spec/frontend/reports/components/test_issue_body_spec.js
@@ -26,7 +26,7 @@ describe('Test Issue body', () => {
props: commonProps,
});
- spyOn(vm, 'openModal');
+ jest.spyOn(vm, 'openModal').mockImplementation(() => {});
vm.$el.querySelector('button').click();
diff --git a/spec/javascripts/reports/mock_data/mock_data.js b/spec/frontend/reports/mock_data/mock_data.js
index 3caaab2fd79..3caaab2fd79 100644
--- a/spec/javascripts/reports/mock_data/mock_data.js
+++ b/spec/frontend/reports/mock_data/mock_data.js
diff --git a/spec/javascripts/reports/mock_data/new_and_fixed_failures_report.json b/spec/frontend/reports/mock_data/new_and_fixed_failures_report.json
index 6141e5433a6..6141e5433a6 100644
--- a/spec/javascripts/reports/mock_data/new_and_fixed_failures_report.json
+++ b/spec/frontend/reports/mock_data/new_and_fixed_failures_report.json
diff --git a/spec/javascripts/reports/mock_data/new_errors_report.json b/spec/frontend/reports/mock_data/new_errors_report.json
index cebf98fdb63..cebf98fdb63 100644
--- a/spec/javascripts/reports/mock_data/new_errors_report.json
+++ b/spec/frontend/reports/mock_data/new_errors_report.json
diff --git a/spec/javascripts/reports/mock_data/new_failures_report.json b/spec/frontend/reports/mock_data/new_failures_report.json
index 8b9c12c6271..8b9c12c6271 100644
--- a/spec/javascripts/reports/mock_data/new_failures_report.json
+++ b/spec/frontend/reports/mock_data/new_failures_report.json
diff --git a/spec/javascripts/reports/mock_data/no_failures_report.json b/spec/frontend/reports/mock_data/no_failures_report.json
index 7da9e0c6211..7da9e0c6211 100644
--- a/spec/javascripts/reports/mock_data/no_failures_report.json
+++ b/spec/frontend/reports/mock_data/no_failures_report.json
diff --git a/spec/javascripts/reports/mock_data/resolved_failures.json b/spec/frontend/reports/mock_data/resolved_failures.json
index 49de6aa840b..49de6aa840b 100644
--- a/spec/javascripts/reports/mock_data/resolved_failures.json
+++ b/spec/frontend/reports/mock_data/resolved_failures.json
diff --git a/spec/javascripts/reports/store/actions_spec.js b/spec/frontend/reports/store/actions_spec.js
index 18fdb179597..3f189736922 100644
--- a/spec/javascripts/reports/store/actions_spec.js
+++ b/spec/frontend/reports/store/actions_spec.js
@@ -1,6 +1,6 @@
import MockAdapter from 'axios-mock-adapter';
-import testAction from 'spec/helpers/vuex_action_helper';
-import { TEST_HOST } from 'spec/test_constants';
+import testAction from 'helpers/vuex_action_helper';
+import { TEST_HOST } from 'helpers/test_constants';
import axios from '~/lib/utils/axios_utils';
import {
setEndpoint,
diff --git a/spec/javascripts/reports/store/mutations_spec.js b/spec/frontend/reports/store/mutations_spec.js
index 9446cd454ab..9446cd454ab 100644
--- a/spec/javascripts/reports/store/mutations_spec.js
+++ b/spec/frontend/reports/store/mutations_spec.js
diff --git a/spec/models/ci/pipeline_spec.rb b/spec/models/ci/pipeline_spec.rb
index d174fac29ce..458dce027a8 100644
--- a/spec/models/ci/pipeline_spec.rb
+++ b/spec/models/ci/pipeline_spec.rb
@@ -53,6 +53,29 @@ describe Ci::Pipeline, :mailer do
end
end
+ describe '#set_status' do
+ where(:from_status, :to_status) do
+ from_status_names = described_class.state_machines[:status].states.map(&:name)
+ to_status_names = from_status_names - [:created] # we never want to transition into created
+
+ from_status_names.product(to_status_names)
+ end
+
+ with_them do
+ it do
+ pipeline.status = from_status.to_s
+
+ if from_status != to_status
+ expect(pipeline.set_status(to_status.to_s))
+ .to eq(true)
+ else
+ expect(pipeline.set_status(to_status.to_s))
+ .to eq(false), "loopback transitions are not allowed"
+ end
+ end
+ end
+ end
+
describe '.processables' do
before do
create(:ci_build, name: 'build', pipeline: pipeline)
diff --git a/spec/models/ci/stage_spec.rb b/spec/models/ci/stage_spec.rb
index 3aeaa27abce..a1549532559 100644
--- a/spec/models/ci/stage_spec.rb
+++ b/spec/models/ci/stage_spec.rb
@@ -3,7 +3,8 @@
require 'spec_helper'
describe Ci::Stage, :models do
- let(:stage) { create(:ci_stage_entity) }
+ let_it_be(:pipeline) { create(:ci_empty_pipeline) }
+ let(:stage) { create(:ci_stage_entity, pipeline: pipeline, project: pipeline.project) }
it_behaves_like 'having unique enum values'
@@ -55,6 +56,29 @@ describe Ci::Stage, :models do
end
end
+ describe '#set_status' do
+ where(:from_status, :to_status) do
+ from_status_names = described_class.state_machines[:status].states.map(&:name)
+ to_status_names = from_status_names - [:created] # we never want to transition into created
+
+ from_status_names.product(to_status_names)
+ end
+
+ with_them do
+ it do
+ stage.status = from_status.to_s
+
+ if from_status != to_status
+ expect(stage.set_status(to_status.to_s))
+ .to eq(true)
+ else
+ expect(stage.set_status(to_status.to_s))
+ .to eq(false), "loopback transitions are not allowed"
+ end
+ end
+ end
+ end
+
describe '#update_status' do
context 'when stage objects needs to be updated' do
before do
diff --git a/spec/services/ci/pipeline_processing/atomic_processing_service/status_collection_spec.rb b/spec/services/ci/pipeline_processing/atomic_processing_service/status_collection_spec.rb
index b487730d07f..de3c7713ac8 100644
--- a/spec/services/ci/pipeline_processing/atomic_processing_service/status_collection_spec.rb
+++ b/spec/services/ci/pipeline_processing/atomic_processing_service/status_collection_spec.rb
@@ -18,7 +18,7 @@ describe Ci::PipelineProcessing::AtomicProcessingService::StatusCollection do
it 'does update existing status of processable' do
collection.set_processable_status(test_a.id, 'success', 100)
- expect(collection.status_for_names(['test-a'])).to eq('success')
+ expect(collection.status_for_names(['test-a'], dag: false)).to eq('success')
end
it 'ignores a missing processable' do
@@ -33,15 +33,18 @@ describe Ci::PipelineProcessing::AtomicProcessingService::StatusCollection do
end
describe '#status_for_names' do
- where(:names, :status) do
- %w[build-a] | 'success'
- %w[build-a build-b] | 'failed'
- %w[build-a test-a] | 'running'
+ where(:names, :status, :dag) do
+ %w[build-a] | 'success' | false
+ %w[build-a build-b] | 'failed' | false
+ %w[build-a test-a] | 'running' | false
+ %w[build-a] | 'success' | true
+ %w[build-a build-b] | 'failed' | true
+ %w[build-a test-a] | 'pending' | true
end
with_them do
it 'returns composite status of given names' do
- expect(collection.status_for_names(names)).to eq(status)
+ expect(collection.status_for_names(names, dag: dag)).to eq(status)
end
end
end
diff --git a/spec/services/ci/pipeline_processing/atomic_processing_service_spec.rb b/spec/services/ci/pipeline_processing/atomic_processing_service_spec.rb
index 13448ea759b..3b66ecff196 100644
--- a/spec/services/ci/pipeline_processing/atomic_processing_service_spec.rb
+++ b/spec/services/ci/pipeline_processing/atomic_processing_service_spec.rb
@@ -2,17 +2,19 @@
require 'spec_helper'
require_relative 'shared_processing_service.rb'
-# require_relative 'shared_processing_service_tests_with_yaml.rb'
+require_relative 'shared_processing_service_tests_with_yaml.rb'
describe Ci::PipelineProcessing::AtomicProcessingService do
before do
stub_feature_flags(ci_atomic_processing: true)
+
+ # This feature flag is implicit
+ # Atomic Processing does not process statuses differently
+ stub_feature_flags(ci_composite_status: true)
end
it_behaves_like 'Pipeline Processing Service'
- # TODO: This needs to be enabled. There is a different behavior when using `needs` depending on
- # a `manual` job. More info: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/29405#note_327520605
- # it_behaves_like 'Pipeline Processing Service Tests With Yaml'
+ it_behaves_like 'Pipeline Processing Service Tests With Yaml'
private
diff --git a/spec/services/ci/pipeline_processing/legacy_processing_service_spec.rb b/spec/services/ci/pipeline_processing/legacy_processing_service_spec.rb
index d4fb03cf643..fd491bf461b 100644
--- a/spec/services/ci/pipeline_processing/legacy_processing_service_spec.rb
+++ b/spec/services/ci/pipeline_processing/legacy_processing_service_spec.rb
@@ -7,11 +7,25 @@ require_relative 'shared_processing_service_tests_with_yaml.rb'
describe Ci::PipelineProcessing::LegacyProcessingService do
before do
stub_feature_flags(ci_atomic_processing: false)
- stub_feature_flags(ci_composite_status: false)
end
- it_behaves_like 'Pipeline Processing Service'
- it_behaves_like 'Pipeline Processing Service Tests With Yaml'
+ context 'when ci_composite_status is enabled' do
+ before do
+ stub_feature_flags(ci_composite_status: true)
+ end
+
+ it_behaves_like 'Pipeline Processing Service'
+ it_behaves_like 'Pipeline Processing Service Tests With Yaml'
+ end
+
+ context 'when ci_composite_status is disabled' do
+ before do
+ stub_feature_flags(ci_composite_status: false)
+ end
+
+ it_behaves_like 'Pipeline Processing Service'
+ it_behaves_like 'Pipeline Processing Service Tests With Yaml'
+ end
private
diff --git a/spec/services/ci/pipeline_processing/shared_processing_service.rb b/spec/services/ci/pipeline_processing/shared_processing_service.rb
index ffe5eacfc48..29fa43001ae 100644
--- a/spec/services/ci/pipeline_processing/shared_processing_service.rb
+++ b/spec/services/ci/pipeline_processing/shared_processing_service.rb
@@ -816,10 +816,10 @@ shared_examples 'Pipeline Processing Service' do
context 'when a needed job is skipped', :sidekiq_inline do
let!(:linux_build) { create_build('linux:build', stage: 'build', stage_idx: 0) }
let!(:linux_rspec) { create_build('linux:rspec', stage: 'test', stage_idx: 1) }
- let!(:deploy) do
- create_build('deploy', stage: 'deploy', stage_idx: 2, scheduling_type: :dag, needs: [
- create(:ci_build_need, name: 'linux:rspec')
- ])
+ let!(:deploy) { create_build('deploy', stage: 'deploy', stage_idx: 2, scheduling_type: :dag) }
+
+ before do
+ create(:ci_build_need, build: deploy, name: 'linux:build')
end
it 'skips the jobs depending on it' do
@@ -836,6 +836,23 @@ shared_examples 'Pipeline Processing Service' do
end
end
+ context 'when a needed job is manual', :sidekiq_inline do
+ let!(:linux_build) { create_build('linux:build', stage: 'build', stage_idx: 0, when: 'manual', allow_failure: true) }
+ let!(:deploy) { create_build('deploy', stage: 'deploy', stage_idx: 1, scheduling_type: :dag) }
+
+ before do
+ create(:ci_build_need, build: deploy, name: 'linux:build')
+ end
+
+ it 'makes deploy DAG to be waiting for optional manual to finish' do
+ expect(process_pipeline).to be_truthy
+
+ expect(stages).to eq(%w(skipped created))
+ expect(all_builds.manual).to contain_exactly(linux_build)
+ expect(all_builds.created).to contain_exactly(deploy)
+ end
+ end
+
private
def all_builds
diff --git a/spec/services/ci/pipeline_processing/shared_processing_service_tests_with_yaml.rb b/spec/services/ci/pipeline_processing/shared_processing_service_tests_with_yaml.rb
index ec3c10b3bb5..93f83f0ea3b 100644
--- a/spec/services/ci/pipeline_processing/shared_processing_service_tests_with_yaml.rb
+++ b/spec/services/ci/pipeline_processing/shared_processing_service_tests_with_yaml.rb
@@ -18,36 +18,40 @@ shared_context 'Pipeline Processing Service Tests With Yaml' do
project.add_developer(user)
end
- it 'follows transitions', :sidekiq_inline do
+ it 'follows transitions' do
expect(pipeline).to be_persisted
- check_expectation(test_file.dig('init', 'expect'))
+ Sidekiq::Worker.drain_all # ensure that all async jobs are executed
+ check_expectation(test_file.dig('init', 'expect'), "init")
- test_file['transitions'].each do |transition|
+ test_file['transitions'].each_with_index do |transition, idx|
event_on_jobs(transition['event'], transition['jobs'])
- check_expectation(transition['expect'])
+ Sidekiq::Worker.drain_all # ensure that all async jobs are executed
+ check_expectation(transition['expect'], "transition:#{idx}")
end
end
private
- def check_expectation(expectation)
- expectation.each do |key, value|
- case key
- when 'pipeline'
- expect(pipeline.reload.status).to eq(value)
- when 'stages'
- expect(pipeline.stages.pluck(:name, :status).to_h).to eq(value)
- when 'jobs'
- expect(pipeline.builds.latest.pluck(:name, :status).to_h).to eq(value)
- end
- end
+ def check_expectation(expectation, message)
+ expect(current_state.deep_stringify_keys).to eq(expectation), message
+ end
+
+ def current_state
+ # reload pipeline and all relations
+ pipeline.reload
+
+ {
+ pipeline: pipeline.status,
+ stages: pipeline.ordered_stages.pluck(:name, :status).to_h,
+ jobs: pipeline.statuses.latest.pluck(:name, :status).to_h
+ }
end
def event_on_jobs(event, job_names)
- builds = pipeline.builds.latest.where(name: job_names).to_a
- expect(builds.count).to eq(job_names.count) # ensure that we have the same counts
+ statuses = pipeline.statuses.latest.by_name(job_names).to_a
+ expect(statuses.count).to eq(job_names.count) # ensure that we have the same counts
- builds.each { |build| build.public_send("#{event}!") }
+ statuses.each { |status| status.public_send("#{event}!") }
end
end
end
diff --git a/spec/services/ci/pipeline_processing/test_cases/dag_test_manual_allow_failure_false.yml b/spec/services/ci/pipeline_processing/test_cases/dag_test_manual_allow_failure_false.yml
index 1a1412f2a11..1d61cd24f8c 100644
--- a/spec/services/ci/pipeline_processing/test_cases/dag_test_manual_allow_failure_false.yml
+++ b/spec/services/ci/pipeline_processing/test_cases/dag_test_manual_allow_failure_false.yml
@@ -24,9 +24,9 @@ transitions:
- event: enqueue
jobs: [test]
expect:
- pipeline: manual
+ pipeline: pending
stages:
- test: manual
+ test: pending
deploy: created
jobs:
test: pending
diff --git a/spec/services/ci/pipeline_processing/test_cases/dag_test_manual_allow_failure_true.yml b/spec/services/ci/pipeline_processing/test_cases/dag_test_manual_allow_failure_true.yml
index 39545617926..d8ca563b141 100644
--- a/spec/services/ci/pipeline_processing/test_cases/dag_test_manual_allow_failure_true.yml
+++ b/spec/services/ci/pipeline_processing/test_cases/dag_test_manual_allow_failure_true.yml
@@ -26,7 +26,7 @@ transitions:
expect:
pipeline: pending
stages:
- test: running
+ test: pending
deploy: created
jobs:
test: pending
diff --git a/spec/services/ci/pipeline_processing/test_cases/dag_test_manual_allow_failure_true_deploy_on_failure.yml b/spec/services/ci/pipeline_processing/test_cases/dag_test_manual_allow_failure_true_deploy_on_failure.yml
index 0c6a5a7e364..d375c6a49e0 100644
--- a/spec/services/ci/pipeline_processing/test_cases/dag_test_manual_allow_failure_true_deploy_on_failure.yml
+++ b/spec/services/ci/pipeline_processing/test_cases/dag_test_manual_allow_failure_true_deploy_on_failure.yml
@@ -27,7 +27,7 @@ transitions:
expect:
pipeline: pending
stages:
- test: running
+ test: pending
deploy: created
jobs:
test: pending
diff --git a/spec/services/ci/pipeline_processing/test_cases/stage_test_manual_allow_failure_false.yml b/spec/services/ci/pipeline_processing/test_cases/stage_test_manual_allow_failure_false.yml
index d37288b2075..2ffa35b56d7 100644
--- a/spec/services/ci/pipeline_processing/test_cases/stage_test_manual_allow_failure_false.yml
+++ b/spec/services/ci/pipeline_processing/test_cases/stage_test_manual_allow_failure_false.yml
@@ -23,9 +23,9 @@ transitions:
- event: enqueue
jobs: [test]
expect:
- pipeline: manual
+ pipeline: pending
stages:
- test: manual
+ test: pending
deploy: created
jobs:
test: pending
diff --git a/spec/services/ci/pipeline_processing/test_cases/stage_test_manual_allow_failure_true.yml b/spec/services/ci/pipeline_processing/test_cases/stage_test_manual_allow_failure_true.yml
index bac339cc58d..088fab5ca09 100644
--- a/spec/services/ci/pipeline_processing/test_cases/stage_test_manual_allow_failure_true.yml
+++ b/spec/services/ci/pipeline_processing/test_cases/stage_test_manual_allow_failure_true.yml
@@ -36,7 +36,7 @@ transitions:
expect:
pipeline: running
stages:
- test: running
+ test: pending
deploy: success
jobs:
test: pending
diff --git a/spec/services/ci/pipeline_processing/test_cases/stage_test_manual_allow_failure_true_deploy_on_failure.yml b/spec/services/ci/pipeline_processing/test_cases/stage_test_manual_allow_failure_true_deploy_on_failure.yml
index ab1b210848a..2b30316aef6 100644
--- a/spec/services/ci/pipeline_processing/test_cases/stage_test_manual_allow_failure_true_deploy_on_failure.yml
+++ b/spec/services/ci/pipeline_processing/test_cases/stage_test_manual_allow_failure_true_deploy_on_failure.yml
@@ -26,7 +26,7 @@ transitions:
expect:
pipeline: pending
stages:
- test: running
+ test: pending
deploy: skipped
jobs:
test: pending