Commit 8fc6a201 authored by Miguel Rincon's avatar Miguel Rincon

Introduce feature flag to render pipeline with Vue

This change adds introduces a feature flag to render the pipeline mini
graph in the commit that has historically been implemented with HAML
and jQuery.
parent 6131d5c5
import { fetchCommitMergeRequests } from '~/commit_merge_requests'; import { fetchCommitMergeRequests } from '~/commit_merge_requests';
import MiniPipelineGraph from '~/mini_pipeline_graph_dropdown'; import MiniPipelineGraph from '~/mini_pipeline_graph_dropdown';
import { initCommitPipelineMiniGraph } from './init_commit_pipeline_mini_graph';
import { initDetailsButton } from './init_details_button'; import { initDetailsButton } from './init_details_button';
import { loadBranches } from './load_branches'; import { loadBranches } from './load_branches';
...@@ -12,10 +13,15 @@ export const initCommitBoxInfo = (containerSelector = '.js-commit-box-info') => ...@@ -12,10 +13,15 @@ export const initCommitBoxInfo = (containerSelector = '.js-commit-box-info') =>
// Related merge requests to this commit // Related merge requests to this commit
fetchCommitMergeRequests(); fetchCommitMergeRequests();
// Display pipeline info for this commit // Display pipeline mini graph for this commit
// Feature flag ci_commit_pipeline_mini_graph_vue
if (gon.features.ciCommitPipelineMiniGraphVue) {
initCommitPipelineMiniGraph();
} else {
new MiniPipelineGraph({ new MiniPipelineGraph({
container: '.js-commit-pipeline-graph', container: '.js-commit-pipeline-graph',
}).bindEvents(); }).bindEvents();
}
initDetailsButton(); initDetailsButton();
}; };
import Vue from 'vue';
export const initCommitPipelineMiniGraph = async (selector = '.js-commit-pipeline-mini-graph') => {
const el = document.querySelector(selector);
if (!el) {
return;
}
// Some commits have no pipeline, code splitting to load the pipeline optionally
const { stages } = el.dataset;
const { default: PipelineMiniGraph } = await import(
/* webpackChunkName: 'pipelineMiniGraph' */ '~/pipelines/components/pipelines_list/pipeline_mini_graph.vue'
);
// eslint-disable-next-line no-new
new Vue({
el,
render(createElement) {
return createElement(PipelineMiniGraph, {
props: {
stages: JSON.parse(stages),
},
});
},
});
};
...@@ -16,9 +16,14 @@ class Projects::CommitController < Projects::ApplicationController ...@@ -16,9 +16,14 @@ class Projects::CommitController < Projects::ApplicationController
before_action :authorize_read_pipeline!, only: [:pipelines] before_action :authorize_read_pipeline!, only: [:pipelines]
before_action :commit before_action :commit
before_action :define_commit_vars, only: [:show, :diff_for_path, :diff_files, :pipelines, :merge_requests] before_action :define_commit_vars, only: [:show, :diff_for_path, :diff_files, :pipelines, :merge_requests]
before_action :define_commit_box_vars, only: [:show, :pipelines]
before_action :define_note_vars, only: [:show, :diff_for_path, :diff_files] before_action :define_note_vars, only: [:show, :diff_for_path, :diff_files]
before_action :authorize_edit_tree!, only: [:revert, :cherry_pick] before_action :authorize_edit_tree!, only: [:revert, :cherry_pick]
before_action only: [:show, :pipelines] do
push_frontend_feature_flag(:ci_commit_pipeline_mini_graph_vue, @project, default_enabled: :yaml)
end
BRANCH_SEARCH_LIMIT = 1000 BRANCH_SEARCH_LIMIT = 1000
COMMIT_DIFFS_PER_PAGE = 75 COMMIT_DIFFS_PER_PAGE = 75
...@@ -202,6 +207,15 @@ class Projects::CommitController < Projects::ApplicationController ...@@ -202,6 +207,15 @@ class Projects::CommitController < Projects::ApplicationController
end end
# rubocop: enable CodeReuse/ActiveRecord # rubocop: enable CodeReuse/ActiveRecord
def define_commit_box_vars
@last_pipeline = @commit.last_pipeline
return unless ::Gitlab::Ci::Features.ci_commit_pipeline_mini_graph_vue_enabled?(@project)
return unless @commit.last_pipeline
@last_pipeline_stages = StageSerializer.new(project: @project, current_user: @current_user).represent(@last_pipeline.stages)
end
def assign_change_commit_vars def assign_change_commit_vars
@start_branch = params[:start_branch] @start_branch = params[:start_branch]
@commit_params = { commit: @commit } @commit_params = { commit: @commit }
......
...@@ -74,22 +74,25 @@ ...@@ -74,22 +74,25 @@
%span.commit-info.merge-requests{ 'data-project-commit-path' => merge_requests_project_commit_path(@project, @commit.id, format: :json) } %span.commit-info.merge-requests{ 'data-project-commit-path' => merge_requests_project_commit_path(@project, @commit.id, format: :json) }
.spinner.vertical-align-middle .spinner.vertical-align-middle
- last_pipeline = @commit.last_pipeline - if can?(current_user, :read_pipeline, @last_pipeline)
- if can?(current_user, :read_pipeline, last_pipeline)
.well-segment.pipeline-info .well-segment.pipeline-info
.status-icon-container .status-icon-container
= link_to project_pipeline_path(@project, last_pipeline.id), class: "ci-status-icon-#{last_pipeline.status}" do = link_to project_pipeline_path(@project, @last_pipeline.id), class: "ci-status-icon-#{@last_pipeline.status}" do
= ci_icon_for_status(last_pipeline.status) = ci_icon_for_status(@last_pipeline.status)
#{ _('Pipeline') } #{ _('Pipeline') }
= link_to "##{last_pipeline.id}", project_pipeline_path(@project, last_pipeline.id) = link_to "##{@last_pipeline.id}", project_pipeline_path(@project, @last_pipeline.id)
= ci_label_for_status(last_pipeline.status) = ci_label_for_status(@last_pipeline.status)
- if last_pipeline.stages_count.nonzero? - if @last_pipeline.stages_count.nonzero?
#{ n_(s_('Pipeline|with stage'), s_('Pipeline|with stages'), last_pipeline.stages_count) } #{ n_(s_('Pipeline|with stage'), s_('Pipeline|with stages'), @last_pipeline.stages_count) }
.mr-widget-pipeline-graph .mr-widget-pipeline-graph
= render 'shared/mini_pipeline_graph', pipeline: last_pipeline, klass: 'js-commit-pipeline-graph' - if ::Gitlab::Ci::Features.ci_commit_pipeline_mini_graph_vue_enabled?(@project)
- if last_pipeline.duration .stage-cell
.js-commit-pipeline-mini-graph{ data: { stages: @last_pipeline_stages.to_json.html_safe } }
- else
= render 'shared/mini_pipeline_graph', pipeline: @last_pipeline, klass: 'js-commit-pipeline-graph'
- if @last_pipeline.duration
in in
= time_interval_in_words last_pipeline.duration = time_interval_in_words @last_pipeline.duration
- if @merge_request - if @merge_request
.well-segment .well-segment
......
---
name: ci_commit_pipeline_mini_graph_vue
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/55363
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/323356
milestone: '13.10'
type: development
group: group::pipeline authoring
default_enabled: false
...@@ -67,6 +67,10 @@ module Gitlab ...@@ -67,6 +67,10 @@ module Gitlab
def self.multiple_cache_per_job? def self.multiple_cache_per_job?
::Feature.enabled?(:multiple_cache_per_job, default_enabled: :yaml) ::Feature.enabled?(:multiple_cache_per_job, default_enabled: :yaml)
end end
def self.ci_commit_pipeline_mini_graph_vue_enabled?(project)
::Feature.enabled?(:ci_commit_pipeline_mini_graph_vue, project, default_enabled: :yaml)
end
end end
end end
end end
...@@ -9,6 +9,8 @@ RSpec.describe Projects::CommitController do ...@@ -9,6 +9,8 @@ RSpec.describe Projects::CommitController do
let(:commit) { project.commit("master") } let(:commit) { project.commit("master") }
let(:master_pickable_sha) { '7d3b0f7cff5f37573aea97cebfd5692ea1689924' } let(:master_pickable_sha) { '7d3b0f7cff5f37573aea97cebfd5692ea1689924' }
let(:master_pickable_commit) { project.commit(master_pickable_sha) } let(:master_pickable_commit) { project.commit(master_pickable_sha) }
let(:pipeline) { create(:ci_pipeline, project: project, ref: project.default_branch, sha: commit.sha, status: :running) }
let(:build) { create(:ci_build, pipeline: pipeline, status: :running) }
before do before do
sign_in(user) sign_in(user)
...@@ -33,6 +35,19 @@ RSpec.describe Projects::CommitController do ...@@ -33,6 +35,19 @@ RSpec.describe Projects::CommitController do
expect(response).to be_ok expect(response).to be_ok
end end
context 'when a pipeline job is running' do
before do
build.run
end
it 'defines last pipeline information' do
go(id: commit.id)
expect(assigns(:last_pipeline)).to have_attributes(id: pipeline.id, status: 'running')
expect(assigns(:last_pipeline_stages)).not_to be_empty
end
end
end end
context 'with invalid id' do context 'with invalid id' do
...@@ -363,15 +378,22 @@ RSpec.describe Projects::CommitController do ...@@ -363,15 +378,22 @@ RSpec.describe Projects::CommitController do
context 'when the commit exists' do context 'when the commit exists' do
context 'when the commit has pipelines' do context 'when the commit has pipelines' do
before do before do
create(:ci_pipeline, project: project, sha: commit.id) build.run
end end
context 'when rendering a HTML format' do context 'when rendering a HTML format' do
it 'shows pipelines' do before do
get_pipelines(id: commit.id) get_pipelines(id: commit.id)
end
it 'shows pipelines' do
expect(response).to be_ok expect(response).to be_ok
end end
it 'defines last pipeline information' do
expect(assigns(:last_pipeline)).to have_attributes(id: pipeline.id, status: 'running')
expect(assigns(:last_pipeline_stages)).not_to be_empty
end
end end
context 'when rendering a JSON format' do context 'when rendering a JSON format' do
......
...@@ -7,25 +7,26 @@ RSpec.describe 'Mini Pipeline Graph in Commit View', :js do ...@@ -7,25 +7,26 @@ RSpec.describe 'Mini Pipeline Graph in Commit View', :js do
context 'when commit has pipelines' do context 'when commit has pipelines' do
let(:pipeline) do let(:pipeline) do
create(:ci_empty_pipeline, create(:ci_pipeline,
status: :running,
project: project, project: project,
ref: project.default_branch, ref: project.default_branch,
sha: project.commit.sha) sha: project.commit.sha)
end end
let(:build) { create(:ci_build, pipeline: pipeline) } let(:build) { create(:ci_build, pipeline: pipeline, status: :running) }
it 'display icon with status' do shared_examples 'shows ci icon and mini pipeline' do
before do
build.run build.run
visit project_commit_path(project, project.commit.id) visit project_commit_path(project, project.commit.id)
end
it 'display icon with status' do
expect(page).to have_selector('.ci-status-icon-running') expect(page).to have_selector('.ci-status-icon-running')
end end
it 'displays a mini pipeline graph' do it 'displays a mini pipeline graph' do
build.run
visit project_commit_path(project, project.commit.id)
expect(page).to have_selector('.mr-widget-pipeline-graph') expect(page).to have_selector('.mr-widget-pipeline-graph')
first('.mini-pipeline-graph-dropdown-toggle').click first('.mini-pipeline-graph-dropdown-toggle').click
...@@ -41,6 +42,23 @@ RSpec.describe 'Mini Pipeline Graph in Commit View', :js do ...@@ -41,6 +42,23 @@ RSpec.describe 'Mini Pipeline Graph in Commit View', :js do
end end
end end
context 'when ci_commit_pipeline_mini_graph_vue is disabled' do
before do
stub_feature_flags(ci_commit_pipeline_mini_graph_vue: false)
end
it_behaves_like 'shows ci icon and mini pipeline'
end
context 'when ci_commit_pipeline_mini_graph_vue is enabled' do
before do
stub_feature_flags(ci_commit_pipeline_mini_graph_vue: true)
end
it_behaves_like 'shows ci icon and mini pipeline'
end
end
context 'when commit does not have pipelines' do context 'when commit does not have pipelines' do
before do before do
visit project_commit_path(project, project.commit.id) visit project_commit_path(project, project.commit.id)
......
...@@ -21,12 +21,37 @@ RSpec.describe 'projects/commit/_commit_box.html.haml' do ...@@ -21,12 +21,37 @@ RSpec.describe 'projects/commit/_commit_box.html.haml' do
end end
context 'when there is a pipeline present' do context 'when there is a pipeline present' do
context 'when pipeline has stages' do
before do
pipeline = create(:ci_pipeline, project: project, sha: project.commit.id, status: 'success')
create(:ci_build, pipeline: pipeline, stage: 'build')
assign(:last_pipeline, project.commit.last_pipeline)
end
it 'shows pipeline stages in vue' do
render
expect(rendered).to have_selector('.js-commit-pipeline-mini-graph')
end
it 'shows pipeline stages in haml when feature flag is disabled' do
stub_feature_flags(ci_commit_pipeline_mini_graph_vue: false)
render
expect(rendered).to have_selector('.js-commit-pipeline-graph')
end
end
context 'when there are multiple pipelines for a commit' do context 'when there are multiple pipelines for a commit' do
it 'shows the last pipeline' do it 'shows the last pipeline' do
create(:ci_pipeline, project: project, sha: project.commit.id, status: 'success') create(:ci_pipeline, project: project, sha: project.commit.id, status: 'success')
create(:ci_pipeline, project: project, sha: project.commit.id, status: 'canceled') create(:ci_pipeline, project: project, sha: project.commit.id, status: 'canceled')
third_pipeline = create(:ci_pipeline, project: project, sha: project.commit.id, status: 'failed') third_pipeline = create(:ci_pipeline, project: project, sha: project.commit.id, status: 'failed')
assign(:last_pipeline, third_pipeline)
render render
expect(rendered).to have_text("Pipeline ##{third_pipeline.id} failed") expect(rendered).to have_text("Pipeline ##{third_pipeline.id} failed")
...@@ -40,6 +65,8 @@ RSpec.describe 'projects/commit/_commit_box.html.haml' do ...@@ -40,6 +65,8 @@ RSpec.describe 'projects/commit/_commit_box.html.haml' do
end end
it 'shows correct pipeline description' do it 'shows correct pipeline description' do
assign(:last_pipeline, pipeline)
render render
expect(rendered).to have_text "Pipeline ##{pipeline.id} " \ expect(rendered).to have_text "Pipeline ##{pipeline.id} " \
......
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