Merge branch 'nfriend-update-job-detail-view-sidebar' into 'master'
Update job detail view sidebar to accommodate post-merge pipelines See merge request gitlab-org/gitlab-ce!25777
This commit is contained in:
commit
6811f1aca5
|
@ -1,5 +1,6 @@
|
|||
<script>
|
||||
import _ from 'underscore';
|
||||
import { GlLink } from '@gitlab/ui';
|
||||
import CiIcon from '~/vue_shared/components/ci_icon.vue';
|
||||
import Icon from '~/vue_shared/components/icon.vue';
|
||||
|
||||
|
@ -7,6 +8,7 @@ export default {
|
|||
components: {
|
||||
CiIcon,
|
||||
Icon,
|
||||
GlLink,
|
||||
},
|
||||
props: {
|
||||
pipeline: {
|
||||
|
@ -26,6 +28,12 @@ export default {
|
|||
hasRef() {
|
||||
return !_.isEmpty(this.pipeline.ref);
|
||||
},
|
||||
isTriggeredByMergeRequest() {
|
||||
return Boolean(this.pipeline.merge_request);
|
||||
},
|
||||
isMergeRequestPipeline() {
|
||||
return Boolean(this.pipeline.flags && this.pipeline.flags.merge_request_pipeline);
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
onStageClick(stage) {
|
||||
|
@ -36,16 +44,41 @@ export default {
|
|||
</script>
|
||||
<template>
|
||||
<div class="block-last dropdown">
|
||||
<ci-icon :status="pipeline.details.status" class="vertical-align-middle" />
|
||||
<div class="js-pipeline-info">
|
||||
<ci-icon :status="pipeline.details.status" class="vertical-align-middle" />
|
||||
|
||||
<span class="font-weight-bold">{{ __('Pipeline') }}</span>
|
||||
<a :href="pipeline.path" class="js-pipeline-path link-commit qa-pipeline-path"
|
||||
>#{{ pipeline.id }}</a
|
||||
>
|
||||
<template v-if="hasRef">
|
||||
{{ __('from') }}
|
||||
<a :href="pipeline.ref.path" class="link-commit ref-name">{{ pipeline.ref.name }}</a>
|
||||
</template>
|
||||
<span class="font-weight-bold">{{ s__('Job|Pipeline') }}</span>
|
||||
<gl-link :href="pipeline.path" class="js-pipeline-path link-commit qa-pipeline-path"
|
||||
>#{{ pipeline.id }}</gl-link
|
||||
>
|
||||
<template v-if="hasRef">
|
||||
{{ s__('Job|for') }}
|
||||
|
||||
<template v-if="isTriggeredByMergeRequest">
|
||||
<gl-link :href="pipeline.merge_request.path" class="link-commit ref-name js-mr-link"
|
||||
>!{{ pipeline.merge_request.iid }}</gl-link
|
||||
>
|
||||
{{ s__('Job|with') }}
|
||||
<gl-link
|
||||
:href="pipeline.merge_request.source_branch_path"
|
||||
class="link-commit ref-name js-source-branch-link"
|
||||
>{{ pipeline.merge_request.source_branch }}</gl-link
|
||||
>
|
||||
|
||||
<template v-if="isMergeRequestPipeline">
|
||||
{{ s__('Job|into') }}
|
||||
<gl-link
|
||||
:href="pipeline.merge_request.target_branch_path"
|
||||
class="link-commit ref-name js-target-branch-link"
|
||||
>{{ pipeline.merge_request.target_branch }}</gl-link
|
||||
>
|
||||
</template>
|
||||
</template>
|
||||
<gl-link v-else :href="pipeline.ref.path" class="link-commit ref-name">{{
|
||||
pipeline.ref.name
|
||||
}}</gl-link>
|
||||
</template>
|
||||
</div>
|
||||
|
||||
<button
|
||||
type="button"
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
title: Update job detail sidebar to accommodate post-merge pipeline information
|
||||
merge_request: 25777
|
||||
author:
|
||||
type: added
|
|
@ -4439,6 +4439,9 @@ msgstr ""
|
|||
msgid "Job|Keep"
|
||||
msgstr ""
|
||||
|
||||
msgid "Job|Pipeline"
|
||||
msgstr ""
|
||||
|
||||
msgid "Job|Scroll to bottom"
|
||||
msgstr ""
|
||||
|
||||
|
@ -4457,6 +4460,15 @@ msgstr ""
|
|||
msgid "Job|This job is stuck because the project doesn't have any runners online assigned to it."
|
||||
msgstr ""
|
||||
|
||||
msgid "Job|for"
|
||||
msgstr ""
|
||||
|
||||
msgid "Job|into"
|
||||
msgstr ""
|
||||
|
||||
msgid "Job|with"
|
||||
msgstr ""
|
||||
|
||||
msgid "Jul"
|
||||
msgstr ""
|
||||
|
||||
|
|
|
@ -2,6 +2,9 @@ require 'spec_helper'
|
|||
require 'tempfile'
|
||||
|
||||
describe 'Jobs', :clean_gitlab_redis_shared_state do
|
||||
include Gitlab::Routing
|
||||
include ProjectForksHelper
|
||||
|
||||
let(:user) { create(:user) }
|
||||
let(:user_access_level) { :developer }
|
||||
let(:project) { create(:project, :repository) }
|
||||
|
@ -121,6 +124,112 @@ describe 'Jobs', :clean_gitlab_redis_shared_state do
|
|||
end
|
||||
end
|
||||
|
||||
context 'pipeline info block', :js do
|
||||
it 'shows pipeline id and source branch' do
|
||||
visit project_job_path(project, job)
|
||||
|
||||
within '.js-pipeline-info' do
|
||||
expect(page).to have_content("Pipeline ##{pipeline.id} for #{pipeline.ref}")
|
||||
end
|
||||
end
|
||||
|
||||
context 'when pipeline is detached merge request pipeline' do
|
||||
let(:merge_request) do
|
||||
create(:merge_request,
|
||||
:with_detached_merge_request_pipeline,
|
||||
target_project: target_project,
|
||||
source_project: source_project)
|
||||
end
|
||||
|
||||
let(:source_project) { project }
|
||||
let(:target_project) { project }
|
||||
let(:pipeline) { merge_request.all_pipelines.last }
|
||||
let(:job) { create(:ci_build, pipeline: pipeline) }
|
||||
|
||||
it 'shows merge request iid and source branch' do
|
||||
visit project_job_path(project, job)
|
||||
|
||||
within '.js-pipeline-info' do
|
||||
expect(page).to have_content("for !#{pipeline.merge_request.iid} " \
|
||||
"with #{pipeline.merge_request.source_branch}")
|
||||
expect(page).to have_link("!#{pipeline.merge_request.iid}",
|
||||
href: project_merge_request_path(project, merge_request))
|
||||
expect(page).to have_link(pipeline.merge_request.source_branch,
|
||||
href: project_commits_path(project, merge_request.source_branch))
|
||||
end
|
||||
end
|
||||
|
||||
context 'when source project is a forked project' do
|
||||
let(:source_project) { fork_project(project, user, repository: true) }
|
||||
let(:target_project) { project }
|
||||
|
||||
it 'shows merge request iid and source branch' do
|
||||
visit project_job_path(source_project, job)
|
||||
|
||||
within '.js-pipeline-info' do
|
||||
expect(page).to have_content("for !#{pipeline.merge_request.iid} " \
|
||||
"with #{pipeline.merge_request.source_branch}")
|
||||
expect(page).to have_link("!#{pipeline.merge_request.iid}",
|
||||
href: project_merge_request_path(project, merge_request))
|
||||
expect(page).to have_link(pipeline.merge_request.source_branch,
|
||||
href: project_commits_path(source_project, merge_request.source_branch))
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'when pipeline is merge request pipeline' do
|
||||
let(:merge_request) do
|
||||
create(:merge_request,
|
||||
:with_merge_request_pipeline,
|
||||
target_project: target_project,
|
||||
source_project: source_project)
|
||||
end
|
||||
|
||||
let(:source_project) { project }
|
||||
let(:target_project) { project }
|
||||
let(:pipeline) { merge_request.all_pipelines.last }
|
||||
let(:job) { create(:ci_build, pipeline: pipeline) }
|
||||
|
||||
it 'shows merge request iid and source branch' do
|
||||
visit project_job_path(project, job)
|
||||
|
||||
within '.js-pipeline-info' do
|
||||
expect(page).to have_content("for !#{pipeline.merge_request.iid} " \
|
||||
"with #{pipeline.merge_request.source_branch} " \
|
||||
"into #{pipeline.merge_request.target_branch}")
|
||||
expect(page).to have_link("!#{pipeline.merge_request.iid}",
|
||||
href: project_merge_request_path(project, merge_request))
|
||||
expect(page).to have_link(pipeline.merge_request.source_branch,
|
||||
href: project_commits_path(project, merge_request.source_branch))
|
||||
expect(page).to have_link(pipeline.merge_request.target_branch,
|
||||
href: project_commits_path(project, merge_request.target_branch))
|
||||
end
|
||||
end
|
||||
|
||||
context 'when source project is a forked project' do
|
||||
let(:source_project) { fork_project(project, user, repository: true) }
|
||||
let(:target_project) { project }
|
||||
|
||||
it 'shows merge request iid and source branch' do
|
||||
visit project_job_path(source_project, job)
|
||||
|
||||
within '.js-pipeline-info' do
|
||||
expect(page).to have_content("for !#{pipeline.merge_request.iid} " \
|
||||
"with #{pipeline.merge_request.source_branch} " \
|
||||
"into #{pipeline.merge_request.target_branch}")
|
||||
expect(page).to have_link("!#{pipeline.merge_request.iid}",
|
||||
href: project_merge_request_path(project, merge_request))
|
||||
expect(page).to have_link(pipeline.merge_request.source_branch,
|
||||
href: project_commits_path(source_project, merge_request.source_branch))
|
||||
expect(page).to have_link(pipeline.merge_request.target_branch,
|
||||
href: project_commits_path(project, merge_request.target_branch))
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'sidebar', :js do
|
||||
let(:job) { create(:ci_build, :success, :trace_live, pipeline: pipeline, name: '<img src=x onerror=alert(document.domain)>') }
|
||||
|
||||
|
|
|
@ -1,59 +1,167 @@
|
|||
import Vue from 'vue';
|
||||
import component from '~/jobs/components/stages_dropdown.vue';
|
||||
import { trimText } from 'spec/helpers/vue_component_helper';
|
||||
import mountComponent from '../../helpers/vue_mount_component_helper';
|
||||
|
||||
describe('Stages Dropdown', () => {
|
||||
const Component = Vue.extend(component);
|
||||
let vm;
|
||||
|
||||
beforeEach(() => {
|
||||
vm = mountComponent(Component, {
|
||||
pipeline: {
|
||||
id: 28029444,
|
||||
details: {
|
||||
status: {
|
||||
details_path: '/gitlab-org/gitlab-ce/pipelines/28029444',
|
||||
group: 'success',
|
||||
has_details: true,
|
||||
icon: 'status_success',
|
||||
label: 'passed',
|
||||
text: 'passed',
|
||||
tooltip: 'passed',
|
||||
},
|
||||
},
|
||||
path: 'pipeline/28029444',
|
||||
const mockPipelineData = {
|
||||
id: 28029444,
|
||||
details: {
|
||||
status: {
|
||||
details_path: '/gitlab-org/gitlab-ce/pipelines/28029444',
|
||||
group: 'success',
|
||||
has_details: true,
|
||||
icon: 'status_success',
|
||||
label: 'passed',
|
||||
text: 'passed',
|
||||
tooltip: 'passed',
|
||||
},
|
||||
stages: [
|
||||
{
|
||||
name: 'build',
|
||||
},
|
||||
{
|
||||
name: 'test',
|
||||
},
|
||||
],
|
||||
selectedStage: 'deploy',
|
||||
},
|
||||
path: 'pipeline/28029444',
|
||||
flags: {
|
||||
merge_request_pipeline: true,
|
||||
detached_merge_request_pipeline: false,
|
||||
},
|
||||
merge_request: {
|
||||
iid: 1234,
|
||||
path: '/root/detached-merge-request-pipelines/merge_requests/1',
|
||||
title: 'Update README.md',
|
||||
source_branch: 'feature-1234',
|
||||
source_branch_path: '/root/detached-merge-request-pipelines/branches/feature-1234',
|
||||
target_branch: 'master',
|
||||
target_branch_path: '/root/detached-merge-request-pipelines/branches/master',
|
||||
},
|
||||
ref: {
|
||||
name: 'test-branch',
|
||||
},
|
||||
};
|
||||
|
||||
describe('without a merge request pipeline', () => {
|
||||
let pipeline;
|
||||
|
||||
beforeEach(() => {
|
||||
pipeline = JSON.parse(JSON.stringify(mockPipelineData));
|
||||
delete pipeline.merge_request;
|
||||
delete pipeline.flags.merge_request_pipeline;
|
||||
delete pipeline.flags.detached_merge_request_pipeline;
|
||||
|
||||
vm = mountComponent(Component, {
|
||||
pipeline,
|
||||
stages: [{ name: 'build' }, { name: 'test' }],
|
||||
selectedStage: 'deploy',
|
||||
});
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
vm.$destroy();
|
||||
});
|
||||
|
||||
it('renders pipeline status', () => {
|
||||
expect(vm.$el.querySelector('.js-ci-status-icon-success')).not.toBeNull();
|
||||
});
|
||||
|
||||
it('renders pipeline link', () => {
|
||||
expect(vm.$el.querySelector('.js-pipeline-path').getAttribute('href')).toEqual(
|
||||
'pipeline/28029444',
|
||||
);
|
||||
});
|
||||
|
||||
it('renders dropdown with stages', () => {
|
||||
expect(vm.$el.querySelector('.dropdown .js-stage-item').textContent).toContain('build');
|
||||
});
|
||||
|
||||
it('rendes selected stage', () => {
|
||||
expect(vm.$el.querySelector('.dropdown .js-selected-stage').textContent).toContain('deploy');
|
||||
});
|
||||
|
||||
it(`renders the pipeline info text like "Pipeline #123 for source_branch"`, () => {
|
||||
const expected = `Pipeline #${pipeline.id} for ${pipeline.ref.name}`;
|
||||
const actual = trimText(vm.$el.querySelector('.js-pipeline-info').innerText);
|
||||
|
||||
expect(actual).toBe(expected);
|
||||
});
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
vm.$destroy();
|
||||
describe('with an "attached" merge request pipeline', () => {
|
||||
let pipeline;
|
||||
|
||||
beforeEach(() => {
|
||||
pipeline = JSON.parse(JSON.stringify(mockPipelineData));
|
||||
pipeline.flags.merge_request_pipeline = true;
|
||||
pipeline.flags.detached_merge_request_pipeline = false;
|
||||
|
||||
vm = mountComponent(Component, {
|
||||
pipeline,
|
||||
stages: [],
|
||||
selectedStage: 'deploy',
|
||||
});
|
||||
});
|
||||
|
||||
it(`renders the pipeline info text like "Pipeline #123 for !456 with source_branch into target_branch"`, () => {
|
||||
const expected = `Pipeline #${pipeline.id} for !${pipeline.merge_request.iid} with ${
|
||||
pipeline.merge_request.source_branch
|
||||
} into ${pipeline.merge_request.target_branch}`;
|
||||
const actual = trimText(vm.$el.querySelector('.js-pipeline-info').innerText);
|
||||
|
||||
expect(actual).toBe(expected);
|
||||
});
|
||||
|
||||
it(`renders the correct merge request link`, () => {
|
||||
const actual = vm.$el.querySelector('.js-mr-link').href;
|
||||
|
||||
expect(actual).toContain(pipeline.merge_request.path);
|
||||
});
|
||||
|
||||
it(`renders the correct source branch link`, () => {
|
||||
const actual = vm.$el.querySelector('.js-source-branch-link').href;
|
||||
|
||||
expect(actual).toContain(pipeline.merge_request.source_branch_path);
|
||||
});
|
||||
|
||||
it(`renders the correct target branch link`, () => {
|
||||
const actual = vm.$el.querySelector('.js-target-branch-link').href;
|
||||
|
||||
expect(actual).toContain(pipeline.merge_request.target_branch_path);
|
||||
});
|
||||
});
|
||||
|
||||
it('renders pipeline status', () => {
|
||||
expect(vm.$el.querySelector('.js-ci-status-icon-success')).not.toBeNull();
|
||||
});
|
||||
describe('with a detached merge request pipeline', () => {
|
||||
let pipeline;
|
||||
|
||||
it('renders pipeline link', () => {
|
||||
expect(vm.$el.querySelector('.js-pipeline-path').getAttribute('href')).toEqual(
|
||||
'pipeline/28029444',
|
||||
);
|
||||
});
|
||||
beforeEach(() => {
|
||||
pipeline = JSON.parse(JSON.stringify(mockPipelineData));
|
||||
pipeline.flags.merge_request_pipeline = false;
|
||||
pipeline.flags.detached_merge_request_pipeline = true;
|
||||
|
||||
it('renders dropdown with stages', () => {
|
||||
expect(vm.$el.querySelector('.dropdown .js-stage-item').textContent).toContain('build');
|
||||
});
|
||||
vm = mountComponent(Component, {
|
||||
pipeline,
|
||||
stages: [],
|
||||
selectedStage: 'deploy',
|
||||
});
|
||||
});
|
||||
|
||||
it('rendes selected stage', () => {
|
||||
expect(vm.$el.querySelector('.dropdown .js-selected-stage').textContent).toContain('deploy');
|
||||
it(`renders the pipeline info like "Pipeline #123 for !456 with source_branch"`, () => {
|
||||
const expected = `Pipeline #${pipeline.id} for !${pipeline.merge_request.iid} with ${
|
||||
pipeline.merge_request.source_branch
|
||||
}`;
|
||||
const actual = trimText(vm.$el.querySelector('.js-pipeline-info').innerText);
|
||||
|
||||
expect(actual).toBe(expected);
|
||||
});
|
||||
|
||||
it(`renders the correct merge request link`, () => {
|
||||
const actual = vm.$el.querySelector('.js-mr-link').href;
|
||||
|
||||
expect(actual).toContain(pipeline.merge_request.path);
|
||||
});
|
||||
|
||||
it(`renders the correct source branch link`, () => {
|
||||
const actual = vm.$el.querySelector('.js-source-branch-link').href;
|
||||
|
||||
expect(actual).toContain(pipeline.merge_request.source_branch_path);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
Loading…
Reference in New Issue