Commit 4c0adb9e authored by James Edwards-Jones's avatar James Edwards-Jones

Build failures summary page for pipelines

parent 992aafbc
...@@ -232,6 +232,7 @@ const ShortcutsBlob = require('./shortcuts_blob'); ...@@ -232,6 +232,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]
...@@ -67,11 +67,11 @@ class Projects::PipelinesController < Projects::ApplicationController ...@@ -67,11 +67,11 @@ class Projects::PipelinesController < Projects::ApplicationController
end end
def builds def builds
respond_to do |format| render_show
format.html do
render 'show'
end
end end
def failures
render_show
end end
def status def status
...@@ -111,6 +111,14 @@ class Projects::PipelinesController < Projects::ApplicationController ...@@ -111,6 +111,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)
if build.has_trace?
build.trace.html(last_lines: 10).html_safe
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
......
...@@ -7,8 +7,10 @@ ...@@ -7,8 +7,10 @@
= 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
%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
Failures
%span.badge.js-failures-counter= pipeline.statuses.latest.failed.count
.tab-content .tab-content
#js-tab-pipeline.tab-pane #js-tab-pipeline.tab-pane
...@@ -39,3 +41,13 @@ ...@@ -39,3 +41,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
#js-tab-failures.build-failures.tab-pane
- failed = @pipeline.statuses.latest.failed
- failed.each do |build|
.build-state
%span.ci-status-icon-failed= custom_icon('icon_status_failed')
%span.stage
= build.stage.titleize
%span.build-name
= render "notify/links/#{build.to_partial_path}", pipeline: @pipeline, build: build
%pre.build-log= build_summary(build)
---
title: Added build failures summary page for pipelines
merge_request: 10719
author:
...@@ -155,6 +155,7 @@ constraints(ProjectUrlConstrainer.new) do ...@@ -155,6 +155,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,42 @@ describe 'Pipeline', :feature, :js do ...@@ -254,4 +254,42 @@ 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_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
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