Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-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.rb22
-rw-r--r--app/helpers/builds_helper.rb12
-rw-r--r--app/views/projects/pipelines/_with_tabs.html.haml19
-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.rb53
8 files changed, 131 insertions, 7 deletions
diff --git a/app/assets/javascripts/dispatcher.js b/app/assets/javascripts/dispatcher.js
index b87c57c38fe..b16ff2a0221 100644
--- a/app/assets/javascripts/dispatcher.js
+++ b/app/assets/javascripts/dispatcher.js
@@ -252,6 +252,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 9115d26c779..5cca77b5bf3 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 2908036607a..f9adedcb074 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]
@@ -69,10 +69,14 @@ class Projects::PipelinesController < Projects::ApplicationController
end
def builds
- respond_to do |format|
- format.html do
- render 'show'
- end
+ render_show
+ end
+
+ def failures
+ if @pipeline.statuses.latest.failed.present?
+ render_show
+ else
+ redirect_to pipeline_path(@pipeline)
end
end
@@ -125,6 +129,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..2eb2c6c7389 100644
--- a/app/helpers/builds_helper.rb
+++ b/app/helpers/builds_helper.rb
@@ -1,4 +1,16 @@
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)
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..1aa48bf9813 100644
--- a/app/views/projects/pipelines/_with_tabs.html.haml
+++ b/app/views/projects/pipelines/_with_tabs.html.haml
@@ -1,3 +1,5 @@
+- failed_builds = @pipeline.statuses.latest.failed
+
.tabs-holder
%ul.pipelines-tabs.nav-links.no-top.no-bottom
%li.js-pipeline-tab-link
@@ -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
Jobs
%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
#js-tab-pipeline.tab-pane
@@ -39,3 +44,13 @@
%th Coverage
%th
= 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)
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 085f5a24e2e..68474a44368 100644
--- a/config/routes/project.rb
+++ b/config/routes/project.rb
@@ -123,6 +123,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..cfac54ef259 100644
--- a/spec/features/projects/pipelines/pipeline_spec.rb
+++ b/spec/features/projects/pipelines/pipeline_spec.rb
@@ -254,4 +254,57 @@ 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_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