summaryrefslogtreecommitdiff
path: root/app/assets/javascripts/pipeline_new
diff options
context:
space:
mode:
Diffstat (limited to 'app/assets/javascripts/pipeline_new')
-rw-r--r--app/assets/javascripts/pipeline_new/components/pipeline_new_form.vue164
-rw-r--r--app/assets/javascripts/pipeline_new/constants.js3
-rw-r--r--app/assets/javascripts/pipeline_new/index.js12
-rw-r--r--app/assets/javascripts/pipeline_new/utils/format_refs.js18
4 files changed, 146 insertions, 51 deletions
diff --git a/app/assets/javascripts/pipeline_new/components/pipeline_new_form.vue b/app/assets/javascripts/pipeline_new/components/pipeline_new_form.vue
index 6552665100a..f2d68054e80 100644
--- a/app/assets/javascripts/pipeline_new/components/pipeline_new_form.vue
+++ b/app/assets/javascripts/pipeline_new/components/pipeline_new_form.vue
@@ -12,14 +12,18 @@ import {
GlLink,
GlDropdown,
GlDropdownItem,
+ GlDropdownSectionHeader,
GlSearchBoxByType,
GlSprintf,
GlLoadingIcon,
} from '@gitlab/ui';
+import * as Sentry from '~/sentry/wrapper';
import { s__, __, n__ } from '~/locale';
import axios from '~/lib/utils/axios_utils';
import { redirectTo } from '~/lib/utils/url_utility';
-import { VARIABLE_TYPE, FILE_TYPE } from '../constants';
+import { VARIABLE_TYPE, FILE_TYPE, CONFIG_VARIABLES_TIMEOUT } from '../constants';
+import { backOff } from '~/lib/utils/common_utils';
+import httpStatusCodes from '~/lib/utils/http_status';
export default {
typeOptions: [
@@ -44,6 +48,7 @@ export default {
GlLink,
GlDropdown,
GlDropdownItem,
+ GlDropdownSectionHeader,
GlSearchBoxByType,
GlSprintf,
GlLoadingIcon,
@@ -57,11 +62,19 @@ export default {
type: String,
required: true,
},
+ defaultBranch: {
+ type: String,
+ required: true,
+ },
projectId: {
type: String,
required: true,
},
- refs: {
+ branches: {
+ type: Array,
+ required: true,
+ },
+ tags: {
type: Array,
required: true,
},
@@ -92,7 +105,9 @@ export default {
data() {
return {
searchTerm: '',
- refValue: this.refParam,
+ refValue: {
+ shortName: this.refParam,
+ },
form: {},
error: null,
warnings: [],
@@ -102,9 +117,21 @@ export default {
};
},
computed: {
- filteredRefs() {
- const lowerCasedSearchTerm = this.searchTerm.toLowerCase();
- return this.refs.filter(ref => ref.toLowerCase().includes(lowerCasedSearchTerm));
+ lowerCasedSearchTerm() {
+ return this.searchTerm.toLowerCase();
+ },
+ filteredBranches() {
+ return this.branches.filter(branch =>
+ branch.shortName.toLowerCase().includes(this.lowerCasedSearchTerm),
+ );
+ },
+ filteredTags() {
+ return this.tags.filter(tag =>
+ tag.shortName.toLowerCase().includes(this.lowerCasedSearchTerm),
+ );
+ },
+ hasTags() {
+ return this.tags.length > 0;
},
overMaxWarningsLimit() {
return this.totalWarnings > this.maxWarnings;
@@ -118,14 +145,27 @@ export default {
shouldShowWarning() {
return this.warnings.length > 0 && !this.isWarningDismissed;
},
+ refShortName() {
+ return this.refValue.shortName;
+ },
+ refFullName() {
+ return this.refValue.fullName;
+ },
variables() {
- return this.form[this.refValue]?.variables ?? [];
+ return this.form[this.refFullName]?.variables ?? [];
},
descriptions() {
- return this.form[this.refValue]?.descriptions ?? {};
+ return this.form[this.refFullName]?.descriptions ?? {};
},
},
created() {
+ // this is needed until we add support for ref type in url query strings
+ // ensure default branch is called with full ref on load
+ // https://gitlab.com/gitlab-org/gitlab/-/issues/287815
+ if (this.refValue.shortName === this.defaultBranch) {
+ this.refValue.fullName = `refs/heads/${this.refValue.shortName}`;
+ }
+
this.setRefSelected(this.refValue);
},
methods: {
@@ -168,19 +208,19 @@ export default {
setRefSelected(refValue) {
this.refValue = refValue;
- if (!this.form[refValue]) {
- this.fetchConfigVariables(refValue)
+ if (!this.form[this.refFullName]) {
+ this.fetchConfigVariables(this.refFullName || this.refShortName)
.then(({ descriptions, params }) => {
- Vue.set(this.form, refValue, {
+ Vue.set(this.form, this.refFullName, {
variables: [],
descriptions,
});
// Add default variables from yml
- this.setVariableParams(refValue, VARIABLE_TYPE, params);
+ this.setVariableParams(this.refFullName, VARIABLE_TYPE, params);
})
.catch(() => {
- Vue.set(this.form, refValue, {
+ Vue.set(this.form, this.refFullName, {
variables: [],
descriptions: {},
});
@@ -188,20 +228,19 @@ export default {
.finally(() => {
// Add/update variables, e.g. from query string
if (this.variableParams) {
- this.setVariableParams(refValue, VARIABLE_TYPE, this.variableParams);
+ this.setVariableParams(this.refFullName, VARIABLE_TYPE, this.variableParams);
}
if (this.fileParams) {
- this.setVariableParams(refValue, FILE_TYPE, this.fileParams);
+ this.setVariableParams(this.refFullName, FILE_TYPE, this.fileParams);
}
// Adds empty var at the end of the form
- this.addEmptyVariable(refValue);
+ this.addEmptyVariable(this.refFullName);
});
}
},
-
isSelected(ref) {
- return ref === this.refValue;
+ return ref.fullName === this.refValue.fullName;
},
removeVariable(index) {
this.variables.splice(index, 1);
@@ -209,34 +248,52 @@ export default {
canRemove(index) {
return index < this.variables.length - 1;
},
-
fetchConfigVariables(refValue) {
- if (gon?.features?.newPipelineFormPrefilledVars) {
- this.isLoading = true;
+ if (!gon?.features?.newPipelineFormPrefilledVars) {
+ return Promise.resolve({ params: {}, descriptions: {} });
+ }
+
+ this.isLoading = true;
- return axios
+ return backOff((next, stop) => {
+ axios
.get(this.configVariablesPath, {
params: {
sha: refValue,
},
})
- .then(({ data }) => {
- const params = {};
- const descriptions = {};
+ .then(({ data, status }) => {
+ if (status === httpStatusCodes.NO_CONTENT) {
+ next();
+ } else {
+ this.isLoading = false;
+ stop(data);
+ }
+ })
+ .catch(error => {
+ stop(error);
+ });
+ }, CONFIG_VARIABLES_TIMEOUT)
+ .then(data => {
+ const params = {};
+ const descriptions = {};
- Object.entries(data).forEach(([key, { value, description }]) => {
- if (description !== null) {
- params[key] = value;
- descriptions[key] = description;
- }
- });
+ Object.entries(data).forEach(([key, { value, description }]) => {
+ if (description !== null) {
+ params[key] = value;
+ descriptions[key] = description;
+ }
+ });
- this.isLoading = false;
+ return { params, descriptions };
+ })
+ .catch(error => {
+ this.isLoading = false;
- return { params, descriptions };
- });
- }
- return Promise.resolve({ params: {}, descriptions: {} });
+ Sentry.captureException(error);
+
+ return { params: {}, descriptions: {} };
+ });
},
createPipeline() {
const filteredVariables = this.variables
@@ -249,7 +306,9 @@ export default {
return axios
.post(this.pipelinesPath, {
- ref: this.refValue,
+ // send shortName as fall back for query params
+ // https://gitlab.com/gitlab-org/gitlab/-/issues/287815
+ ref: this.refValue.fullName || this.refShortName,
variables_attributes: filteredVariables,
})
.then(({ data }) => {
@@ -307,20 +366,29 @@ export default {
</details>
</gl-alert>
<gl-form-group :label="s__('Pipeline|Run for')">
- <gl-dropdown :text="refValue" block>
- <gl-search-box-by-type
- v-model.trim="searchTerm"
- :placeholder="__('Search branches and tags')"
- />
+ <gl-dropdown :text="refShortName" block>
+ <gl-search-box-by-type v-model.trim="searchTerm" :placeholder="__('Search refs')" />
+ <gl-dropdown-section-header>{{ __('Branches') }}</gl-dropdown-section-header>
+ <gl-dropdown-item
+ v-for="branch in filteredBranches"
+ :key="branch.fullName"
+ class="gl-font-monospace"
+ is-check-item
+ :is-checked="isSelected(branch)"
+ @click="setRefSelected(branch)"
+ >
+ {{ branch.shortName }}
+ </gl-dropdown-item>
+ <gl-dropdown-section-header v-if="hasTags">{{ __('Tags') }}</gl-dropdown-section-header>
<gl-dropdown-item
- v-for="(ref, index) in filteredRefs"
- :key="index"
+ v-for="tag in filteredTags"
+ :key="tag.fullName"
class="gl-font-monospace"
is-check-item
- :is-checked="isSelected(ref)"
- @click="setRefSelected(ref)"
+ :is-checked="isSelected(tag)"
+ @click="setRefSelected(tag)"
>
- {{ ref }}
+ {{ tag.shortName }}
</gl-dropdown-item>
</gl-dropdown>
@@ -353,7 +421,7 @@ export default {
:placeholder="s__('CiVariables|Input variable key')"
:class="$options.formElementClasses"
data-testid="pipeline-form-ci-variable-key"
- @change="addEmptyVariable(refValue)"
+ @change="addEmptyVariable(refFullName)"
/>
<gl-form-input
v-model="variable.value"
diff --git a/app/assets/javascripts/pipeline_new/constants.js b/app/assets/javascripts/pipeline_new/constants.js
index b4ab1143f60..004bbe7daf4 100644
--- a/app/assets/javascripts/pipeline_new/constants.js
+++ b/app/assets/javascripts/pipeline_new/constants.js
@@ -1,2 +1,5 @@
export const VARIABLE_TYPE = 'env_var';
export const FILE_TYPE = 'file';
+export const CONFIG_VARIABLES_TIMEOUT = 5000;
+export const BRANCH_REF_TYPE = 'branch';
+export const TAG_REF_TYPE = 'tag';
diff --git a/app/assets/javascripts/pipeline_new/index.js b/app/assets/javascripts/pipeline_new/index.js
index ff4f677654e..0b85184ec90 100644
--- a/app/assets/javascripts/pipeline_new/index.js
+++ b/app/assets/javascripts/pipeline_new/index.js
@@ -1,5 +1,6 @@
import Vue from 'vue';
import PipelineNewForm from './components/pipeline_new_form.vue';
+import formatRefs from './utils/format_refs';
export default () => {
const el = document.getElementById('js-new-pipeline');
@@ -7,17 +8,20 @@ export default () => {
projectId,
pipelinesPath,
configVariablesPath,
+ defaultBranch,
refParam,
varParam,
fileParam,
- refNames,
+ branchRefs,
+ tagRefs,
settingsLink,
maxWarnings,
} = el?.dataset;
const variableParams = JSON.parse(varParam);
const fileParams = JSON.parse(fileParam);
- const refs = JSON.parse(refNames);
+ const branches = formatRefs(JSON.parse(branchRefs), 'branch');
+ const tags = formatRefs(JSON.parse(tagRefs), 'tag');
return new Vue({
el,
@@ -27,10 +31,12 @@ export default () => {
projectId,
pipelinesPath,
configVariablesPath,
+ defaultBranch,
refParam,
variableParams,
fileParams,
- refs,
+ branches,
+ tags,
settingsLink,
maxWarnings: Number(maxWarnings),
},
diff --git a/app/assets/javascripts/pipeline_new/utils/format_refs.js b/app/assets/javascripts/pipeline_new/utils/format_refs.js
new file mode 100644
index 00000000000..e217cd25413
--- /dev/null
+++ b/app/assets/javascripts/pipeline_new/utils/format_refs.js
@@ -0,0 +1,18 @@
+import { BRANCH_REF_TYPE, TAG_REF_TYPE } from '../constants';
+
+export default (refs, type) => {
+ let fullName;
+
+ return refs.map(ref => {
+ if (type === BRANCH_REF_TYPE) {
+ fullName = `refs/heads/${ref}`;
+ } else if (type === TAG_REF_TYPE) {
+ fullName = `refs/tags/${ref}`;
+ }
+
+ return {
+ shortName: ref,
+ fullName,
+ };
+ });
+};