2009-02-25 12:03:13 +00:00
|
|
|
package Hydra::Controller::Build;
|
|
|
|
|
|
|
|
use strict;
|
|
|
|
use warnings;
|
2009-03-04 12:23:54 +00:00
|
|
|
use base 'Hydra::Base::Controller::NixChannel';
|
2009-02-25 12:03:13 +00:00
|
|
|
use Hydra::Helper::Nix;
|
|
|
|
use Hydra::Helper::CatalystUtils;
|
2009-10-26 15:39:14 +00:00
|
|
|
use Hydra::Helper::AddBuilds;
|
2009-04-16 15:22:14 +00:00
|
|
|
use File::stat;
|
2010-01-22 13:31:59 +00:00
|
|
|
use Data::Dump qw(dump);
|
2011-11-30 14:25:28 +00:00
|
|
|
use Nix::Store;
|
2009-02-25 12:03:13 +00:00
|
|
|
|
2011-09-15 08:27:17 +00:00
|
|
|
|
2009-02-25 12:03:13 +00:00
|
|
|
sub build : Chained('/') PathPart CaptureArgs(1) {
|
|
|
|
my ($self, $c, $id) = @_;
|
|
|
|
|
|
|
|
$c->stash->{id} = $id;
|
|
|
|
|
|
|
|
$c->stash->{build} = getBuild($c, $id);
|
2010-03-05 13:03:41 +00:00
|
|
|
|
|
|
|
notFound($c, "Build with ID $id doesn't exist.")
|
|
|
|
if !defined $c->stash->{build};
|
|
|
|
|
2010-02-22 13:21:34 +00:00
|
|
|
$c->stash->{prevBuild} = getPreviousBuild($c, $c->stash->{build});
|
|
|
|
$c->stash->{prevSuccessfulBuild} = getPreviousSuccessfulBuild($c, $c->stash->{build});
|
2010-07-14 07:31:14 +00:00
|
|
|
$c->stash->{firstBrokenBuild} = getNextBuild($c, $c->stash->{prevSuccessfulBuild});
|
2009-02-25 14:34:29 +00:00
|
|
|
|
2010-02-25 15:32:56 +00:00
|
|
|
$c->stash->{mappers} = [$c->model('DB::UriRevMapper')->all];
|
|
|
|
|
2009-03-13 15:41:19 +00:00
|
|
|
$c->stash->{project} = $c->stash->{build}->project;
|
2009-02-25 12:03:13 +00:00
|
|
|
}
|
|
|
|
|
2011-09-15 08:27:17 +00:00
|
|
|
|
2009-02-25 12:03:13 +00:00
|
|
|
sub view_build : Chained('build') PathPart('') Args(0) {
|
|
|
|
my ($self, $c) = @_;
|
|
|
|
|
|
|
|
my $build = $c->stash->{build};
|
|
|
|
|
|
|
|
$c->stash->{template} = 'build.tt';
|
|
|
|
$c->stash->{available} = isValidPath $build->outpath;
|
2009-02-27 15:31:49 +00:00
|
|
|
$c->stash->{drvAvailable} = isValidPath $build->drvpath;
|
2009-03-06 12:49:01 +00:00
|
|
|
$c->stash->{flashMsg} = $c->flash->{buildMsg};
|
2009-02-25 12:03:13 +00:00
|
|
|
|
2012-02-29 01:22:49 +00:00
|
|
|
$c->stash->{pathHash} = $c->stash->{available} ? queryPathHash($build->outpath) : undef;
|
2010-04-27 07:55:19 +00:00
|
|
|
|
2012-02-29 01:22:49 +00:00
|
|
|
if (!$build->finished && $build->busy) {
|
|
|
|
my $logfile = $build->logfile;
|
2010-08-31 14:08:59 +00:00
|
|
|
$c->stash->{logtext} = `cat $logfile` if defined $logfile && -e $logfile;
|
2009-02-25 12:03:13 +00:00
|
|
|
}
|
2010-01-15 14:18:12 +00:00
|
|
|
|
2012-03-05 20:52:47 +00:00
|
|
|
if ($build->finished && $build->iscachedbuild) {
|
2010-01-15 14:18:12 +00:00
|
|
|
(my $cachedBuildStep) = $c->model('DB::BuildSteps')->search({ outpath => $build->outpath }, {}) ;
|
2010-01-19 16:35:16 +00:00
|
|
|
$c->stash->{cachedBuild} = $cachedBuildStep->build if defined $cachedBuildStep;
|
2010-01-15 14:18:12 +00:00
|
|
|
}
|
2010-02-05 20:32:07 +00:00
|
|
|
|
2010-02-06 07:15:31 +00:00
|
|
|
(my $lastBuildStep) = $build->buildsteps->search({},{order_by => "stepnr DESC", rows => 1});
|
2010-02-08 11:46:39 +00:00
|
|
|
my $path = defined $lastBuildStep ? $lastBuildStep->logfile : "" ;
|
2012-03-05 20:52:47 +00:00
|
|
|
if ($build->finished && ($build->buildstatus == 1 || $build->buildstatus == 6) && !($path eq "") && -f $lastBuildStep->logfile) {
|
2011-06-10 10:48:51 +00:00
|
|
|
my $logtext = `tail -n 50 $path`;
|
|
|
|
$c->stash->{logtext} = removeAsciiEscapes($logtext);
|
2010-02-08 11:46:39 +00:00
|
|
|
}
|
2010-01-15 14:18:12 +00:00
|
|
|
|
2012-03-05 20:52:47 +00:00
|
|
|
if ($build->finished) {
|
|
|
|
$c->stash->{prevBuilds} = [$c->model('DB::Builds')->search(
|
2010-02-10 10:15:09 +00:00
|
|
|
{ project => $c->stash->{project}->name
|
|
|
|
, jobset => $c->stash->{build}->jobset->name
|
|
|
|
, job => $c->stash->{build}->job->name
|
2010-08-31 15:30:20 +00:00
|
|
|
, 'me.system' => $build->system
|
2010-02-10 10:15:09 +00:00
|
|
|
, finished => 1
|
|
|
|
, buildstatus => 0
|
2010-02-11 12:23:46 +00:00
|
|
|
, 'me.id' => { '<=' => $build->id }
|
|
|
|
}
|
|
|
|
, { join => "actualBuildStep"
|
|
|
|
, "+select" => ["actualBuildStep.stoptime - actualBuildStep.starttime"]
|
|
|
|
, "+as" => ["actualBuildTime"]
|
2011-03-15 13:54:43 +00:00
|
|
|
, order_by => "me.id DESC"
|
2010-02-11 12:23:46 +00:00
|
|
|
, rows => 50
|
2010-02-10 10:15:09 +00:00
|
|
|
}
|
|
|
|
)
|
|
|
|
];
|
|
|
|
}
|
|
|
|
|
2012-02-29 01:22:49 +00:00
|
|
|
#my $r = joinWithResultInfo( $c, $c->model('DB::Builds'))->search(
|
|
|
|
# { eval => { -in => $build->jobsetevalmembers->all->get_column('eval')->as_query } }
|
|
|
|
# , { join => 'jobsetevalmembers', order_by => [ 'project', 'jobset', 'job'], distinct => 1 }
|
|
|
|
# );
|
|
|
|
#if ($r->count <= 100) {
|
|
|
|
# $c->stash->{relatedbuilds} = [$r->all];
|
|
|
|
#}
|
2009-02-25 12:03:13 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2009-03-14 23:27:08 +00:00
|
|
|
sub view_nixlog : Chained('build') PathPart('nixlog') {
|
|
|
|
my ($self, $c, $stepnr, $mode) = @_;
|
2009-02-25 12:03:13 +00:00
|
|
|
|
|
|
|
my $step = $c->stash->{build}->buildsteps->find({stepnr => $stepnr});
|
2009-02-25 14:34:29 +00:00
|
|
|
notFound($c, "Build doesn't have a build step $stepnr.") if !defined $step;
|
2009-02-25 12:03:13 +00:00
|
|
|
|
|
|
|
$c->stash->{step} = $step;
|
|
|
|
|
2009-03-14 23:27:08 +00:00
|
|
|
showLog($c, $step->logfile, $mode);
|
2009-02-25 12:03:13 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2009-03-14 23:27:08 +00:00
|
|
|
sub view_log : Chained('build') PathPart('log') {
|
|
|
|
my ($self, $c, $mode) = @_;
|
2009-02-25 12:03:13 +00:00
|
|
|
|
2012-03-05 20:52:47 +00:00
|
|
|
error($c, "Build didn't produce a log.") if !defined $c->stash->{build}->logfile;
|
2009-02-25 12:03:13 +00:00
|
|
|
|
2012-03-05 20:52:47 +00:00
|
|
|
showLog($c, $c->stash->{build}->logfile, $mode);
|
2009-02-25 12:03:13 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2009-03-14 23:27:08 +00:00
|
|
|
sub showLog {
|
|
|
|
my ($c, $path, $mode) = @_;
|
2009-02-25 12:03:13 +00:00
|
|
|
|
2010-08-10 13:11:41 +00:00
|
|
|
my $fallbackpath = -f $path ? $path : "$path.bz2";
|
|
|
|
|
|
|
|
notFound($c, "Log file $path no longer exists.") unless -f $fallbackpath;
|
|
|
|
$path = $fallbackpath;
|
|
|
|
|
|
|
|
my $pipestart = ($path =~ /.bz2$/ ? "cat $path | bzip2 -d" : "cat $path") ;
|
2009-02-25 12:03:13 +00:00
|
|
|
|
2009-03-16 12:16:33 +00:00
|
|
|
if (!$mode) {
|
2009-03-14 23:27:08 +00:00
|
|
|
# !!! quick hack
|
2010-08-10 13:11:41 +00:00
|
|
|
my $pipeline = $pipestart
|
2009-03-14 23:27:08 +00:00
|
|
|
. " | nix-log2xml | xsltproc " . $c->path_to("xsl/mark-errors.xsl") . " -"
|
|
|
|
. " | xsltproc " . $c->path_to("xsl/log2html.xsl") . " - | tail -n +2";
|
|
|
|
|
|
|
|
$c->stash->{template} = 'log.tt';
|
|
|
|
$c->stash->{logtext} = `$pipeline`;
|
|
|
|
}
|
|
|
|
|
|
|
|
elsif ($mode eq "raw") {
|
2010-08-10 13:11:41 +00:00
|
|
|
$c->stash->{'plain'} = { data => (scalar `$pipestart`) || " " };
|
|
|
|
$c->forward('Hydra::View::Plain');
|
2009-03-14 23:27:08 +00:00
|
|
|
}
|
|
|
|
|
2011-02-02 09:00:52 +00:00
|
|
|
elsif ($mode eq "tail-reload") {
|
|
|
|
my $url = $c->request->uri->as_string;
|
|
|
|
$url =~ s/tail-reload/tail/g;
|
|
|
|
$c->stash->{url} = $url;
|
2012-02-29 01:22:49 +00:00
|
|
|
$c->stash->{reload} = !$c->stash->{build}->finished && $c->stash->{build}->busy;
|
2011-02-02 09:00:52 +00:00
|
|
|
$c->stash->{title} = "";
|
|
|
|
$c->stash->{contents} = (scalar `$pipestart | tail -n 50`) || " ";
|
|
|
|
$c->stash->{template} = 'plain-reload.tt';
|
|
|
|
}
|
|
|
|
|
2009-03-16 12:16:33 +00:00
|
|
|
elsif ($mode eq "tail") {
|
2010-08-10 13:11:41 +00:00
|
|
|
$c->stash->{'plain'} = { data => (scalar `$pipestart | tail -n 50`) || " " };
|
2009-03-16 12:16:33 +00:00
|
|
|
$c->forward('Hydra::View::Plain');
|
|
|
|
}
|
|
|
|
|
2009-03-14 23:27:08 +00:00
|
|
|
else {
|
|
|
|
error($c, "Unknown log display mode `$mode'.");
|
|
|
|
}
|
2009-02-25 12:03:13 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2009-04-08 08:09:39 +00:00
|
|
|
sub defaultUriForProduct {
|
|
|
|
my ($self, $c, $product, @path) = @_;
|
|
|
|
my $x = $product->productnr
|
|
|
|
. ($product->name ? "/" . $product->name : "")
|
|
|
|
. ($product->defaultpath ? "/" . $product->defaultpath : "");
|
2011-08-19 16:23:01 +00:00
|
|
|
return $c->uri_for($self->action_for("download"), $c->req->captures, (split /\//, $x), @path);
|
2009-04-08 08:09:39 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2009-03-18 17:40:12 +00:00
|
|
|
sub download : Chained('build') PathPart {
|
2009-03-06 13:34:53 +00:00
|
|
|
my ($self, $c, $productnr, @path) = @_;
|
2009-02-25 12:03:13 +00:00
|
|
|
|
2009-04-08 09:37:05 +00:00
|
|
|
$productnr = 1 if !defined $productnr;
|
|
|
|
|
2009-02-25 12:03:13 +00:00
|
|
|
my $product = $c->stash->{build}->buildproducts->find({productnr => $productnr});
|
2009-04-08 09:37:05 +00:00
|
|
|
notFound($c, "Build doesn't have a product #$productnr.") if !defined $product;
|
2009-02-25 12:03:13 +00:00
|
|
|
|
2009-02-27 15:31:49 +00:00
|
|
|
notFound($c, "Product " . $product->path . " has disappeared.") unless -e $product->path;
|
2009-02-25 12:03:13 +00:00
|
|
|
|
2009-04-08 08:09:39 +00:00
|
|
|
return $c->res->redirect(defaultUriForProduct($self, $c, $product, @path))
|
|
|
|
if scalar @path == 0 && ($product->name || $product->defaultpath);
|
|
|
|
|
2009-03-06 13:34:53 +00:00
|
|
|
# If the product has a name, then the first path element can be
|
|
|
|
# ignored (it's the name included in the URL for informational purposes).
|
|
|
|
shift @path if $product->name;
|
|
|
|
|
2009-02-25 12:03:13 +00:00
|
|
|
# Security paranoia.
|
|
|
|
foreach my $elem (@path) {
|
2009-02-25 14:34:29 +00:00
|
|
|
error($c, "Invalid filename $elem.") if $elem !~ /^$pathCompRE$/;
|
2009-02-25 12:03:13 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
my $path = $product->path;
|
|
|
|
$path .= "/" . join("/", @path) if scalar @path > 0;
|
|
|
|
|
|
|
|
# If this is a directory but no "/" is attached, then redirect.
|
|
|
|
if (-d $path && substr($c->request->uri, -1) ne "/") {
|
|
|
|
return $c->res->redirect($c->request->uri . "/");
|
|
|
|
}
|
|
|
|
|
|
|
|
$path = "$path/index.html" if -d $path && -e "$path/index.html";
|
|
|
|
|
2009-02-25 14:34:29 +00:00
|
|
|
notFound($c, "File $path does not exist.") if !-e $path;
|
2009-02-25 12:03:13 +00:00
|
|
|
|
2009-03-06 13:34:53 +00:00
|
|
|
notFound($c, "Path $path is a directory.") if -d $path;
|
|
|
|
|
2009-02-25 12:03:13 +00:00
|
|
|
$c->serve_static_file($path);
|
2011-09-15 15:22:00 +00:00
|
|
|
$c->response->headers->last_modified($c->stash->{build}->timestamp);
|
2009-02-25 12:03:13 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2009-04-08 08:09:39 +00:00
|
|
|
# Redirect to a download with the given type. Useful when you want to
|
|
|
|
# link to some build product of the latest build (i.e. in conjunction
|
|
|
|
# with the .../latest redirect).
|
|
|
|
sub download_by_type : Chained('build') PathPart('download-by-type') {
|
|
|
|
my ($self, $c, $type, $subtype, @path) = @_;
|
|
|
|
|
|
|
|
notFound($c, "You need to specify a type and a subtype in the URI.")
|
|
|
|
unless defined $type && defined $subtype;
|
|
|
|
|
|
|
|
(my $product) = $c->stash->{build}->buildproducts->search(
|
2009-10-12 17:07:36 +00:00
|
|
|
{type => $type, subtype => $subtype}, {order_by => "productnr"});
|
2009-04-08 08:09:39 +00:00
|
|
|
notFound($c, "Build doesn't have a build product with type $type/$subtype.")
|
|
|
|
if !defined $product;
|
|
|
|
|
|
|
|
$c->res->redirect(defaultUriForProduct($self, $c, $product, @path));
|
|
|
|
}
|
|
|
|
|
2011-09-15 08:27:17 +00:00
|
|
|
|
2009-03-18 18:50:42 +00:00
|
|
|
sub contents : Chained('build') PathPart Args(1) {
|
|
|
|
my ($self, $c, $productnr) = @_;
|
2009-03-18 17:40:12 +00:00
|
|
|
|
|
|
|
my $product = $c->stash->{build}->buildproducts->find({productnr => $productnr});
|
|
|
|
notFound($c, "Build doesn't have a product $productnr.") if !defined $product;
|
|
|
|
|
|
|
|
my $path = $product->path;
|
|
|
|
|
|
|
|
notFound($c, "Product $path has disappeared.") unless -e $path;
|
|
|
|
|
|
|
|
my $res;
|
|
|
|
|
2010-02-05 20:07:49 +00:00
|
|
|
if ($product->type eq "nix-build" && -d $path) {
|
2009-03-18 17:40:12 +00:00
|
|
|
$res = `cd $path && find . -print0 | xargs -0 ls -ld --`;
|
|
|
|
error($c, "`ls -lR' error: $?") if $? != 0;
|
2011-01-04 12:50:59 +00:00
|
|
|
|
|
|
|
my $baseuri = $c->uri_for('/build', $c->stash->{build}->id, 'download', $product->productnr);
|
|
|
|
$baseuri .= "/".$product->name if $product->name;
|
|
|
|
$res =~ s/(\.\/)($relPathRE)/<a href="$baseuri\/$2">$1$2<\/a>/g;
|
2009-03-18 17:40:12 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
elsif ($path =~ /\.rpm$/) {
|
|
|
|
$res = `rpm --query --info --package "$path"`;
|
|
|
|
error($c, "RPM error: $?") if $? != 0;
|
|
|
|
$res .= "===\n";
|
|
|
|
$res .= `rpm --query --list --verbose --package "$path"`;
|
|
|
|
error($c, "RPM error: $?") if $? != 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
elsif ($path =~ /\.deb$/) {
|
|
|
|
$res = `dpkg-deb --info "$path"`;
|
|
|
|
error($c, "`dpkg-deb' error: $?") if $? != 0;
|
|
|
|
$res .= "===\n";
|
|
|
|
$res .= `dpkg-deb --contents "$path"`;
|
|
|
|
error($c, "`dpkg-deb' error: $?") if $? != 0;
|
|
|
|
}
|
|
|
|
|
2011-11-16 15:32:32 +00:00
|
|
|
elsif ($path =~ /\.(tar(\.gz|\.bz2|\.xz|\.lzma)?|tgz)$/ ) {
|
2009-03-18 17:40:12 +00:00
|
|
|
$res = `tar tvfa "$path"`;
|
|
|
|
error($c, "`tar' error: $?") if $? != 0;
|
|
|
|
}
|
|
|
|
|
2009-06-18 13:23:04 +00:00
|
|
|
elsif ($path =~ /\.(zip|jar)$/ ) {
|
2009-03-18 17:40:12 +00:00
|
|
|
$res = `unzip -v "$path"`;
|
|
|
|
error($c, "`unzip' error: $?") if $? != 0;
|
2009-07-07 11:37:47 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
elsif ($path =~ /\.iso$/ ) {
|
|
|
|
$res = `isoinfo -d -i "$path" && isoinfo -l -R -i "$path"`;
|
|
|
|
error($c, "`isoinfo' error: $?") if $? != 0;
|
2009-03-18 17:40:12 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
else {
|
|
|
|
error($c, "Unsupported file type.");
|
|
|
|
}
|
|
|
|
|
|
|
|
die unless $res;
|
|
|
|
|
2011-01-04 12:50:59 +00:00
|
|
|
$c->stash->{title} = "Contents of ".$product->path;
|
|
|
|
$c->stash->{contents} = "<pre>$res</pre>";
|
|
|
|
$c->stash->{template} = 'plain.tt';
|
2009-03-18 17:40:12 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2009-02-27 15:31:49 +00:00
|
|
|
sub runtimedeps : Chained('build') PathPart('runtime-deps') {
|
|
|
|
my ($self, $c) = @_;
|
|
|
|
|
|
|
|
my $build = $c->stash->{build};
|
|
|
|
|
|
|
|
notFound($c, "Path " . $build->outpath . " is no longer available.")
|
|
|
|
unless isValidPath($build->outpath);
|
|
|
|
|
2010-06-22 12:00:19 +00:00
|
|
|
$c->stash->{current_view} = 'NixDepGraph';
|
2009-02-27 15:31:49 +00:00
|
|
|
$c->stash->{storePaths} = [$build->outpath];
|
|
|
|
|
2009-03-04 10:59:14 +00:00
|
|
|
$c->res->content_type('image/png'); # !!!
|
2009-02-27 15:31:49 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
sub buildtimedeps : Chained('build') PathPart('buildtime-deps') {
|
|
|
|
my ($self, $c) = @_;
|
|
|
|
|
|
|
|
my $build = $c->stash->{build};
|
|
|
|
|
|
|
|
notFound($c, "Path " . $build->drvpath . " is no longer available.")
|
|
|
|
unless isValidPath($build->drvpath);
|
|
|
|
|
2010-06-22 12:00:19 +00:00
|
|
|
$c->stash->{current_view} = 'NixDepGraph';
|
2009-02-27 15:31:49 +00:00
|
|
|
$c->stash->{storePaths} = [$build->drvpath];
|
|
|
|
|
2009-03-04 10:59:14 +00:00
|
|
|
$c->res->content_type('image/png'); # !!!
|
2009-02-27 15:31:49 +00:00
|
|
|
}
|
|
|
|
|
2011-09-15 08:27:17 +00:00
|
|
|
|
2010-01-22 13:31:59 +00:00
|
|
|
sub deps : Chained('build') PathPart('deps') {
|
|
|
|
my ($self, $c) = @_;
|
|
|
|
|
|
|
|
my $build = $c->stash->{build};
|
|
|
|
$c->stash->{available} = isValidPath $build->outpath;
|
|
|
|
$c->stash->{drvAvailable} = isValidPath $build->drvpath;
|
|
|
|
|
|
|
|
my $drvpath = $build->drvpath;
|
|
|
|
my $outpath = $build->outpath;
|
|
|
|
|
|
|
|
my @buildtimepaths = ();
|
|
|
|
my @buildtimedeps = ();
|
|
|
|
@buildtimepaths = split '\n', `nix-store --query --requisites --include-outputs $drvpath` if isValidPath($build->drvpath);
|
|
|
|
|
|
|
|
my @runtimepaths = ();
|
|
|
|
my @runtimedeps = ();
|
|
|
|
@runtimepaths = split '\n', `nix-store --query --requisites --include-outputs $outpath` if isValidPath($build->outpath);
|
|
|
|
|
|
|
|
foreach my $p (@buildtimepaths) {
|
|
|
|
my $buildStep;
|
|
|
|
($buildStep) = $c->model('DB::BuildSteps')->search({ outpath => $p }, {}) ;
|
|
|
|
my %dep = ( buildstep => $buildStep, path => $p ) ;
|
|
|
|
push(@buildtimedeps, \%dep);
|
|
|
|
}
|
|
|
|
|
|
|
|
foreach my $p (@runtimepaths) {
|
|
|
|
my $buildStep;
|
|
|
|
($buildStep) = $c->model('DB::BuildSteps')->search({ outpath => $p }, {}) ;
|
|
|
|
my %dep = ( buildstep => $buildStep, path => $p ) ;
|
|
|
|
push(@runtimedeps, \%dep);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
$c->stash->{buildtimedeps} = \@buildtimedeps;
|
|
|
|
$c->stash->{runtimedeps} = \@runtimedeps;
|
|
|
|
|
|
|
|
$c->stash->{template} = 'deps.tt';
|
|
|
|
}
|
|
|
|
|
2009-02-27 15:31:49 +00:00
|
|
|
|
2009-02-25 14:34:29 +00:00
|
|
|
sub nix : Chained('build') PathPart('nix') CaptureArgs(0) {
|
|
|
|
my ($self, $c) = @_;
|
|
|
|
|
|
|
|
my $build = $c->stash->{build};
|
|
|
|
|
2009-02-27 14:57:06 +00:00
|
|
|
notFound($c, "Build cannot be downloaded as a closure or Nix package.")
|
2009-02-25 14:34:29 +00:00
|
|
|
if !$build->buildproducts->find({type => "nix-build"});
|
|
|
|
|
2009-02-27 14:57:06 +00:00
|
|
|
notFound($c, "Path " . $build->outpath . " is no longer available.")
|
2009-02-25 14:34:29 +00:00
|
|
|
unless isValidPath($build->outpath);
|
|
|
|
|
2010-02-18 15:09:13 +00:00
|
|
|
$c->stash->{storePaths} = [$build->outpath];
|
2009-02-25 16:29:54 +00:00
|
|
|
|
2009-03-04 14:49:21 +00:00
|
|
|
my $pkgName = $build->nixname . "-" . $build->system;
|
|
|
|
$c->stash->{nixPkgs} = {"${pkgName}.nixpkg" => {build => $build, name => $pkgName}};
|
2009-02-25 14:34:29 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2009-03-06 12:49:01 +00:00
|
|
|
sub restart : Chained('build') PathPart Args(0) {
|
2009-03-02 16:03:41 +00:00
|
|
|
my ($self, $c) = @_;
|
|
|
|
|
|
|
|
my $build = $c->stash->{build};
|
|
|
|
|
|
|
|
requireProjectOwner($c, $build->project);
|
2010-12-03 08:40:34 +00:00
|
|
|
|
|
|
|
my $drvpath = $build->drvpath ;
|
|
|
|
error($c, "This build cannot be restarted.")
|
|
|
|
unless $build->finished && -f $drvpath ;
|
2009-03-02 16:03:41 +00:00
|
|
|
|
2010-12-07 13:25:29 +00:00
|
|
|
restartBuild($c->model('DB')->schema, $build);
|
2009-03-02 16:03:41 +00:00
|
|
|
|
2009-03-06 12:49:01 +00:00
|
|
|
$c->flash->{buildMsg} = "Build has been restarted.";
|
|
|
|
|
|
|
|
$c->res->redirect($c->uri_for($self->action_for("view_build"), $c->req->captures));
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
sub cancel : Chained('build') PathPart Args(0) {
|
|
|
|
my ($self, $c) = @_;
|
|
|
|
|
|
|
|
my $build = $c->stash->{build};
|
|
|
|
|
|
|
|
requireProjectOwner($c, $build->project);
|
|
|
|
|
2009-04-22 22:43:04 +00:00
|
|
|
txn_do($c->model('DB')->schema, sub {
|
2009-03-06 12:49:01 +00:00
|
|
|
error($c, "This build cannot be cancelled.")
|
2012-02-29 01:22:49 +00:00
|
|
|
if $build->finished || $build->busy;
|
2009-03-06 12:49:01 +00:00
|
|
|
|
|
|
|
# !!! Actually, it would be nice to be able to cancel busy
|
|
|
|
# builds as well, but we would have to send a signal or
|
|
|
|
# something to the build process.
|
|
|
|
|
2012-02-29 01:22:49 +00:00
|
|
|
$build->update({finished => 1, busy => 0, timestamp => time});
|
2009-03-06 12:49:01 +00:00
|
|
|
|
|
|
|
$c->model('DB::BuildResultInfo')->create(
|
|
|
|
{ id => $build->id
|
|
|
|
, iscachedbuild => 0
|
|
|
|
, buildstatus => 4 # = cancelled
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
$c->flash->{buildMsg} = "Build has been cancelled.";
|
2009-03-02 16:03:41 +00:00
|
|
|
|
2009-03-04 10:59:14 +00:00
|
|
|
$c->res->redirect($c->uri_for($self->action_for("view_build"), $c->req->captures));
|
2009-03-02 16:03:41 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2009-03-14 23:56:57 +00:00
|
|
|
sub keep : Chained('build') PathPart Args(1) {
|
|
|
|
my ($self, $c, $newStatus) = @_;
|
|
|
|
|
|
|
|
my $build = $c->stash->{build};
|
|
|
|
|
|
|
|
requireProjectOwner($c, $build->project);
|
|
|
|
|
|
|
|
die unless $newStatus == 0 || $newStatus == 1;
|
|
|
|
|
2009-03-16 10:57:44 +00:00
|
|
|
registerRoot $build->outpath if $newStatus == 1;
|
|
|
|
|
2009-04-22 22:43:04 +00:00
|
|
|
txn_do($c->model('DB')->schema, sub {
|
2012-03-05 20:52:47 +00:00
|
|
|
$build->update({keep => int $newStatus});
|
2009-03-14 23:56:57 +00:00
|
|
|
});
|
|
|
|
|
|
|
|
$c->flash->{buildMsg} =
|
|
|
|
$newStatus == 0 ? "Build will not be kept." : "Build will be kept.";
|
|
|
|
|
|
|
|
$c->res->redirect($c->uri_for($self->action_for("view_build"), $c->req->captures));
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2009-10-23 15:57:18 +00:00
|
|
|
sub add_to_release : Chained('build') PathPart('add-to-release') Args(0) {
|
|
|
|
my ($self, $c) = @_;
|
|
|
|
|
|
|
|
my $build = $c->stash->{build};
|
|
|
|
|
|
|
|
requireProjectOwner($c, $build->project);
|
|
|
|
|
|
|
|
my $releaseName = trim $c->request->params->{name};
|
|
|
|
|
|
|
|
my $release = $build->project->releases->find({name => $releaseName});
|
|
|
|
|
|
|
|
error($c, "This project has no release named `$releaseName'.") unless $release;
|
|
|
|
|
|
|
|
error($c, "This build is already a part of release `$releaseName'.")
|
|
|
|
if $release->releasemembers->find({build => $build->id});
|
2009-10-26 10:46:57 +00:00
|
|
|
|
|
|
|
registerRoot $build->outpath;
|
|
|
|
|
|
|
|
error($c, "This build is no longer available.") unless isValidPath $build->outpath;
|
2009-10-23 15:57:18 +00:00
|
|
|
|
|
|
|
$release->releasemembers->create({build => $build->id, description => $build->description});
|
|
|
|
|
|
|
|
$c->flash->{buildMsg} = "Build added to project <tt>$releaseName</tt>.";
|
|
|
|
|
|
|
|
$c->res->redirect($c->uri_for($self->action_for("view_build"), $c->req->captures));
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2009-10-26 14:30:42 +00:00
|
|
|
sub clone : Chained('build') PathPart('clone') Args(0) {
|
|
|
|
my ($self, $c) = @_;
|
|
|
|
|
|
|
|
my $build = $c->stash->{build};
|
|
|
|
|
|
|
|
requireProjectOwner($c, $build->project);
|
|
|
|
|
|
|
|
$c->stash->{template} = 'clone-build.tt';
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
sub clone_submit : Chained('build') PathPart('clone/submit') Args(0) {
|
|
|
|
my ($self, $c) = @_;
|
|
|
|
|
|
|
|
my $build = $c->stash->{build};
|
|
|
|
|
|
|
|
requireProjectOwner($c, $build->project);
|
|
|
|
|
2009-10-26 17:01:23 +00:00
|
|
|
my ($nixExprPath, $nixExprInputName) = Hydra::Controller::Jobset::nixExprPathFromParams $c;
|
2009-10-26 15:39:14 +00:00
|
|
|
|
|
|
|
my $jobName = trim $c->request->params->{"jobname"};
|
|
|
|
error($c, "Invalid job name: $jobName") if $jobName !~ /^$jobNameRE$/;
|
|
|
|
|
2009-10-26 17:01:23 +00:00
|
|
|
my $inputInfo = {};
|
|
|
|
|
2009-10-26 15:39:14 +00:00
|
|
|
foreach my $param (keys %{$c->request->params}) {
|
|
|
|
next unless $param =~ /^input-(\w+)-name$/;
|
|
|
|
my $baseName = $1;
|
|
|
|
my ($inputName, $inputType) =
|
|
|
|
Hydra::Controller::Jobset::checkInput($c, $baseName);
|
|
|
|
my $inputValue = Hydra::Controller::Jobset::checkInputValue(
|
|
|
|
$c, $inputType, $c->request->params->{"input-$baseName-value"});
|
|
|
|
eval {
|
2009-10-26 17:01:23 +00:00
|
|
|
# !!! fetchInput can take a long time, which might cause
|
|
|
|
# the current HTTP request to time out. So maybe this
|
|
|
|
# should be done asynchronously. But then error reporting
|
|
|
|
# becomes harder.
|
|
|
|
my $info = fetchInput(
|
2009-10-26 15:39:14 +00:00
|
|
|
$c->model('DB'), $build->project, $build->jobset,
|
|
|
|
$inputName, $inputType, $inputValue);
|
2009-10-26 17:01:23 +00:00
|
|
|
push @{$$inputInfo{$inputName}}, $info if defined $info;
|
2009-10-26 15:39:14 +00:00
|
|
|
};
|
|
|
|
error($c, $@) if $@;
|
|
|
|
}
|
|
|
|
|
2009-10-26 17:01:23 +00:00
|
|
|
my ($jobs, $nixExprInput) = evalJobs($inputInfo, $nixExprInputName, $nixExprPath);
|
|
|
|
|
|
|
|
my $job;
|
|
|
|
foreach my $j (@{$jobs->{job}}) {
|
|
|
|
print STDERR $j->{jobName}, "\n";
|
|
|
|
if ($j->{jobName} eq $jobName) {
|
|
|
|
error($c, "Nix expression returned multiple builds for job $jobName.")
|
|
|
|
if $job;
|
|
|
|
$job = $j;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
error($c, "Nix expression did not return a job named $jobName.") unless $job;
|
|
|
|
|
|
|
|
my %currentBuilds;
|
|
|
|
my $newBuild = checkBuild(
|
|
|
|
$c->model('DB'), $build->project, $build->jobset,
|
|
|
|
$inputInfo, $nixExprInput, $job, \%currentBuilds);
|
|
|
|
|
|
|
|
error($c, "This build has already been performed.") unless $newBuild;
|
|
|
|
|
|
|
|
$c->flash->{buildMsg} = "Build " . $newBuild->id . " added to the queue.";
|
2009-10-26 14:30:42 +00:00
|
|
|
|
|
|
|
$c->res->redirect($c->uri_for($c->controller('Root')->action_for('queue')));
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-09-15 08:27:17 +00:00
|
|
|
sub get_info : Chained('build') PathPart('api/get-info') Args(0) {
|
|
|
|
my ($self, $c) = @_;
|
|
|
|
my $build = $c->stash->{build};
|
|
|
|
# !!! strip the json prefix
|
|
|
|
$c->stash->{jsonBuildId} = $build->id;
|
|
|
|
$c->stash->{jsonDrvPath} = $build->drvpath;
|
|
|
|
$c->stash->{jsonOutPath} = $build->outpath;
|
|
|
|
$c->forward('View::JSON');
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2009-02-25 12:03:13 +00:00
|
|
|
1;
|