Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2021-07-20 12:55:51 +0300
committerGitLab Bot <gitlab-bot@gitlab.com>2021-07-20 12:55:51 +0300
commite8d2c2579383897a1dd7f9debd359abe8ae8373d (patch)
treec42be41678c2586d49a75cabce89322082698334 /app/assets/javascripts/pipeline_editor
parentfc845b37ec3a90aaa719975f607740c22ba6a113 (diff)
Add latest changes from gitlab-org/gitlab@14-1-stable-eev14.1.0-rc42
Diffstat (limited to 'app/assets/javascripts/pipeline_editor')
-rw-r--r--app/assets/javascripts/pipeline_editor/components/commit/commit_form.vue1
-rw-r--r--app/assets/javascripts/pipeline_editor/components/editor/ci_config_merged_preview.vue6
-rw-r--r--app/assets/javascripts/pipeline_editor/components/editor/ci_editor_header.vue38
-rw-r--r--app/assets/javascripts/pipeline_editor/components/editor/text_editor.vue10
-rw-r--r--app/assets/javascripts/pipeline_editor/components/file_nav/branch_switcher.vue8
-rw-r--r--app/assets/javascripts/pipeline_editor/components/header/pipeline_status.vue1
-rw-r--r--app/assets/javascripts/pipeline_editor/components/header/validation_segment.vue2
-rw-r--r--app/assets/javascripts/pipeline_editor/components/pipeline_editor_tabs.vue3
-rw-r--r--app/assets/javascripts/pipeline_editor/constants.js10
-rw-r--r--app/assets/javascripts/pipeline_editor/graphql/mutations/update_commit_sha.mutation.graphql3
-rw-r--r--app/assets/javascripts/pipeline_editor/graphql/queries/blob_content.graphql12
-rw-r--r--app/assets/javascripts/pipeline_editor/graphql/queries/ci_config.graphql4
-rw-r--r--app/assets/javascripts/pipeline_editor/graphql/queries/latest_commit_sha.query.graphql12
-rw-r--r--app/assets/javascripts/pipeline_editor/graphql/resolvers.js24
-rw-r--r--app/assets/javascripts/pipeline_editor/pipeline_editor_app.vue110
15 files changed, 189 insertions, 55 deletions
diff --git a/app/assets/javascripts/pipeline_editor/components/commit/commit_form.vue b/app/assets/javascripts/pipeline_editor/components/commit/commit_form.vue
index f6e88738002..f1fe8cf10fd 100644
--- a/app/assets/javascripts/pipeline_editor/components/commit/commit_form.vue
+++ b/app/assets/javascripts/pipeline_editor/components/commit/commit_form.vue
@@ -103,6 +103,7 @@ export default {
v-model="targetBranch"
class="gl-font-monospace!"
required
+ data-qa-selector="target_branch_field"
/>
<gl-form-checkbox
v-if="!isCurrentBranchTarget"
diff --git a/app/assets/javascripts/pipeline_editor/components/editor/ci_config_merged_preview.vue b/app/assets/javascripts/pipeline_editor/components/editor/ci_config_merged_preview.vue
index 455990f2791..853e839a7ab 100644
--- a/app/assets/javascripts/pipeline_editor/components/editor/ci_config_merged_preview.vue
+++ b/app/assets/javascripts/pipeline_editor/components/editor/ci_config_merged_preview.vue
@@ -2,14 +2,14 @@
import { GlIcon } from '@gitlab/ui';
import { uniqueId } from 'lodash';
import { s__ } from '~/locale';
-import EditorLite from '~/vue_shared/components/editor_lite.vue';
+import SourceEditor from '~/vue_shared/components/source_editor.vue';
export default {
i18n: {
viewOnlyMessage: s__('Pipelines|Merged YAML is view only'),
},
components: {
- EditorLite,
+ SourceEditor,
GlIcon,
},
inject: ['ciConfigPath'],
@@ -41,7 +41,7 @@ export default {
{{ $options.i18n.viewOnlyMessage }}
</div>
<div class="gl-mt-3 gl-border-solid gl-border-gray-100 gl-border-1">
- <editor-lite
+ <source-editor
ref="editor"
:value="mergedYaml"
:file-name="ciConfigPath"
diff --git a/app/assets/javascripts/pipeline_editor/components/editor/ci_editor_header.vue b/app/assets/javascripts/pipeline_editor/components/editor/ci_editor_header.vue
new file mode 100644
index 00000000000..b4e9ab81d38
--- /dev/null
+++ b/app/assets/javascripts/pipeline_editor/components/editor/ci_editor_header.vue
@@ -0,0 +1,38 @@
+<script>
+import { GlButton } from '@gitlab/ui';
+import { __ } from '~/locale';
+import Tracking from '~/tracking';
+import { pipelineEditorTrackingOptions, TEMPLATE_REPOSITORY_URL } from '../../constants';
+
+export default {
+ i18n: {
+ browseTemplates: __('Browse templates'),
+ },
+ TEMPLATE_REPOSITORY_URL,
+ components: {
+ GlButton,
+ },
+ mixins: [Tracking.mixin()],
+ methods: {
+ trackTemplateBrowsing() {
+ const { label, actions } = pipelineEditorTrackingOptions;
+
+ this.track(actions.browse_templates, { label });
+ },
+ },
+};
+</script>
+
+<template>
+ <div class="gl-bg-gray-10 gl-p-3 gl-border-solid gl-border-gray-100 gl-border-1">
+ <gl-button
+ :href="$options.TEMPLATE_REPOSITORY_URL"
+ size="small"
+ icon="external-link"
+ target="_blank"
+ @click="trackTemplateBrowsing"
+ >
+ {{ $options.i18n.browseTemplates }}
+ </gl-button>
+ </div>
+</template>
diff --git a/app/assets/javascripts/pipeline_editor/components/editor/text_editor.vue b/app/assets/javascripts/pipeline_editor/components/editor/text_editor.vue
index d373f74a5c4..77ede396496 100644
--- a/app/assets/javascripts/pipeline_editor/components/editor/text_editor.vue
+++ b/app/assets/javascripts/pipeline_editor/components/editor/text_editor.vue
@@ -1,13 +1,13 @@
<script>
import { EDITOR_READY_EVENT } from '~/editor/constants';
-import { CiSchemaExtension } from '~/editor/extensions/editor_ci_schema_ext';
-import EditorLite from '~/vue_shared/components/editor_lite.vue';
+import { CiSchemaExtension } from '~/editor/extensions/source_editor_ci_schema_ext';
+import SourceEditor from '~/vue_shared/components/source_editor.vue';
import glFeatureFlagMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
import getCommitSha from '../../graphql/queries/client/commit_sha.graphql';
export default {
components: {
- EditorLite,
+ SourceEditor,
},
mixins: [glFeatureFlagMixin()],
inject: ['ciConfigPath', 'projectPath', 'projectNamespace', 'defaultBranch'],
@@ -43,8 +43,8 @@ export default {
};
</script>
<template>
- <div class="gl-border-solid gl-border-gray-100 gl-border-1">
- <editor-lite
+ <div class="gl-border-solid gl-border-gray-100 gl-border-1 gl-border-t-none!">
+ <source-editor
ref="editor"
:file-name="ciConfigPath"
v-bind="$attrs"
diff --git a/app/assets/javascripts/pipeline_editor/components/file_nav/branch_switcher.vue b/app/assets/javascripts/pipeline_editor/components/file_nav/branch_switcher.vue
index 05b87abecd5..ee6d4ff7c4d 100644
--- a/app/assets/javascripts/pipeline_editor/components/file_nav/branch_switcher.vue
+++ b/app/assets/javascripts/pipeline_editor/components/file_nav/branch_switcher.vue
@@ -158,6 +158,12 @@ export default {
const updatedPath = setUrlParams({ branch_name: newBranch });
historyPushState(updatedPath);
+ this.$emit('updateCommitSha', { newBranch });
+
+ // refetching the content will cause a lot of components to re-render,
+ // including the text editor which uses the commit sha to register the CI schema
+ // so we need to make sure the commit sha is updated first
+ await this.$nextTick();
this.$emit('refetchContent');
},
async setSearchTerm(newSearchTerm) {
@@ -205,6 +211,7 @@ export default {
:header-text="$options.i18n.dropdownHeader"
:text="currentBranch"
icon="branch"
+ data-qa-selector="branch_selector_button"
>
<gl-search-box-by-type :debounce="$options.inputDebounce" @input="setSearchTerm" />
<gl-dropdown-section-header>
@@ -222,6 +229,7 @@ export default {
:key="branch"
:is-checked="currentBranch === branch"
:is-check-item="true"
+ data-qa-selector="menu_branch_button"
@click="selectBranch(branch)"
>
{{ branch }}
diff --git a/app/assets/javascripts/pipeline_editor/components/header/pipeline_status.vue b/app/assets/javascripts/pipeline_editor/components/header/pipeline_status.vue
index 368a026bdaa..6af3361e7e6 100644
--- a/app/assets/javascripts/pipeline_editor/components/header/pipeline_status.vue
+++ b/app/assets/javascripts/pipeline_editor/components/header/pipeline_status.vue
@@ -66,6 +66,7 @@ export default {
},
data() {
return {
+ commitSha: '',
hasError: false,
};
},
diff --git a/app/assets/javascripts/pipeline_editor/components/header/validation_segment.vue b/app/assets/javascripts/pipeline_editor/components/header/validation_segment.vue
index d1534655a00..8bffd893473 100644
--- a/app/assets/javascripts/pipeline_editor/components/header/validation_segment.vue
+++ b/app/assets/javascripts/pipeline_editor/components/header/validation_segment.vue
@@ -87,7 +87,7 @@ export default {
<template>
<div>
<template v-if="isLoading">
- <gl-loading-icon inline />
+ <gl-loading-icon size="sm" inline />
{{ $options.i18n.loading }}
</template>
diff --git a/app/assets/javascripts/pipeline_editor/components/pipeline_editor_tabs.vue b/app/assets/javascripts/pipeline_editor/components/pipeline_editor_tabs.vue
index c3dcc00af6e..e463fcf379d 100644
--- a/app/assets/javascripts/pipeline_editor/components/pipeline_editor_tabs.vue
+++ b/app/assets/javascripts/pipeline_editor/components/pipeline_editor_tabs.vue
@@ -16,6 +16,7 @@ import {
} from '../constants';
import getAppStatus from '../graphql/queries/client/app_status.graphql';
import CiConfigMergedPreview from './editor/ci_config_merged_preview.vue';
+import CiEditorHeader from './editor/ci_editor_header.vue';
import TextEditor from './editor/text_editor.vue';
import CiLint from './lint/ci_lint.vue';
import EditorTab from './ui/editor_tab.vue';
@@ -49,6 +50,7 @@ export default {
},
components: {
CiConfigMergedPreview,
+ CiEditorHeader,
CiLint,
EditorTab,
GlAlert,
@@ -107,6 +109,7 @@ export default {
data-testid="editor-tab"
@click="setCurrentTab($options.tabConstants.CREATE_TAB)"
>
+ <ci-editor-header />
<text-editor :value="ciFileContent" v-on="$listeners" />
</editor-tab>
<editor-tab
diff --git a/app/assets/javascripts/pipeline_editor/constants.js b/app/assets/javascripts/pipeline_editor/constants.js
index 1467abd7289..d05b06d16db 100644
--- a/app/assets/javascripts/pipeline_editor/constants.js
+++ b/app/assets/javascripts/pipeline_editor/constants.js
@@ -33,3 +33,13 @@ export const BRANCH_PAGINATION_LIMIT = 20;
export const BRANCH_SEARCH_DEBOUNCE = '500';
export const STARTER_TEMPLATE_NAME = 'Getting-Started';
+
+export const pipelineEditorTrackingOptions = {
+ label: 'pipeline_editor',
+ actions: {
+ browse_templates: 'browse_templates',
+ },
+};
+
+export const TEMPLATE_REPOSITORY_URL =
+ 'https://gitlab.com/gitlab-org/gitlab-foss/tree/master/lib/gitlab/ci/templates';
diff --git a/app/assets/javascripts/pipeline_editor/graphql/mutations/update_commit_sha.mutation.graphql b/app/assets/javascripts/pipeline_editor/graphql/mutations/update_commit_sha.mutation.graphql
new file mode 100644
index 00000000000..dce17cad808
--- /dev/null
+++ b/app/assets/javascripts/pipeline_editor/graphql/mutations/update_commit_sha.mutation.graphql
@@ -0,0 +1,3 @@
+mutation updateCommitSha($commitSha: String) {
+ updateCommitSha(commitSha: $commitSha) @client
+}
diff --git a/app/assets/javascripts/pipeline_editor/graphql/queries/blob_content.graphql b/app/assets/javascripts/pipeline_editor/graphql/queries/blob_content.graphql
index 9f1b5b13088..5500244b430 100644
--- a/app/assets/javascripts/pipeline_editor/graphql/queries/blob_content.graphql
+++ b/app/assets/javascripts/pipeline_editor/graphql/queries/blob_content.graphql
@@ -1,5 +1,11 @@
-query getBlobContent($projectPath: ID!, $path: String, $ref: String!) {
- blobContent(projectPath: $projectPath, path: $path, ref: $ref) @client {
- rawData
+query getBlobContent($projectPath: ID!, $path: String!, $ref: String) {
+ project(fullPath: $projectPath) {
+ repository {
+ blobs(paths: [$path], ref: $ref) {
+ nodes {
+ rawBlob
+ }
+ }
+ }
}
}
diff --git a/app/assets/javascripts/pipeline_editor/graphql/queries/ci_config.graphql b/app/assets/javascripts/pipeline_editor/graphql/queries/ci_config.graphql
index 30c18a96536..df7de6a1f54 100644
--- a/app/assets/javascripts/pipeline_editor/graphql/queries/ci_config.graphql
+++ b/app/assets/javascripts/pipeline_editor/graphql/queries/ci_config.graphql
@@ -1,7 +1,7 @@
#import "~/pipelines/graphql/fragments/pipeline_stages_connection.fragment.graphql"
-query getCiConfigData($projectPath: ID!, $content: String!) {
- ciConfig(projectPath: $projectPath, content: $content) {
+query getCiConfigData($projectPath: ID!, $sha: String, $content: String!) {
+ ciConfig(projectPath: $projectPath, sha: $sha, content: $content) {
errors
mergedYaml
status
diff --git a/app/assets/javascripts/pipeline_editor/graphql/queries/latest_commit_sha.query.graphql b/app/assets/javascripts/pipeline_editor/graphql/queries/latest_commit_sha.query.graphql
new file mode 100644
index 00000000000..219c23bb22b
--- /dev/null
+++ b/app/assets/javascripts/pipeline_editor/graphql/queries/latest_commit_sha.query.graphql
@@ -0,0 +1,12 @@
+query getLatestCommitSha($projectPath: ID!, $ref: String) {
+ project(fullPath: $projectPath) {
+ pipelines(ref: $ref) {
+ nodes {
+ id
+ sha
+ path
+ commitPath
+ }
+ }
+ }
+}
diff --git a/app/assets/javascripts/pipeline_editor/graphql/resolvers.js b/app/assets/javascripts/pipeline_editor/graphql/resolvers.js
index 8cead7f3315..2bec2006e95 100644
--- a/app/assets/javascripts/pipeline_editor/graphql/resolvers.js
+++ b/app/assets/javascripts/pipeline_editor/graphql/resolvers.js
@@ -1,20 +1,10 @@
import produce from 'immer';
-import Api from '~/api';
import axios from '~/lib/utils/axios_utils';
+import getCommitShaQuery from './queries/client/commit_sha.graphql';
import getCurrentBranchQuery from './queries/client/current_branch.graphql';
import getLastCommitBranchQuery from './queries/client/last_commit_branch.query.graphql';
export const resolvers = {
- Query: {
- blobContent(_, { projectPath, path, ref }) {
- return {
- __typename: 'BlobContent',
- rawData: Api.getRawFile(projectPath, path, { ref }).then(({ data }) => {
- return data;
- }),
- };
- },
- },
Mutation: {
lintCI: (_, { endpoint, content, dry_run }) => {
return axios.post(endpoint, { content, dry_run }).then(({ data }) => ({
@@ -42,7 +32,15 @@ export const resolvers = {
__typename: 'CiLintContent',
}));
},
- updateCurrentBranch: (_, { currentBranch = undefined }, { cache }) => {
+ updateCommitSha: (_, { commitSha }, { cache }) => {
+ cache.writeQuery({
+ query: getCommitShaQuery,
+ data: produce(cache.readQuery({ query: getCommitShaQuery }), (draftData) => {
+ draftData.commitSha = commitSha;
+ }),
+ });
+ },
+ updateCurrentBranch: (_, { currentBranch }, { cache }) => {
cache.writeQuery({
query: getCurrentBranchQuery,
data: produce(cache.readQuery({ query: getCurrentBranchQuery }), (draftData) => {
@@ -50,7 +48,7 @@ export const resolvers = {
}),
});
},
- updateLastCommitBranch: (_, { lastCommitBranch = undefined }, { cache }) => {
+ updateLastCommitBranch: (_, { lastCommitBranch }, { cache }) => {
cache.writeQuery({
query: getLastCommitBranchQuery,
data: produce(cache.readQuery({ query: getLastCommitBranchQuery }), (draftData) => {
diff --git a/app/assets/javascripts/pipeline_editor/pipeline_editor_app.vue b/app/assets/javascripts/pipeline_editor/pipeline_editor_app.vue
index c24e6523352..0e8a6805a59 100644
--- a/app/assets/javascripts/pipeline_editor/pipeline_editor_app.vue
+++ b/app/assets/javascripts/pipeline_editor/pipeline_editor_app.vue
@@ -1,7 +1,7 @@
<script>
import { GlLoadingIcon } from '@gitlab/ui';
import { fetchPolicies } from '~/lib/graphql';
-import httpStatusCodes from '~/lib/utils/http_status';
+import { queryToObject } from '~/lib/utils/url_utility';
import { s__ } from '~/locale';
import { unwrapStagesWithNeeds } from '~/pipelines/components/unwrapping_utils';
@@ -16,12 +16,15 @@ import {
LOAD_FAILURE_UNKNOWN,
STARTER_TEMPLATE_NAME,
} from './constants';
+import updateCommitShaMutation from './graphql/mutations/update_commit_sha.mutation.graphql';
import getBlobContent from './graphql/queries/blob_content.graphql';
import getCiConfigData from './graphql/queries/ci_config.graphql';
import getAppStatus from './graphql/queries/client/app_status.graphql';
+import getCommitSha from './graphql/queries/client/commit_sha.graphql';
import getCurrentBranch from './graphql/queries/client/current_branch.graphql';
import getIsNewCiConfigFile from './graphql/queries/client/is_new_ci_config_file.graphql';
import getTemplate from './graphql/queries/get_starter_template.query.graphql';
+import getLatestCommitShaQuery from './graphql/queries/latest_commit_sha.query.graphql';
import PipelineEditorHome from './pipeline_editor_home.vue';
export default {
@@ -42,6 +45,7 @@ export default {
},
data() {
return {
+ starterTemplateName: STARTER_TEMPLATE_NAME,
ciConfigData: {},
failureType: null,
failureReasons: [],
@@ -76,22 +80,40 @@ export default {
};
},
update(data) {
- return data?.blobContent?.rawData;
+ return data?.project?.repository?.blobs?.nodes[0]?.rawBlob;
},
result({ data }) {
- const fileContent = data?.blobContent?.rawData ?? '';
+ const nodes = data?.project?.repository?.blobs?.nodes;
+ if (!nodes) {
+ this.reportFailure(LOAD_FAILURE_UNKNOWN);
+ } else {
+ const rawBlob = nodes[0]?.rawBlob;
+ const fileContent = rawBlob ?? '';
- this.lastCommittedContent = fileContent;
- this.currentCiFileContent = fileContent;
+ this.lastCommittedContent = fileContent;
+ this.currentCiFileContent = fileContent;
- // make sure to reset the start screen flag during a refetch
- // e.g. when switching branches
- if (fileContent.length) {
- this.showStartScreen = false;
+ // If rawBlob is defined and returns a string, it means that there is
+ // a CI config file with empty content. If `rawBlob` is not defined
+ // at all, it means there was no file found.
+ const hasCIFile = rawBlob === '' || fileContent.length > 0;
+
+ if (!fileContent.length) {
+ this.setAppStatus(EDITOR_APP_STATUS_EMPTY);
+ }
+
+ if (!hasCIFile) {
+ this.showStartScreen = true;
+ } else if (fileContent.length) {
+ // If the file content is > 0, then we make sure to reset the
+ // start screen flag during a refetch
+ // e.g. when switching branches
+ this.showStartScreen = false;
+ }
}
},
- error(error) {
- this.handleBlobContentError(error);
+ error() {
+ this.reportFailure(LOAD_FAILURE_UNKNOWN);
},
watchLoading(isLoading) {
if (isLoading) {
@@ -107,6 +129,7 @@ export default {
variables() {
return {
projectPath: this.projectFullPath,
+ sha: this.commitSha,
content: this.currentCiFileContent,
};
},
@@ -132,6 +155,9 @@ export default {
appStatus: {
query: getAppStatus,
},
+ commitSha: {
+ query: getCommitSha,
+ },
currentBranch: {
query: getCurrentBranch,
},
@@ -143,7 +169,7 @@ export default {
variables() {
return {
projectPath: this.projectFullPath,
- templateName: STARTER_TEMPLATE_NAME,
+ templateName: this.starterTemplateName,
};
},
skip({ isNewCiConfigFile }) {
@@ -186,23 +212,10 @@ export default {
}
},
},
+ mounted() {
+ this.loadTemplateFromURL();
+ },
methods: {
- handleBlobContentError(error = {}) {
- const { networkError } = error;
-
- const { response } = networkError;
- // 404 for missing CI file
- // 400 for blank projects with no repository
- if (
- response?.status === httpStatusCodes.NOT_FOUND ||
- response?.status === httpStatusCodes.BAD_REQUEST
- ) {
- this.setAppStatus(EDITOR_APP_STATUS_EMPTY);
- this.showStartScreen = true;
- } else {
- this.reportFailure(LOAD_FAILURE_UNKNOWN);
- }
- },
hideFailure() {
this.showFailure = false;
},
@@ -244,6 +257,38 @@ export default {
updateCiConfig(ciFileContent) {
this.currentCiFileContent = ciFileContent;
},
+ async updateCommitSha({ newBranch }) {
+ let fetchResults;
+
+ try {
+ fetchResults = await this.$apollo.query({
+ query: getLatestCommitShaQuery,
+ variables: {
+ projectPath: this.projectFullPath,
+ ref: newBranch,
+ },
+ });
+ } catch {
+ this.showFetchError();
+ return;
+ }
+
+ if (fetchResults.errors?.length > 0) {
+ this.showFetchError();
+ return;
+ }
+
+ const pipelineNodes = fetchResults?.data?.project?.pipelines?.nodes ?? [];
+ if (pipelineNodes.length === 0) {
+ return;
+ }
+
+ const commitSha = pipelineNodes[0].sha;
+ this.$apollo.mutate({
+ mutation: updateCommitShaMutation,
+ variables: { commitSha },
+ });
+ },
updateOnCommit({ type }) {
this.reportSuccess(type);
@@ -257,6 +302,14 @@ export default {
// if the user has made changes to the file that are unsaved.
this.lastCommittedContent = this.currentCiFileContent;
},
+ loadTemplateFromURL() {
+ const templateName = queryToObject(window.location.search)?.template;
+
+ if (templateName) {
+ this.starterTemplateName = templateName;
+ this.setNewEmptyCiConfigFile();
+ }
+ },
},
};
</script>
@@ -288,6 +341,7 @@ export default {
@showError="showErrorAlert"
@refetchContent="refetchContent"
@updateCiConfig="updateCiConfig"
+ @updateCommitSha="updateCommitSha"
/>
<confirm-unsaved-changes-dialog :has-unsaved-changes="hasUnsavedChanges" />
</div>