diff --git a/src/HydraFrontend/lib/HydraFrontend/Controller/Root.pm b/src/HydraFrontend/lib/HydraFrontend/Controller/Root.pm
index f5100ea5..b68aa9ff 100644
--- a/src/HydraFrontend/lib/HydraFrontend/Controller/Root.pm
+++ b/src/HydraFrontend/lib/HydraFrontend/Controller/Root.pm
@@ -37,7 +37,7 @@ sub index :Path :Args(0) {
# Get the latest finished build for each unique job.
$c->stash->{latestBuilds} = [$c->model('DB::Builds')->search(undef,
{ join => 'resultInfo'
- , where => "finished != 0 and timestamp = (select max(timestamp) from Builds where project == me.project and attrName == me.attrName)"
+ , where => "finished != 0 and timestamp = (select max(timestamp) from Builds where project == me.project and attrName == me.attrName and finished != 0)"
, order_by => "project, attrname"
})];
}
@@ -106,6 +106,24 @@ sub log :Local {
}
+sub nixlog :Local {
+ my ( $self, $c, $id, $stepnr ) = @_;
+
+ my $build = getBuild($c, $id);
+ return error($c, "Build with ID $id doesn't exist.") if !defined $build;
+
+ my $step = $build->buildsteps->find({stepnr => $stepnr});
+ return error($c, "Build $id doesn't have a build step $stepnr.") if !defined $step;
+
+ $c->stash->{template} = 'log.tt';
+ $c->stash->{id} = $id;
+ $c->stash->{step} = $step;
+
+ # !!! should be done in the view (as a TT plugin).
+ $c->stash->{logtext} = loadLog($step->logfile);
+}
+
+
sub loadLog {
my ($path) = @_;
# !!! all a quick hack
diff --git a/src/HydraFrontend/lib/HydraFrontend/Schema.pm b/src/HydraFrontend/lib/HydraFrontend/Schema.pm
index 052fc9cf..1a381468 100644
--- a/src/HydraFrontend/lib/HydraFrontend/Schema.pm
+++ b/src/HydraFrontend/lib/HydraFrontend/Schema.pm
@@ -8,8 +8,8 @@ use base 'DBIx::Class::Schema';
__PACKAGE__->load_classes;
-# Created by DBIx::Class::Schema::Loader v0.04005 @ 2008-11-11 13:41:38
-# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:1AgCf4sf5h2RU24Slo0sTA
+# Created by DBIx::Class::Schema::Loader v0.04005 @ 2008-11-11 18:02:00
+# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:gS2Lp7T6IZ160iYQbEhd+g
# You can replace this text with custom content, and it will be preserved on regeneration
diff --git a/src/HydraFrontend/lib/HydraFrontend/Schema/Buildinputs.pm b/src/HydraFrontend/lib/HydraFrontend/Schema/Buildinputs.pm
index eda11d4d..6b96dd61 100644
--- a/src/HydraFrontend/lib/HydraFrontend/Schema/Buildinputs.pm
+++ b/src/HydraFrontend/lib/HydraFrontend/Schema/Buildinputs.pm
@@ -38,8 +38,8 @@ __PACKAGE__->belongs_to(
);
-# Created by DBIx::Class::Schema::Loader v0.04005 @ 2008-11-11 13:41:38
-# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:dKMSSomUN+gJX57Z5e295w
+# Created by DBIx::Class::Schema::Loader v0.04005 @ 2008-11-11 18:02:00
+# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:MtL3cwH9upjNmhaZkGszRA
# You can replace this text with custom content, and it will be preserved on regeneration
diff --git a/src/HydraFrontend/lib/HydraFrontend/Schema/Buildlogs.pm b/src/HydraFrontend/lib/HydraFrontend/Schema/Buildlogs.pm
index 2f21bb8f..2d67b001 100644
--- a/src/HydraFrontend/lib/HydraFrontend/Schema/Buildlogs.pm
+++ b/src/HydraFrontend/lib/HydraFrontend/Schema/Buildlogs.pm
@@ -21,8 +21,8 @@ __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-11 13:41:38
-# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:ZOxJeT+ltgyc/zuDl9aEDQ
+# Created by DBIx::Class::Schema::Loader v0.04005 @ 2008-11-11 18:02:00
+# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:vvyGq3BeKyyK7K6uDxJHyQ
# You can replace this text with custom content, and it will be preserved on regeneration
diff --git a/src/HydraFrontend/lib/HydraFrontend/Schema/Buildproducts.pm b/src/HydraFrontend/lib/HydraFrontend/Schema/Buildproducts.pm
index 22ef546a..ff1f4cf3 100644
--- a/src/HydraFrontend/lib/HydraFrontend/Schema/Buildproducts.pm
+++ b/src/HydraFrontend/lib/HydraFrontend/Schema/Buildproducts.pm
@@ -21,8 +21,8 @@ __PACKAGE__->set_primary_key("build", "path");
__PACKAGE__->belongs_to("build", "HydraFrontend::Schema::Builds", { id => "build" });
-# Created by DBIx::Class::Schema::Loader v0.04005 @ 2008-11-11 13:41:38
-# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:rZPTilX/PAiIoxffxc0nJw
+# Created by DBIx::Class::Schema::Loader v0.04005 @ 2008-11-11 18:02:00
+# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:et00AvSBi5LZUoIrIUOKFQ
# You can replace this text with custom content, and it will be preserved on regeneration
diff --git a/src/HydraFrontend/lib/HydraFrontend/Schema/Buildresultinfo.pm b/src/HydraFrontend/lib/HydraFrontend/Schema/Buildresultinfo.pm
index 1125256d..d14fd269 100644
--- a/src/HydraFrontend/lib/HydraFrontend/Schema/Buildresultinfo.pm
+++ b/src/HydraFrontend/lib/HydraFrontend/Schema/Buildresultinfo.pm
@@ -25,8 +25,8 @@ __PACKAGE__->set_primary_key("id");
__PACKAGE__->belongs_to("id", "HydraFrontend::Schema::Builds", { id => "id" });
-# Created by DBIx::Class::Schema::Loader v0.04005 @ 2008-11-11 13:41:38
-# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:2Vfqs9RUhbDrje18yZb3AA
+# Created by DBIx::Class::Schema::Loader v0.04005 @ 2008-11-11 18:02:00
+# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:8zXrs7iT2h3xp6C/2q37uQ
# You can replace this text with custom content, and it will be preserved on regeneration
diff --git a/src/HydraFrontend/lib/HydraFrontend/Schema/Builds.pm b/src/HydraFrontend/lib/HydraFrontend/Schema/Builds.pm
index 92d358d6..5f393542 100644
--- a/src/HydraFrontend/lib/HydraFrontend/Schema/Builds.pm
+++ b/src/HydraFrontend/lib/HydraFrontend/Schema/Builds.pm
@@ -70,10 +70,15 @@ __PACKAGE__->has_many(
"HydraFrontend::Schema::Buildlogs",
{ "foreign.build" => "self.id" },
);
+__PACKAGE__->has_many(
+ "buildsteps",
+ "HydraFrontend::Schema::Buildsteps",
+ { "foreign.id" => "self.id" },
+);
-# Created by DBIx::Class::Schema::Loader v0.04005 @ 2008-11-11 13:41:38
-# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:1GZeB3YVr064AZrGargmFg
+# Created by DBIx::Class::Schema::Loader v0.04005 @ 2008-11-11 18:02:00
+# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:c8feWTpKijITXXSdJICuFg
__PACKAGE__->has_many(dependents => 'HydraFrontend::Schema::Buildinputs', 'dependency');
diff --git a/src/HydraFrontend/lib/HydraFrontend/Schema/Buildschedulinginfo.pm b/src/HydraFrontend/lib/HydraFrontend/Schema/Buildschedulinginfo.pm
index 851a75b0..3f521f67 100644
--- a/src/HydraFrontend/lib/HydraFrontend/Schema/Buildschedulinginfo.pm
+++ b/src/HydraFrontend/lib/HydraFrontend/Schema/Buildschedulinginfo.pm
@@ -23,8 +23,8 @@ __PACKAGE__->set_primary_key("id");
__PACKAGE__->belongs_to("id", "HydraFrontend::Schema::Builds", { id => "id" });
-# Created by DBIx::Class::Schema::Loader v0.04005 @ 2008-11-11 13:41:38
-# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:rN7v2+MnC8TkrEHUzt2Gqg
+# Created by DBIx::Class::Schema::Loader v0.04005 @ 2008-11-11 18:02:00
+# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:Z65HteUghCT7sXfXpsHYXg
# You can replace this text with custom content, and it will be preserved on regeneration
diff --git a/src/HydraFrontend/lib/HydraFrontend/Schema/Buildsteps.pm b/src/HydraFrontend/lib/HydraFrontend/Schema/Buildsteps.pm
new file mode 100644
index 00000000..21064ad8
--- /dev/null
+++ b/src/HydraFrontend/lib/HydraFrontend/Schema/Buildsteps.pm
@@ -0,0 +1,43 @@
+package HydraFrontend::Schema::Buildsteps;
+
+use strict;
+use warnings;
+
+use base 'DBIx::Class';
+
+__PACKAGE__->load_components("Core");
+__PACKAGE__->table("BuildSteps");
+__PACKAGE__->add_columns(
+ "id",
+ { data_type => "integer", is_nullable => 0, size => undef },
+ "stepnr",
+ { data_type => "integer", is_nullable => 0, size => undef },
+ "type",
+ { data_type => "integer", is_nullable => 0, size => undef },
+ "drvpath",
+ { data_type => "text", is_nullable => 0, size => undef },
+ "outpath",
+ { data_type => "text", is_nullable => 0, size => undef },
+ "logfile",
+ { data_type => "text", is_nullable => 0, size => undef },
+ "busy",
+ { data_type => "integer", is_nullable => 0, size => undef },
+ "status",
+ { data_type => "integer", is_nullable => 0, size => undef },
+ "errormsg",
+ { data_type => "text", is_nullable => 0, size => undef },
+ "starttime",
+ { data_type => "integer", is_nullable => 0, size => undef },
+ "stoptime",
+ { data_type => "integer", is_nullable => 0, size => undef },
+);
+__PACKAGE__->set_primary_key("id", "stepnr");
+__PACKAGE__->belongs_to("id", "HydraFrontend::Schema::Builds", { id => "id" });
+
+
+# Created by DBIx::Class::Schema::Loader v0.04005 @ 2008-11-11 18:02:00
+# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:GmvM5Rhj4MY7eNQpqTz7bw
+
+
+# You can replace this text with custom content, and it will be preserved on regeneration
+1;
diff --git a/src/HydraFrontend/lib/HydraFrontend/Schema/Jobsetinputalts.pm b/src/HydraFrontend/lib/HydraFrontend/Schema/Jobsetinputalts.pm
index f7603979..35013dce 100644
--- a/src/HydraFrontend/lib/HydraFrontend/Schema/Jobsetinputalts.pm
+++ b/src/HydraFrontend/lib/HydraFrontend/Schema/Jobsetinputalts.pm
@@ -33,8 +33,8 @@ __PACKAGE__->belongs_to(
);
-# Created by DBIx::Class::Schema::Loader v0.04005 @ 2008-11-11 13:41:38
-# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:bvEulSFMDlAMs39sIyHgZQ
+# Created by DBIx::Class::Schema::Loader v0.04005 @ 2008-11-11 18:02:00
+# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:mng7GAPMDxsznKupYdhwQw
# You can replace this text with custom content, and it will be preserved on regeneration
diff --git a/src/HydraFrontend/lib/HydraFrontend/Schema/Jobsetinputs.pm b/src/HydraFrontend/lib/HydraFrontend/Schema/Jobsetinputs.pm
index 61bfcfd3..71f22994 100644
--- a/src/HydraFrontend/lib/HydraFrontend/Schema/Jobsetinputs.pm
+++ b/src/HydraFrontend/lib/HydraFrontend/Schema/Jobsetinputs.pm
@@ -43,8 +43,8 @@ __PACKAGE__->has_many(
);
-# Created by DBIx::Class::Schema::Loader v0.04005 @ 2008-11-11 13:41:38
-# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:54xK3D1D0Jm5oKgRelXN7Q
+# Created by DBIx::Class::Schema::Loader v0.04005 @ 2008-11-11 18:02:00
+# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:vEXBbzKUTBQmGmL8uh9mIA
# You can replace this text with custom content, and it will be preserved on regeneration
diff --git a/src/HydraFrontend/lib/HydraFrontend/Schema/Jobsets.pm b/src/HydraFrontend/lib/HydraFrontend/Schema/Jobsets.pm
index 06f0d939..ca2c3c32 100644
--- a/src/HydraFrontend/lib/HydraFrontend/Schema/Jobsets.pm
+++ b/src/HydraFrontend/lib/HydraFrontend/Schema/Jobsets.pm
@@ -48,8 +48,8 @@ __PACKAGE__->has_many(
);
-# Created by DBIx::Class::Schema::Loader v0.04005 @ 2008-11-11 13:41:38
-# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:JHirlq7Jc8dQOy+Op/VflA
+# Created by DBIx::Class::Schema::Loader v0.04005 @ 2008-11-11 18:02:00
+# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:hMYI8zT3UB/k9IbddK1X4g
# You can replace this text with custom content, and it will be preserved on regeneration
diff --git a/src/HydraFrontend/lib/HydraFrontend/Schema/Projects.pm b/src/HydraFrontend/lib/HydraFrontend/Schema/Projects.pm
index 564297e5..bc10b085 100644
--- a/src/HydraFrontend/lib/HydraFrontend/Schema/Projects.pm
+++ b/src/HydraFrontend/lib/HydraFrontend/Schema/Projects.pm
@@ -24,8 +24,8 @@ __PACKAGE__->has_many(
);
-# Created by DBIx::Class::Schema::Loader v0.04005 @ 2008-11-11 13:41:38
-# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:7Ag5ZfYVgfw3MJZkNUmBYw
+# Created by DBIx::Class::Schema::Loader v0.04005 @ 2008-11-11 18:02:00
+# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:1DTnCjRw929OuAfeJ5gsXA
# You can replace this text with custom content, and it will be preserved on regeneration
diff --git a/src/HydraFrontend/root/build.tt b/src/HydraFrontend/root/build.tt
index b824a0c9..09838701 100644
--- a/src/HydraFrontend/root/build.tt
+++ b/src/HydraFrontend/root/build.tt
@@ -33,10 +33,10 @@
Success
[% ELSIF build.resultInfo.buildstatus == 1 %]
- Build returned a non-zero exit code
+ Build returned a non-zero exit code
[% ELSE %]
- Build failed
+ Build failed
[% END %]
[% ELSIF build.schedulingInfo.busy %]
Build in progress
@@ -134,6 +134,39 @@
+[% IF build.buildsteps %]
+
+
Nr | What | Status |
---|---|---|
[% step.stepnr %] | ++ Build of [% step.outpath %] + | ++ [% IF step.busy == 1 %] + Building + [% ELSIF step.status == 0 %] + Succeeded + [% ELSE %] + Failed: [% step.errormsg %] + [% END %] + (log) + | +
diff --git a/src/build.pl b/src/build.pl index 1a4dfae8..08e71d17 100644 --- a/src/build.pl +++ b/src/build.pl @@ -32,7 +32,66 @@ sub doBuild { $startTime = time(); - my $res = system("nix-store --realise $drvPath"); + # Run Nix to perform the build, and monitor the stderr output + # to get notifications about specific build steps, the + # associated log files, etc. + my $cmd = "nix-store --keep-going --no-build-output " . + "--log-type flat --print-build-trace --realise $drvPath 2>&1"; + + my $buildStepNr = 1; + + open OUT, "$cmd |" or die; + + while () { + unless (/^@\s+/) { + print STDERR "$_"; + next; + } + print STDERR "GOT $_"; + + if (/^@\s+build-started\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+)$/) { + $db->txn_do(sub { + $db->resultset('Buildsteps')->create( + { id => $build->id + , stepnr => $buildStepNr++ + , type => 0 # = build + , drvpath => $1 + , outpath => $2 + , logfile => $4 + , busy => 1 + }); + }); + } + + if (/^@\s+build-succeeded\s+(\S+)\s+(\S+)$/) { + $db->txn_do(sub { + my $drvPath = $1; + (my $step) = $db->resultset('Buildsteps')->search( + {id => $build->id, type => 0, drvpath => $drvPath}, {}); + die unless $step; + $step->busy(0); + $step->status(0); + $step->update; + }); + } + + if (/^@\s+build-failed\s+(\S+)\s+(\S+)\s+(\S+)\s+(.*)$/) { + $db->txn_do(sub { + my $drvPath = $1; + (my $step) = $db->resultset('Buildsteps')->search( + {id => $build->id, type => 0, drvpath => $drvPath}, {}); + die unless $step; + $step->busy(0); + $step->status(1); + $step->errormsg($4); + $step->update; + }); + } + } + + close OUT; + + my $res = $?; $stopTime = time(); @@ -64,7 +123,7 @@ sub doBuild { my $logPath = "/nix/var/log/nix/drvs/" . basename $drvPath; if (-e $logPath) { - print "found log $logPath\n"; + print STDERR "found log $logPath\n"; $db->resultset('Buildlogs')->create( { build => $build->id , logphase => "full" @@ -77,7 +136,7 @@ sub doBuild { if (-e "$outPath/log") { foreach my $logPath (glob "$outPath/log/*") { - print "found log $logPath\n"; + print STDERR "found log $logPath\n"; $db->resultset('Buildlogs')->create( { build => $build->id , logphase => basename($logPath) @@ -119,7 +178,7 @@ sub doBuild { my $buildId = $ARGV[0] or die; -print "performing build $buildId\n"; +print STDERR "performing build $buildId\n"; # Lock the build. If necessary, steal the lock from the parent # process (runner.pl). This is so that if the runner dies, the diff --git a/src/hydra.sql b/src/hydra.sql index bd3b6d7c..d000b7ff 100644 --- a/src/hydra.sql +++ b/src/hydra.sql @@ -59,6 +59,31 @@ create table BuildResultInfo ( ); +create table BuildSteps ( + id integer not null, + stepnr integer not null, + + type integer not null, -- 0 = build, 1 = substitution + + drvPath text, + outPath text, + + logfile text, + + busy integer not null, + + status integer, + + errorMsg text, + + startTime integer, -- in Unix time, 0 = used cached build result + stopTime integer, + + primary key (id, stepnr), + foreign key (id) references Builds(id) on delete cascade -- ignored by sqlite +); + + -- Inputs of builds. create table BuildInputs ( id integer primary key autoincrement not null, diff --git a/src/runner.pl b/src/runner.pl index 394ed1d0..438de2c9 100644 --- a/src/runner.pl +++ b/src/runner.pl @@ -16,7 +16,6 @@ $db->txn_do(sub { my @jobs = $db->resultset('Builds')->search( {finished => 0, busy => 1}, {join => 'schedulingInfo'}); foreach my $job (@jobs) { - print $job, "\n"; my $pid = $job->schedulingInfo->locker; if (kill(0, $pid) != 1) { # see if we can signal the process print "job ", $job->id, " pid $pid died, unlocking\n";