From 052bab169daee14002e9753ee2f3446bbaecc392 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Fri, 4 Oct 2013 17:01:47 +0200 Subject: [PATCH] Add a jobset eval action to restart all aborted/cancelled builds --- src/lib/Hydra/Controller/Build.pm | 11 ++----- src/lib/Hydra/Controller/JobsetEval.pm | 10 +++++++ src/lib/Hydra/Helper/AddBuilds.pm | 27 +---------------- src/lib/Hydra/Helper/Nix.pm | 40 ++++++++++++++++++++++++-- src/root/jobset-eval.tt | 1 + 5 files changed, 52 insertions(+), 37 deletions(-) diff --git a/src/lib/Hydra/Controller/Build.pm b/src/lib/Hydra/Controller/Build.pm index a134a307..068a0ccc 100644 --- a/src/lib/Hydra/Controller/Build.pm +++ b/src/lib/Hydra/Controller/Build.pm @@ -437,18 +437,11 @@ sub nix : Chained('buildChain') PathPart('nix') CaptureArgs(0) { sub restart : Chained('buildChain') PathPart Args(0) { my ($self, $c) = @_; - my $build = $c->stash->{build}; - requireProjectOwner($c, $build->project); - - error($c, "This build cannot be restarted.") - unless $build->finished && -f $build->drvpath; - - restartBuild($c->model('DB')->schema, $build); - + my $n = restartBuilds($c->model('DB')->schema, $c->model('DB::Builds')->search({ id => $build->id })); + error($c, "This build cannot be restarted.") if $n != 1; $c->flash->{successMsg} = "Build has been restarted."; - $c->res->redirect($c->uri_for($self->action_for("build"), $c->req->captures)); } diff --git a/src/lib/Hydra/Controller/JobsetEval.pm b/src/lib/Hydra/Controller/JobsetEval.pm index cc06ba5a..40b52cb3 100644 --- a/src/lib/Hydra/Controller/JobsetEval.pm +++ b/src/lib/Hydra/Controller/JobsetEval.pm @@ -163,6 +163,16 @@ sub cancel : Chained('eval') PathPart('cancel') Args(0) { } +sub restart_aborted : Chained('eval') PathPart('restart-aborted') Args(0) { + my ($self, $c) = @_; + requireProjectOwner($c, $c->stash->{eval}->project); + my $builds = $c->stash->{eval}->builds->search({ finished => 1, buildstatus => { -in => [3, 4] } }); + my $n = restartBuilds($c->model('DB')->schema, $builds); + $c->flash->{successMsg} = "$n builds have been restarted."; + $c->res->redirect($c->uri_for($c->controller('JobsetEval')->action_for('view'), $c->req->captures)); +} + + # Hydra::Base::Controller::NixChannel needs this. sub nix : Chained('eval') PathPart('channel') CaptureArgs(0) { my ($self, $c) = @_; diff --git a/src/lib/Hydra/Helper/AddBuilds.pm b/src/lib/Hydra/Helper/AddBuilds.pm index 1a575e66..e0196a81 100644 --- a/src/lib/Hydra/Helper/AddBuilds.pm +++ b/src/lib/Hydra/Helper/AddBuilds.pm @@ -553,29 +553,4 @@ sub checkBuild { }; -sub restartBuild { - my ($db, $build) = @_; - - txn_do($db, sub { - my @paths; - push @paths, $build->drvpath; - push @paths, $_->drvpath foreach $build->buildsteps; - - my $r = `nix-store --clear-failed-paths @paths`; - - $build->update( - { finished => 0 - , busy => 0 - , locker => "" - , iscachedbuild => 0 - }); - - $build->buildproducts->delete; - - # Reset the stats for the evals to which this build belongs. - # !!! Should do this in a trigger. - foreach my $m ($build->jobsetevalmembers->all) { - $m->eval->update({nrsucceeded => undef}); - } - }); -} +1; diff --git a/src/lib/Hydra/Helper/Nix.pm b/src/lib/Hydra/Helper/Nix.pm index f5d62c7a..26742625 100644 --- a/src/lib/Hydra/Helper/Nix.pm +++ b/src/lib/Hydra/Helper/Nix.pm @@ -7,6 +7,7 @@ use File::Basename; use Config::General; use Hydra::Helper::CatalystUtils; use Hydra::Model::DB; +use Nix::Store; our @ISA = qw(Exporter); our @EXPORT = qw( @@ -22,7 +23,7 @@ our @EXPORT = qw( pathIsInsidePrefix captureStdoutStderr run grab getTotalShares - cancelBuilds); + cancelBuilds restartBuilds); sub getHydraHome { @@ -274,7 +275,7 @@ sub findLog { my $logPath = getDrvLogPath($drvPath); return $logPath if defined $logPath; } - + return undef if scalar @outPaths == 0; my @steps = $c->model('DB::BuildSteps')->search( @@ -561,4 +562,39 @@ sub cancelBuilds($$) { } +sub restartBuilds($$) { + my ($db, $builds) = @_; + my $n = 0; + + txn_do($db, sub { + my @paths; + + $builds = $builds->search({ finished => 1 }); + foreach my $build ($builds->all) { + next if !isValidPath($build->drvpath); + push @paths, $build->drvpath; + push @paths, $_->drvpath foreach $build->buildsteps; + + $build->update( + { finished => 0 + , busy => 0 + , locker => "" + , iscachedbuild => 0 + }); + $n++; + + # Reset the stats for the evals to which this build belongs. + # !!! Should do this in a trigger. + $build->jobsetevals->update({nrsucceeded => undef}); + } + + # Clear Nix's negative failure cache. + # FIXME: Add this to the API. + system("nix-store", "--clear-failed-paths", @paths); + }); + + return $n; +} + + 1; diff --git a/src/root/jobset-eval.tt b/src/root/jobset-eval.tt index 41755f9f..73ef4828 100644 --- a/src/root/jobset-eval.tt +++ b/src/root/jobset-eval.tt @@ -43,6 +43,7 @@ c.uri_for(c.controller('JobsetEval').action_for('view'), [% END %]