summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJames Edwards-Jones <jedwardsjones@gitlab.com>2017-04-16 02:33:01 +0100
committerJames Edwards-Jones <jedwardsjones@gitlab.com>2017-05-05 15:01:50 +0100
commit4c0adb9ee9ee6631b7cda6562d0e20b7daab8a9e (patch)
treebc5ca0c37afcbe140cfb4bad2752e32ba35043dc
parent992aafbc03e315b6f8fa6355ab1856934f95d758 (diff)
downloadgitlab-ce-4c0adb9ee9ee6631b7cda6562d0e20b7daab8a9e.tar.gz
Build failures summary page for pipelines
-rw-r--r--app/assets/javascripts/dispatcher.js1
-rw-r--r--app/assets/stylesheets/pages/pipelines.scss26
-rw-r--r--app/controllers/projects/pipelines_controller.rb20
-rw-r--r--app/helpers/builds_helper.rb8
-rw-r--r--app/views/projects/pipelines/_with_tabs.html.haml16
-rw-r--r--changelogs/unreleased/24883-build-failure-summary-page.yml4
-rw-r--r--config/routes/project.rb1
-rw-r--r--spec/features/projects/pipelines/pipeline_spec.rb38
8 files changed, 106 insertions, 8 deletions
diff --git a/app/assets/javascripts/dispatcher.js b/app/assets/javascripts/dispatcher.js
index f277e1dddc7..32cc6623c7e 100644
--- a/app/assets/javascripts/dispatcher.js
+++ b/app/assets/javascripts/dispatcher.js
@@ -232,6 +232,7 @@ const ShortcutsBlob = require('./shortcuts_blob');
}
break;
case 'projects:pipelines:builds':
+ case 'projects:pipelines:failures':
case 'projects:pipelines:show':
const { controllerAction } = document.querySelector('.js-pipeline-container').dataset;
const pipelineStatusUrl = `${document.querySelector('.js-pipeline-tab-link a').getAttribute('href')}/status.json`;
diff --git a/app/assets/stylesheets/pages/pipelines.scss b/app/assets/stylesheets/pages/pipelines.scss
index a4fe652b52f..22500698af3 100644
--- a/app/assets/stylesheets/pages/pipelines.scss
+++ b/app/assets/stylesheets/pages/pipelines.scss
@@ -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 {
width: 100%;
diff --git a/app/controllers/projects/pipelines_controller.rb b/app/controllers/projects/pipelines_controller.rb
index 1780cc0233c..915f0bc63f7 100644
--- a/app/controllers/projects/pipelines_controller.rb
+++ b/app/controllers/projects/pipelines_controller.rb
@@ -1,6 +1,6 @@
class Projects::PipelinesController < Projects::ApplicationController
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_create_pipeline!, only: [:new, :create]
before_action :authorize_update_pipeline!, only: [:retry, :cancel]
@@ -67,11 +67,11 @@ class Projects::PipelinesController < Projects::ApplicationController
end
def builds
- respond_to do |format|
- format.html do
- render 'show'
- end
- end
+ render_show
+ end
+
+ def failures
+ render_show
end
def status
@@ -111,6 +111,14 @@ class Projects::PipelinesController < Projects::ApplicationController
private
+ def render_show
+ respond_to do |format|
+ format.html do
+ render 'show'
+ end
+ end
+ end
+
def create_params
params.require(:pipeline).permit(:ref)
end
diff --git a/app/helpers/builds_helper.rb b/app/helpers/builds_helper.rb
index 2fcb7a59fc3..0145029fb60 100644
--- a/app/helpers/builds_helper.rb
+++ b/app/helpers/builds_helper.rb
@@ -1,4 +1,12 @@
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)
build_class = ''
build_class += ' active' if build.id === current_build.id
diff --git a/app/views/projects/pipelines/_with_tabs.html.haml b/app/views/projects/pipelines/_with_tabs.html.haml
index d7cefb8613e..76eb8533cc3 100644
--- a/app/views/projects/pipelines/_with_tabs.html.haml
+++ b/app/views/projects/pipelines/_with_tabs.html.haml
@@ -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
Jobs
%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
#js-tab-pipeline.tab-pane
@@ -39,3 +41,13 @@
%th Coverage
%th
= 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)
diff --git a/changelogs/unreleased/24883-build-failure-summary-page.yml b/changelogs/unreleased/24883-build-failure-summary-page.yml
new file mode 100644
index 00000000000..214cd3e2bc7
--- /dev/null
+++ b/changelogs/unreleased/24883-build-failure-summary-page.yml
@@ -0,0 +1,4 @@
+---
+title: Added build failures summary page for pipelines
+merge_request: 10719
+author:
diff --git a/config/routes/project.rb b/config/routes/project.rb
index f5009186344..5f5b41afbf4 100644
--- a/config/routes/project.rb
+++ b/config/routes/project.rb
@@ -155,6 +155,7 @@ constraints(ProjectUrlConstrainer.new) do
post :cancel
post :retry
get :builds
+ get :failures
get :status
end
end
diff --git a/spec/features/projects/pipelines/pipeline_spec.rb b/spec/features/projects/pipelines/pipeline_spec.rb
index 5a53e48f5f8..ab7c002704d 100644
--- a/spec/features/projects/pipelines/pipeline_spec.rb
+++ b/spec/features/projects/pipelines/pipeline_spec.rb
@@ -254,4 +254,42 @@ describe 'Pipeline', :feature, :js do
it { expect(build_manual.reload).to be_pending }
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