forked from lix-project/hydra
* Get rid of "positive failures" and separate log phases.
* Specifically log, for a build, whether the top-level derivation failed, or some dependency failed, or Nix itself barfed. In the latter case log the error output from Nix.
This commit is contained in:
parent
125d7a985e
commit
e742833da3
|
@ -301,20 +301,18 @@ sub build :Local {
|
||||||
|
|
||||||
|
|
||||||
sub log :Local {
|
sub log :Local {
|
||||||
my ( $self, $c, $id, $logPhase ) = @_;
|
my ( $self, $c, $id ) = @_;
|
||||||
|
|
||||||
my $build = getBuild($c, $id);
|
my $build = getBuild($c, $id);
|
||||||
return error($c, "Build with ID $id doesn't exist.") if !defined $build;
|
return error($c, "Build $id doesn't exist.") if !defined $build;
|
||||||
|
|
||||||
my $log = $build->buildlogs->find({logphase => $logPhase});
|
return error($c, "Build $id didn't produce a log.") if !defined $build->resultInfo->logfile;
|
||||||
return error($c, "Build $id doesn't have a log phase named $logPhase.") if !defined $log;
|
|
||||||
|
|
||||||
$c->stash->{template} = 'log.tt';
|
$c->stash->{template} = 'log.tt';
|
||||||
$c->stash->{id} = $id;
|
$c->stash->{build} = $build;
|
||||||
$c->stash->{log} = $log;
|
|
||||||
|
|
||||||
# !!! should be done in the view (as a TT plugin).
|
# !!! should be done in the view (as a TT plugin).
|
||||||
$c->stash->{logtext} = loadLog($log->path);
|
$c->stash->{logtext} = loadLog($build->resultInfo->logfile);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -341,6 +339,8 @@ sub nixlog :Local {
|
||||||
sub loadLog {
|
sub loadLog {
|
||||||
my ($path) = @_;
|
my ($path) = @_;
|
||||||
|
|
||||||
|
die unless defined $path;
|
||||||
|
|
||||||
# !!! quick hack
|
# !!! quick hack
|
||||||
my $pipeline = ($path =~ /.bz2$/ ? "cat $path | bzip2 -d" : "cat $path")
|
my $pipeline = ($path =~ /.bz2$/ ? "cat $path | bzip2 -d" : "cat $path")
|
||||||
. " | nix-log2xml | xsltproc xsl/mark-errors.xsl - | xsltproc xsl/log2html.xsl - | tail -n +2";
|
. " | nix-log2xml | xsltproc xsl/mark-errors.xsl - | xsltproc xsl/log2html.xsl - | tail -n +2";
|
||||||
|
|
|
@ -8,8 +8,8 @@ use base 'DBIx::Class::Schema';
|
||||||
__PACKAGE__->load_classes;
|
__PACKAGE__->load_classes;
|
||||||
|
|
||||||
|
|
||||||
# Created by DBIx::Class::Schema::Loader v0.04005 @ 2008-11-17 17:09:46
|
# Created by DBIx::Class::Schema::Loader v0.04005 @ 2008-11-24 17:46:46
|
||||||
# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:uZCNqZeWS46Z2RdysLEDaA
|
# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:rS2THZrlrDHnIAWmvduE1g
|
||||||
|
|
||||||
|
|
||||||
# You can replace this text with custom content, and it will be preserved on regeneration
|
# You can replace this text with custom content, and it will be preserved on regeneration
|
||||||
|
|
|
@ -29,7 +29,7 @@ __PACKAGE__->add_columns(
|
||||||
"path",
|
"path",
|
||||||
{ data_type => "text", is_nullable => 0, size => undef },
|
{ data_type => "text", is_nullable => 0, size => undef },
|
||||||
"sha256hash",
|
"sha256hash",
|
||||||
{ data_type => "VARCHAR", is_nullable => 0, size => undef },
|
{ data_type => "text", is_nullable => 0, size => undef },
|
||||||
);
|
);
|
||||||
__PACKAGE__->set_primary_key("id");
|
__PACKAGE__->set_primary_key("id");
|
||||||
__PACKAGE__->belongs_to("build", "HydraFrontend::Schema::Builds", { id => "build" });
|
__PACKAGE__->belongs_to("build", "HydraFrontend::Schema::Builds", { id => "build" });
|
||||||
|
@ -40,8 +40,8 @@ __PACKAGE__->belongs_to(
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
# Created by DBIx::Class::Schema::Loader v0.04005 @ 2008-11-17 17:09:46
|
# Created by DBIx::Class::Schema::Loader v0.04005 @ 2008-11-24 17:46:46
|
||||||
# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:96p2HKZ/6kk0zZKq3JuvDg
|
# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:9u9ep3Cq/SginPyhrzXlTA
|
||||||
|
|
||||||
|
|
||||||
# You can replace this text with custom content, and it will be preserved on regeneration
|
# You can replace this text with custom content, and it will be preserved on regeneration
|
||||||
|
|
|
@ -1,29 +0,0 @@
|
||||||
package HydraFrontend::Schema::Buildlogs;
|
|
||||||
|
|
||||||
use strict;
|
|
||||||
use warnings;
|
|
||||||
|
|
||||||
use base 'DBIx::Class';
|
|
||||||
|
|
||||||
__PACKAGE__->load_components("Core");
|
|
||||||
__PACKAGE__->table("BuildLogs");
|
|
||||||
__PACKAGE__->add_columns(
|
|
||||||
"build",
|
|
||||||
{ data_type => "integer", is_nullable => 0, size => undef },
|
|
||||||
"logphase",
|
|
||||||
{ data_type => "text", is_nullable => 0, size => undef },
|
|
||||||
"path",
|
|
||||||
{ data_type => "text", is_nullable => 0, size => undef },
|
|
||||||
"type",
|
|
||||||
{ data_type => "text", is_nullable => 0, size => undef },
|
|
||||||
);
|
|
||||||
__PACKAGE__->set_primary_key("build", "logphase");
|
|
||||||
__PACKAGE__->belongs_to("build", "HydraFrontend::Schema::Builds", { id => "build" });
|
|
||||||
|
|
||||||
|
|
||||||
# Created by DBIx::Class::Schema::Loader v0.04005 @ 2008-11-17 17:09:46
|
|
||||||
# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:zWuDHHMl7eWUWU238D5MWg
|
|
||||||
|
|
||||||
|
|
||||||
# You can replace this text with custom content, and it will be preserved on regeneration
|
|
||||||
1;
|
|
|
@ -33,8 +33,8 @@ __PACKAGE__->set_primary_key("build", "productnr");
|
||||||
__PACKAGE__->belongs_to("build", "HydraFrontend::Schema::Builds", { id => "build" });
|
__PACKAGE__->belongs_to("build", "HydraFrontend::Schema::Builds", { id => "build" });
|
||||||
|
|
||||||
|
|
||||||
# Created by DBIx::Class::Schema::Loader v0.04005 @ 2008-11-17 17:09:46
|
# Created by DBIx::Class::Schema::Loader v0.04005 @ 2008-11-24 17:46:46
|
||||||
# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:kiP5lQxpuaZUZiqHigHYxQ
|
# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:d85fCxlq/WDfQa20zXYuzw
|
||||||
|
|
||||||
|
|
||||||
# You can replace this text with custom content, and it will be preserved on regeneration
|
# You can replace this text with custom content, and it will be preserved on regeneration
|
||||||
|
|
|
@ -20,13 +20,15 @@ __PACKAGE__->add_columns(
|
||||||
{ data_type => "integer", is_nullable => 0, size => undef },
|
{ data_type => "integer", is_nullable => 0, size => undef },
|
||||||
"stoptime",
|
"stoptime",
|
||||||
{ data_type => "integer", is_nullable => 0, size => undef },
|
{ data_type => "integer", is_nullable => 0, size => undef },
|
||||||
|
"logfile",
|
||||||
|
{ data_type => "text", is_nullable => 0, size => undef },
|
||||||
);
|
);
|
||||||
__PACKAGE__->set_primary_key("id");
|
__PACKAGE__->set_primary_key("id");
|
||||||
__PACKAGE__->belongs_to("id", "HydraFrontend::Schema::Builds", { id => "id" });
|
__PACKAGE__->belongs_to("id", "HydraFrontend::Schema::Builds", { id => "id" });
|
||||||
|
|
||||||
|
|
||||||
# Created by DBIx::Class::Schema::Loader v0.04005 @ 2008-11-17 17:09:46
|
# Created by DBIx::Class::Schema::Loader v0.04005 @ 2008-11-24 17:46:46
|
||||||
# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:MqQ972Qn6sjoWbbbzmE1cg
|
# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:c2KXbqA8Xan4Lgf7AlK2EA
|
||||||
|
|
||||||
|
|
||||||
# You can replace this text with custom content, and it will be preserved on regeneration
|
# You can replace this text with custom content, and it will be preserved on regeneration
|
||||||
|
|
|
@ -72,15 +72,10 @@ __PACKAGE__->has_many(
|
||||||
"HydraFrontend::Schema::Buildproducts",
|
"HydraFrontend::Schema::Buildproducts",
|
||||||
{ "foreign.build" => "self.id" },
|
{ "foreign.build" => "self.id" },
|
||||||
);
|
);
|
||||||
__PACKAGE__->has_many(
|
|
||||||
"buildlogs",
|
|
||||||
"HydraFrontend::Schema::Buildlogs",
|
|
||||||
{ "foreign.build" => "self.id" },
|
|
||||||
);
|
|
||||||
|
|
||||||
|
|
||||||
# Created by DBIx::Class::Schema::Loader v0.04005 @ 2008-11-17 17:09:46
|
# Created by DBIx::Class::Schema::Loader v0.04005 @ 2008-11-24 17:46:46
|
||||||
# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:yYcxVJ1KnjD3KKWt4XQFMg
|
# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:/Iabv2HeyAsubLe+yPc/6Q
|
||||||
|
|
||||||
__PACKAGE__->has_many(dependents => 'HydraFrontend::Schema::Buildinputs', 'dependency');
|
__PACKAGE__->has_many(dependents => 'HydraFrontend::Schema::Buildinputs', 'dependency');
|
||||||
|
|
||||||
|
|
|
@ -23,8 +23,8 @@ __PACKAGE__->set_primary_key("id");
|
||||||
__PACKAGE__->belongs_to("id", "HydraFrontend::Schema::Builds", { id => "id" });
|
__PACKAGE__->belongs_to("id", "HydraFrontend::Schema::Builds", { id => "id" });
|
||||||
|
|
||||||
|
|
||||||
# Created by DBIx::Class::Schema::Loader v0.04005 @ 2008-11-17 17:09:46
|
# Created by DBIx::Class::Schema::Loader v0.04005 @ 2008-11-24 17:46:46
|
||||||
# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:uAs9z69gMZRAQSzvOGsqEQ
|
# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:vqJ7HEML5YNn5VIXEhZbnw
|
||||||
|
|
||||||
|
|
||||||
# You can replace this text with custom content, and it will be preserved on regeneration
|
# You can replace this text with custom content, and it will be preserved on regeneration
|
||||||
|
|
|
@ -35,8 +35,8 @@ __PACKAGE__->set_primary_key("id", "stepnr");
|
||||||
__PACKAGE__->belongs_to("id", "HydraFrontend::Schema::Builds", { id => "id" });
|
__PACKAGE__->belongs_to("id", "HydraFrontend::Schema::Builds", { id => "id" });
|
||||||
|
|
||||||
|
|
||||||
# Created by DBIx::Class::Schema::Loader v0.04005 @ 2008-11-17 17:09:46
|
# Created by DBIx::Class::Schema::Loader v0.04005 @ 2008-11-24 17:46:46
|
||||||
# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:mM/rt5x2l2wMZn+EnctifQ
|
# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:BuZp6PHq9l/9xyA/x7TOVQ
|
||||||
|
|
||||||
|
|
||||||
# You can replace this text with custom content, and it will be preserved on regeneration
|
# You can replace this text with custom content, and it will be preserved on regeneration
|
||||||
|
|
|
@ -31,8 +31,8 @@ __PACKAGE__->belongs_to(
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
# Created by DBIx::Class::Schema::Loader v0.04005 @ 2008-11-17 17:09:46
|
# Created by DBIx::Class::Schema::Loader v0.04005 @ 2008-11-24 17:46:46
|
||||||
# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:xj0LojYsbdSMWCv+KUH8sw
|
# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:x7OCv8YzB2L4H+RxEfwjbg
|
||||||
|
|
||||||
|
|
||||||
# You can replace this text with custom content, and it will be preserved on regeneration
|
# You can replace this text with custom content, and it will be preserved on regeneration
|
||||||
|
|
|
@ -43,8 +43,8 @@ __PACKAGE__->has_many(
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
# Created by DBIx::Class::Schema::Loader v0.04005 @ 2008-11-17 17:09:46
|
# Created by DBIx::Class::Schema::Loader v0.04005 @ 2008-11-24 17:46:46
|
||||||
# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:VO/SU4tv5UxNAmiwsqn6UA
|
# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:SKU48+1LqxIcuVY5gaDHCg
|
||||||
|
|
||||||
|
|
||||||
# You can replace this text with custom content, and it will be preserved on regeneration
|
# You can replace this text with custom content, and it will be preserved on regeneration
|
||||||
|
|
|
@ -48,8 +48,8 @@ __PACKAGE__->has_many(
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
# Created by DBIx::Class::Schema::Loader v0.04005 @ 2008-11-17 17:09:46
|
# Created by DBIx::Class::Schema::Loader v0.04005 @ 2008-11-24 17:46:46
|
||||||
# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:jZ0kG9EzEJn5mJFSp2WFpw
|
# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:F3WF5YS/Yas12dK2Gyekpg
|
||||||
|
|
||||||
|
|
||||||
# You can replace this text with custom content, and it will be preserved on regeneration
|
# You can replace this text with custom content, and it will be preserved on regeneration
|
||||||
|
|
|
@ -13,7 +13,7 @@ __PACKAGE__->add_columns(
|
||||||
"displayname",
|
"displayname",
|
||||||
{ data_type => "text", is_nullable => 0, size => undef },
|
{ data_type => "text", is_nullable => 0, size => undef },
|
||||||
"description",
|
"description",
|
||||||
{ data_type => "VARCHAR", is_nullable => 0, size => undef },
|
{ data_type => "text", is_nullable => 0, size => undef },
|
||||||
"enabled",
|
"enabled",
|
||||||
{ data_type => "integer", is_nullable => 0, size => undef },
|
{ data_type => "integer", is_nullable => 0, size => undef },
|
||||||
);
|
);
|
||||||
|
@ -30,8 +30,8 @@ __PACKAGE__->has_many(
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
# Created by DBIx::Class::Schema::Loader v0.04005 @ 2008-11-17 17:09:46
|
# Created by DBIx::Class::Schema::Loader v0.04005 @ 2008-11-24 17:46:46
|
||||||
# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:XkQtF1ABmLxvxND62rBlCw
|
# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:M+HA5YEL1oKKTQlLvhb6dw
|
||||||
|
|
||||||
|
|
||||||
# You can replace this text with custom content, and it will be preserved on regeneration
|
# You can replace this text with custom content, and it will be preserved on regeneration
|
||||||
|
|
|
@ -36,10 +36,14 @@
|
||||||
<strong>Success</strong>
|
<strong>Success</strong>
|
||||||
[% ELSIF build.resultInfo.buildstatus == 1 %]
|
[% ELSIF build.resultInfo.buildstatus == 1 %]
|
||||||
<img src="/static/images/failure.gif" />
|
<img src="/static/images/failure.gif" />
|
||||||
<strong class="error-msg">Build returned a non-zero exit code</strong>
|
<span class="error">Build returned a non-zero exit code</span>
|
||||||
|
[% ELSIF build.resultInfo.buildstatus == 2 %]
|
||||||
|
<img src="/static/images/failure.gif" />
|
||||||
|
<span class="error">A dependency of the build failed</span>
|
||||||
[% ELSE %]
|
[% ELSE %]
|
||||||
<img src="/static/images/failure.gif" />
|
<img src="/static/images/failure.gif" />
|
||||||
<strong class="error-msg">Build failed</strong>
|
<span class="error">Build failed</span>
|
||||||
|
(see <a href="#nix-error">below</a>)
|
||||||
[% END %]
|
[% END %]
|
||||||
[% ELSIF build.schedulingInfo.busy %]
|
[% ELSIF build.schedulingInfo.busy %]
|
||||||
<strong>Build in progress</strong>
|
<strong>Build in progress</strong>
|
||||||
|
@ -99,6 +103,14 @@
|
||||||
[% END %]
|
[% END %]
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
[% IF build.resultInfo.logfile %]
|
||||||
|
<tr>
|
||||||
|
<th>Logfile:</th>
|
||||||
|
<td>
|
||||||
|
<a href="[% c.uri_for('/log' build.id) %]"><strong>Available</strong></a>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
[% END %]
|
||||||
[% ELSE %]
|
[% ELSE %]
|
||||||
<tr>
|
<tr>
|
||||||
<th>Priority:</th>
|
<th>Priority:</th>
|
||||||
|
@ -143,7 +155,7 @@
|
||||||
|
|
||||||
[% IF build.buildsteps %]
|
[% IF build.buildsteps %]
|
||||||
|
|
||||||
<h2>Build steps</h2>
|
<h2 id="buildsteps">Build steps</h2>
|
||||||
|
|
||||||
<table class="tablesorter">
|
<table class="tablesorter">
|
||||||
<thead>
|
<thead>
|
||||||
|
@ -164,16 +176,24 @@
|
||||||
[% IF step.busy == 0 %]
|
[% IF step.busy == 0 %]
|
||||||
[% step.stoptime - step.starttime %]s
|
[% step.stoptime - step.starttime %]s
|
||||||
[% ELSE %]
|
[% ELSE %]
|
||||||
[% curTime - step.starttime %]s
|
[% IF build.finished %]
|
||||||
|
[% build.resultInfo.stoptime - step.starttime %]s
|
||||||
|
[% ELSE %]
|
||||||
|
[% curTime - step.starttime %]s
|
||||||
|
[% END %]
|
||||||
[% END %]
|
[% END %]
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
[% IF step.busy == 1 %]
|
[% IF step.busy == 1 %]
|
||||||
<strong>Building</strong>
|
[% IF build.finished %]
|
||||||
|
<span class="error">Aborted</span>
|
||||||
|
[% ELSE %]
|
||||||
|
<strong>Building</strong>
|
||||||
|
[% END %]
|
||||||
[% ELSIF step.status == 0 %]
|
[% ELSIF step.status == 0 %]
|
||||||
Succeeded
|
Succeeded
|
||||||
[% ELSE %]
|
[% ELSE %]
|
||||||
<strong class="error-msg">Failed: [% step.errormsg %]</strong>
|
<span class="error">Failed: [% HTML.escape(step.errormsg) %]</span>
|
||||||
[% END %]
|
[% END %]
|
||||||
[% IF step.logfile %]
|
[% IF step.logfile %]
|
||||||
(<a href="[% c.uri_for('/nixlog' build.id step.stepnr) %]">log</a>)
|
(<a href="[% c.uri_for('/nixlog' build.id step.stepnr) %]">log</a>)
|
||||||
|
@ -190,6 +210,17 @@
|
||||||
[% IF build.finished %]
|
[% IF build.finished %]
|
||||||
|
|
||||||
|
|
||||||
|
[% IF build.resultInfo.errormsg %]
|
||||||
|
|
||||||
|
<h2 id="nix-error">Nix error output</h2>
|
||||||
|
|
||||||
|
<pre class="buildlog">
|
||||||
|
[% HTML.escape(build.resultInfo.errormsg) -%]
|
||||||
|
</pre>
|
||||||
|
|
||||||
|
[% END %]
|
||||||
|
|
||||||
|
|
||||||
[% IF build.buildproducts %]
|
[% IF build.buildproducts %]
|
||||||
|
|
||||||
|
|
||||||
|
@ -299,26 +330,6 @@
|
||||||
[% END %]
|
[% END %]
|
||||||
|
|
||||||
|
|
||||||
[% IF build.buildlogs %]
|
|
||||||
|
|
||||||
<div>
|
|
||||||
|
|
||||||
<h2>Logs</h2>
|
|
||||||
|
|
||||||
<table>
|
|
||||||
<tr><th>Phase</th></tr>
|
|
||||||
[% FOREACH log IN build.buildlogs -%]
|
|
||||||
<tr>
|
|
||||||
<td><a href="[% c.uri_for('/log' build.id log.logphase) %]">[% log.logphase %]</a></td>
|
|
||||||
</tr>
|
|
||||||
[% END -%]
|
|
||||||
</table>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
[% END %]
|
|
||||||
|
|
||||||
|
|
||||||
[% IF build.dependents %]
|
[% IF build.dependents %]
|
||||||
|
|
||||||
<h2>Used by</h2>
|
<h2>Used by</h2>
|
||||||
|
@ -349,9 +360,8 @@
|
||||||
|
|
||||||
<h2>Log</h2>
|
<h2>Log</h2>
|
||||||
|
|
||||||
<!-- !!! escaping -->
|
|
||||||
<pre class="buildlog">
|
<pre class="buildlog">
|
||||||
[% logtext -%]
|
[% HTML.escape(logtext) -%]
|
||||||
</pre>
|
</pre>
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
[% WRAPPER layout.tt title="Hydra Overview" %]
|
[% WRAPPER layout.tt title="Hydra Overview" %]
|
||||||
|
|
||||||
<h1>Build log [% IF step %] of step [% step.stepnr %] [% ELSE %]<tt>[% log.logphase %]</tt>[% END %] of build ID [% id %]</h1>
|
<h1>Logfile for <tt>[% build.project.name %]:[% build.attrname %]</tt> build [% build.id %]</h1>
|
||||||
|
|
||||||
<div class="buildlog">
|
<div class="buildlog">
|
||||||
[% logtext -%]
|
[% logtext -%]
|
||||||
|
|
|
@ -153,6 +153,11 @@ td.buildfarmMainColumn {
|
||||||
white-space: pre;
|
white-space: pre;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.error {
|
||||||
|
color: red;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
pre.buildlog {
|
pre.buildlog {
|
||||||
border: 1px solid black;
|
border: 1px solid black;
|
||||||
padding: 0.3em;
|
padding: 0.3em;
|
||||||
|
|
|
@ -75,7 +75,7 @@ em.storeref:hover span.popup {
|
||||||
font-size: larger;
|
font-size: larger;
|
||||||
}
|
}
|
||||||
|
|
||||||
.error {
|
.errorLine {
|
||||||
color: #ff0000;
|
color: #ff0000;
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
}
|
}
|
||||||
|
|
|
@ -63,7 +63,7 @@
|
||||||
<xsl:template match="head|line">
|
<xsl:template match="head|line">
|
||||||
<code>
|
<code>
|
||||||
<xsl:if test="@error">
|
<xsl:if test="@error">
|
||||||
<xsl:attribute name="class">error</xsl:attribute>
|
<xsl:attribute name="class">errorLine</xsl:attribute>
|
||||||
</xsl:if>
|
</xsl:if>
|
||||||
<xsl:apply-templates/>
|
<xsl:apply-templates/>
|
||||||
</code>
|
</code>
|
||||||
|
|
66
src/build.pl
66
src/build.pl
|
@ -28,11 +28,18 @@ sub doBuild {
|
||||||
my $startTime = 0;
|
my $startTime = 0;
|
||||||
my $stopTime = 0;
|
my $stopTime = 0;
|
||||||
|
|
||||||
|
my $buildStatus = 0; # = succeeded
|
||||||
|
|
||||||
|
my $errormsg = undef;
|
||||||
|
|
||||||
if (!isValidPath($outPath)) {
|
if (!isValidPath($outPath)) {
|
||||||
$isCachedBuild = 0;
|
$isCachedBuild = 0;
|
||||||
|
|
||||||
$startTime = time();
|
$startTime = time();
|
||||||
|
|
||||||
|
my $thisBuildFailed = 0;
|
||||||
|
my $someBuildFailed = 0;
|
||||||
|
|
||||||
# Run Nix to perform the build, and monitor the stderr output
|
# Run Nix to perform the build, and monitor the stderr output
|
||||||
# to get notifications about specific build steps, the
|
# to get notifications about specific build steps, the
|
||||||
# associated log files, etc.
|
# associated log files, etc.
|
||||||
|
@ -44,6 +51,8 @@ sub doBuild {
|
||||||
open OUT, "$cmd |" or die;
|
open OUT, "$cmd |" or die;
|
||||||
|
|
||||||
while (<OUT>) {
|
while (<OUT>) {
|
||||||
|
$errormsg .= $_;
|
||||||
|
|
||||||
unless (/^@\s+/) {
|
unless (/^@\s+/) {
|
||||||
print STDERR "$_";
|
print STDERR "$_";
|
||||||
next;
|
next;
|
||||||
|
@ -78,10 +87,12 @@ sub doBuild {
|
||||||
}
|
}
|
||||||
|
|
||||||
elsif (/^@\s+build-failed\s+(\S+)\s+(\S+)\s+(\S+)\s+(.*)$/) {
|
elsif (/^@\s+build-failed\s+(\S+)\s+(\S+)\s+(\S+)\s+(.*)$/) {
|
||||||
my $drvPath = $1;
|
my $drvPathStep = $1;
|
||||||
|
$someBuildFailed = 1;
|
||||||
|
$thisBuildFailed = 1 if $drvPath eq $drvPathStep;
|
||||||
$db->txn_do(sub {
|
$db->txn_do(sub {
|
||||||
(my $step) = $db->resultset('Buildsteps')->search(
|
(my $step) = $db->resultset('Buildsteps')->search(
|
||||||
{id => $build->id, type => 0, drvpath => $drvPath}, {});
|
{id => $build->id, type => 0, drvpath => $drvPathStep}, {});
|
||||||
if ($step) {
|
if ($step) {
|
||||||
die unless $step;
|
die unless $step;
|
||||||
$step->busy(0);
|
$step->busy(0);
|
||||||
|
@ -94,7 +105,7 @@ sub doBuild {
|
||||||
{ id => $build->id
|
{ id => $build->id
|
||||||
, stepnr => $buildStepNr++
|
, stepnr => $buildStepNr++
|
||||||
, type => 0 # = build
|
, type => 0 # = build
|
||||||
, drvpath => $drvPath
|
, drvpath => $drvPathStep
|
||||||
, outpath => $2
|
, outpath => $2
|
||||||
, logfile => $4
|
, logfile => $4
|
||||||
, busy => 0
|
, busy => 0
|
||||||
|
@ -159,17 +170,14 @@ sub doBuild {
|
||||||
|
|
||||||
$stopTime = time();
|
$stopTime = time();
|
||||||
|
|
||||||
$outputCreated = $res == 0;
|
if ($res != 0) {
|
||||||
}
|
if ($thisBuildFailed) { $buildStatus = 1; }
|
||||||
|
elsif ($someBuildFailed) { $buildStatus = 2; }
|
||||||
|
else { $buildStatus = 3; }
|
||||||
|
}
|
||||||
|
|
||||||
my $buildStatus;
|
# Only store the output of running Nix if we have a miscellaneous error.
|
||||||
|
$errormsg = undef unless $buildStatus == 3;
|
||||||
if ($outputCreated) {
|
|
||||||
# "Positive" failures, e.g. the builder returned exit code 0
|
|
||||||
# but flagged some error condition.
|
|
||||||
$buildStatus = -e "$outPath/nix-support/failed" ? 2 : 0;
|
|
||||||
} else {
|
|
||||||
$buildStatus = 1; # = Nix failure
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$db->txn_do(sub {
|
$db->txn_do(sub {
|
||||||
|
@ -177,41 +185,23 @@ sub doBuild {
|
||||||
$build->timestamp(time());
|
$build->timestamp(time());
|
||||||
$build->update;
|
$build->update;
|
||||||
|
|
||||||
|
my $logPath = "/nix/var/log/nix/drvs/" . basename $drvPath;
|
||||||
|
$logPath = undef unless -e $logPath;
|
||||||
|
|
||||||
$db->resultset('Buildresultinfo')->create(
|
$db->resultset('Buildresultinfo')->create(
|
||||||
{ id => $build->id
|
{ id => $build->id
|
||||||
, iscachedbuild => $isCachedBuild
|
, iscachedbuild => $isCachedBuild
|
||||||
, buildstatus => $buildStatus
|
, buildstatus => $buildStatus
|
||||||
, starttime => $startTime
|
, starttime => $startTime
|
||||||
, stoptime => $stopTime
|
, stoptime => $stopTime
|
||||||
|
, logfile => $logPath
|
||||||
|
, errormsg => $errormsg
|
||||||
});
|
});
|
||||||
|
|
||||||
my $logPath = "/nix/var/log/nix/drvs/" . basename $drvPath;
|
if ($buildStatus == 0) {
|
||||||
if (-e $logPath) {
|
|
||||||
print STDERR "found log $logPath\n";
|
|
||||||
$db->resultset('Buildlogs')->create(
|
|
||||||
{ build => $build->id
|
|
||||||
, logphase => "full"
|
|
||||||
, path => $logPath
|
|
||||||
, type => "raw"
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($outputCreated) {
|
|
||||||
|
|
||||||
my $productnr = 1;
|
my $productnr = 1;
|
||||||
|
|
||||||
if (-e "$outPath/log") {
|
|
||||||
foreach my $logPath (glob "$outPath/log/*") {
|
|
||||||
print STDERR "found log $logPath\n";
|
|
||||||
$db->resultset('Buildlogs')->create(
|
|
||||||
{ build => $build->id
|
|
||||||
, logphase => basename($logPath)
|
|
||||||
, path => $logPath
|
|
||||||
, type => "raw"
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (-e "$outPath/nix-support/hydra-build-products") {
|
if (-e "$outPath/nix-support/hydra-build-products") {
|
||||||
open LIST, "$outPath/nix-support/hydra-build-products" or die;
|
open LIST, "$outPath/nix-support/hydra-build-products" or die;
|
||||||
while (<LIST>) {
|
while (<LIST>) {
|
||||||
|
@ -251,7 +241,7 @@ sub doBuild {
|
||||||
close LIST;
|
close LIST;
|
||||||
}
|
}
|
||||||
|
|
||||||
elsif ($buildStatus == 0) {
|
else {
|
||||||
$db->resultset('Buildproducts')->create(
|
$db->resultset('Buildproducts')->create(
|
||||||
{ build => $build->id
|
{ build => $build->id
|
||||||
, productnr => $productnr++
|
, productnr => $productnr++
|
||||||
|
|
|
@ -2,8 +2,7 @@
|
||||||
-- scheduled builds, additional info (such as the priority) can be
|
-- scheduled builds, additional info (such as the priority) can be
|
||||||
-- found in the BuildSchedulingInfo table. For finished builds,
|
-- found in the BuildSchedulingInfo table. For finished builds,
|
||||||
-- additional info (such as the logs, build products, etc.) can be
|
-- additional info (such as the logs, build products, etc.) can be
|
||||||
-- found in several tables, such as BuildResultInfo, BuildLogs and
|
-- found in several tables, such as BuildResultInfo and BuildProducts.
|
||||||
-- BuildProducts.
|
|
||||||
create table Builds (
|
create table Builds (
|
||||||
id integer primary key autoincrement not null,
|
id integer primary key autoincrement not null,
|
||||||
|
|
||||||
|
@ -49,13 +48,20 @@ create table BuildResultInfo (
|
||||||
|
|
||||||
isCachedBuild integer not null, -- boolean
|
isCachedBuild integer not null, -- boolean
|
||||||
|
|
||||||
buildStatus integer, -- 0 = succeeded, 1 = Nix build failure, 2 = positive build failure
|
-- Status codes:
|
||||||
|
-- 0 = succeeded
|
||||||
|
-- 1 = build of this derivation failed
|
||||||
|
-- 2 = build of some dependency failed
|
||||||
|
-- 3 = other failure (see errorMsg)
|
||||||
|
buildStatus integer,
|
||||||
|
|
||||||
errorMsg text, -- error message in case of a Nix failure
|
errorMsg text, -- error message in case of a Nix failure
|
||||||
|
|
||||||
startTime integer, -- in Unix time, 0 = used cached build result
|
startTime integer, -- in Unix time, 0 = used cached build result
|
||||||
stopTime integer,
|
stopTime integer,
|
||||||
|
|
||||||
|
logfile text, -- the path of the logfile
|
||||||
|
|
||||||
foreign key (id) references Builds(id) on delete cascade -- ignored by sqlite
|
foreign key (id) references Builds(id) on delete cascade -- ignored by sqlite
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -126,16 +132,6 @@ create table BuildProducts (
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
create table BuildLogs (
|
|
||||||
build integer not null,
|
|
||||||
logPhase text not null,
|
|
||||||
path text not null,
|
|
||||||
type text not null,
|
|
||||||
primary key (build, logPhase),
|
|
||||||
foreign key (build) references Builds(id) on delete cascade -- ignored by sqlite
|
|
||||||
);
|
|
||||||
|
|
||||||
|
|
||||||
-- Emulate "on delete cascade" foreign key constraints.
|
-- Emulate "on delete cascade" foreign key constraints.
|
||||||
create trigger cascadeBuildDeletion
|
create trigger cascadeBuildDeletion
|
||||||
before delete on Builds
|
before delete on Builds
|
||||||
|
@ -143,7 +139,6 @@ create trigger cascadeBuildDeletion
|
||||||
delete from BuildSchedulingInfo where id = old.id;
|
delete from BuildSchedulingInfo where id = old.id;
|
||||||
delete from BuildResultInfo where id = old.id;
|
delete from BuildResultInfo where id = old.id;
|
||||||
delete from BuildInputs where build = old.id;
|
delete from BuildInputs where build = old.id;
|
||||||
delete from BuildLogs where build = old.id;
|
|
||||||
delete from BuildProducts where build = old.id;
|
delete from BuildProducts where build = old.id;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
|
@ -4,8 +4,6 @@ insert into jobSetInputs(project, jobset, name, type) values('patchelf', 'trunk'
|
||||||
insert into jobSetInputAlts(project, jobset, input, altnr, value) values('patchelf', 'trunk', 'patchelfSrc', 0, '/home/eelco/Dev/patchelf-wc');
|
insert into jobSetInputAlts(project, jobset, input, altnr, value) values('patchelf', 'trunk', 'patchelfSrc', 0, '/home/eelco/Dev/patchelf-wc');
|
||||||
insert into jobSetInputs(project, jobset, name, type) values('patchelf', 'trunk', 'nixpkgs', 'path');
|
insert into jobSetInputs(project, jobset, name, type) values('patchelf', 'trunk', 'nixpkgs', 'path');
|
||||||
insert into jobSetInputAlts(project, jobset, input, altnr, value) values('patchelf', 'trunk', 'nixpkgs', 0, '/home/eelco/Dev/nixpkgs-wc');
|
insert into jobSetInputAlts(project, jobset, input, altnr, value) values('patchelf', 'trunk', 'nixpkgs', 0, '/home/eelco/Dev/nixpkgs-wc');
|
||||||
insert into jobSetInputs(project, jobset, name, type) values('patchelf', 'trunk', 'release', 'path');
|
|
||||||
insert into jobSetInputAlts(project, jobset, input, altnr, value) values('patchelf', 'trunk', 'release', 0, '/home/eelco/Dev/release');
|
|
||||||
insert into jobSetInputs(project, jobset, name, type) values('patchelf', 'trunk', 'system', 'string');
|
insert into jobSetInputs(project, jobset, name, type) values('patchelf', 'trunk', 'system', 'string');
|
||||||
insert into jobSetInputAlts(project, jobset, input, altnr, value) values('patchelf', 'trunk', 'system', 0, 'i686-linux');
|
insert into jobSetInputAlts(project, jobset, input, altnr, value) values('patchelf', 'trunk', 'system', 0, 'i686-linux');
|
||||||
insert into jobSetInputAlts(project, jobset, input, altnr, value) values('patchelf', 'trunk', 'system', 1, 'x86_64-linux');
|
insert into jobSetInputAlts(project, jobset, input, altnr, value) values('patchelf', 'trunk', 'system', 1, 'x86_64-linux');
|
||||||
|
|
Loading…
Reference in a new issue