Commit f1b867e8 authored by Alex Buijs's avatar Alex Buijs

Open the new CI Pipeline Editor when opening a template

From the empty pipelines page
parent 7aefdbc4
<script>
import { GlLoadingIcon } from '@gitlab/ui';
import { fetchPolicies } from '~/lib/graphql';
import { queryToObject } from '~/lib/utils/url_utility';
import { s__ } from '~/locale';
import { unwrapStagesWithNeeds } from '~/pipelines/components/unwrapping_utils';
......@@ -41,6 +42,7 @@ export default {
},
data() {
return {
starterTemplateName: STARTER_TEMPLATE_NAME,
ciConfigData: {},
failureType: null,
failureReasons: [],
......@@ -160,7 +162,7 @@ export default {
variables() {
return {
projectPath: this.projectFullPath,
templateName: STARTER_TEMPLATE_NAME,
templateName: this.starterTemplateName,
};
},
skip({ isNewCiConfigFile }) {
......@@ -203,6 +205,9 @@ export default {
}
},
},
mounted() {
this.loadTemplateFromURL();
},
methods: {
hideFailure() {
this.showFailure = false;
......@@ -258,6 +263,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>
......
......@@ -2,8 +2,8 @@
import { GlAvatar, GlButton, GlCard, GlSprintf } from '@gitlab/ui';
import { mergeUrlParams } from '~/lib/utils/url_utility';
import { s__, sprintf } from '~/locale';
import { STARTER_TEMPLATE_NAME } from '~/pipeline_editor/constants';
import Tracking from '~/tracking';
import { HELLO_WORLD_TEMPLATE_KEY } from '../../constants';
export default {
components: {
......@@ -13,7 +13,7 @@ export default {
GlSprintf,
},
mixins: [Tracking.mixin()],
HELLO_WORLD_TEMPLATE_KEY,
STARTER_TEMPLATE_NAME,
i18n: {
cta: s__('Pipelines|Use template'),
testTemplates: {
......@@ -21,10 +21,10 @@ export default {
subtitle: s__(
'Pipelines|Use a sample %{codeStart}.gitlab-ci.yml%{codeEnd} template file to explore how CI/CD works.',
),
helloWorld: {
title: s__('Pipelines|“Hello world” with GitLab CI/CD'),
gettingStarted: {
title: s__('Pipelines|Get started with GitLab CI/CD'),
description: s__(
'Pipelines|Get familiar with GitLab CI/CD syntax by starting with a simple pipeline that runs a “Hello world” script.',
'Pipelines|Get familiar with GitLab CI/CD syntax by starting with a basic 3 stage CI/CD pipeline.',
),
},
},
......@@ -36,22 +36,22 @@ export default {
description: s__('Pipelines|CI/CD template to test and deploy your %{name} project.'),
},
},
inject: ['addCiYmlPath', 'suggestedCiTemplates'],
inject: ['pipelineEditorPath', 'suggestedCiTemplates'],
data() {
const templates = this.suggestedCiTemplates.map(({ name, logo }) => {
return {
name,
logo,
link: mergeUrlParams({ template: name }, this.addCiYmlPath),
link: mergeUrlParams({ template: name }, this.pipelineEditorPath),
description: sprintf(this.$options.i18n.templates.description, { name }),
};
});
return {
templates,
helloWorldTemplateUrl: mergeUrlParams(
{ template: HELLO_WORLD_TEMPLATE_KEY },
this.addCiYmlPath,
gettingStartedTemplateUrl: mergeUrlParams(
{ template: STARTER_TEMPLATE_NAME },
this.pipelineEditorPath,
),
};
},
......@@ -82,18 +82,18 @@ export default {
<div class="gl-py-5"><gl-emoji class="gl-font-size-h2-xl" data-name="wave" /></div>
<div class="gl-mb-3">
<strong class="gl-text-gray-800 gl-mb-2">{{
$options.i18n.testTemplates.helloWorld.title
$options.i18n.testTemplates.gettingStarted.title
}}</strong>
</div>
<p class="gl-font-sm">{{ $options.i18n.testTemplates.helloWorld.description }}</p>
<p class="gl-font-sm">{{ $options.i18n.testTemplates.gettingStarted.description }}</p>
</div>
<gl-button
category="primary"
variant="confirm"
:href="helloWorldTemplateUrl"
:href="gettingStartedTemplateUrl"
data-testid="test-template-link"
@click="trackEvent($options.HELLO_WORLD_TEMPLATE_KEY)"
@click="trackEvent($options.STARTER_TEMPLATE_NAME)"
>
{{ $options.i18n.cta }}
</gl-button>
......
......@@ -35,6 +35,3 @@ export const POST_FAILURE = 'post_failure';
export const UNSUPPORTED_DATA = 'unsupported_data';
export const CHILD_VIEW = 'child';
// The key of the template is the same as the filename
export const HELLO_WORLD_TEMPLATE_KEY = 'Hello-World';
......@@ -29,7 +29,7 @@ export const initPipelinesIndex = (selector = '#pipelines-list-vue') => {
errorStateSvgPath,
noPipelinesSvgPath,
newPipelinePath,
addCiYmlPath,
pipelineEditorPath,
suggestedCiTemplates,
canCreatePipeline,
hasGitlabCi,
......@@ -44,7 +44,7 @@ export const initPipelinesIndex = (selector = '#pipelines-list-vue') => {
return new Vue({
el,
provide: {
addCiYmlPath,
pipelineEditorPath,
artifactsEndpoint,
artifactsEndpointPlaceholder,
suggestedCiTemplates: JSON.parse(suggestedCiTemplates),
......
......@@ -135,10 +135,6 @@ class ProjectPresenter < Gitlab::View::Presenter::Delegated
ide_edit_path(project, default_branch_or_main, 'README.md')
end
def add_ci_yml_path
add_special_file_path(file_name: ci_config_path_or_default)
end
def add_code_quality_ci_yml_path
add_special_file_path(
file_name: ci_config_path_or_default,
......
......@@ -22,7 +22,7 @@
"ci-lint-path" => can?(current_user, :create_pipeline, @project) && project_ci_lint_path(@project),
"reset-cache-path" => can?(current_user, :admin_pipeline, @project) && reset_cache_project_settings_ci_cd_path(@project),
"has-gitlab-ci" => has_gitlab_ci?(@project).to_s,
"add-ci-yml-path" => can?(current_user, :create_pipeline, @project) && @project.present(current_user: current_user).add_ci_yml_path,
"pipeline-editor-path" => can?(current_user, :create_pipeline, @project) && project_ci_pipeline_editor_path(@project),
"suggested-ci-templates" => suggested_ci_templates.to_json,
"code-quality-page-path" => @project.present(current_user: current_user).add_code_quality_ci_yml_path,
"ci-runner-settings-path" => project_settings_ci_cd_path(@project, ci_runner_templates: true, anchor: 'js-runners-settings') } }
# To contribute improvements to CI/CD templates, please follow the Development guide at:
# https://docs.gitlab.com/ee/development/cicd/templates.html
# This specific template is located at:
# https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Grails.gitlab-ci.yml
#
# This file is a template demonstrating the `script` keyword.
# Learn more about this keyword here: https://docs.gitlab.com/ee/ci/yaml/README.html#script
# After committing this template, visit CI/CD > Jobs to see the script output.
job:
script:
# provide a shell script as argument for this keyword.
- echo "Hello World"
......@@ -23924,7 +23924,10 @@ msgstr ""
msgid "Pipelines|Editor"
msgstr ""
msgid "Pipelines|Get familiar with GitLab CI/CD syntax by starting with a simple pipeline that runs a “Hello world” script."
msgid "Pipelines|Get familiar with GitLab CI/CD syntax by starting with a basic 3 stage CI/CD pipeline."
msgstr ""
msgid "Pipelines|Get started with GitLab CI/CD"
msgstr ""
msgid "Pipelines|GitLab CI/CD can automatically build, test, and deploy your code. Let GitLab take care of time consuming tasks, so you can spend more time creating."
......@@ -24065,9 +24068,6 @@ msgstr ""
msgid "Pipelines|parent"
msgstr ""
msgid "Pipelines|“Hello world” with GitLab CI/CD"
msgstr ""
msgid "Pipeline|Actions"
msgstr ""
......
......@@ -12,6 +12,7 @@ import PipelineEditorMessages from '~/pipeline_editor/components/ui/pipeline_edi
import { COMMIT_SUCCESS, COMMIT_FAILURE } from '~/pipeline_editor/constants';
import getBlobContent from '~/pipeline_editor/graphql/queries/blob_content.graphql';
import getCiConfigData from '~/pipeline_editor/graphql/queries/ci_config.graphql';
import getTemplate from '~/pipeline_editor/graphql/queries/get_starter_template.query.graphql';
import PipelineEditorApp from '~/pipeline_editor/pipeline_editor_app.vue';
import PipelineEditorHome from '~/pipeline_editor/pipeline_editor_home.vue';
import {
......@@ -47,6 +48,7 @@ describe('Pipeline editor app component', () => {
let mockApollo;
let mockBlobContentData;
let mockCiConfigData;
let mockGetTemplate;
const createComponent = ({ blobLoading = false, options = {}, provide = {} } = {}) => {
wrapper = shallowMount(PipelineEditorApp, {
......@@ -81,6 +83,7 @@ describe('Pipeline editor app component', () => {
const handlers = [
[getBlobContent, mockBlobContentData],
[getCiConfigData, mockCiConfigData],
[getTemplate, mockGetTemplate],
];
mockApollo = createMockApollo(handlers);
......@@ -112,6 +115,7 @@ describe('Pipeline editor app component', () => {
beforeEach(() => {
mockBlobContentData = jest.fn();
mockCiConfigData = jest.fn();
mockGetTemplate = jest.fn();
});
afterEach(() => {
......@@ -318,4 +322,29 @@ describe('Pipeline editor app component', () => {
expect(findEditorHome().exists()).toBe(true);
});
});
describe('when a template parameter is present in the URL', () => {
const { location } = window;
beforeEach(() => {
delete window.location;
window.location = new URL('https://localhost?template=Android');
});
afterEach(() => {
window.location = location;
});
it('renders the given template', async () => {
await createComponentWithApollo();
expect(mockGetTemplate).toHaveBeenCalledWith({
projectPath: mockProjectFullPath,
templateName: 'Android',
});
expect(findEmptyState().exists()).toBe(false);
expect(findTextEditor().exists()).toBe(true);
});
});
});
......@@ -13,7 +13,7 @@ describe('Pipelines Empty State', () => {
const createWrapper = (props = {}) => {
wrapper = mount(EmptyState, {
provide: {
addCiYmlPath: '',
pipelineEditorPath: '',
suggestedCiTemplates: [],
},
propsData: {
......
......@@ -3,7 +3,7 @@ import { shallowMount } from '@vue/test-utils';
import { mockTracking } from 'helpers/tracking_helper';
import PipelinesCiTemplate from '~/pipelines/components/pipelines_list/pipelines_ci_templates.vue';
const addCiYmlPath = "/-/new/main?commit_message='Add%20.gitlab-ci.yml'";
const pipelineEditorPath = '/-/ci/editor';
const suggestedCiTemplates = [
{ name: 'Android', logo: '/assets/illustrations/logos/android.svg' },
{ name: 'Bash', logo: '/assets/illustrations/logos/bash.svg' },
......@@ -17,7 +17,7 @@ describe('Pipelines CI Templates', () => {
const createWrapper = () => {
return shallowMount(PipelinesCiTemplate, {
provide: {
addCiYmlPath,
pipelineEditorPath,
suggestedCiTemplates,
},
});
......@@ -39,9 +39,9 @@ describe('Pipelines CI Templates', () => {
wrapper = createWrapper();
});
it('links to the hello world template', () => {
it('links to the getting started template', () => {
expect(findTestTemplateLinks().at(0).attributes('href')).toBe(
addCiYmlPath.concat('&template=Hello-World'),
pipelineEditorPath.concat('?template=Getting-Started'),
);
});
});
......@@ -63,7 +63,7 @@ describe('Pipelines CI Templates', () => {
it('links to the correct template', () => {
expect(findTemplateLinks().at(0).attributes('href')).toBe(
addCiYmlPath.concat('&template=Android'),
pipelineEditorPath.concat('?template=Android'),
);
});
......@@ -95,12 +95,12 @@ describe('Pipelines CI Templates', () => {
});
});
it('sends an event when Hello-World template is clicked', () => {
it('sends an event when Getting-Started template is clicked', () => {
findTestTemplateLinks().at(0).vm.$emit('click');
expect(trackingSpy).toHaveBeenCalledTimes(1);
expect(trackingSpy).toHaveBeenCalledWith(undefined, 'template_clicked', {
label: 'Hello-World',
label: 'Getting-Started',
});
});
});
......
......@@ -84,7 +84,7 @@ describe('Pipelines', () => {
wrapper = extendedWrapper(
mount(PipelinesComponent, {
provide: {
addCiYmlPath: '',
pipelineEditorPath: '',
suggestedCiTemplates: [],
},
propsData: {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment