diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2020-11-27 15:09:14 +0300 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2020-11-27 15:09:14 +0300 |
commit | 95ff19a65c5236863e4c7c7e198bfc1e2fa70f07 (patch) | |
tree | e543a0b23941611b93a7d435b7644eafcdd8cbeb /app/assets/javascripts/pipeline_editor | |
parent | 2df573afed782aebce8c020d92b42e9da7d2868e (diff) |
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'app/assets/javascripts/pipeline_editor')
7 files changed, 371 insertions, 3 deletions
diff --git a/app/assets/javascripts/pipeline_editor/components/lint/ci_lint_results.vue b/app/assets/javascripts/pipeline_editor/components/lint/ci_lint_results.vue new file mode 100644 index 00000000000..0d1c214c5b1 --- /dev/null +++ b/app/assets/javascripts/pipeline_editor/components/lint/ci_lint_results.vue @@ -0,0 +1,143 @@ +<script> +import { GlAlert, GlLink, GlSprintf, GlTable } from '@gitlab/ui'; +import CiLintWarnings from './ci_lint_warnings.vue'; +import CiLintResultsValue from './ci_lint_results_value.vue'; +import CiLintResultsParam from './ci_lint_results_param.vue'; +import { __ } from '~/locale'; + +const thBorderColor = 'gl-border-gray-100!'; + +export default { + correct: { + variant: 'success', + text: __('syntax is correct.'), + }, + incorrect: { + variant: 'danger', + text: __('syntax is incorrect.'), + }, + includesText: __( + 'CI configuration validated, including all configuration added with the %{codeStart}includes%{codeEnd} keyword. %{link}', + ), + warningTitle: __('The form contains the following warning:'), + fields: [ + { + key: 'parameter', + label: __('Parameter'), + thClass: thBorderColor, + }, + { + key: 'value', + label: __('Value'), + thClass: thBorderColor, + }, + ], + components: { + GlAlert, + GlLink, + GlSprintf, + GlTable, + CiLintWarnings, + CiLintResultsValue, + CiLintResultsParam, + }, + props: { + valid: { + type: Boolean, + required: true, + }, + jobs: { + type: Array, + required: true, + }, + errors: { + type: Array, + required: true, + }, + warnings: { + type: Array, + required: true, + }, + dryRun: { + type: Boolean, + required: true, + }, + lintHelpPagePath: { + type: String, + required: true, + }, + }, + data() { + return { + isWarningDismissed: false, + }; + }, + computed: { + status() { + return this.valid ? this.$options.correct : this.$options.incorrect; + }, + shouldShowTable() { + return this.errors.length === 0; + }, + shouldShowError() { + return this.errors.length > 0; + }, + shouldShowWarning() { + return this.warnings.length > 0 && !this.isWarningDismissed; + }, + }, +}; +</script> + +<template> + <div> + <gl-alert + class="gl-mb-5" + :variant="status.variant" + :title="__('Status:')" + :dismissible="false" + data-testid="ci-lint-status" + >{{ status.text }} + <gl-sprintf :message="$options.includesText"> + <template #code="{content}"> + <code> + {{ content }} + </code> + </template> + <template #link> + <gl-link :href="lintHelpPagePath" target="_blank"> + {{ __('More information') }} + </gl-link> + </template> + </gl-sprintf> + </gl-alert> + + <pre + v-if="shouldShowError" + class="gl-mb-5" + data-testid="ci-lint-errors" + ><div v-for="error in errors" :key="error">{{ error }}</div></pre> + + <ci-lint-warnings + v-if="shouldShowWarning" + :warnings="warnings" + data-testid="ci-lint-warnings" + @dismiss="isWarningDismissed = true" + /> + + <gl-table + v-if="shouldShowTable" + :items="jobs" + :fields="$options.fields" + bordered + data-testid="ci-lint-table" + > + <template #cell(parameter)="{ item }"> + <ci-lint-results-param :stage="item.stage" :job-name="item.name" /> + </template> + <template #cell(value)="{ item }"> + <ci-lint-results-value :item="item" :dry-run="dryRun" /> + </template> + </gl-table> + </div> +</template> diff --git a/app/assets/javascripts/pipeline_editor/components/lint/ci_lint_results_param.vue b/app/assets/javascripts/pipeline_editor/components/lint/ci_lint_results_param.vue new file mode 100644 index 00000000000..23808bcb292 --- /dev/null +++ b/app/assets/javascripts/pipeline_editor/components/lint/ci_lint_results_param.vue @@ -0,0 +1,26 @@ +<script> +import { __ } from '~/locale'; +import { capitalizeFirstCharacter } from '~/lib/utils/text_utility'; + +export default { + props: { + stage: { + type: String, + required: true, + }, + jobName: { + type: String, + required: true, + }, + }, + computed: { + formatParameter() { + return __(`${capitalizeFirstCharacter(this.stage)} Job - ${this.jobName}`); + }, + }, +}; +</script> + +<template> + <span data-testid="ci-lint-parameter">{{ formatParameter }}</span> +</template> diff --git a/app/assets/javascripts/pipeline_editor/components/lint/ci_lint_results_value.vue b/app/assets/javascripts/pipeline_editor/components/lint/ci_lint_results_value.vue new file mode 100644 index 00000000000..4929c3206df --- /dev/null +++ b/app/assets/javascripts/pipeline_editor/components/lint/ci_lint_results_value.vue @@ -0,0 +1,81 @@ +<script> +import { isEmpty } from 'lodash'; + +export default { + props: { + item: { + type: Object, + required: true, + }, + dryRun: { + type: Boolean, + required: true, + }, + }, + computed: { + tagList() { + return this.item.tagList.join(', '); + }, + onlyPolicy() { + return this.item.only ? this.item.only.refs.join(', ') : this.item.only; + }, + exceptPolicy() { + return this.item.except ? this.item.except.refs.join(', ') : this.item.except; + }, + scripts() { + return { + beforeScript: { + show: !isEmpty(this.item.beforeScript), + content: this.item.beforeScript.join('\n'), + }, + script: { + show: !isEmpty(this.item.script), + content: this.item.script.join('\n'), + }, + afterScript: { + show: !isEmpty(this.item.afterScript), + content: this.item.afterScript.join('\n'), + }, + }; + }, + }, +}; +</script> + +<template> + <div> + <pre v-if="scripts.beforeScript.show" data-testid="ci-lint-before-script">{{ + scripts.beforeScript.content + }}</pre> + <pre v-if="scripts.script.show" data-testid="ci-lint-script">{{ scripts.script.content }}</pre> + <pre v-if="scripts.afterScript.show" data-testid="ci-lint-after-script">{{ + scripts.afterScript.content + }}</pre> + + <ul class="gl-list-style-none gl-pl-0 gl-mb-0"> + <li> + <b>{{ __('Tag list:') }}</b> + {{ tagList }} + </li> + <div v-if="!dryRun" data-testid="ci-lint-only-except"> + <li> + <b>{{ __('Only policy:') }}</b> + {{ onlyPolicy }} + </li> + <li> + <b>{{ __('Except policy:') }}</b> + {{ exceptPolicy }} + </li> + </div> + <li> + <b>{{ __('Environment:') }}</b> + {{ item.environment }} + </li> + <li> + <b>{{ __('When:') }}</b> + {{ item.when }} + <b v-if="item.allowFailure">{{ __('Allowed to fail') }}</b> + </li> + </ul> + </div> +</template> diff --git a/app/assets/javascripts/pipeline_editor/components/lint/ci_lint_warnings.vue b/app/assets/javascripts/pipeline_editor/components/lint/ci_lint_warnings.vue new file mode 100644 index 00000000000..ac0332cb0bd --- /dev/null +++ b/app/assets/javascripts/pipeline_editor/components/lint/ci_lint_warnings.vue @@ -0,0 +1,69 @@ +<script> +import { GlAlert, GlSprintf } from '@gitlab/ui'; +import { __, n__ } from '~/locale'; + +export default { + maxWarningsSummary: __('%{total} warnings found: showing first %{warningsDisplayed}'), + components: { + GlAlert, + GlSprintf, + }, + props: { + warnings: { + type: Array, + required: true, + }, + maxWarnings: { + type: Number, + required: false, + default: 25, + }, + title: { + type: String, + required: false, + default: __('The form contains the following warning:'), + }, + }, + computed: { + totalWarnings() { + return this.warnings.length; + }, + overMaxWarningsLimit() { + return this.totalWarnings > this.maxWarnings; + }, + warningsSummary() { + return n__('%d warning found:', '%d warnings found:', this.totalWarnings); + }, + summaryMessage() { + return this.overMaxWarningsLimit ? this.$options.maxWarningsSummary : this.warningsSummary; + }, + limitWarnings() { + return this.warnings.slice(0, this.maxWarnings); + }, + }, +}; +</script> + +<template> + <gl-alert class="gl-mb-4" :title="title" variant="warning" @dismiss="$emit('dismiss')"> + <details> + <summary> + <gl-sprintf :message="summaryMessage"> + <template #total> + {{ totalWarnings }} + </template> + <template #warningsDisplayed> + {{ maxWarnings }} + </template> + </gl-sprintf> + </summary> + <p + v-for="(warning, index) in limitWarnings" + :key="`warning-${index}`" + data-testid="ci-lint-warning" + > + {{ warning }} + </p> + </details> + </gl-alert> +</template> diff --git a/app/assets/javascripts/pipeline_editor/graphql/mutations/lint_ci.mutation.graphql b/app/assets/javascripts/pipeline_editor/graphql/mutations/lint_ci.mutation.graphql new file mode 100644 index 00000000000..496036f690f --- /dev/null +++ b/app/assets/javascripts/pipeline_editor/graphql/mutations/lint_ci.mutation.graphql @@ -0,0 +1,22 @@ +mutation lintCI($endpoint: String, $content: String, $dry: Boolean) { + lintCI(endpoint: $endpoint, content: $content, dry_run: $dry) @client { + valid + errors + warnings + jobs { + afterScript + allowFailure + beforeScript + environment + except + name + only { + refs + } + afterScript + stage + tagList + when + } + } +} diff --git a/app/assets/javascripts/pipeline_editor/graphql/resolvers.js b/app/assets/javascripts/pipeline_editor/graphql/resolvers.js index 7b8c70ac93e..c1cdb5eb2ee 100644 --- a/app/assets/javascripts/pipeline_editor/graphql/resolvers.js +++ b/app/assets/javascripts/pipeline_editor/graphql/resolvers.js @@ -1,4 +1,5 @@ import Api from '~/api'; +import axios from '~/lib/utils/axios_utils'; export const resolvers = { Query: { @@ -11,6 +12,32 @@ export const resolvers = { }; }, }, -}; + Mutation: { + lintCI: (_, { endpoint, content, dry_run }) => { + return axios.post(endpoint, { content, dry_run }).then(({ data }) => ({ + valid: data.valid, + errors: data.errors, + warnings: data.warnings, + jobs: data.jobs.map(job => { + const only = job.only ? { refs: job.only.refs, __typename: 'CiLintJobOnlyPolicy' } : null; -export default resolvers; + return { + name: job.name, + stage: job.stage, + beforeScript: job.before_script, + script: job.script, + afterScript: job.after_script, + tagList: job.tag_list, + environment: job.environment, + when: job.when, + allowFailure: job.allow_failure, + only, + except: job.except, + __typename: 'CiLintJob', + }; + }), + __typename: 'CiLintContent', + })); + }, + }, +}; diff --git a/app/assets/javascripts/pipeline_editor/pipeline_editor_app.vue b/app/assets/javascripts/pipeline_editor/pipeline_editor_app.vue index 59635296de4..a4bdc27d1a0 100644 --- a/app/assets/javascripts/pipeline_editor/pipeline_editor_app.vue +++ b/app/assets/javascripts/pipeline_editor/pipeline_editor_app.vue @@ -6,8 +6,8 @@ import { redirectTo, mergeUrlParams, refreshCurrentPage } from '~/lib/utils/url_ import PipelineGraph from '~/pipelines/components/pipeline_graph/pipeline_graph.vue'; import CommitForm from './components/commit/commit_form.vue'; import TextEditor from './components/text_editor.vue'; -import commitCiFileMutation from './graphql/mutations/commit_ci_file.mutation.graphql'; +import commitCiFileMutation from './graphql/mutations/commit_ci_file.mutation.graphql'; import getBlobContent from './graphql/queries/blob_content.graphql'; const MR_SOURCE_BRANCH = 'merge_request[source_branch]'; |