diff --git a/subprojects/hydra/lib/Hydra/Controller/Build.pm b/subprojects/hydra/lib/Hydra/Controller/Build.pm
index ca9a22cff..43cd0a8f6 100644
--- a/subprojects/hydra/lib/Hydra/Controller/Build.pm
+++ b/subprojects/hydra/lib/Hydra/Controller/Build.pm
@@ -6,6 +6,7 @@ use warnings;
use base 'Hydra::Base::Controller::NixChannel';
use Hydra::Helper::Nix;
use Hydra::Helper::CatalystUtils;
+use Hydra::Helper::LogEndpoints;
use File::Basename;
use File::LibMagic;
use File::stat;
@@ -133,17 +134,13 @@ sub constituents_GET {
}
-sub view_nixlog : Chained('buildChain') PathPart('nixlog') {
+# Redirect old /build/:id/nixlog/:stepnr[/:mode] URLs to new canonical paths
+sub nixlog_redirect : Chained('buildChain') PathPart('nixlog') {
my ($self, $c, $stepnr, $mode) = @_;
- my $step = $c->stash->{build}->buildsteps->find({stepnr => $stepnr});
- notFound($c, "Build doesn't have a build step $stepnr.") if !defined $step;
-
- $c->stash->{step} = $step;
-
- my $drvPath = $step->drvpath;
- my $log_uri = $c->uri_for($c->controller('Root')->action_for("log"), [WWW::Form::UrlEncoded::PP::url_encode(basename($drvPath))]);
- showLog($c, $mode, $log_uri);
+ my @path = ('/build', $c->stash->{id}, 'step', $stepnr, 'log');
+ push @path, $mode if defined $mode;
+ $c->res->redirect($c->uri_for(@path), 301);
}
@@ -166,32 +163,6 @@ sub view_runcommandlog : Chained('buildChain') PathPart('runcommandlog') {
}
-sub showLog {
- my ($c, $mode, $log_uri) = @_;
- $mode //= "pretty";
-
- if ($mode eq "pretty") {
- $c->stash->{log_uri} = $log_uri;
- $c->stash->{template} = 'log.tt';
- }
-
- elsif ($mode eq "raw") {
- $c->res->redirect($log_uri);
- }
-
- elsif ($mode eq "tail") {
- my $lines = 50;
- $c->stash->{log_uri} = $log_uri . "?tail=$lines";
- $c->stash->{tail} = $lines;
- $c->stash->{template} = 'log.tt';
- }
-
- else {
- error($c, "Unknown log display mode '$mode'.");
- }
-}
-
-
sub defaultUriForProduct {
my ($self, $c, $product, @path) = @_;
my $x = $product->productnr
diff --git a/subprojects/hydra/lib/Hydra/Controller/BuildStep.pm b/subprojects/hydra/lib/Hydra/Controller/BuildStep.pm
new file mode 100644
index 000000000..6ba585601
--- /dev/null
+++ b/subprojects/hydra/lib/Hydra/Controller/BuildStep.pm
@@ -0,0 +1,38 @@
+package Hydra::Controller::BuildStep;
+
+use utf8;
+use strict;
+use warnings;
+use base 'Hydra::Base::Controller::REST';
+use Hydra::Helper::CatalystUtils;
+use Hydra::Helper::LogEndpoints;
+use File::Basename;
+use WWW::Form::UrlEncoded::PP qw();
+
+
+sub buildStepChain :Chained('/build/buildChain') :PathPart('step') :CaptureArgs(1) {
+ my ($self, $c, $stepnr) = @_;
+
+ my $step = $c->stash->{build}->buildsteps->find({stepnr => $stepnr});
+ notFound($c, "Build doesn't have a build step $stepnr.") if !defined $step;
+
+ $c->stash->{step} = $step;
+}
+
+
+sub buildStep : Chained('buildStepChain') PathPart('') Args(0) {
+ my ($self, $c) = @_;
+ $c->stash->{template} = 'build-step.tt';
+}
+
+
+sub view_nixlog : Chained('buildStepChain') PathPart('log') {
+ my ($self, $c, $mode) = @_;
+
+ my $drvPath = $c->stash->{step}->drvpath;
+ my $log_uri = $c->uri_for($c->controller('Root')->action_for("log"), [WWW::Form::UrlEncoded::PP::url_encode(basename($drvPath))]);
+ showLog($c, $mode, $log_uri);
+}
+
+
+1;
diff --git a/subprojects/hydra/lib/Hydra/Helper/LogEndpoints.pm b/subprojects/hydra/lib/Hydra/Helper/LogEndpoints.pm
new file mode 100644
index 000000000..685737498
--- /dev/null
+++ b/subprojects/hydra/lib/Hydra/Helper/LogEndpoints.pm
@@ -0,0 +1,36 @@
+package Hydra::Helper::LogEndpoints;
+
+use strict;
+use warnings;
+use Exporter;
+use Hydra::Helper::CatalystUtils;
+
+our @ISA = qw(Exporter);
+our @EXPORT = qw(showLog);
+
+sub showLog {
+ my ($c, $mode, $log_uri) = @_;
+ $mode //= "pretty";
+
+ if ($mode eq "pretty") {
+ $c->stash->{log_uri} = $log_uri;
+ $c->stash->{template} = 'log.tt';
+ }
+
+ elsif ($mode eq "raw") {
+ $c->res->redirect($log_uri);
+ }
+
+ elsif ($mode eq "tail") {
+ my $lines = 50;
+ $c->stash->{log_uri} = $log_uri . "?tail=$lines";
+ $c->stash->{tail} = $lines;
+ $c->stash->{template} = 'log.tt';
+ }
+
+ else {
+ error($c, "Unknown log display mode '$mode'.");
+ }
+}
+
+1;
diff --git a/subprojects/hydra/root/build-common.tt b/subprojects/hydra/root/build-common.tt
new file mode 100644
index 000000000..a26e88937
--- /dev/null
+++ b/subprojects/hydra/root/build-common.tt
@@ -0,0 +1,79 @@
+[% BLOCK renderLogButtons %]
+ url) %]>pretty
+ url _ "/raw") %]>raw
+ url _ "/tail") %]>tail
+[% END %]
+
+[% BLOCK renderOutputs %]
+ [% start=1; FOREACH output IN outputs %]
+ [% IF !start %],
[% END; start=0; output.path %]
+ [% END %]
+[% END %]
+
+[% BLOCK renderOutputsTable %]
+
+ [% FOREACH output IN outputs %]
+
+ | [% output.name | html %] |
+ [% IF output.path; output.path | html; ELSE %]n/a[% END %] |
+
+ [% END %]
+
+[% END; %]
+
+[% BLOCK renderStepDuration %]
+ [% IF step.busy == 0 %]
+ [% IF step.stoptime %]
+ [% INCLUDE renderDuration duration = step.stoptime - step.starttime %]
+ [% ELSE %]
+ n/a
+ [% END %]
+ [% ELSIF build.finished %]
+ [% INCLUDE renderDuration duration = build.stoptime - step.starttime %]
+ [% ELSE %]
+ [% INCLUDE renderDuration duration = curTime - step.starttime %]
+ [% END %]
+[% END %]
+
+[% BLOCK renderStepMachine %]
+ [% IF step.busy != 0 || ((step.machine || step.starttime) && (step.status == 0 || step.status == 1 || step.status == 3 || step.status == 4 || step.status == 7)) %]
+ [% INCLUDE renderMachineName machine=step.machine %]
+ [% ELSE %]
+ n/a
+ [% END %]
+[% END %]
+
+[% BLOCK renderStepStatus %]
+ [% IF step.busy != 0 %]
+ [% INCLUDE renderBusyStatus %]
+ [% ELSIF step.status == 0 %]
+ [% IF step.isnondeterministic %]
+ Succeeded with non-determistic result
+ [% ELSE %]
+ Succeeded
+ [% END %]
+ [% IF step.timesbuilt && step.timesbuilt > 1 %]
+ ([% step.timesbuilt %] times)
+ [% END %]
+ [% ELSIF step.status == 3 %]
+ Aborted[% IF step.errormsg %]: [% HTML.escape(step.errormsg) %][% END %]
+ [% ELSIF step.status == 4 %]
+ Cancelled
+ [% ELSIF step.status == 7 %]
+ Timed out
+ [% ELSIF step.status == 8 %]
+ Cached failure
+ [% ELSIF step.status == 9 %]
+ Unsupported system type
+ [% ELSIF step.status == 10 %]
+ Log limit exceeded
+ [% ELSIF step.status == 11 %]
+ Output limit exceeded
+ [% ELSIF step.status == 12 %]
+ Non-determinism detected[% IF step.timesbuilt %] after [% HTML.escape(step.timesbuilt) %] times[% END %]
+ [% ELSIF step.errormsg %]
+ Failed: [% HTML.escape(step.errormsg) %]
+ [% ELSE %]
+ Failed
+ [% END %]
+[% END %]
diff --git a/subprojects/hydra/root/build-step.tt b/subprojects/hydra/root/build-step.tt
new file mode 100644
index 000000000..38ce9a906
--- /dev/null
+++ b/subprojects/hydra/root/build-step.tt
@@ -0,0 +1,61 @@
+[%
+ buildUrl = c.uri_for('/build', build.id);
+%]
+[% WRAPPER layout.tt
+ title="Step ${step.stepnr} of build ${build.id} of job " _ makeNameTextForJob(build.jobset, job)
+ titleHTML="Step ${step.stepnr}"
+ _ " of build ${build.id}"
+ _ " of job " _ linkToJob(build.jobset, job)
+%]
+[% PROCESS common.tt %]
+[% PROCESS "build-common.tt" %]
+[% USE HTML %]
+
+[% logUrl = c.uri_for('/build' build.id 'step' step.stepnr 'log') %]
+[% has_log = buildStepLogExists(step) %]
+
+
+
+ | Type: |
+ [% IF step.type == 0 %]Build[% ELSE %]Substitution[% END %] |
+
+
+ | Derivation: |
+ [% step.drvpath | html %] |
+
+
+ | Output store paths: |
+ [% INCLUDE renderOutputsTable outputs=step.buildstepoutputs %] |
+
+ [% IF step.system %]
+
+ | System: |
+ [% step.system | html %] |
+
+ [% END %]
+
+ | Machine: |
+ [% INCLUDE renderStepMachine %] |
+
+
+ | Duration: |
+ [% INCLUDE renderStepDuration %] |
+
+
+ | Status: |
+
+ [% INCLUDE renderStepStatus %]
+ [% IF step.propagatedfrom %]
+ (propagated from [% INCLUDE renderBuildIdLink id=step.propagatedfrom.get_column('id') %])
+ [% END %]
+ |
+
+ [% IF has_log %]
+
+ | Logfile: |
+ [% INCLUDE renderLogButtons url=logUrl %] |
+
+ [% END %]
+
+
+[% END %]
diff --git a/subprojects/hydra/root/build.tt b/subprojects/hydra/root/build.tt
index 23fc5493b..3263b1101 100644
--- a/subprojects/hydra/root/build.tt
+++ b/subprojects/hydra/root/build.tt
@@ -3,6 +3,7 @@
titleHTML="Build $id of job " _ linkToJob(jobset, job)
%]
[% PROCESS common.tt %]
+[% PROCESS "build-common.tt" %]
[% PROCESS "product-list.tt" %]
[% USE HTML %]
[% USE Date %]
@@ -19,23 +20,6 @@ FOR step IN steps;
END;
%]
-[% BLOCK renderOutputs %]
- [% start=1; FOREACH output IN outputs %]
- [% IF !start %],
[% END; start=0; output.path %]
- [% END %]
-[% END %]
-
-[% BLOCK renderOutputsTable %]
-
- [% FOREACH output IN outputs %]
-
- | [% output.name | html %] |
- [% IF output.path; output.path | html; ELSE %]n/a[% END %] |
-
- [% END %]
-
-[% END; %]
-
[% BLOCK renderBuildSteps %]
@@ -46,9 +30,10 @@ END;
[% IF ( type == "All" ) || ( type == "Failed" && step.busy == 0 && step.status != 0 ) || ( type == "Running" && step.busy != 0 ) %]
[% has_log = seen.${step.drvpath} ? 0 : buildStepLogExists(step);
seen.${step.drvpath} = 1;
- log = c.uri_for('/build' build.id 'nixlog' step.stepnr); %]
+ stepUrl = c.uri_for('/build' build.id 'step' step.stepnr);
+ logUrl = c.uri_for('/build' build.id 'step' step.stepnr 'log'); %]
- | [% HTML.escape(step.stepnr) %] |
+ stepUrl) %]>[% HTML.escape(step.stepnr) %] |
[% IF step.type == 0 %]
Build of [% INCLUDE renderOutputs outputs=step.buildstepoutputs %]
@@ -56,54 +41,11 @@ END;
Substitution of [% INCLUDE renderOutputs outputs=step.buildstepoutputs %]
[% END %]
|
-
- [% IF step.busy == 0;
- IF step.stoptime;
- INCLUDE renderDuration duration = step.stoptime - step.starttime;
- ELSE;
- %]n/a[%
- END;
- ELSIF build.finished;
- INCLUDE renderDuration duration = build.stoptime - step.starttime;
- ELSE;
- INCLUDE renderDuration duration = curTime - step.starttime;
- END %]
- |
- [% IF step.busy != 0 || ((step.machine || step.starttime) && (step.status == 0 || step.status == 1 || step.status == 3 || step.status == 4 || step.status == 7)); INCLUDE renderMachineName machine=step.machine; ELSE; "n/a"; END %] |
+ [% INCLUDE renderStepDuration %] |
+ [% INCLUDE renderStepMachine %] |
- [% IF step.busy != 0 %]
- [% INCLUDE renderBusyStatus %]
- [% ELSIF step.status == 0 %]
- [% IF step.isnondeterministic %]
- Succeeded with non-determistic result
- [% ELSE %]
- Succeeded
- [% END %]
- [% IF step.timesbuilt && step.timesbuilt > 1 %]
- ([% step.timesbuilt %] times)
- [% END %]
- [% ELSIF step.status == 3 %]
- Aborted[% IF step.errormsg %]: [% HTML.escape(step.errormsg) %][% END %]
- [% ELSIF step.status == 4 %]
- Cancelled
- [% ELSIF step.status == 7 %]
- Timed out
- [% ELSIF step.status == 8 %]
- Cached failure
- [% ELSIF step.status == 9 %]
- Unsupported system type
- [% ELSIF step.status == 10 %]
- Log limit exceeded
- [% ELSIF step.status == 11 %]
- Output limit exceeded
- [% ELSIF step.status == 12 %]
- Non-determinism detected [% IF step.timesbuilt %] after [% HTML.escape(step.timesbuilt) %] times[% END %]
- [% ELSIF step.errormsg %]
- Failed: [% HTML.escape(step.errormsg) %]
- [% ELSE %]
- Failed
- [% END %]
- [%%] [%+ IF has_log; INCLUDE renderLogLinks url=log inRow=1; END %]
+ [% INCLUDE renderStepStatus %]
+ [%%] [%+ IF has_log; INCLUDE renderLogLinks url=logUrl; END %]
[%+ IF step.propagatedfrom; %](propagated from [% INCLUDE renderBuildIdLink id=step.propagatedfrom.get_column('id') %])[% END %]
|
@@ -236,10 +178,8 @@ END;
| Logfile: |
- [% actualLog = cachedBuildStep ? c.uri_for('/build' cachedBuild.id 'nixlog' cachedBuildStep.stepnr) : c.uri_for('/build' build.id 'log') %]
- actualLog) %]>pretty
- actualLog _ "/raw") %]>raw
- actualLog _ "/tail") %]>tail
+ [% actualLog = cachedBuildStep ? c.uri_for('/build' cachedBuild.id 'step' cachedBuildStep.stepnr 'log') : c.uri_for('/build' build.id 'log') %]
+ [% INCLUDE renderLogButtons url=actualLog %]
|
[% END %]
@@ -542,11 +482,7 @@ END;
[% END %]
[% IF runcommandlog.uuid != undef %]
[% runLog = c.uri_for('/build', build.id, 'runcommandlog', runcommandlog.uuid) %]
-
+ [% INCLUDE renderLogButtons url=runLog %]
[% END %]
[% ELSE %]
diff --git a/subprojects/hydra/root/deps.tt b/subprojects/hydra/root/deps.tt
index 4cb49af49..91a08335d 100644
--- a/subprojects/hydra/root/deps.tt
+++ b/subprojects/hydra/root/deps.tt
@@ -13,7 +13,7 @@
[% IF node.buildStep %]
c.uri_for('/build' node.buildStep.get_column('build'))) %]>[% node.name %] [%
IF buildStepLogExists(node.buildStep);
- INCLUDE renderLogLinks url=c.uri_for('/build' node.buildStep.get_column('build') 'nixlog' node.buildStep.stepnr);
+ INCLUDE renderLogLinks url=c.uri_for('/build' node.buildStep.get_column('build') 'step' node.buildStep.stepnr 'log');
END %]
[% ELSE %]
[% node.name | html %] (no info)
diff --git a/subprojects/hydra/root/log.tt b/subprojects/hydra/root/log.tt
index 999c849e0..164a964c7 100644
--- a/subprojects/hydra/root/log.tt
+++ b/subprojects/hydra/root/log.tt
@@ -1,10 +1,11 @@
[%
buildUrl = c.uri_for('/build', build.id);
IF step;
- logUrl = c.uri_for('/build', build.id, 'nixlog', step.stepnr);
+ stepUrl = c.uri_for('/build', build.id, 'step', step.stepnr);
+ logUrl = c.uri_for('/build', build.id, 'step', step.stepnr, 'log');
drvpath = step.drvpath;
titleText = "Log of step ${step.stepnr} of build ${build.id} of job " _ makeNameTextForJob(build.jobset, job);
- titleLink = "Log of step ${step.stepnr}"
+ titleLink = "Log of step ${step.stepnr}"
_ " of build ${build.id}"
_ " of job " _ linkToJob(build.jobset, job);
ELSE;
diff --git a/subprojects/hydra/root/machine-status.tt b/subprojects/hydra/root/machine-status.tt
index e8113beaf..fa777f93a 100644
--- a/subprojects/hydra/root/machine-status.tt
+++ b/subprojects/hydra/root/machine-status.tt
@@ -77,7 +77,7 @@
| [% INCLUDE renderFullJobName project=step.project jobset=step.jobset job=step.job %] |
c.uri_for('/build' step.build)) %]>[% HTML.escape(step.build) %] |
- [% IF step.busy >= 30 %] c.uri_for('/build' step.build 'nixlog' step.stepnr 'tail')) %]>[% HTML.escape(step.stepnr) %][% ELSE; HTML.escape(step.stepnr); END %] |
+ [% IF step.busy >= 30 %] c.uri_for('/build' step.build 'step' step.stepnr 'log' 'tail')) %]>[% HTML.escape(step.stepnr) %][% ELSE; HTML.escape(step.stepnr); END %] |
[% step.drvpath.match('-(.*)').0 | html %] |
[% INCLUDE renderBusyStatus %] |
[% INCLUDE renderDuration duration = curTime - step.starttime %] |
diff --git a/subprojects/hydra/root/steps.tt b/subprojects/hydra/root/steps.tt
index e53a41b70..703226a65 100644
--- a/subprojects/hydra/root/steps.tt
+++ b/subprojects/hydra/root/steps.tt
@@ -25,7 +25,7 @@ order of descending finish time.
[% step.drvpath.match('-(.*).drv').0 %] |
[% INCLUDE renderFullJobNameOfBuild build=step.build %] |
c.uri_for('/build' step.build.id)) %]>[% HTML.escape(step.build.id) %] |
- c.uri_for('/build' step.build.id 'nixlog' step.stepnr 'tail')) %]>[% HTML.escape(step.stepnr) %] |
+ c.uri_for('/build' step.build.id 'step' step.stepnr 'log' 'tail')) %]>[% HTML.escape(step.stepnr) %] |
[% INCLUDE renderRelativeDate timestamp=step.stoptime %] |
[% INCLUDE renderDuration duration = step.stoptime - step.starttime %] |
[% INCLUDE renderMachineName machine=step.machine %] |