Commit eb75844f authored by Phil Hughes's avatar Phil Hughes

Merge branch '44267-improve-failed-jobs-tab' into 'master'

Resolve "Show `failure_reason` and improve failed jobs tab in pipeline detail view"

Closes #44267

See merge request gitlab-org/gitlab-ce!19485
parents d2aa3e3d d64ab8df
...@@ -39,6 +39,11 @@ table { ...@@ -39,6 +39,11 @@ table {
&.wide { &.wide {
width: 55%; width: 55%;
} }
&.table-th-transparent {
background: none;
color: $gl-text-color-secondary;
}
} }
td { td {
...@@ -46,9 +51,86 @@ table { ...@@ -46,9 +51,86 @@ table {
} }
} }
} }
&.responsive-table {
@include media-breakpoint-down(sm) {
thead {
display: none;
}
td {
display: block;
color: $gl-text-color-secondary;
}
tbody td.responsive-table-cell {
padding: $gl-padding 0;
width: 100%;
display: flex;
text-align: right;
align-items: center;
justify-content: space-between;
&[data-column]::before {
content: attr(data-column);
display: block;
text-align: left;
padding-right: $gl-padding;
color: $gl-text-color-secondary;
}
&:not([data-column]) {
flex-direction: row-reverse;
}
}
tr.responsive-table-border-start,
tr.responsive-table-border-end {
display: block;
border: solid $gl-text-color-quaternary;
padding-left: 0;
padding-right: 0;
> td {
border-color: $gl-text-color-quaternary;
&,
&:last-child {
padding-left: $gl-padding;
padding-right: $gl-padding;
}
}
}
tr.responsive-table-border-start {
border-width: 1px 1px 0;
border-radius: $border-radius-default $border-radius-default 0 0;
padding-top: 0;
padding-bottom: 0;
> td:first-child {
border-top: 0; // always have the <table> top border
}
> td:last-child {
border-bottom: 1px solid $gl-text-color-quaternary;
}
}
tr.responsive-table-border-end {
border-width: 0 1px 1px;
border-radius: 0 0 $border-radius-default $border-radius-default;
margin-bottom: 2 * $gl-padding;
> :last-child {
border-bottom: 0;
}
}
}
}
} }
.responsive-table { .responsive-table:not(table) {
@include media-breakpoint-down(sm) { @include media-breakpoint-down(sm) {
th { th {
width: 100%; width: 100%;
......
...@@ -12,26 +12,22 @@ ...@@ -12,26 +12,22 @@
@keyframes blinking-dots { @keyframes blinking-dots {
0% { 0% {
background-color: rgba($white-light, 1); background-color: rgba($white-light, 1);
box-shadow: 12px 0 0 0 rgba($white-light, 0.2), box-shadow: 12px 0 0 0 rgba($white-light, 0.2), 24px 0 0 0 rgba($white-light, 0.2);
24px 0 0 0 rgba($white-light, 0.2);
} }
25% { 25% {
background-color: rgba($white-light, 0.4); background-color: rgba($white-light, 0.4);
box-shadow: 12px 0 0 0 rgba($white-light, 2), box-shadow: 12px 0 0 0 rgba($white-light, 2), 24px 0 0 0 rgba($white-light, 0.2);
24px 0 0 0 rgba($white-light, 0.2);
} }
75% { 75% {
background-color: rgba($white-light, 0.4); background-color: rgba($white-light, 0.4);
box-shadow: 12px 0 0 0 rgba($white-light, 0.2), box-shadow: 12px 0 0 0 rgba($white-light, 0.2), 24px 0 0 0 rgba($white-light, 1);
24px 0 0 0 rgba($white-light, 1);
} }
100% { 100% {
background-color: rgba($white-light, 1); background-color: rgba($white-light, 1);
box-shadow: 12px 0 0 0 rgba($white-light, 0.2), box-shadow: 12px 0 0 0 rgba($white-light, 0.2), 24px 0 0 0 rgba($white-light, 0.2);
24px 0 0 0 rgba($white-light, 0.2);
} }
} }
...@@ -71,6 +67,10 @@ ...@@ -71,6 +67,10 @@
.bash { .bash {
display: block; display: block;
} }
&.build-trace-rounded {
border-radius: $border-radius-base;
}
} }
.top-bar { .top-bar {
......
...@@ -321,18 +321,17 @@ ...@@ -321,18 +321,17 @@
} }
.build-failures { .build-failures {
th {
border-top: 0;
}
.build-state { .build-state {
padding: 20px 2px; padding: 20px 2px;
.build-name { .build-name {
float: right;
font-weight: $gl-font-weight-normal; font-weight: $gl-font-weight-normal;
} }
.ci-status-icon-failed svg {
vertical-align: middle;
}
.stage { .stage {
color: $gl-text-color-secondary; color: $gl-text-color-secondary;
font-weight: $gl-font-weight-normal; font-weight: $gl-font-weight-normal;
...@@ -344,6 +343,81 @@ ...@@ -344,6 +343,81 @@
border: 0; border: 0;
line-height: initial; line-height: initial;
} }
.build-trace-row td {
border-top: 0;
border-bottom-width: 1px;
border-bottom-style: solid;
padding-top: 0;
}
.build-trace {
width: 100%;
text-align: left;
margin-top: $gl-padding;
}
.build-name {
width: 196px;
a {
font-weight: $gl-font-weight-bold;
color: $gl-text-color;
text-decoration: none;
&:focus,
&:hover {
text-decoration: underline;
}
}
}
.build-actions {
width: 70px;
text-align: right;
}
.build-stage {
width: 140px;
}
.ci-status-icon-failed {
padding: 10px 0 10px 12px;
width: 12px + 24px; // padding-left + svg width
}
.build-icon svg {
width: 24px;
height: 24px;
vertical-align: middle;
}
.build-state,
.build-trace-row {
> td:last-child {
padding-right: 0;
}
}
@include media-breakpoint-down(sm) {
td:empty {
display: none;
}
.ci-table {
margin-top: 2 * $gl-padding;
}
.build-trace-container {
padding-top: $gl-padding;
padding-bottom: $gl-padding;
}
.build-trace {
margin-bottom: 0;
margin-top: 0;
}
}
} }
.pipeline-tab-content { .pipeline-tab-content {
...@@ -929,7 +1003,7 @@ button.mini-pipeline-graph-dropdown-toggle { ...@@ -929,7 +1003,7 @@ button.mini-pipeline-graph-dropdown-toggle {
&.dropdown-menu { &.dropdown-menu {
transform: translate(-80%, 0); transform: translate(-80%, 0);
@media(min-width: map-get($grid-breakpoints, md)) { @media (min-width: map-get($grid-breakpoints, md)) {
transform: translate(-50%, 0); transform: translate(-50%, 0);
right: auto; right: auto;
left: 50%; left: 50%;
......
.tabs-holder .tabs-holder
%ul.pipelines-tabs.nav-links.no-top.no-bottom.mobile-separator.nav.nav-tabs %ul.pipelines-tabs.nav-links.no-top.no-bottom.mobile-separator.nav.nav-tabs
%li.js-pipeline-tab-link %li.js-pipeline-tab-link
= link_to project_pipeline_path(@project, @pipeline), data: { target: '#js-tab-pipeline', action: 'pipelines', toggle: 'tab' }, class: 'pipeline-tab' do = link_to project_pipeline_path(@project, @pipeline), data: { target: '#js-tab-pipeline', action: 'pipelines', toggle: 'tab' }, class: 'pipeline-tab' do
= _("Pipeline") = _("Pipeline")
%li.js-builds-tab-link %li.js-builds-tab-link
= link_to builds_project_pipeline_path(@project, @pipeline), data: { target: '#js-tab-builds', action: 'builds', toggle: 'tab' }, class: 'builds-tab' do = link_to builds_project_pipeline_path(@project, @pipeline), data: { target: '#js-tab-builds', action: 'builds', toggle: 'tab' }, class: 'builds-tab' do
...@@ -43,12 +43,36 @@ ...@@ -43,12 +43,36 @@
= render partial: "projects/stage/stage", collection: pipeline.legacy_stages, as: :stage = render partial: "projects/stage/stage", collection: pipeline.legacy_stages, as: :stage
- if @pipeline.failed_builds.present? - if @pipeline.failed_builds.present?
#js-tab-failures.build-failures.tab-pane #js-tab-failures.build-failures.tab-pane.build-page
- @pipeline.failed_builds.each_with_index do |build, index| %table.table.responsive-table.ci-table.responsive-table-sm-rounded
.build-state %thead
%span.ci-status-icon-failed= custom_icon('icon_status_failed') %th.table-th-transparent
%span.stage %th.table-th-transparent= _("Name")
= build.stage.titleize %th.table-th-transparent= _("Stage")
%span.build-name %th.table-th-transparent= _("Failure")
= link_to build.name, pipeline_job_url(pipeline, build)
%pre.build-log= build_summary(build, skip: index >= 10) %tbody
- @pipeline.failed_builds.each_with_index do |build, index|
- job = build.present(current_user: current_user)
%tr.build-state.responsive-table-border-start
%td.responsive-table-cell.ci-status-icon-failed{ data: { column: "Status"} }
.d-none.d-md-block.build-icon
= custom_icon("icon_status_#{build.status}")
.d-md-none.build-badge
= render "ci/status/badge", link: false, status: job.detailed_status(current_user)
%td.responsive-table-cell.build-name{ data: { column: _("Name")} }
= link_to build.name, pipeline_job_url(pipeline, build)
%td.responsive-table-cell.build-stage{ data: { column: _("Stage")} }
= build.stage.titleize
%td.responsive-table-cell.build-failure{ data: { column: _("Failure")} }
= build.present.callout_failure_message
%td.responsive-table-cell.build-actions
= link_to retry_project_job_path(build.project, build, return_to: request.original_url), method: :post, title: _('Retry'), class: 'btn btn-build' do
= icon('repeat')
%tr.build-trace-row.responsive-table-border-end
%td
%td.responsive-table-cell.build-trace-container{ colspan: 4 }
%pre.build-trace.build-trace-rounded
%code.bash.js-build-output
= build_summary(build)
---
title: Improve Failed Jobs tab in the Pipeline detail page
merge_request:
author:
type: changed
...@@ -344,6 +344,16 @@ describe 'Pipeline', :js do ...@@ -344,6 +344,16 @@ describe 'Pipeline', :js do
it 'shows build failure logs' do it 'shows build failure logs' do
expect(page).to have_content('4 examples, 1 failure') expect(page).to have_content('4 examples, 1 failure')
end end
it 'shows the failure reason' do
expect(page).to have_content('There is an unknown failure, please try again')
end
it 'shows retry button for failed build' do
page.within(find('.build-failures', match: :first)) do
expect(page).to have_link('Retry')
end
end
end end
context 'when missing build logs' do context 'when missing build logs' do
......
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