Commit 9caa7e7a authored by Phil Hughes's avatar Phil Hughes

Merge branch '24883-build-failure-summary-page' into 'master'

Build failures summary page for pipelines

Closes #24883

See merge request !10719
parents 24040015 9f3f22c8
...@@ -252,6 +252,7 @@ const ShortcutsBlob = require('./shortcuts_blob'); ...@@ -252,6 +252,7 @@ const ShortcutsBlob = require('./shortcuts_blob');
} }
break; break;
case 'projects:pipelines:builds': case 'projects:pipelines:builds':
case 'projects:pipelines:failures':
case 'projects:pipelines:show': case 'projects:pipelines:show':
const { controllerAction } = document.querySelector('.js-pipeline-container').dataset; const { controllerAction } = document.querySelector('.js-pipeline-container').dataset;
const pipelineStatusUrl = `${document.querySelector('.js-pipeline-tab-link a').getAttribute('href')}/status.json`; const pipelineStatusUrl = `${document.querySelector('.js-pipeline-tab-link a').getAttribute('href')}/status.json`;
......
...@@ -316,6 +316,32 @@ ...@@ -316,6 +316,32 @@
} }
} }
.build-failures {
.build-state {
padding: 20px 2px;
.build-name {
float: right;
font-weight: 500;
}
.ci-status-icon-failed svg {
vertical-align: middle;
}
.stage {
color: $gl-text-color-secondary;
font-weight: 500;
vertical-align: middle;
}
}
.build-log {
border: none;
line-height: initial;
}
}
// Pipeline graph // Pipeline graph
.pipeline-graph { .pipeline-graph {
width: 100%; width: 100%;
......
class Projects::PipelinesController < Projects::ApplicationController class Projects::PipelinesController < Projects::ApplicationController
before_action :pipeline, except: [:index, :new, :create, :charts] before_action :pipeline, except: [:index, :new, :create, :charts]
before_action :commit, only: [:show, :builds] before_action :commit, only: [:show, :builds, :failures]
before_action :authorize_read_pipeline! before_action :authorize_read_pipeline!
before_action :authorize_create_pipeline!, only: [:new, :create] before_action :authorize_create_pipeline!, only: [:new, :create]
before_action :authorize_update_pipeline!, only: [:retry, :cancel] before_action :authorize_update_pipeline!, only: [:retry, :cancel]
...@@ -69,10 +69,14 @@ class Projects::PipelinesController < Projects::ApplicationController ...@@ -69,10 +69,14 @@ class Projects::PipelinesController < Projects::ApplicationController
end end
def builds def builds
respond_to do |format| render_show
format.html do
render 'show'
end end
def failures
if @pipeline.statuses.latest.failed.present?
render_show
else
redirect_to pipeline_path(@pipeline)
end end
end end
...@@ -125,6 +129,14 @@ class Projects::PipelinesController < Projects::ApplicationController ...@@ -125,6 +129,14 @@ class Projects::PipelinesController < Projects::ApplicationController
private private
def render_show
respond_to do |format|
format.html do
render 'show'
end
end
end
def create_params def create_params
params.require(:pipeline).permit(:ref) params.require(:pipeline).permit(:ref)
end end
......
module BuildsHelper module BuildsHelper
def build_summary(build, skip: false)
if build.has_trace?
if skip
link_to "View job trace", pipeline_build_url(build.pipeline, build)
else
build.trace.html(last_lines: 10).html_safe
end
else
"No job trace"
end
end
def sidebar_build_class(build, current_build) def sidebar_build_class(build, current_build)
build_class = '' build_class = ''
build_class += ' active' if build.id === current_build.id build_class += ' active' if build.id === current_build.id
......
- failed_builds = @pipeline.statuses.latest.failed
.tabs-holder .tabs-holder
%ul.pipelines-tabs.nav-links.no-top.no-bottom %ul.pipelines-tabs.nav-links.no-top.no-bottom
%li.js-pipeline-tab-link %li.js-pipeline-tab-link
...@@ -7,8 +9,11 @@ ...@@ -7,8 +9,11 @@
= link_to builds_namespace_project_pipeline_path(@project.namespace, @project, @pipeline), data: {target: 'div#js-tab-builds', action: 'builds', toggle: 'tab' }, class: 'builds-tab' do = link_to builds_namespace_project_pipeline_path(@project.namespace, @project, @pipeline), data: {target: 'div#js-tab-builds', action: 'builds', toggle: 'tab' }, class: 'builds-tab' do
Jobs Jobs
%span.badge.js-builds-counter= pipeline.statuses.count %span.badge.js-builds-counter= pipeline.statuses.count
- if failed_builds.present?
%li.js-failures-tab-link
= link_to failures_namespace_project_pipeline_path(@project.namespace, @project, @pipeline), data: {target: 'div#js-tab-failures', action: 'failures', toggle: 'tab' }, class: 'failures-tab' do
Failed Jobs
%span.badge.js-failures-counter= failed_builds.count
.tab-content .tab-content
#js-tab-pipeline.tab-pane #js-tab-pipeline.tab-pane
...@@ -39,3 +44,13 @@ ...@@ -39,3 +44,13 @@
%th Coverage %th Coverage
%th %th
= render partial: "projects/stage/stage", collection: pipeline.stages, as: :stage = render partial: "projects/stage/stage", collection: pipeline.stages, as: :stage
- if failed_builds.present?
#js-tab-failures.build-failures.tab-pane
- failed_builds.each_with_index do |build, index|
.build-state
%span.ci-status-icon-failed= custom_icon('icon_status_failed')
%span.stage
= build.stage.titleize
%span.build-name
= link_to build.name, pipeline_build_url(pipeline, build)
%pre.build-log= build_summary(build, skip: index >= 10)
---
title: Added build failures summary page for pipelines
merge_request: 10719
author:
...@@ -123,6 +123,7 @@ constraints(ProjectUrlConstrainer.new) do ...@@ -123,6 +123,7 @@ constraints(ProjectUrlConstrainer.new) do
post :cancel post :cancel
post :retry post :retry
get :builds get :builds
get :failures
get :status get :status
end end
end end
......
...@@ -254,4 +254,57 @@ describe 'Pipeline', :feature, :js do ...@@ -254,4 +254,57 @@ describe 'Pipeline', :feature, :js do
it { expect(build_manual.reload).to be_pending } it { expect(build_manual.reload).to be_pending }
end end
end end
describe 'GET /:project/pipelines/:id/failures' do
let(:project) { create(:project) }
let(:pipeline) { create(:ci_pipeline, project: project, ref: 'master', sha: project.commit.id) }
let(:pipeline_failures_page) { failures_namespace_project_pipeline_path(project.namespace, project, pipeline) }
let!(:failed_build) { create(:ci_build, :failed, pipeline: pipeline) }
context 'with failed build' do
before do
failed_build.trace.set('4 examples, 1 failure')
visit pipeline_failures_page
end
it 'shows jobs tab pane as active' do
expect(page).to have_content('Failed Jobs')
expect(page).to have_css('#js-tab-failures.active')
end
it 'lists failed builds' do
expect(page).to have_content(failed_build.name)
expect(page).to have_content(failed_build.stage)
end
it 'shows build failure logs' do
expect(page).to have_content('4 examples, 1 failure')
end
end
context 'when missing build logs' do
before do
visit pipeline_failures_page
end
it 'includes failed jobs' do
expect(page).to have_content('No job trace')
end
end
context 'without failures' do
before do
failed_build.update!(status: :success)
visit pipeline_failures_page
end
it 'displays the pipeline graph' do
expect(current_path).to eq(pipeline_path(pipeline))
expect(page).not_to have_content('Failed Jobs')
expect(page).to have_selector('.pipeline-visualization')
end
end
end
end end
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