From f75924db9570935648a3e0570e05cb0baadc55e9 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Mon, 2 Mar 2009 16:03:41 +0000 Subject: [PATCH] * Allow builds to be restarted (if they failed with a transient error, e.g. interrupted or network problems). --- src/Hydra/lib/Hydra/Controller/Build.pm | 32 +++++++++++++++++++++ src/Hydra/lib/Hydra/Controller/Root.pm | 24 +++------------- src/Hydra/lib/Hydra/Helper/CatalystUtils.pm | 21 +++++++++++++- src/Hydra/root/build.tt | 10 ++++++- src/Hydra/root/static/css/hydra.css | 6 +++- 5 files changed, 70 insertions(+), 23 deletions(-) diff --git a/src/Hydra/lib/Hydra/Controller/Build.pm b/src/Hydra/lib/Hydra/Controller/Build.pm index 7b549d9b..6f20ac8a 100644 --- a/src/Hydra/lib/Hydra/Controller/Build.pm +++ b/src/Hydra/lib/Hydra/Controller/Build.pm @@ -30,6 +30,7 @@ sub view_build : Chained('build') PathPart('') Args(0) { $c->stash->{curTime} = time; $c->stash->{available} = isValidPath $build->outpath; $c->stash->{drvAvailable} = isValidPath $build->drvpath; + $c->stash->{flashMsg} = $c->flash->{afterRestart}; if (!$build->finished && $build->schedulingInfo->busy) { my $logfile = $build->schedulingInfo->logfile; @@ -155,4 +156,35 @@ sub nix : Chained('build') PathPart('nix') CaptureArgs(0) { } +sub restart : Chained('build') PathPart('restart') Args(0) { + my ($self, $c) = @_; + + my $build = $c->stash->{build}; + + requireProjectOwner($c, $build->project); + + error($c, "This build cannot be restarted.") + unless $build->finished && $build->resultInfo->buildstatus == 3; + + $c->model('DB')->schema->txn_do(sub { + $build->finished(0); + $build->timestamp(time()); + $build->update; + + $build->resultInfo->delete; + + $c->model('DB::BuildSchedulingInfo')->create( + { id => $build->id + , priority => 0 # don't know the original priority anymore... + , busy => 0 + , locker => "" + }); + }); + + $c->flash->{afterRestart} = "Build has been restarted."; + + $c->response->redirect($c->uri_for($self->action_for("view_build"), $c->req->captures)); +} + + 1; diff --git a/src/Hydra/lib/Hydra/Controller/Root.pm b/src/Hydra/lib/Hydra/Controller/Root.pm index 8da4b111..b4c331b8 100644 --- a/src/Hydra/lib/Hydra/Controller/Root.pm +++ b/src/Hydra/lib/Hydra/Controller/Root.pm @@ -82,13 +82,6 @@ sub logout :Local { } -sub requireLogin { - my ($c) = @_; - $c->flash->{afterLogin} = $c->request->uri; - $c->response->redirect($c->uri_for('/login')); -} - - sub queue :Local { my ($self, $c) = @_; $c->stash->{template} = 'queue.tt'; @@ -230,10 +223,7 @@ sub releases :Local { if (defined $subcommand && $subcommand ne "") { - return requireLogin($c) if !$c->user_exists; - - error($c, "Only the project owner or the administrator can perform this operation.") - unless $c->check_user_roles('admin') || $c->user->username eq $project->owner->username; + requireProjectOwner($c, $project); if ($subcommand eq "edit") { $c->stash->{template} = 'edit-releaseset.tt'; @@ -272,10 +262,7 @@ sub create_releaseset :Local { die "Project $projectName doesn't exist." if !defined $project; $c->stash->{curProject} = $project; - return requireLogin($c) if !$c->user_exists; - - error($c, "Only the project owner or the administrator can perform this operation.") - unless $c->check_user_roles('admin') || $c->user->username eq $project->owner->username; + requireProjectOwner($c, $project); if (defined $subcommand && $subcommand eq "submit") { my $releaseSetName = $c->request->params->{name}; @@ -468,10 +455,7 @@ sub project :Local { elsif ($subcommand ne "") { - return requireLogin($c) if !$c->user_exists; - - error($c, "Only the project owner or the administrator can perform this operation.") - unless $c->check_user_roles('admin') || $c->user->username eq $project->owner->username; + requireProjectOwner($c, $project); if ($subcommand eq "edit") { $c->stash->{edit} = 1; @@ -506,7 +490,7 @@ sub project :Local { sub createproject :Local { my ($self, $c, $subcommand) = @_; - return requireLogin($c) if !$c->user_exists; + requireLogin($c) if !$c->user_exists; error($c, "Only administrators can create projects.") unless $c->check_user_roles('admin'); diff --git a/src/Hydra/lib/Hydra/Helper/CatalystUtils.pm b/src/Hydra/lib/Hydra/Helper/CatalystUtils.pm index 865666e6..58d9e81e 100644 --- a/src/Hydra/lib/Hydra/Helper/CatalystUtils.pm +++ b/src/Hydra/lib/Hydra/Helper/CatalystUtils.pm @@ -7,6 +7,7 @@ use Readonly; our @ISA = qw(Exporter); our @EXPORT = qw( getBuild error notFound + requireLogin requireProjectOwner $pathCompRE $relPathRE ); @@ -21,7 +22,7 @@ sub getBuild { sub error { my ($c, $msg) = @_; $c->error($msg); - $c->detach; + $c->detach; # doesn't return } @@ -32,6 +33,24 @@ sub notFound { } +sub requireLogin { + my ($c) = @_; + $c->flash->{afterLogin} = $c->request->uri; + $c->response->redirect($c->uri_for('/login')); + $c->detach; # doesn't return +} + + +sub requireProjectOwner { + my ($c, $project) = @_; + + requireLogin($c) if !$c->user_exists; + + error($c, "Only the project owner or the administrator can perform this operation.") + unless $c->check_user_roles('admin') || $c->user->username eq $project->owner->username; +} + + # Security checking of filenames. Readonly::Scalar our $pathCompRE => "(?:[A-Za-z0-9-\+][A-Za-z0-9-\+\._]*)"; Readonly::Scalar our $relPathRE => "(?:$pathCompRE(?:\/$pathCompRE)*)"; diff --git a/src/Hydra/root/build.tt b/src/Hydra/root/build.tt index 152a410c..4c1d639d 100644 --- a/src/Hydra/root/build.tt +++ b/src/Hydra/root/build.tt @@ -15,6 +15,11 @@ +[% IF flashMsg %] +

[% flashMsg %]

+[% END %] + +

Information

@@ -31,7 +36,7 @@ Success [% ELSIF build.resultInfo.buildstatus == 1 %] - Build returned a non-zero exit code + Build returned a non-zero exit code [% ELSIF build.resultInfo.buildstatus == 2 %] A dependency of the build failed @@ -39,6 +44,9 @@ Build failed (see below) + + + [% END %] [% ELSIF build.schedulingInfo.busy %] Build in progress diff --git a/src/Hydra/root/static/css/hydra.css b/src/Hydra/root/static/css/hydra.css index 672a4bad..efd5b046 100644 --- a/src/Hydra/root/static/css/hydra.css +++ b/src/Hydra/root/static/css/hydra.css @@ -436,4 +436,8 @@ select { button { background-color: #f0f0e0; -} \ No newline at end of file +} + +form.inline { + display: inline; +}