diff options
Diffstat (limited to 'app/assets/javascripts/pipeline_editor')
16 files changed, 233 insertions, 141 deletions
diff --git a/app/assets/javascripts/pipeline_editor/components/code_snippet_alert/constants.js b/app/assets/javascripts/pipeline_editor/components/code_snippet_alert/constants.js index 582fdfea6c9..e4fd423249b 100644 --- a/app/assets/javascripts/pipeline_editor/components/code_snippet_alert/constants.js +++ b/app/assets/javascripts/pipeline_editor/components/code_snippet_alert/constants.js @@ -2,10 +2,16 @@ import { helpPagePath } from '~/helpers/help_page_helper'; export const CODE_SNIPPET_SOURCE_URL_PARAM = 'code_snippet_copied_from'; export const CODE_SNIPPET_SOURCE_API_FUZZING = 'api_fuzzing'; -export const CODE_SNIPPET_SOURCES = [CODE_SNIPPET_SOURCE_API_FUZZING]; +export const CODE_SNIPPET_SOURCE_DAST = 'dast'; + +export const CODE_SNIPPET_SOURCES = [CODE_SNIPPET_SOURCE_API_FUZZING, CODE_SNIPPET_SOURCE_DAST]; export const CODE_SNIPPET_SOURCE_SETTINGS = { [CODE_SNIPPET_SOURCE_API_FUZZING]: { datasetKey: 'apiFuzzingConfigurationPath', docsPath: helpPagePath('user/application_security/api_fuzzing/index'), }, + [CODE_SNIPPET_SOURCE_DAST]: { + datasetKey: 'dastConfigurationPath', + docsPath: helpPagePath('user/application_security/dast/index'), + }, }; diff --git a/app/assets/javascripts/pipeline_editor/components/commit/commit_section.vue b/app/assets/javascripts/pipeline_editor/components/commit/commit_section.vue index 567164cb0ee..8f4894a0bde 100644 --- a/app/assets/javascripts/pipeline_editor/components/commit/commit_section.vue +++ b/app/assets/javascripts/pipeline_editor/components/commit/commit_section.vue @@ -8,6 +8,8 @@ import { COMMIT_SUCCESS, } from '../../constants'; import commitCIFile from '../../graphql/mutations/commit_ci_file.mutation.graphql'; +import updateCurrentBranchMutation from '../../graphql/mutations/update_current_branch.mutation.graphql'; +import updateLastCommitBranchMutation from '../../graphql/mutations/update_last_commit_branch.mutation.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'; @@ -113,6 +115,8 @@ export default { this.redirectToNewMergeRequest(targetBranch); } else { this.$emit('commit', { type: COMMIT_SUCCESS }); + this.updateLastCommitBranch(targetBranch); + this.updateCurrentBranch(targetBranch); } } catch (error) { this.$emit('showError', { type: COMMIT_FAILURE, reasons: [error?.message] }); @@ -123,6 +127,18 @@ export default { onCommitCancel() { this.$emit('resetContent'); }, + updateCurrentBranch(currentBranch) { + this.$apollo.mutate({ + mutation: updateCurrentBranchMutation, + variables: { currentBranch }, + }); + }, + updateLastCommitBranch(lastCommitBranch) { + this.$apollo.mutate({ + mutation: updateLastCommitBranchMutation, + variables: { lastCommitBranch }, + }); + }, }, }; </script> diff --git a/app/assets/javascripts/pipeline_editor/components/drawer/cards/first_pipeline_card.vue b/app/assets/javascripts/pipeline_editor/components/drawer/cards/first_pipeline_card.vue index 22c1563350d..a8ad56ab6a5 100644 --- a/app/assets/javascripts/pipeline_editor/components/drawer/cards/first_pipeline_card.vue +++ b/app/assets/javascripts/pipeline_editor/components/drawer/cards/first_pipeline_card.vue @@ -1,20 +1,22 @@ <script> import { GlCard, GlLink, GlSprintf } from '@gitlab/ui'; import { s__ } from '~/locale'; -import PipelineVisualReference from '../ui/pipeline_visual_reference.vue'; export default { i18n: { title: s__('PipelineEditorTutorial|🚀 Run your first pipeline'), firstParagraph: s__( - 'PipelineEditorTutorial|A typical GitLab pipeline consists of three stages: build, test and deploy. Each stage can have one or more jobs.', - ), - secondParagraph: s__( - 'PipelineEditorTutorial|In the example below, %{codeStart}build%{codeEnd} and %{codeStart}deploy%{codeEnd} each contain one job, and %{codeStart}test%{codeEnd} contains two jobs. Your scripts run in jobs like these.', - ), - thirdParagraph: s__( - 'PipelineEditorTutorial|You can use %{linkStart}CI/CD examples and templates%{linkEnd} to get your first %{codeStart}.gitlab-ci.yml%{codeEnd} configuration file started. Your first pipeline runs when you commit the changes.', + 'PipelineEditorTutorial|This template creates a simple test pipeline. To use it:', ), + listItems: [ + s__( + 'PipelineEditorTutorial|Commit the file to your repository. The pipeline then runs automatically.', + ), + s__('PipelineEditorTutorial|The pipeline status is at the top of the page.'), + s__( + 'PipelineEditorTutorial|Select the pipeline ID to view the full details about your first pipeline run.', + ), + ], note: s__( 'PipelineEditorTutorial|If you’re using a self-managed GitLab instance, %{linkStart}make sure your instance has runners available.%{linkEnd}', ), @@ -23,9 +25,8 @@ export default { GlCard, GlLink, GlSprintf, - PipelineVisualReference, }, - inject: ['ciExamplesHelpPagePath', 'runnerHelpPagePath'], + inject: ['runnerHelpPagePath'], }; </script> <template> @@ -33,26 +34,9 @@ export default { <template #default> <h4 class="gl-font-lg gl-mt-0">{{ $options.i18n.title }}</h4> <p class="gl-mb-3">{{ $options.i18n.firstParagraph }}</p> - <p class="gl-mb-3"> - <gl-sprintf :message="$options.i18n.secondParagraph"> - <template #code="{ content }"> - <code>{{ content }}</code> - </template> - </gl-sprintf> - </p> - <pipeline-visual-reference /> - <p class="gl-my-3"> - <gl-sprintf :message="$options.i18n.thirdParagraph"> - <template #link="{ content }"> - <gl-link :href="ciExamplesHelpPagePath" target="_blank"> - {{ content }} - </gl-link> - </template> - <template #code="{ content }"> - <code>{{ content }}</code> - </template> - </gl-sprintf> - </p> + <ol class="gl-mb-3"> + <li v-for="(item, i) in $options.i18n.listItems" :key="`li-${i}`">{{ item }}</li> + </ol> <p class="gl-mb-0"> <gl-sprintf :message="$options.i18n.note"> <template #link="{ content }"> diff --git a/app/assets/javascripts/pipeline_editor/components/drawer/ui/pipeline_visual_reference.vue b/app/assets/javascripts/pipeline_editor/components/drawer/ui/pipeline_visual_reference.vue deleted file mode 100644 index 1017237365b..00000000000 --- a/app/assets/javascripts/pipeline_editor/components/drawer/ui/pipeline_visual_reference.vue +++ /dev/null @@ -1,43 +0,0 @@ -<script> -import { s__ } from '~/locale'; -import DemoJobPill from './demo_job_pill.vue'; - -export default { - i18n: { - stageNames: { - build: s__('StageName|Build'), - test: s__('StageName|Test'), - deploy: s__('StageName|Deploy'), - }, - jobNames: { - build: s__('JobName|build-job'), - test_1: s__('JobName|unit-test'), - test_2: s__('JobName|lint-test'), - deploy: s__('JobName|deploy-app'), - }, - }, - stageClasses: - 'gl-bg-blue-50 gl-display-flex gl-flex-direction-column gl-align-items-center gl-p-4 gl-rounded-base', - titleClasses: 'gl-text-blue-600 gl-mb-4', - components: { - DemoJobPill, - }, -}; -</script> -<template> - <div class="gl-display-flex gl-justify-content-center"> - <div :class="$options.stageClasses" class="gl-mr-5"> - <div :class="$options.titleClasses">{{ $options.i18n.stageNames.build }}</div> - <demo-job-pill :job-name="$options.i18n.jobNames.build" /> - </div> - <div :class="$options.stageClasses" class="gl-mr-5"> - <div :class="$options.titleClasses">{{ $options.i18n.stageNames.test }}</div> - <demo-job-pill class="gl-mb-3" :job-name="$options.i18n.jobNames.test_1" /> - <demo-job-pill :job-name="$options.i18n.jobNames.test_2" /> - </div> - <div :class="$options.stageClasses"> - <div :class="$options.titleClasses">{{ $options.i18n.stageNames.deploy }}</div> - <demo-job-pill :job-name="$options.i18n.jobNames.deploy" /> - </div> - </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 a3410d7b837..d373f74a5c4 100644 --- a/app/assets/javascripts/pipeline_editor/components/editor/text_editor.vue +++ b/app/assets/javascripts/pipeline_editor/components/editor/text_editor.vue @@ -2,13 +2,15 @@ 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 glFeatureFlagMixin from '~/vue_shared/mixins/gl_feature_flags_mixin'; import getCommitSha from '../../graphql/queries/client/commit_sha.graphql'; export default { components: { EditorLite, }, - inject: ['ciConfigPath', 'projectPath', 'projectNamespace'], + mixins: [glFeatureFlagMixin()], + inject: ['ciConfigPath', 'projectPath', 'projectNamespace', 'defaultBranch'], inheritAttrs: false, data() { return { @@ -25,14 +27,16 @@ export default { this.$emit('updateCiConfig', content); }, registerCiSchema() { - const editorInstance = this.$refs.editor.getEditor(); + if (this.glFeatures.schemaLinting) { + const editorInstance = this.$refs.editor.getEditor(); - editorInstance.use(new CiSchemaExtension({ instance: editorInstance })); - editorInstance.registerCiSchema({ - projectPath: this.projectPath, - projectNamespace: this.projectNamespace, - ref: this.commitSha, - }); + editorInstance.use(new CiSchemaExtension({ instance: editorInstance })); + editorInstance.registerCiSchema({ + projectPath: this.projectPath, + projectNamespace: this.projectNamespace, + ref: this.commitSha || this.defaultBranch, + }); + } }, }, readyEvent: EDITOR_READY_EVENT, 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 1acf3a03e73..05b87abecd5 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 @@ -6,7 +6,10 @@ import { GlInfiniteScroll, GlLoadingIcon, GlSearchBoxByType, + GlTooltipDirective, } from '@gitlab/ui'; +import { produce } from 'immer'; +import { fetchPolicies } from '~/lib/graphql'; import { historyPushState } from '~/lib/utils/common_utils'; import { setUrlParams } from '~/lib/utils/url_utility'; import { s__ } from '~/locale'; @@ -15,12 +18,14 @@ import { BRANCH_SEARCH_DEBOUNCE, DEFAULT_FAILURE, } from '~/pipeline_editor/constants'; -import getAvailableBranches from '~/pipeline_editor/graphql/queries/available_branches.graphql'; -import getCurrentBranch from '~/pipeline_editor/graphql/queries/client/current_branch.graphql'; +import updateCurrentBranchMutation from '~/pipeline_editor/graphql/mutations/update_current_branch.mutation.graphql'; +import getAvailableBranchesQuery from '~/pipeline_editor/graphql/queries/available_branches.graphql'; +import getCurrentBranchQuery from '~/pipeline_editor/graphql/queries/client/current_branch.graphql'; +import getLastCommitBranchQuery from '~/pipeline_editor/graphql/queries/client/last_commit_branch.query.graphql'; export default { i18n: { - dropdownHeader: s__('Switch Branch'), + dropdownHeader: s__('Switch branch'), title: s__('Branches'), fetchError: s__('Unable to fetch branch list for this project.'), }, @@ -33,6 +38,9 @@ export default { GlLoadingIcon, GlSearchBoxByType, }, + directives: { + GlTooltip: GlTooltipDirective, + }, inject: ['projectFullPath', 'totalBranches'], props: { paginationLimit: { @@ -43,101 +51,147 @@ export default { }, data() { return { - branches: [], - page: { - limit: this.paginationLimit, - offset: 0, - searchTerm: '', - }, + availableBranches: [], + filteredBranches: [], + isSearchingBranches: false, + pageLimit: this.paginationLimit, + pageCounter: 0, + searchTerm: '', + lastCommitBranch: '', }; }, apollo: { availableBranches: { - query: getAvailableBranches, + query: getAvailableBranchesQuery, variables() { return { - limit: this.page.limit, - offset: this.page.offset, + limit: this.paginationLimit, + offset: 0, projectFullPath: this.projectFullPath, - searchPattern: this.searchPattern, + searchPattern: '*', }; }, update(data) { return data.project?.repository?.branchNames || []; }, - result({ data }) { - const newBranches = data.project?.repository?.branchNames || []; - - // check that we're not re-concatenating existing fetch results - if (!this.branches.includes(newBranches[0])) { - this.branches = this.branches.concat(newBranches); - } + result() { + this.pageCounter += 1; }, error() { - this.$emit('showError', { - type: DEFAULT_FAILURE, - reasons: [this.$options.i18n.fetchError], - }); + this.showFetchError(); }, }, currentBranch: { - query: getCurrentBranch, + query: getCurrentBranchQuery, + }, + lastCommitBranch: { + query: getLastCommitBranchQuery, + result({ data: { lastCommitBranch } }) { + if (lastCommitBranch === '' || this.availableBranches.includes(lastCommitBranch)) { + return; + } + this.availableBranches.unshift(lastCommitBranch); + }, }, }, computed: { + branches() { + return this.searchTerm.length > 0 ? this.filteredBranches : this.availableBranches; + }, isBranchesLoading() { - return this.$apollo.queries.availableBranches.loading; + return this.$apollo.queries.availableBranches.loading || this.isSearchingBranches; }, showBranchSwitcher() { - return this.branches.length > 0 || this.page.searchTerm.length > 0; + return this.branches.length > 0 || this.searchTerm.length > 0; }, - searchPattern() { - if (this.page.searchTerm === '') { - return '*'; + }, + methods: { + availableBranchesQueryVars(varsOverride = {}) { + if (this.searchTerm.length > 0) { + return { + limit: this.totalBranches, + offset: 0, + projectFullPath: this.projectFullPath, + searchPattern: `*${this.searchTerm}*`, + ...varsOverride, + }; } - return `*${this.page.searchTerm}*`; + return { + limit: this.paginationLimit, + offset: this.pageCounter * this.paginationLimit, + projectFullPath: this.projectFullPath, + searchPattern: '*', + ...varsOverride, + }; }, - }, - methods: { // if there is no searchPattern, paginate by {paginationLimit} branches fetchNextBranches() { if ( this.isBranchesLoading || - this.page.searchTerm.length > 0 || - this.branches.length === this.totalBranches + this.searchTerm.length > 0 || + this.branches.length >= this.totalBranches ) { return; } - this.page = { - ...this.page, - limit: this.paginationLimit, - offset: this.page.offset + this.paginationLimit, - }; + this.$apollo.queries.availableBranches + .fetchMore({ + variables: this.availableBranchesQueryVars(), + updateQuery(previousResult, { fetchMoreResult }) { + const previousBranches = previousResult.project.repository.branchNames; + const newBranches = fetchMoreResult.project.repository.branchNames; + + return produce(fetchMoreResult, (draftData) => { + draftData.project.repository.branchNames = previousBranches.concat(newBranches); + }); + }, + }) + .catch(this.showFetchError); }, async selectBranch(newBranch) { if (newBranch === this.currentBranch) { return; } - await this.$apollo.getClient().writeQuery({ - query: getCurrentBranch, - data: { currentBranch: newBranch }, - }); - + this.updateCurrentBranch(newBranch); const updatedPath = setUrlParams({ branch_name: newBranch }); historyPushState(updatedPath); this.$emit('refetchContent'); }, - setSearchTerm(newSearchTerm) { - this.branches = []; - this.page = { - limit: newSearchTerm.trim() === '' ? this.paginationLimit : this.totalBranches, - offset: 0, - searchTerm: newSearchTerm.trim(), - }; + async setSearchTerm(newSearchTerm) { + this.pageCounter = 0; + this.searchTerm = newSearchTerm.trim(); + + if (this.searchTerm === '') { + this.pageLimit = this.paginationLimit; + return; + } + + this.isSearchingBranches = true; + const fetchResults = await this.$apollo + .query({ + query: getAvailableBranchesQuery, + fetchPolicy: fetchPolicies.NETWORK_ONLY, + variables: this.availableBranchesQueryVars(), + }) + .catch(this.showFetchError); + + this.isSearchingBranches = false; + this.filteredBranches = fetchResults?.data?.project?.repository?.branchNames || []; + }, + showFetchError() { + this.$emit('showError', { + type: DEFAULT_FAILURE, + reasons: [this.$options.i18n.fetchError], + }); + }, + updateCurrentBranch(currentBranch) { + this.$apollo.mutate({ + mutation: updateCurrentBranchMutation, + variables: { currentBranch }, + }); }, }, }; @@ -146,7 +200,8 @@ export default { <template> <gl-dropdown v-if="showBranchSwitcher" - class="gl-ml-2" + v-gl-tooltip.hover + :title="$options.i18n.dropdownHeader" :header-text="$options.i18n.dropdownHeader" :text="currentBranch" icon="branch" @@ -158,7 +213,6 @@ export default { <gl-infinite-scroll :fetched-items="branches.length" - :total-items="totalBranches" :max-list-height="250" @bottomReached="fetchNextBranches" > diff --git a/app/assets/javascripts/pipeline_editor/components/file_nav/pipeline_editor_file_nav.vue b/app/assets/javascripts/pipeline_editor/components/file_nav/pipeline_editor_file_nav.vue index a945fc542a5..ebe73bdcec3 100644 --- a/app/assets/javascripts/pipeline_editor/components/file_nav/pipeline_editor_file_nav.vue +++ b/app/assets/javascripts/pipeline_editor/components/file_nav/pipeline_editor_file_nav.vue @@ -15,7 +15,7 @@ export default { }; </script> <template> - <div class="gl-mb-5"> + <div class="gl-mb-4"> <branch-switcher v-if="showBranchSwitcher" v-on="$listeners" /> </div> </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 4e2f26af51d..c3dcc00af6e 100644 --- a/app/assets/javascripts/pipeline_editor/components/pipeline_editor_tabs.vue +++ b/app/assets/javascripts/pipeline_editor/components/pipeline_editor_tabs.vue @@ -22,7 +22,7 @@ import EditorTab from './ui/editor_tab.vue'; export default { i18n: { - tabEdit: s__('Pipelines|Write pipeline configuration'), + tabEdit: s__('Pipelines|Edit'), tabGraph: s__('Pipelines|Visualize'), tabLint: s__('Pipelines|Lint'), tabMergedYaml: s__('Pipelines|View merged YAML'), @@ -114,6 +114,7 @@ export default { :empty-message="$options.i18n.empty.visualization" :is-empty="isEmpty" :is-invalid="isInvalid" + :keep-component-mounted="false" :title="$options.i18n.tabGraph" lazy data-testid="visualization-tab" diff --git a/app/assets/javascripts/pipeline_editor/constants.js b/app/assets/javascripts/pipeline_editor/constants.js index f0a24e0c061..1467abd7289 100644 --- a/app/assets/javascripts/pipeline_editor/constants.js +++ b/app/assets/javascripts/pipeline_editor/constants.js @@ -31,3 +31,5 @@ export const DRAWER_EXPANDED_KEY = 'pipeline_editor_drawer_expanded'; export const BRANCH_PAGINATION_LIMIT = 20; export const BRANCH_SEARCH_DEBOUNCE = '500'; + +export const STARTER_TEMPLATE_NAME = 'Getting-Started'; diff --git a/app/assets/javascripts/pipeline_editor/graphql/mutations/update_current_branch.mutation.graphql b/app/assets/javascripts/pipeline_editor/graphql/mutations/update_current_branch.mutation.graphql new file mode 100644 index 00000000000..b722c147f5f --- /dev/null +++ b/app/assets/javascripts/pipeline_editor/graphql/mutations/update_current_branch.mutation.graphql @@ -0,0 +1,3 @@ +mutation updateCurrentBranch($currentBranch: String) { + updateCurrentBranch(currentBranch: $currentBranch) @client +} diff --git a/app/assets/javascripts/pipeline_editor/graphql/mutations/update_last_commit_branch.mutation.graphql b/app/assets/javascripts/pipeline_editor/graphql/mutations/update_last_commit_branch.mutation.graphql new file mode 100644 index 00000000000..9561312f2b6 --- /dev/null +++ b/app/assets/javascripts/pipeline_editor/graphql/mutations/update_last_commit_branch.mutation.graphql @@ -0,0 +1,3 @@ +mutation updateLastCommitBranch($lastCommitBranch: String) { + updateLastCommitBranch(lastCommitBranch: $lastCommitBranch) @client +} diff --git a/app/assets/javascripts/pipeline_editor/graphql/queries/client/last_commit_branch.query.graphql b/app/assets/javascripts/pipeline_editor/graphql/queries/client/last_commit_branch.query.graphql new file mode 100644 index 00000000000..e8a32d728d5 --- /dev/null +++ b/app/assets/javascripts/pipeline_editor/graphql/queries/client/last_commit_branch.query.graphql @@ -0,0 +1,3 @@ +query getLastCommitBranchQuery { + lastCommitBranch @client +} diff --git a/app/assets/javascripts/pipeline_editor/graphql/queries/get_starter_template.query.graphql b/app/assets/javascripts/pipeline_editor/graphql/queries/get_starter_template.query.graphql new file mode 100644 index 00000000000..88825718f7b --- /dev/null +++ b/app/assets/javascripts/pipeline_editor/graphql/queries/get_starter_template.query.graphql @@ -0,0 +1,7 @@ +query getTemplate($projectPath: ID!, $templateName: String!) { + project(fullPath: $projectPath) { + ciTemplate(name: $templateName) { + content + } + } +} diff --git a/app/assets/javascripts/pipeline_editor/graphql/resolvers.js b/app/assets/javascripts/pipeline_editor/graphql/resolvers.js index 81e75c32846..8cead7f3315 100644 --- a/app/assets/javascripts/pipeline_editor/graphql/resolvers.js +++ b/app/assets/javascripts/pipeline_editor/graphql/resolvers.js @@ -1,5 +1,8 @@ +import produce from 'immer'; import Api from '~/api'; import axios from '~/lib/utils/axios_utils'; +import getCurrentBranchQuery from './queries/client/current_branch.graphql'; +import getLastCommitBranchQuery from './queries/client/last_commit_branch.query.graphql'; export const resolvers = { Query: { @@ -39,5 +42,21 @@ export const resolvers = { __typename: 'CiLintContent', })); }, + updateCurrentBranch: (_, { currentBranch = undefined }, { cache }) => { + cache.writeQuery({ + query: getCurrentBranchQuery, + data: produce(cache.readQuery({ query: getCurrentBranchQuery }), (draftData) => { + draftData.currentBranch = currentBranch; + }), + }); + }, + updateLastCommitBranch: (_, { lastCommitBranch = undefined }, { cache }) => { + cache.writeQuery({ + query: getLastCommitBranchQuery, + data: produce(cache.readQuery({ query: getLastCommitBranchQuery }), (draftData) => { + draftData.lastCommitBranch = lastCommitBranch; + }), + }); + }, }, }; diff --git a/app/assets/javascripts/pipeline_editor/index.js b/app/assets/javascripts/pipeline_editor/index.js index 66158bdba88..e0f8d889cad 100644 --- a/app/assets/javascripts/pipeline_editor/index.js +++ b/app/assets/javascripts/pipeline_editor/index.js @@ -6,6 +6,7 @@ import { resetServiceWorkersPublicPath } from '../lib/utils/webpack'; import { CODE_SNIPPET_SOURCE_SETTINGS } from './components/code_snippet_alert/constants'; import getCommitSha from './graphql/queries/client/commit_sha.graphql'; import getCurrentBranch from './graphql/queries/client/current_branch.graphql'; +import getLastCommitBranchQuery from './graphql/queries/client/last_commit_branch.query.graphql'; import getPipelineEtag from './graphql/queries/client/pipeline_etag.graphql'; import { resolvers } from './graphql/resolvers'; import typeDefs from './graphql/typedefs.graphql'; @@ -82,6 +83,13 @@ export const initPipelineEditor = (selector = '#js-pipeline-editor') => { }, }); + cache.writeQuery({ + query: getLastCommitBranchQuery, + data: { + lastCommitBranch: '', + }, + }); + return new Vue({ el, apolloProvider, diff --git a/app/assets/javascripts/pipeline_editor/pipeline_editor_app.vue b/app/assets/javascripts/pipeline_editor/pipeline_editor_app.vue index 79a2a51cebc..c24e6523352 100644 --- a/app/assets/javascripts/pipeline_editor/pipeline_editor_app.vue +++ b/app/assets/javascripts/pipeline_editor/pipeline_editor_app.vue @@ -14,12 +14,14 @@ import { EDITOR_APP_STATUS_ERROR, EDITOR_APP_STATUS_LOADING, LOAD_FAILURE_UNKNOWN, + STARTER_TEMPLATE_NAME, } from './constants'; 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 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 PipelineEditorHome from './pipeline_editor_home.vue'; export default { @@ -51,12 +53,13 @@ export default { showStartScreen: false, showSuccess: false, showFailure: false, + starterTemplate: '', }; }, apollo: { initialCiFileContent: { - fetchPolicy: fetchPolicies.NETWORK, + fetchPolicy: fetchPolicies.NETWORK_ONLY, query: getBlobContent, // If it's a brand new file, we don't want to fetch the content. // Then when the user commits the first time, the query would run @@ -135,6 +138,27 @@ export default { isNewCiConfigFile: { query: getIsNewCiConfigFile, }, + starterTemplate: { + query: getTemplate, + variables() { + return { + projectPath: this.projectFullPath, + templateName: STARTER_TEMPLATE_NAME, + }; + }, + skip({ isNewCiConfigFile }) { + return !isNewCiConfigFile; + }, + update(data) { + return data.project?.ciTemplate?.content || ''; + }, + result({ data }) { + this.updateCiConfig(data.project?.ciTemplate?.content || ''); + }, + error() { + this.reportFailure(LOAD_FAILURE_UNKNOWN); + }, + }, }, computed: { hasUnsavedChanges() { @@ -151,7 +175,7 @@ export default { }, }, i18n: { - tabEdit: s__('Pipelines|Write pipeline configuration'), + tabEdit: s__('Pipelines|Edit'), tabGraph: s__('Pipelines|Visualize'), tabLint: s__('Pipelines|Lint'), }, @@ -228,7 +252,8 @@ export default { .getClient() .writeQuery({ query: getIsNewCiConfigFile, data: { isNewCiConfigFile: false } }); } - // Keep track of the latest commited content to know + + // Keep track of the latest committed content to know // if the user has made changes to the file that are unsaved. this.lastCommittedContent = this.currentCiFileContent; }, |