* Allow builds to be restarted (if they failed with a transient error,

e.g. interrupted or network problems).
This commit is contained in:
Eelco Dolstra 2009-03-02 16:03:41 +00:00
parent c7736f0643
commit f75924db95
5 changed files with 70 additions and 23 deletions

View file

@ -30,6 +30,7 @@ sub view_build : Chained('build') PathPart('') Args(0) {
$c->stash->{curTime} = time; $c->stash->{curTime} = time;
$c->stash->{available} = isValidPath $build->outpath; $c->stash->{available} = isValidPath $build->outpath;
$c->stash->{drvAvailable} = isValidPath $build->drvpath; $c->stash->{drvAvailable} = isValidPath $build->drvpath;
$c->stash->{flashMsg} = $c->flash->{afterRestart};
if (!$build->finished && $build->schedulingInfo->busy) { if (!$build->finished && $build->schedulingInfo->busy) {
my $logfile = $build->schedulingInfo->logfile; 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; 1;

View file

@ -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 { sub queue :Local {
my ($self, $c) = @_; my ($self, $c) = @_;
$c->stash->{template} = 'queue.tt'; $c->stash->{template} = 'queue.tt';
@ -230,10 +223,7 @@ sub releases :Local {
if (defined $subcommand && $subcommand ne "") { if (defined $subcommand && $subcommand ne "") {
return requireLogin($c) if !$c->user_exists; requireProjectOwner($c, $project);
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;
if ($subcommand eq "edit") { if ($subcommand eq "edit") {
$c->stash->{template} = 'edit-releaseset.tt'; $c->stash->{template} = 'edit-releaseset.tt';
@ -272,10 +262,7 @@ sub create_releaseset :Local {
die "Project $projectName doesn't exist." if !defined $project; die "Project $projectName doesn't exist." if !defined $project;
$c->stash->{curProject} = $project; $c->stash->{curProject} = $project;
return requireLogin($c) if !$c->user_exists; requireProjectOwner($c, $project);
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;
if (defined $subcommand && $subcommand eq "submit") { if (defined $subcommand && $subcommand eq "submit") {
my $releaseSetName = $c->request->params->{name}; my $releaseSetName = $c->request->params->{name};
@ -468,10 +455,7 @@ sub project :Local {
elsif ($subcommand ne "") { elsif ($subcommand ne "") {
return requireLogin($c) if !$c->user_exists; requireProjectOwner($c, $project);
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;
if ($subcommand eq "edit") { if ($subcommand eq "edit") {
$c->stash->{edit} = 1; $c->stash->{edit} = 1;
@ -506,7 +490,7 @@ sub project :Local {
sub createproject :Local { sub createproject :Local {
my ($self, $c, $subcommand) = @_; my ($self, $c, $subcommand) = @_;
return requireLogin($c) if !$c->user_exists; requireLogin($c) if !$c->user_exists;
error($c, "Only administrators can create projects.") error($c, "Only administrators can create projects.")
unless $c->check_user_roles('admin'); unless $c->check_user_roles('admin');

View file

@ -7,6 +7,7 @@ use Readonly;
our @ISA = qw(Exporter); our @ISA = qw(Exporter);
our @EXPORT = qw( our @EXPORT = qw(
getBuild error notFound getBuild error notFound
requireLogin requireProjectOwner
$pathCompRE $relPathRE $pathCompRE $relPathRE
); );
@ -21,7 +22,7 @@ sub getBuild {
sub error { sub error {
my ($c, $msg) = @_; my ($c, $msg) = @_;
$c->error($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. # Security checking of filenames.
Readonly::Scalar our $pathCompRE => "(?:[A-Za-z0-9-\+][A-Za-z0-9-\+\._]*)"; Readonly::Scalar our $pathCompRE => "(?:[A-Za-z0-9-\+][A-Za-z0-9-\+\._]*)";
Readonly::Scalar our $relPathRE => "(?:$pathCompRE(?:\/$pathCompRE)*)"; Readonly::Scalar our $relPathRE => "(?:$pathCompRE(?:\/$pathCompRE)*)";

View file

@ -15,6 +15,11 @@
</h1> </h1>
[% IF flashMsg %]
<p class="error">[% flashMsg %]</p>
[% END %]
<h2>Information</h2> <h2>Information</h2>
<table class="layoutTable"> <table class="layoutTable">
@ -39,6 +44,9 @@
<img src="/static/images/failure.gif" /> <img src="/static/images/failure.gif" />
<span class="error">Build failed</span> <span class="error">Build failed</span>
(see <a href="#nix-error">below</a>) (see <a href="#nix-error">below</a>)
<form action="[% c.uri_for('/build' build.id 'restart') %]" method="post" class="inline">
<button id="delete-project" type="submit">Restart</button>
</form>
[% END %] [% END %]
[% ELSIF build.schedulingInfo.busy %] [% ELSIF build.schedulingInfo.busy %]
<strong>Build in progress</strong> <strong>Build in progress</strong>

View file

@ -437,3 +437,7 @@ select {
button { button {
background-color: #f0f0e0; background-color: #f0f0e0;
} }
form.inline {
display: inline;
}