Merge the BuildResultInfo table into the Builds table
This commit is contained in:
parent
25334715f8
commit
68a867da67
|
@ -10,14 +10,12 @@ use Hydra::Helper::CatalystUtils;
|
|||
sub getJobStatus {
|
||||
my ($self, $c) = @_;
|
||||
|
||||
my $latest = joinWithResultInfo($c, $c->stash->{jobStatus});
|
||||
|
||||
my $maintainer = $c->request->params->{"maintainer"};
|
||||
|
||||
$latest = $latest->search(
|
||||
my $latest = $c->stash->{jobStatus}->search(
|
||||
defined $maintainer ? { maintainers => { like => "%$maintainer%" } } : {},
|
||||
{ '+select' => ["me.statusChangeId", "me.statusChangeTime", "resultInfo.buildStatus"]
|
||||
, '+as' => ["statusChangeId", "statusChangeTime", "buildStatus"]
|
||||
{ '+select' => ["me.statusChangeId", "me.statusChangeTime"]
|
||||
, '+as' => ["statusChangeId", "statusChangeTime"]
|
||||
, order_by => "coalesce(statusChangeTime, 0) desc"
|
||||
});
|
||||
|
||||
|
@ -43,7 +41,7 @@ sub errors : Chained('get_builds') PathPart Args(0) {
|
|||
[$c->stash->{allJobs}->search({errormsg => {'!=' => ''}})]
|
||||
if defined $c->stash->{allJobs};
|
||||
$c->stash->{brokenBuilds} =
|
||||
[getJobStatus($self, $c)->search({'resultInfo.buildstatus' => {'!=' => 0}})];
|
||||
[getJobStatus($self, $c)->search({buildStatus => {'!=' => 0}})];
|
||||
}
|
||||
|
||||
|
||||
|
@ -64,11 +62,9 @@ sub all : Chained('get_builds') PathPart {
|
|||
$c->stash->{resultsPerPage} = $resultsPerPage;
|
||||
$c->stash->{totalBuilds} = $nrBuilds;
|
||||
|
||||
$c->stash->{builds} = [ joinWithResultInfo($c, $c->stash->{allBuilds})->search(
|
||||
$c->stash->{builds} = [ $c->stash->{allBuilds}->search(
|
||||
{ finished => 1 },
|
||||
{ '+select' => ["resultInfo.buildStatus"]
|
||||
, '+as' => ["buildStatus"]
|
||||
, order_by => "timestamp DESC"
|
||||
{ order_by => "timestamp DESC"
|
||||
, rows => $resultsPerPage
|
||||
, page => $page }) ];
|
||||
}
|
||||
|
@ -97,8 +93,8 @@ sub nix : Chained('get_builds') PathPart('channel') CaptureArgs(1) {
|
|||
sub latest : Chained('get_builds') PathPart('latest') {
|
||||
my ($self, $c, @rest) = @_;
|
||||
|
||||
my ($latest) = joinWithResultInfo($c, $c->stash->{allBuilds})
|
||||
->search({finished => 1, buildstatus => 0}, {order_by => ["isCurrent DESC", "timestamp DESC"]});
|
||||
my ($latest) = $c->stash->{allBuilds}->search(
|
||||
{finished => 1, buildstatus => 0}, {order_by => ["isCurrent DESC", "timestamp DESC"]});
|
||||
|
||||
notFound($c, "There is no successful build to redirect to.") unless defined $latest;
|
||||
|
||||
|
@ -112,8 +108,8 @@ sub latest_for : Chained('get_builds') PathPart('latest-for') {
|
|||
|
||||
notFound($c, "You need to specify a platform type in the URL.") unless defined $system;
|
||||
|
||||
my ($latest) = joinWithResultInfo($c, $c->stash->{allBuilds})
|
||||
->search({finished => 1, buildstatus => 0, system => $system}, {order_by => ["isCurrent DESC", "timestamp DESC"]});
|
||||
my ($latest) = $c->stash->{allBuilds}->search(
|
||||
{finished => 1, buildstatus => 0, system => $system}, {order_by => ["isCurrent DESC", "timestamp DESC"]});
|
||||
|
||||
notFound($c, "There is no successful build for platform `$system' to redirect to.") unless defined $latest;
|
||||
|
||||
|
|
|
@ -15,11 +15,13 @@ use File::Slurp;
|
|||
|
||||
# !!! Rewrite this to use View::JSON.
|
||||
|
||||
|
||||
sub api : Chained('/') PathPart('api') CaptureArgs(0) {
|
||||
my ($self, $c) = @_;
|
||||
$c->response->content_type('application/json');
|
||||
}
|
||||
|
||||
|
||||
sub projectToHash {
|
||||
my ($project) = @_;
|
||||
return {
|
||||
|
@ -28,14 +30,15 @@ sub projectToHash {
|
|||
};
|
||||
}
|
||||
|
||||
|
||||
sub projects : Chained('api') PathPart('projects') Args(0) {
|
||||
my ($self, $c) = @_;
|
||||
|
||||
my @projects = $c->model('DB::Projects')->search({hidden => 0}, {order_by => 'name'}) ;
|
||||
my @projects = $c->model('DB::Projects')->search({hidden => 0}, {order_by => 'name'});
|
||||
|
||||
my @list ;
|
||||
my @list;
|
||||
foreach my $p (@projects) {
|
||||
push @list, projectToHash($p) ;
|
||||
push @list, projectToHash($p);
|
||||
}
|
||||
|
||||
$c->stash->{'plain'} = {
|
||||
|
@ -44,6 +47,7 @@ sub projects : Chained('api') PathPart('projects') Args(0) {
|
|||
$c->forward('Hydra::View::Plain');
|
||||
}
|
||||
|
||||
|
||||
sub buildToHash {
|
||||
my ($build) = @_;
|
||||
my $result = {
|
||||
|
@ -58,7 +62,7 @@ sub buildToHash {
|
|||
};
|
||||
|
||||
if($build->finished) {
|
||||
$result->{'buildstatus'} = $build->get_column("buildstatus") ;
|
||||
$result->{'buildstatus'} = $build->get_column("buildstatus");
|
||||
} else {
|
||||
$result->{'busy'} = $build->get_column("busy");
|
||||
$result->{'priority'} = $build->get_column("priority");
|
||||
|
@ -67,28 +71,27 @@ sub buildToHash {
|
|||
return $result;
|
||||
};
|
||||
|
||||
|
||||
sub latestbuilds : Chained('api') PathPart('latestbuilds') Args(0) {
|
||||
my ($self, $c) = @_;
|
||||
my $nr = $c->request->params->{nr} ;
|
||||
my $nr = $c->request->params->{nr};
|
||||
error($c, "Parameter not defined!") if !defined $nr;
|
||||
|
||||
my $project = $c->request->params->{project} ;
|
||||
my $jobset = $c->request->params->{jobset} ;
|
||||
my $job = $c->request->params->{job} ;
|
||||
my $system = $c->request->params->{system} ;
|
||||
my $project = $c->request->params->{project};
|
||||
my $jobset = $c->request->params->{jobset};
|
||||
my $job = $c->request->params->{job};
|
||||
my $system = $c->request->params->{system};
|
||||
|
||||
my $filter = {finished => 1} ;
|
||||
my $filter = {finished => 1};
|
||||
$filter->{project} = $project if ! $project eq "";
|
||||
$filter->{jobset} = $jobset if ! $jobset eq "";
|
||||
$filter->{job} = $job if !$job eq "";
|
||||
$filter->{system} = $system if !$system eq "";
|
||||
|
||||
my @latest = joinWithResultInfo($c, $c->model('DB::Builds'))->search($filter, {rows => $nr, order_by => ["timestamp DESC"] });
|
||||
my @latest = $c->model('DB::Builds')->search($filter, {rows => $nr, order_by => ["timestamp DESC"] });
|
||||
|
||||
my @list ;
|
||||
foreach my $b (@latest) {
|
||||
push @list, buildToHash($b) ;
|
||||
}
|
||||
my @list;
|
||||
push @list, buildToHash($_) foreach @latest;
|
||||
|
||||
$c->stash->{'plain'} = {
|
||||
data => scalar (JSON::Any->objToJson(\@list))
|
||||
|
@ -96,6 +99,7 @@ sub latestbuilds : Chained('api') PathPart('latestbuilds') Args(0) {
|
|||
$c->forward('Hydra::View::Plain');
|
||||
}
|
||||
|
||||
|
||||
sub jobsetToHash {
|
||||
my ($jobset) = @_;
|
||||
return {
|
||||
|
@ -108,10 +112,11 @@ sub jobsetToHash {
|
|||
};
|
||||
}
|
||||
|
||||
|
||||
sub jobsets : Chained('api') PathPart('jobsets') Args(0) {
|
||||
my ($self, $c) = @_;
|
||||
|
||||
my $projectName = $c->request->params->{project} ;
|
||||
my $projectName = $c->request->params->{project};
|
||||
error($c, "Parameter 'project' not defined!") if !defined $projectName;
|
||||
|
||||
my $project = $c->model('DB::Projects')->find($projectName)
|
||||
|
@ -119,10 +124,8 @@ sub jobsets : Chained('api') PathPart('jobsets') Args(0) {
|
|||
|
||||
my @jobsets = jobsetOverview($c, $project);
|
||||
|
||||
my @list ;
|
||||
foreach my $j (@jobsets) {
|
||||
push @list, jobsetToHash($j) ;
|
||||
}
|
||||
my @list;
|
||||
push @list, jobsetToHash($_) foreach @jobsets;
|
||||
|
||||
$c->stash->{'plain'} = {
|
||||
data => scalar (JSON::Any->objToJson(\@list))
|
||||
|
@ -130,10 +133,11 @@ sub jobsets : Chained('api') PathPart('jobsets') Args(0) {
|
|||
$c->forward('Hydra::View::Plain');
|
||||
}
|
||||
|
||||
|
||||
sub queue : Chained('api') PathPart('queue') Args(0) {
|
||||
my ($self, $c) = @_;
|
||||
|
||||
my $nr = $c->request->params->{nr} ;
|
||||
my $nr = $c->request->params->{nr};
|
||||
error($c, "Parameter not defined!") if !defined $nr;
|
||||
|
||||
my @builds = $c->model('DB::Builds')->search({finished => 0}, {rows => $nr, order_by => ["busy DESC", "priority DESC", "timestamp"]});
|
||||
|
@ -147,6 +151,7 @@ sub queue : Chained('api') PathPart('queue') Args(0) {
|
|||
$c->forward('Hydra::View::Plain');
|
||||
}
|
||||
|
||||
|
||||
sub nrqueue : Chained('api') PathPart('nrqueue') Args(0) {
|
||||
my ($self, $c) = @_;
|
||||
my $nrQueuedBuilds = $c->model('DB::Builds')->search({finished => 0})->count();
|
||||
|
@ -156,6 +161,7 @@ sub nrqueue : Chained('api') PathPart('nrqueue') Args(0) {
|
|||
$c->forward('Hydra::View::Plain');
|
||||
}
|
||||
|
||||
|
||||
sub nrrunning : Chained('api') PathPart('nrrunning') Args(0) {
|
||||
my ($self, $c) = @_;
|
||||
my $nrRunningBuilds = $c->model('DB::Builds')->search({finished => 0, busy => 1 })->count();
|
||||
|
@ -165,20 +171,21 @@ sub nrrunning : Chained('api') PathPart('nrrunning') Args(0) {
|
|||
$c->forward('Hydra::View::Plain');
|
||||
}
|
||||
|
||||
|
||||
sub nrbuilds : Chained('api') PathPart('nrbuilds') Args(0) {
|
||||
my ($self, $c) = @_;
|
||||
my $nr = $c->request->params->{nr} ;
|
||||
my $period = $c->request->params->{period} ;
|
||||
my $nr = $c->request->params->{nr};
|
||||
my $period = $c->request->params->{period};
|
||||
|
||||
error($c, "Parameter not defined!") if !defined $nr || !defined $period;
|
||||
my $base;
|
||||
|
||||
my $project = $c->request->params->{project} ;
|
||||
my $jobset = $c->request->params->{jobset} ;
|
||||
my $job = $c->request->params->{job} ;
|
||||
my $system = $c->request->params->{system} ;
|
||||
my $project = $c->request->params->{project};
|
||||
my $jobset = $c->request->params->{jobset};
|
||||
my $job = $c->request->params->{job};
|
||||
my $system = $c->request->params->{system};
|
||||
|
||||
my $filter = {finished => 1} ;
|
||||
my $filter = {finished => 1};
|
||||
$filter->{project} = $project if ! $project eq "";
|
||||
$filter->{jobset} = $jobset if ! $jobset eq "";
|
||||
$filter->{job} = $job if !$job eq "";
|
||||
|
@ -187,11 +194,9 @@ sub nrbuilds : Chained('api') PathPart('nrbuilds') Args(0) {
|
|||
$base = 60*60 if($period eq "hour");
|
||||
$base = 24*60*60 if($period eq "day");
|
||||
|
||||
my @stats = $c->model('DB::Builds')->search($filter, {select => [{ count => "*" }], as => ["nr"], group_by => ["timestamp - timestamp % $base"], order_by => "timestamp - timestamp % $base DESC", rows => $nr}) ;
|
||||
my @arr ;
|
||||
foreach my $d (@stats) {
|
||||
push @arr, int($d->get_column("nr"));
|
||||
}
|
||||
my @stats = $c->model('DB::Builds')->search($filter, {select => [{ count => "*" }], as => ["nr"], group_by => ["timestamp - timestamp % $base"], order_by => "timestamp - timestamp % $base DESC", rows => $nr});
|
||||
my @arr;
|
||||
push @arr, int($_->get_column("nr")) foreach @stats;
|
||||
@arr = reverse(@arr);
|
||||
|
||||
$c->stash->{'plain'} = {
|
||||
|
@ -200,38 +205,40 @@ sub nrbuilds : Chained('api') PathPart('nrbuilds') Args(0) {
|
|||
$c->forward('Hydra::View::Plain');
|
||||
}
|
||||
|
||||
|
||||
sub scmdiff : Chained('api') PathPart('scmdiff') Args(0) {
|
||||
my ($self, $c) = @_;
|
||||
|
||||
my $uri = $c->request->params->{uri} ;
|
||||
my $type = $c->request->params->{type} ;
|
||||
my $rev1 = $c->request->params->{rev1} ;
|
||||
my $rev2 = $c->request->params->{rev2} ;
|
||||
my $uri = $c->request->params->{uri};
|
||||
my $type = $c->request->params->{type};
|
||||
my $rev1 = $c->request->params->{rev1};
|
||||
my $rev2 = $c->request->params->{rev2};
|
||||
my $branch;
|
||||
|
||||
die("invalid revisions: [$rev1] [$rev2]") if $rev1 !~ m/^[a-zA-Z0-9_.]+$/ || $rev2 !~ m/^[a-zA-Z0-9_.]+$/ ;
|
||||
die("invalid revisions: [$rev1] [$rev2]") if $rev1 !~ m/^[a-zA-Z0-9_.]+$/ || $rev2 !~ m/^[a-zA-Z0-9_.]+$/;
|
||||
|
||||
my $diff = "";
|
||||
if($type eq "hg") {
|
||||
if ($type eq "hg") {
|
||||
my $clonePath = scmPath . "/" . sha256_hex($uri);
|
||||
die if ! -d $clonePath;
|
||||
$branch = `(cd $clonePath ; hg log --template '{branch}' -r $rev2)`;
|
||||
$diff .= `(cd $clonePath ; hg log -r $rev1 -r $rev2 -b $branch)`;
|
||||
$diff .= `(cd $clonePath ; hg diff -r $rev1:$rev2)`;
|
||||
$branch = `(cd $clonePath; hg log --template '{branch}' -r $rev2)`;
|
||||
$diff .= `(cd $clonePath; hg log -r $rev1 -r $rev2 -b $branch)`;
|
||||
$diff .= `(cd $clonePath; hg diff -r $rev1:$rev2)`;
|
||||
} elsif ($type eq "git") {
|
||||
my $clonePath = scmPath . "/" . sha256_hex($uri);
|
||||
die if ! -d $clonePath;
|
||||
$diff .= `(cd $clonePath ; git log $rev1..$rev2)`;
|
||||
$diff .= `(cd $clonePath ; git diff $rev1..$rev2)`;
|
||||
$diff .= `(cd $clonePath; git log $rev1..$rev2)`;
|
||||
$diff .= `(cd $clonePath; git diff $rev1..$rev2)`;
|
||||
}
|
||||
|
||||
$c->stash->{'plain'} = { data => (scalar $diff) || " " };
|
||||
$c->forward('Hydra::View::Plain');
|
||||
}
|
||||
|
||||
|
||||
sub readNormalizedLog {
|
||||
my ($file) = @_;
|
||||
my $pipe = (-f "$file.bz2" ? "cat $file.bz2 | bzip2 -d" : "cat $file") ;
|
||||
my $pipe = (-f "$file.bz2" ? "cat $file.bz2 | bzip2 -d" : "cat $file");
|
||||
my $res = `$pipe`;
|
||||
|
||||
$res =~ s/\/nix\/store\/[a-z0-9]*-/\/nix\/store\/...-/g;
|
||||
|
@ -240,6 +247,7 @@ sub readNormalizedLog {
|
|||
return $res;
|
||||
}
|
||||
|
||||
|
||||
sub logdiff : Chained('api') PathPart('logdiff') Args(2) {
|
||||
my ($self, $c, $buildid1, $buildid2) = @_;
|
||||
|
||||
|
@ -252,9 +260,9 @@ sub logdiff : Chained('api') PathPart('logdiff') Args(2) {
|
|||
notFound($c, "Build with ID $buildid2 doesn't exist.")
|
||||
if !defined $build2;
|
||||
|
||||
if (-f $build1->resultInfo->logfile && -f $build2->resultInfo->logfile) {
|
||||
my $logtext1 = readNormalizedLog($build1->resultInfo->logfile);
|
||||
my $logtext2 = readNormalizedLog($build2->resultInfo->logfile);
|
||||
if (-f $build1->logfile && -f $build2->logfile) {
|
||||
my $logtext1 = readNormalizedLog($build1->logfile);
|
||||
my $logtext2 = readNormalizedLog($build2->logfile);
|
||||
$diff = diff \$logtext1, \$logtext2;
|
||||
} else {
|
||||
$c->response->status(404);
|
||||
|
@ -265,4 +273,5 @@ sub logdiff : Chained('api') PathPart('logdiff') Args(2) {
|
|||
$c->forward('Hydra::View::Plain');
|
||||
}
|
||||
|
||||
|
||||
1;
|
||||
|
|
|
@ -48,20 +48,20 @@ sub view_build : Chained('build') PathPart('') Args(0) {
|
|||
$c->stash->{logtext} = `cat $logfile` if defined $logfile && -e $logfile;
|
||||
}
|
||||
|
||||
if (defined $build->resultInfo && $build->resultInfo->iscachedbuild) {
|
||||
if ($build->finished && $build->iscachedbuild) {
|
||||
(my $cachedBuildStep) = $c->model('DB::BuildSteps')->search({ outpath => $build->outpath }, {}) ;
|
||||
$c->stash->{cachedBuild} = $cachedBuildStep->build if defined $cachedBuildStep;
|
||||
}
|
||||
|
||||
(my $lastBuildStep) = $build->buildsteps->search({},{order_by => "stepnr DESC", rows => 1});
|
||||
my $path = defined $lastBuildStep ? $lastBuildStep->logfile : "" ;
|
||||
if (defined $build->resultInfo && ($build->resultInfo->buildstatus == 1 || $build->resultInfo->buildstatus == 6) && !($path eq "") && -f $lastBuildStep->logfile) {
|
||||
if ($build->finished && ($build->buildstatus == 1 || $build->buildstatus == 6) && !($path eq "") && -f $lastBuildStep->logfile) {
|
||||
my $logtext = `tail -n 50 $path`;
|
||||
$c->stash->{logtext} = removeAsciiEscapes($logtext);
|
||||
}
|
||||
|
||||
if($build->finished) {
|
||||
$c->stash->{prevBuilds} = [joinWithResultInfo($c, $c->model('DB::Builds'))->search(
|
||||
if ($build->finished) {
|
||||
$c->stash->{prevBuilds} = [$c->model('DB::Builds')->search(
|
||||
{ project => $c->stash->{project}->name
|
||||
, jobset => $c->stash->{build}->jobset->name
|
||||
, job => $c->stash->{build}->job->name
|
||||
|
@ -105,9 +105,9 @@ sub view_nixlog : Chained('build') PathPart('nixlog') {
|
|||
sub view_log : Chained('build') PathPart('log') {
|
||||
my ($self, $c, $mode) = @_;
|
||||
|
||||
error($c, "Build didn't produce a log.") if !defined $c->stash->{build}->resultInfo->logfile;
|
||||
error($c, "Build didn't produce a log.") if !defined $c->stash->{build}->logfile;
|
||||
|
||||
showLog($c, $c->stash->{build}->resultInfo->logfile, $mode);
|
||||
showLog($c, $c->stash->{build}->logfile, $mode);
|
||||
}
|
||||
|
||||
|
||||
|
@ -438,7 +438,7 @@ sub keep : Chained('build') PathPart Args(1) {
|
|||
registerRoot $build->outpath if $newStatus == 1;
|
||||
|
||||
txn_do($c->model('DB')->schema, sub {
|
||||
$build->resultInfo->update({keep => int $newStatus});
|
||||
$build->update({keep => int $newStatus});
|
||||
});
|
||||
|
||||
$c->flash->{buildMsg} =
|
||||
|
|
|
@ -25,16 +25,11 @@ sub overview : Chained('job') PathPart('') Args(0) {
|
|||
|
||||
#getBuildStats($c, scalar $c->stash->{job}->builds);
|
||||
|
||||
$c->stash->{currentBuilds} = [$c->stash->{job}->builds->search({iscurrent => 1}, { join => 'resultInfo', '+select' => ["resultInfo.releasename", "resultInfo.buildStatus"]
|
||||
, '+as' => ["releasename", "buildStatus"], order_by => 'system' })];
|
||||
$c->stash->{currentBuilds} = [$c->stash->{job}->builds->search({finished => 1, iscurrent => 1}, { order_by => 'system' })];
|
||||
|
||||
$c->stash->{lastBuilds} =
|
||||
[ $c->stash->{job}->builds->search({ finished => 1 },
|
||||
{ join => 'resultInfo',
|
||||
, '+select' => ["resultInfo.releasename", "resultInfo.buildStatus"]
|
||||
, '+as' => ["releasename", "buildStatus"]
|
||||
, order_by => 'timestamp DESC', rows => 10
|
||||
}) ];
|
||||
{ order_by => 'timestamp DESC', rows => 10 }) ];
|
||||
|
||||
$c->stash->{runningBuilds} = [
|
||||
$c->stash->{job}->builds->search(
|
||||
|
|
|
@ -65,9 +65,9 @@ sub jobsetIndex {
|
|||
my @as = ();
|
||||
push(@select, "job"); push(@as, "job");
|
||||
foreach my $system (@systems) {
|
||||
push(@select, "(select buildstatus from BuildResultInfo bri join Builds b using (id) where b.id = (select max(id) from Builds t where t.project = me.project and t.jobset = me.jobset and t.job = me.job and t.system = '$system' and t.iscurrent = 1 ))");
|
||||
push(@select, "(select buildstatus from Builds b where b.id = (select max(id) from Builds t where t.project = me.project and t.jobset = me.jobset and t.job = me.job and t.system = '$system' and t.iscurrent = 1 ))");
|
||||
push(@as, $system);
|
||||
push(@select, "(select b.id from BuildResultInfo bri join Builds b using (id) where b.id = (select max(id) from Builds t where t.project = me.project and t.jobset = me.jobset and t.job = me.job and t.system = '$system' and t.iscurrent = 1 ))");
|
||||
push(@select, "(select b.id from Builds b where b.id = (select max(id) from Builds t where t.project = me.project and t.jobset = me.jobset and t.job = me.job and t.system = '$system' and t.iscurrent = 1 ))");
|
||||
push(@as, "$system-build");
|
||||
}
|
||||
$c->stash->{activeJobsStatus} =
|
||||
|
@ -81,13 +81,9 @@ sub jobsetIndex {
|
|||
}
|
||||
|
||||
# Last builds for jobset.
|
||||
my $tmp = $c->stash->{jobset}->builds;
|
||||
$c->stash->{lastBuilds} =
|
||||
[ joinWithResultInfo($c, $tmp)->search({ finished => 1 },
|
||||
{ order_by => "timestamp DESC", rows => 5
|
||||
, '+select' => ["resultInfo.buildStatus"]
|
||||
, '+as' => ["buildStatus"]
|
||||
}) ];
|
||||
[ $c->stash->{jobset}->builds->search({ finished => 1 },
|
||||
{ order_by => "timestamp DESC", rows => 5 }) ];
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -86,13 +86,10 @@ sub timeline :Local {
|
|||
$pit = $pit-(24*60*60)-1;
|
||||
|
||||
$c->stash->{template} = 'timeline.tt';
|
||||
$c->stash->{builds} = [$c->model('DB::Builds')->search(
|
||||
{finished => 1, stoptime => { '>' => $pit } }
|
||||
, { join => 'resultInfo'
|
||||
, order_by => ["starttime"]
|
||||
, '+select' => [ 'resultInfo.starttime', 'resultInfo.stoptime', 'resultInfo.buildstatus' ]
|
||||
, '+as' => [ 'starttime', 'stoptime', 'buildstatus' ]
|
||||
})];
|
||||
$c->stash->{builds} = [ $c->model('DB::Builds')->search
|
||||
( { finished => 1, stoptime => { '>' => $pit } }
|
||||
, { order_by => ["starttime"] }
|
||||
) ];
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -153,10 +153,7 @@ sub result : Chained('view') PathPart('') {
|
|||
|
||||
# Note: we don't actually check whether $id is a primary build,
|
||||
# but who cares?
|
||||
my $primaryBuild = $c->stash->{project}->builds->find($id,
|
||||
{ join => 'resultInfo',
|
||||
, '+select' => ["resultInfo.releasename", "resultInfo.buildstatus"]
|
||||
, '+as' => ["releasename", "buildstatus"] })
|
||||
my $primaryBuild = $c->stash->{project}->builds->find($id)
|
||||
or error($c, "Build $id doesn't exist.");
|
||||
|
||||
my $result = getViewResult($primaryBuild, $c->stash->{jobs});
|
||||
|
|
|
@ -244,7 +244,7 @@ sub fetchInputBuild {
|
|||
(my $prevBuild) = $db->resultset('Builds')->search(
|
||||
{ finished => 1, project => $projectName, jobset => $jobsetName
|
||||
, job => $jobName, buildStatus => 0 },
|
||||
{ join => 'resultInfo', order_by => "me.id DESC", rows => 1
|
||||
{ order_by => "me.id DESC", rows => 1
|
||||
, where => \ attrsToSQL($attrs, "me.id") });
|
||||
|
||||
if (!defined $prevBuild || !isValidPath($prevBuild->outpath)) {
|
||||
|
@ -257,7 +257,7 @@ sub fetchInputBuild {
|
|||
my $pkgNameRE = "(?:(?:[A-Za-z0-9]|(?:-[^0-9]))+)";
|
||||
my $versionRE = "(?:[A-Za-z0-9\.\-]+)";
|
||||
|
||||
my $relName = ($prevBuild->resultInfo->releasename or $prevBuild->nixname);
|
||||
my $relName = ($prevBuild->releasename or $prevBuild->nixname);
|
||||
my $version = $2 if $relName =~ /^($pkgNameRE)-($versionRE)$/;
|
||||
|
||||
return
|
||||
|
@ -294,7 +294,7 @@ sub fetchInputSystemBuild {
|
|||
my $pkgNameRE = "(?:(?:[A-Za-z0-9]|(?:-[^0-9]))+)";
|
||||
my $versionRE = "(?:[A-Za-z0-9\.\-]+)";
|
||||
|
||||
my $relName = ($prevBuild->resultInfo->releasename or $prevBuild->nixname);
|
||||
my $relName = ($prevBuild->releasename or $prevBuild->nixname);
|
||||
my $version = $2 if $relName =~ /^($pkgNameRE)-($versionRE)$/;
|
||||
|
||||
my $input =
|
||||
|
@ -855,9 +855,9 @@ sub checkBuild {
|
|||
|
||||
if (isValidPath($outPath)) {
|
||||
print STDERR "marked as cached build ", $build->id, "\n";
|
||||
$build->update({ finished => 1 });
|
||||
$build->create_related('buildresultinfo',
|
||||
{ iscachedbuild => 1
|
||||
$build->update(
|
||||
{ finished => 1
|
||||
, iscachedbuild => 1
|
||||
, buildstatus => 0
|
||||
, starttime => $time
|
||||
, stoptime => $time
|
||||
|
@ -921,7 +921,5 @@ sub restartBuild {
|
|||
, busy => 0
|
||||
, locker => ""
|
||||
});
|
||||
|
||||
$build->resultInfo->delete;
|
||||
});
|
||||
}
|
||||
|
|
|
@ -8,7 +8,7 @@ use Hydra::Helper::Nix;
|
|||
|
||||
our @ISA = qw(Exporter);
|
||||
our @EXPORT = qw(
|
||||
getBuild getPreviousBuild getNextBuild getPreviousSuccessfulBuild getBuildStats joinWithResultInfo getChannelData
|
||||
getBuild getPreviousBuild getNextBuild getPreviousSuccessfulBuild getBuildStats getChannelData
|
||||
error notFound
|
||||
requireLogin requireProjectOwner requireAdmin requirePost isAdmin isProjectOwner
|
||||
trim
|
||||
|
@ -58,7 +58,7 @@ sub getPreviousSuccessfulBuild {
|
|||
my ($c, $build) = @_;
|
||||
return undef if !defined $build;
|
||||
|
||||
(my $prevBuild) = joinWithResultInfo($c, $c->model('DB::Builds'))->search(
|
||||
(my $prevBuild) = $c->model('DB::Builds')->search(
|
||||
{ finished => 1
|
||||
, system => $build->system
|
||||
, project => $build->project->name
|
||||
|
@ -76,43 +76,24 @@ sub getBuildStats {
|
|||
|
||||
$c->stash->{finishedBuilds} = $builds->search({finished => 1}) || 0;
|
||||
|
||||
$c->stash->{succeededBuilds} = $builds->search(
|
||||
{finished => 1, buildStatus => 0},
|
||||
{join => 'resultInfo'}) || 0;
|
||||
$c->stash->{succeededBuilds} = $builds->search({finished => 1, buildStatus => 0}) || 0;
|
||||
|
||||
$c->stash->{scheduledBuilds} = $builds->search({finished => 0}) || 0;
|
||||
|
||||
$c->stash->{busyBuilds} = $builds->search({finished => 0, busy => 1}) || 0;
|
||||
|
||||
my $res;
|
||||
$res = $builds->search({},
|
||||
{join => 'resultInfo', select => {sum => 'stoptime - starttime'}, as => ['sum']})
|
||||
->first ;
|
||||
$res = $builds->search({}, {select => {sum => 'stoptime - starttime'}, as => ['sum']})->first;
|
||||
|
||||
$c->stash->{totalBuildTime} = defined ($res) ? $res->get_column('sum') : 0 ;
|
||||
|
||||
}
|
||||
|
||||
|
||||
# Add the releaseName and buildStatus attributes from the
|
||||
# BuildResultInfo table for each build.
|
||||
sub joinWithResultInfo {
|
||||
my ($c, $source) = @_;
|
||||
|
||||
return $source->search(
|
||||
{ },
|
||||
{ join => 'resultInfo'
|
||||
, '+select' => ["resultInfo.releasename", "resultInfo.buildstatus"]
|
||||
, '+as' => ["releasename", "buildStatus"]
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
sub getChannelData {
|
||||
my ($c, $builds) = @_;
|
||||
|
||||
my @builds2 = joinWithResultInfo($c, $builds)
|
||||
->search_literal("exists (select 1 from buildproducts where build = resultInfo.id and type = 'nix-build')");
|
||||
my @builds2 = $builds->search_literal("exists (select 1 from buildproducts where build = me.id and type = 'nix-build')");
|
||||
|
||||
my @storePaths = ();
|
||||
foreach my $build (@builds2) {
|
||||
|
|
|
@ -121,9 +121,7 @@ sub allPrimaryBuilds {
|
|||
my ($project, $primaryJob) = @_;
|
||||
my $allPrimaryBuilds = $project->builds->search(
|
||||
{ jobset => $primaryJob->get_column('jobset'), job => $primaryJob->get_column('job'), finished => 1 },
|
||||
{ join => 'resultInfo', order_by => "timestamp DESC"
|
||||
, '+select' => ["resultInfo.releasename", "resultInfo.buildstatus"]
|
||||
, '+as' => ["releasename", "buildstatus"]
|
||||
{ order_by => "timestamp DESC"
|
||||
, where => \ attrsToSQL($primaryJob->attrs, "me.id")
|
||||
});
|
||||
return $allPrimaryBuilds;
|
||||
|
@ -165,10 +163,9 @@ sub findLastJobForBuilds {
|
|||
{
|
||||
$thisBuild = $ev->builds->find(
|
||||
{ job => $job->get_column('job'), finished => 1 },
|
||||
{ join => 'resultInfo', rows => 1
|
||||
{ rows => 1
|
||||
, order_by => ["build.id"]
|
||||
, where => \ attrsToSQL($job->attrs, "build.id")
|
||||
, '+select' => ["resultInfo.buildstatus"], '+as' => ["buildstatus"]
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -180,30 +177,31 @@ sub findLastJobForBuilds {
|
|||
{ project => $project, jobset => $jobset
|
||||
, job => $job->get_column('job'), finished => 1
|
||||
},
|
||||
{ join => 'resultInfo', rows => 1
|
||||
{ rows => 1
|
||||
, order_by => ["buildstatus", "timestamp"]
|
||||
, where => \ attrsToSQL($job->attrs, "build.id")
|
||||
, '+select' => ["resultInfo.buildstatus"], '+as' => ["buildstatus"]
|
||||
})
|
||||
unless defined $thisBuild;
|
||||
|
||||
return $thisBuild;
|
||||
}
|
||||
|
||||
|
||||
sub jobsetOverview {
|
||||
my ($c, $project) = @_;
|
||||
return $project->jobsets->search( isProjectOwner($c, $project) ? {} : { hidden => 0 },
|
||||
{ order_by => "name"
|
||||
, "+select" =>
|
||||
[ "(select count(*) from Builds as a where a.finished = 0 and me.project = a.project and me.name = a.jobset and a.isCurrent = 1)"
|
||||
, "(select count(*) from Builds as a join BuildResultInfo r using (id) where me.project = a.project and me.name = a.jobset and buildstatus <> 0 and a.isCurrent = 1)"
|
||||
, "(select count(*) from Builds as a join BuildResultInfo r using (id) where me.project = a.project and me.name = a.jobset and buildstatus = 0 and a.isCurrent = 1)"
|
||||
, "(select count(*) from Builds as a where a.finished = 1 and me.project = a.project and me.name = a.jobset and buildstatus <> 0 and a.isCurrent = 1)"
|
||||
, "(select count(*) from Builds as a where a.finished = 1 and me.project = a.project and me.name = a.jobset and buildstatus = 0 and a.isCurrent = 1)"
|
||||
, "(select count(*) from Builds as a where me.project = a.project and me.name = a.jobset and a.isCurrent = 1)"
|
||||
]
|
||||
, "+as" => ["nrscheduled", "nrfailed", "nrsucceeded", "nrtotal"]
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
sub getViewResult {
|
||||
my ($primaryBuild, $jobs) = @_;
|
||||
|
||||
|
@ -258,10 +256,12 @@ sub getLatestSuccessfulViewResult {
|
|||
return undef;
|
||||
}
|
||||
|
||||
|
||||
sub removeAsciiEscapes {
|
||||
my ($logtext) = @_;
|
||||
$logtext =~ s/\e\[[0-9]*[A-Za-z]//g;
|
||||
return $logtext;
|
||||
}
|
||||
|
||||
|
||||
1;
|
||||
|
|
|
@ -1,174 +0,0 @@
|
|||
use utf8;
|
||||
package Hydra::Schema::BuildResultInfo;
|
||||
|
||||
# Created by DBIx::Class::Schema::Loader
|
||||
# DO NOT MODIFY THE FIRST PART OF THIS FILE
|
||||
|
||||
=head1 NAME
|
||||
|
||||
Hydra::Schema::BuildResultInfo
|
||||
|
||||
=cut
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use base 'DBIx::Class::Core';
|
||||
|
||||
=head1 TABLE: C<BuildResultInfo>
|
||||
|
||||
=cut
|
||||
|
||||
__PACKAGE__->table("BuildResultInfo");
|
||||
|
||||
=head1 ACCESSORS
|
||||
|
||||
=head2 id
|
||||
|
||||
data_type: 'integer'
|
||||
is_auto_increment: 1
|
||||
is_foreign_key: 1
|
||||
is_nullable: 0
|
||||
|
||||
=head2 iscachedbuild
|
||||
|
||||
data_type: 'integer'
|
||||
is_nullable: 0
|
||||
|
||||
=head2 buildstatus
|
||||
|
||||
data_type: 'integer'
|
||||
is_nullable: 1
|
||||
|
||||
=head2 errormsg
|
||||
|
||||
data_type: 'text'
|
||||
is_nullable: 1
|
||||
|
||||
=head2 starttime
|
||||
|
||||
data_type: 'integer'
|
||||
is_nullable: 1
|
||||
|
||||
=head2 stoptime
|
||||
|
||||
data_type: 'integer'
|
||||
is_nullable: 1
|
||||
|
||||
=head2 logfile
|
||||
|
||||
data_type: 'text'
|
||||
is_nullable: 1
|
||||
|
||||
=head2 logsize
|
||||
|
||||
data_type: 'bigint'
|
||||
default_value: 0
|
||||
is_nullable: 0
|
||||
|
||||
=head2 size
|
||||
|
||||
data_type: 'bigint'
|
||||
default_value: 0
|
||||
is_nullable: 0
|
||||
|
||||
=head2 closuresize
|
||||
|
||||
data_type: 'bigint'
|
||||
default_value: 0
|
||||
is_nullable: 0
|
||||
|
||||
=head2 releasename
|
||||
|
||||
data_type: 'text'
|
||||
is_nullable: 1
|
||||
|
||||
=head2 keep
|
||||
|
||||
data_type: 'integer'
|
||||
default_value: 0
|
||||
is_nullable: 0
|
||||
|
||||
=head2 faileddepbuild
|
||||
|
||||
data_type: 'integer'
|
||||
is_nullable: 1
|
||||
|
||||
=head2 faileddepstepnr
|
||||
|
||||
data_type: 'integer'
|
||||
is_nullable: 1
|
||||
|
||||
=cut
|
||||
|
||||
__PACKAGE__->add_columns(
|
||||
"id",
|
||||
{
|
||||
data_type => "integer",
|
||||
is_auto_increment => 1,
|
||||
is_foreign_key => 1,
|
||||
is_nullable => 0,
|
||||
},
|
||||
"iscachedbuild",
|
||||
{ data_type => "integer", is_nullable => 0 },
|
||||
"buildstatus",
|
||||
{ data_type => "integer", is_nullable => 1 },
|
||||
"errormsg",
|
||||
{ data_type => "text", is_nullable => 1 },
|
||||
"starttime",
|
||||
{ data_type => "integer", is_nullable => 1 },
|
||||
"stoptime",
|
||||
{ data_type => "integer", is_nullable => 1 },
|
||||
"logfile",
|
||||
{ data_type => "text", is_nullable => 1 },
|
||||
"logsize",
|
||||
{ data_type => "bigint", default_value => 0, is_nullable => 0 },
|
||||
"size",
|
||||
{ data_type => "bigint", default_value => 0, is_nullable => 0 },
|
||||
"closuresize",
|
||||
{ data_type => "bigint", default_value => 0, is_nullable => 0 },
|
||||
"releasename",
|
||||
{ data_type => "text", is_nullable => 1 },
|
||||
"keep",
|
||||
{ data_type => "integer", default_value => 0, is_nullable => 0 },
|
||||
"faileddepbuild",
|
||||
{ data_type => "integer", is_nullable => 1 },
|
||||
"faileddepstepnr",
|
||||
{ data_type => "integer", is_nullable => 1 },
|
||||
);
|
||||
|
||||
=head1 PRIMARY KEY
|
||||
|
||||
=over 4
|
||||
|
||||
=item * L</id>
|
||||
|
||||
=back
|
||||
|
||||
=cut
|
||||
|
||||
__PACKAGE__->set_primary_key("id");
|
||||
|
||||
=head1 RELATIONS
|
||||
|
||||
=head2 id
|
||||
|
||||
Type: belongs_to
|
||||
|
||||
Related object: L<Hydra::Schema::Builds>
|
||||
|
||||
=cut
|
||||
|
||||
__PACKAGE__->belongs_to("id", "Hydra::Schema::Builds", { id => "id" }, {});
|
||||
|
||||
|
||||
# Created by DBIx::Class::Schema::Loader v0.07014 @ 2011-12-05 14:15:43
|
||||
# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:hX3+iQYrGslQqY9vKvyw3g
|
||||
|
||||
__PACKAGE__->belongs_to(
|
||||
"failedDep",
|
||||
"Hydra::Schema::BuildSteps",
|
||||
{ build => "faileddepbuild", stepnr => "faileddepstepnr" },
|
||||
);
|
||||
|
||||
1;
|
|
@ -163,6 +163,52 @@ __PACKAGE__->table("Builds");
|
|||
data_type: 'integer'
|
||||
is_nullable: 1
|
||||
|
||||
=head2 stoptime
|
||||
|
||||
data_type: 'integer'
|
||||
is_nullable: 1
|
||||
|
||||
=head2 iscachedbuild
|
||||
|
||||
data_type: 'integer'
|
||||
is_nullable: 1
|
||||
|
||||
=head2 buildstatus
|
||||
|
||||
data_type: 'integer'
|
||||
is_nullable: 1
|
||||
|
||||
=head2 errormsg
|
||||
|
||||
data_type: 'text'
|
||||
is_nullable: 1
|
||||
|
||||
=head2 logsize
|
||||
|
||||
data_type: 'bigint'
|
||||
is_nullable: 1
|
||||
|
||||
=head2 size
|
||||
|
||||
data_type: 'bigint'
|
||||
is_nullable: 1
|
||||
|
||||
=head2 closuresize
|
||||
|
||||
data_type: 'bigint'
|
||||
is_nullable: 1
|
||||
|
||||
=head2 releasename
|
||||
|
||||
data_type: 'text'
|
||||
is_nullable: 1
|
||||
|
||||
=head2 keep
|
||||
|
||||
data_type: 'integer'
|
||||
default_value: 0
|
||||
is_nullable: 0
|
||||
|
||||
=cut
|
||||
|
||||
__PACKAGE__->add_columns(
|
||||
|
@ -218,6 +264,24 @@ __PACKAGE__->add_columns(
|
|||
{ data_type => "integer", default_value => 0, is_nullable => 0 },
|
||||
"starttime",
|
||||
{ data_type => "integer", is_nullable => 1 },
|
||||
"stoptime",
|
||||
{ data_type => "integer", is_nullable => 1 },
|
||||
"iscachedbuild",
|
||||
{ data_type => "integer", is_nullable => 1 },
|
||||
"buildstatus",
|
||||
{ data_type => "integer", is_nullable => 1 },
|
||||
"errormsg",
|
||||
{ data_type => "text", is_nullable => 1 },
|
||||
"logsize",
|
||||
{ data_type => "bigint", is_nullable => 1 },
|
||||
"size",
|
||||
{ data_type => "bigint", is_nullable => 1 },
|
||||
"closuresize",
|
||||
{ data_type => "bigint", is_nullable => 1 },
|
||||
"releasename",
|
||||
{ data_type => "text", is_nullable => 1 },
|
||||
"keep",
|
||||
{ data_type => "integer", default_value => 0, is_nullable => 0 },
|
||||
);
|
||||
|
||||
=head1 PRIMARY KEY
|
||||
|
@ -279,21 +343,6 @@ __PACKAGE__->has_many(
|
|||
{},
|
||||
);
|
||||
|
||||
=head2 buildresultinfo
|
||||
|
||||
Type: might_have
|
||||
|
||||
Related object: L<Hydra::Schema::BuildResultInfo>
|
||||
|
||||
=cut
|
||||
|
||||
__PACKAGE__->might_have(
|
||||
"buildresultinfo",
|
||||
"Hydra::Schema::BuildResultInfo",
|
||||
{ "foreign.id" => "self.id" },
|
||||
{},
|
||||
);
|
||||
|
||||
=head2 buildsteps
|
||||
|
||||
Type: has_many
|
||||
|
@ -380,8 +429,8 @@ __PACKAGE__->has_many(
|
|||
);
|
||||
|
||||
|
||||
# Created by DBIx::Class::Schema::Loader v0.07014 @ 2012-02-29 00:47:54
|
||||
# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:VnnyFTwnLncGb2Dj2/giiA
|
||||
# Created by DBIx::Class::Schema::Loader v0.07014 @ 2012-02-29 18:56:22
|
||||
# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:w16c86FRReLPdA8H0yTIRg
|
||||
|
||||
use Hydra::Helper::Nix;
|
||||
|
||||
|
@ -399,12 +448,6 @@ __PACKAGE__->has_many(
|
|||
{ "foreign.build" => "self.id" },
|
||||
);
|
||||
|
||||
__PACKAGE__->belongs_to(
|
||||
"resultInfo",
|
||||
"Hydra::Schema::BuildResultInfo",
|
||||
{ id => "id" },
|
||||
);
|
||||
|
||||
__PACKAGE__->has_one(
|
||||
"actualBuildStep",
|
||||
"Hydra::Schema::BuildSteps",
|
||||
|
@ -432,36 +475,16 @@ sub makeSource {
|
|||
sub makeQueries {
|
||||
my ($name, $constraint) = @_;
|
||||
|
||||
my $joinWithStatusChange =
|
||||
<<QUERY;
|
||||
join BuildResultInfo r using (id)
|
||||
left join Builds b on
|
||||
b.id =
|
||||
(select max(c.id)
|
||||
from builds c join buildresultinfo r2 on c.id = r2.id
|
||||
where
|
||||
x.project = c.project and x.jobset = c.jobset and x.job = c.job and x.system = c.system and
|
||||
x.id > c.id and
|
||||
((r.buildstatus = 0 and r2.buildstatus != 0) or
|
||||
(r.buildstatus != 0 and r2.buildstatus = 0)))
|
||||
QUERY
|
||||
|
||||
my $activeJobs = "(select distinct project, jobset, job, system from Builds where isCurrent = 1 $constraint)";
|
||||
|
||||
makeSource(
|
||||
"JobStatus$name",
|
||||
# Urgh, can't use "*" in the "select" here because of the status change join.
|
||||
<<QUERY
|
||||
select
|
||||
x.id, x.finished, x.timestamp, x.project, x.jobset, x.job, x.nixname,
|
||||
x.description, x.drvpath, x.outpath, x.system, x.longdescription,
|
||||
x.license, x.homepage, x.maintainers, x.isCurrent, x.nixExprInput,
|
||||
x.nixExprPath, x.maxsilent, x.timeout, x.priority, x.busy, x.locker,
|
||||
x.logfile, x.disabled, x.startTime,
|
||||
b.id as statusChangeId, b.timestamp as statusChangeTime
|
||||
select x.*, b.id as statusChangeId, b.timestamp as statusChangeTime
|
||||
from
|
||||
(select
|
||||
(select max(b.id) from builds b
|
||||
(select max(b.id) from Builds b
|
||||
where
|
||||
project = activeJobs.project and jobset = activeJobs.jobset
|
||||
and job = activeJobs.job and system = activeJobs.system
|
||||
|
@ -470,7 +493,15 @@ QUERY
|
|||
from $activeJobs as activeJobs
|
||||
) as latest
|
||||
join Builds x using (id)
|
||||
$joinWithStatusChange
|
||||
left join Builds b on
|
||||
b.id =
|
||||
(select max(c.id) from Builds c
|
||||
where
|
||||
c.finished = 1 and
|
||||
x.project = c.project and x.jobset = c.jobset and x.job = c.job and x.system = c.system and
|
||||
x.id > c.id and
|
||||
((x.buildStatus = 0 and c.buildStatus != 0) or
|
||||
(x.buildStatus != 0 and c.buildStatus = 0)))
|
||||
QUERY
|
||||
);
|
||||
|
||||
|
@ -486,8 +517,7 @@ QUERY
|
|||
where
|
||||
project = activeJobs.project and jobset = activeJobs.jobset
|
||||
and job = activeJobs.job and system = activeJobs.system
|
||||
and finished = 1
|
||||
and exists (select 1 from buildresultinfo where id = b.id and buildstatus = 0)
|
||||
and finished = 1 and buildstatus = 0
|
||||
) as id
|
||||
from $activeJobs as activeJobs
|
||||
) as latest
|
||||
|
|
|
@ -7,7 +7,6 @@
|
|||
[% project = build.project %]
|
||||
[% jobset = build.jobset %]
|
||||
[% job = build.job %]
|
||||
[% resultInfo = build.resultInfo %]
|
||||
|
||||
[% BLOCK renderBuildSteps %]
|
||||
|
||||
|
@ -35,7 +34,7 @@
|
|||
[% INCLUDE renderDuration duration = step.stoptime - step.starttime %]
|
||||
[% ELSE %]
|
||||
[% IF build.finished %]
|
||||
[% INCLUDE renderDuration duration = resultInfo.stoptime - step.starttime %]
|
||||
[% INCLUDE renderDuration duration = build.stoptime - step.starttime %]
|
||||
[% ELSE %]
|
||||
[% INCLUDE renderDuration duration = curTime - step.starttime %]
|
||||
[% END %]
|
||||
|
@ -106,10 +105,10 @@
|
|||
<th>Build ID:</th>
|
||||
<td>[% build.id %]</td>
|
||||
</tr>
|
||||
[% IF resultInfo.releasename %]
|
||||
[% IF build.releasename %]
|
||||
<tr>
|
||||
<th>Release name:</th>
|
||||
<td><tt>[% HTML.escape(resultInfo.releasename) %]</tt></td>
|
||||
<td><tt>[% HTML.escape(build.releasename) %]</tt></td>
|
||||
</tr>
|
||||
[% ELSE %]
|
||||
<tr>
|
||||
|
@ -131,15 +130,15 @@
|
|||
<tr>
|
||||
<th>Duration:</th>
|
||||
<td>
|
||||
[% IF resultInfo.iscachedbuild %]
|
||||
[% IF build.iscachedbuild %]
|
||||
(cached[% IF cachedBuild %] from [% INCLUDE renderFullBuildLink build=cachedBuild %][% END %])
|
||||
[% ELSE %]
|
||||
[% INCLUDE renderDuration duration = resultInfo.stoptime - resultInfo.starttime %] <tt>finished at [% INCLUDE renderDateTime timestamp = resultInfo.stoptime %]</tt>
|
||||
[% INCLUDE renderDuration duration = build.stoptime - build.starttime %] <tt>finished at [% INCLUDE renderDateTime timestamp = build.stoptime %]</tt>
|
||||
[% END %]
|
||||
</td>
|
||||
</tr>
|
||||
[% END %]
|
||||
[% IF resultInfo.logfile %]
|
||||
[% IF build.logfile %]
|
||||
<tr>
|
||||
<th>Logfile:</th>
|
||||
<td>
|
||||
|
@ -182,7 +181,7 @@
|
|||
[% END %]
|
||||
|
||||
[% IF build.finished %]
|
||||
[% IF build.buildsteps && resultInfo.buildstatus != 0 && resultInfo.buildstatus != 6 %]
|
||||
[% IF build.buildsteps && build.buildstatus != 0 && build.buildstatus != 6 %]
|
||||
[% INCLUDE renderBuildSteps type="Failed" %]
|
||||
[% END %]
|
||||
|
||||
|
@ -214,11 +213,11 @@
|
|||
</table>
|
||||
[% END %]
|
||||
|
||||
[% IF resultInfo.errormsg && resultInfo.buildstatus != 5 %]
|
||||
[% IF build.errormsg && build.buildstatus != 5 %]
|
||||
|
||||
<h2 id="nix-error">Nix error output</h2>
|
||||
|
||||
<pre class="buildlog">[% HTML.escape(resultInfo.errormsg) -%]</pre>
|
||||
<pre class="buildlog">[% HTML.escape(build.errormsg) -%]</pre>
|
||||
[% END %]
|
||||
[% END %]
|
||||
[% IF logtext %]
|
||||
|
@ -264,10 +263,10 @@
|
|||
<th>Nix name:</th>
|
||||
<td><tt>[% build.nixname %]</tt></td>
|
||||
</tr>
|
||||
[% IF resultInfo.releasename %]
|
||||
[% IF build.releasename %]
|
||||
<tr>
|
||||
<th>Release name:</th>
|
||||
<td><tt>[% HTML.escape(resultInfo.releasename) %]</tt></td>
|
||||
<td><tt>[% HTML.escape(build.releasename) %]</tt></td>
|
||||
</tr>
|
||||
[% END %]
|
||||
<tr>
|
||||
|
@ -328,8 +327,8 @@
|
|||
<th>Time added:</th>
|
||||
<td>[% INCLUDE renderDateTime timestamp = build.timestamp %]</td>
|
||||
</tr>
|
||||
[% IF build.finished && resultInfo.buildstatus != 4 %]
|
||||
[% IF resultInfo.iscachedbuild && cachedBuild %]
|
||||
[% IF build.finished && build.buildstatus != 4 %]
|
||||
[% IF build.iscachedbuild && cachedBuild %]
|
||||
<tr>
|
||||
<th>Cached build:</th>
|
||||
<td>[% INCLUDE renderFullBuildLink build=cachedBuild %]</td>
|
||||
|
@ -338,23 +337,23 @@
|
|||
|
||||
<tr>
|
||||
<th>Build started:</th>
|
||||
<td>[% IF resultInfo.starttime %][% INCLUDE renderDateTime timestamp = resultInfo.starttime %][% ELSE %]<em>(cached build)</em>[% END %]</td>
|
||||
<td>[% IF build.starttime %][% INCLUDE renderDateTime timestamp = build.starttime %][% ELSE %]<em>(cached build)</em>[% END %]</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Build finished:</th>
|
||||
<td>[% IF resultInfo.stoptime %][% INCLUDE renderDateTime timestamp = resultInfo.stoptime %][% ELSE %]<em>(cached build)</em>[% END %]</td>
|
||||
<td>[% IF build.stoptime %][% INCLUDE renderDateTime timestamp = build.stoptime %][% ELSE %]<em>(cached build)</em>[% END %]</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Duration:</th>
|
||||
<td>
|
||||
[% IF resultInfo.iscachedbuild %]
|
||||
[% IF build.iscachedbuild %]
|
||||
<em>(cached build)</em>
|
||||
[% ELSE %]
|
||||
[% INCLUDE renderDuration duration = resultInfo.stoptime - resultInfo.starttime %]
|
||||
[% INCLUDE renderDuration duration = build.stoptime - build.starttime %]
|
||||
[% END %]
|
||||
</td>
|
||||
</tr>
|
||||
[% IF resultInfo.logfile %]
|
||||
[% IF build.logfile %]
|
||||
<tr>
|
||||
<th>Logfile:</th>
|
||||
<td>
|
||||
|
@ -377,7 +376,7 @@
|
|||
<td>
|
||||
[% IF !available %]
|
||||
<em>Build output is no longer available</em>
|
||||
[% ELSIF resultInfo.keep %]
|
||||
[% ELSIF build.keep %]
|
||||
<em>Build output will be kept permanently</em>
|
||||
[% IF c.user_exists %]
|
||||
<form action="[% c.uri_for('/build' build.id 'keep' 0) %]" method="post" class="inline">
|
||||
|
@ -487,10 +486,9 @@
|
|||
$(function() {
|
||||
var d = [];
|
||||
var ids = [];
|
||||
[% FOREACH prevbuild IN prevBuilds %][% IF prevbuild.resultInfo.starttime != 0 %]
|
||||
[% pbResultInfo = prevbuild.resultInfo %]
|
||||
d.push([[% pbResultInfo.starttime * 1000 %],[% prevbuild.get_column('actualBuildTime') %]]);
|
||||
ids[[% pbResultInfo.starttime * 1000 %]] = [% prevbuild.id %] ;
|
||||
[% FOREACH prevbuild IN prevBuilds %][% IF prevbuild.build.starttime != 0 %]
|
||||
d.push([[% prevbuild.starttime * 1000 %],[% prevbuild.get_column('actualBuildTime') %]]);
|
||||
ids[[% prevbuild.starttime * 1000 %]] = [% prevbuild.id %] ;
|
||||
[% END %][% END %]
|
||||
|
||||
var options = {
|
||||
|
@ -560,9 +558,9 @@
|
|||
$(function() {
|
||||
var d = [];
|
||||
var ids = [];
|
||||
[% FOREACH prevbuild IN prevBuilds %][% IF prevbuild.resultInfo.size != 0 %]
|
||||
d.push([[% prevbuild.resultInfo.starttime * 1000 %],[% prevbuild.resultInfo.size / (1024*1024.0) %]]);
|
||||
ids[[% prevbuild.resultInfo.starttime * 1000 %]] = [% prevbuild.id %] ;
|
||||
[% FOREACH prevbuild IN prevBuilds %][% IF prevbuild.size != 0 %]
|
||||
d.push([[% prevbuild.starttime * 1000 %],[% prevbuild.size / (1024*1024.0) %]]);
|
||||
ids[[% prevbuild.starttime * 1000 %]] = [% prevbuild.id %] ;
|
||||
[% END %][% END %]
|
||||
|
||||
var options = {
|
||||
|
|
|
@ -100,7 +100,7 @@
|
|||
onclick="if(event.which == 2) return true; window.location = '[% c.uri_for('/build' build.id) %]'">
|
||||
[%- IF !hideResultInfo -%]
|
||||
<td>
|
||||
[%- INCLUDE renderBuildStatusIcon size=16 busy=(showSchedulingInfo ? 1 : 0) buildstatus=build.get_column('buildStatus') -%]
|
||||
[%- INCLUDE renderBuildStatusIcon size=16 busy=(showSchedulingInfo ? 1 : 0) buildstatus=build.buildstatus -%]
|
||||
</td>
|
||||
[%- END -%]
|
||||
<td><a href="[% c.uri_for('/build' build.id) %]">[% build.id %]</a></td>
|
||||
|
@ -204,7 +204,7 @@
|
|||
[%- BLOCK renderBuildStatusIcon -%]
|
||||
[%- finished = build != undef ? build.finished : 1 -%]
|
||||
[%- busy = busy != undef ? busy : build.busy -%]
|
||||
[%- buildstatus = buildstatus != undef ? buildstatus : build.resultInfo.buildstatus -%]
|
||||
[%- buildstatus = buildstatus != undef ? buildstatus : build.buildstatus -%]
|
||||
[%- IF finished -%]
|
||||
[%- IF buildstatus == 0 -%]
|
||||
<img src="/static/images/checkmark_[% size %].png" alt="Succeeded" />
|
||||
|
@ -230,7 +230,7 @@
|
|||
|
||||
[% BLOCK renderStatus %]
|
||||
[% IF build.finished %]
|
||||
[% buildstatus = build.resultInfo.buildstatus %]
|
||||
[% buildstatus = build.buildstatus %]
|
||||
[% INCLUDE renderBuildStatusIcon size=16 %]
|
||||
[% IF buildstatus == 0 %]
|
||||
<strong>Success</strong>
|
||||
|
@ -242,8 +242,6 @@
|
|||
<span class="error">Cancelled by user</span>
|
||||
[% ELSIF buildstatus == 5 %]
|
||||
<span class="error">Build inhibited because a dependency previously failed to build</span>
|
||||
[% failedDep = build.resultInfo.failedDep %]
|
||||
(namely, <a href="[% c.uri_for('/build' failedDep.build.id 'nixlog' failedDep.stepnr) %]"><tt>[% failedDep.outpath %]</tt></a>)
|
||||
[% ELSIF buildstatus == 6 %]
|
||||
<span class="error">Build failed (with result)</span>
|
||||
[% ELSE %]
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
[% SWITCH product.type %]
|
||||
|
||||
[% CASE "nix-build" %]
|
||||
[% IF build.resultInfo.buildstatus == 6 %]
|
||||
[% IF build.buildstatus == 6 %]
|
||||
[% filename = "${build.nixname}.closure.gz" %]
|
||||
[% uri = c.uri_for('/build' build.id 'nix' 'closure' filename ) %]
|
||||
<tr class="product">
|
||||
|
|
|
@ -24,7 +24,7 @@
|
|||
|
||||
[% IF j.build %]
|
||||
|
||||
[% IF j.build.resultInfo.buildstatus == 0 %]
|
||||
[% IF j.build.buildstatus == 0 %]
|
||||
|
||||
[% IF j.build.buildproducts %]
|
||||
[% p = jobNames.${j.job.job} > 1 ? "-${j.build.system}" : "";
|
||||
|
|
|
@ -34,9 +34,9 @@ sub sendTwitterNotification {
|
|||
my $addURL = defined $config{'base_uri'};
|
||||
|
||||
my $jobName = $build->project->name . ":" . $build->jobset->name . ":" . $build->job->name;
|
||||
my $status = $build->resultInfo->buildstatus == 0 ? "SUCCEEDED" : "FAILED";
|
||||
my $status = $build->buildstatus == 0 ? "SUCCEEDED" : "FAILED";
|
||||
my $system = $build->system;
|
||||
my $duration = ($build->resultInfo->stoptime - $build->resultInfo->starttime) . " seconds";
|
||||
my $duration = ($build->stoptime - $build->starttime) . " seconds";
|
||||
my $url = $config{'base_uri'}."/build/".$build->id ;
|
||||
|
||||
my $nt = Net::Twitter::Lite->new(
|
||||
|
@ -74,7 +74,7 @@ sub statusDescription {
|
|||
sub sendEmailNotification {
|
||||
my ($build) = @_;
|
||||
|
||||
die unless defined $build->resultInfo;
|
||||
die unless $build->finished;
|
||||
|
||||
return if ! ( $build->jobset->enableemail && ($build->maintainers ne "" || $build->jobset->emailoverride ne "") );
|
||||
|
||||
|
@ -93,13 +93,13 @@ sub sendEmailNotification {
|
|||
);
|
||||
|
||||
# if there is a previous build with same buildstatus, do not send email
|
||||
if (defined $prevBuild && ($build->resultInfo->buildstatus == $prevBuild->resultInfo->buildstatus)) {
|
||||
if (defined $prevBuild && ($build->buildstatus == $prevBuild->buildstatus)) {
|
||||
return;
|
||||
}
|
||||
|
||||
# if buildstatus of this build or the previous one is aborted, do
|
||||
# not send email
|
||||
if ($build->resultInfo->buildstatus == 3 || (defined $prevBuild && ($prevBuild->resultInfo->buildstatus == 3))) {
|
||||
if ($build->buildstatus == 3 || (defined $prevBuild && ($prevBuild->buildstatus == 3))) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -110,7 +110,7 @@ sub sendEmailNotification {
|
|||
|
||||
my $jobName = $build->project->name . ":" . $build->jobset->name . ":" . $build->job->name;
|
||||
|
||||
my $status = statusDescription($build->resultInfo->buildstatus);
|
||||
my $status = statusDescription($build->buildstatus);
|
||||
|
||||
my $baseurl = hostname_long ;
|
||||
my $sender = $config{'notification_sender'} ||
|
||||
|
@ -132,10 +132,10 @@ sub sendEmailNotification {
|
|||
[ "Time added:", showTime $build->timestamp ],
|
||||
);
|
||||
push @lines, (
|
||||
[ "Build started:", showTime $build->resultInfo->starttime ],
|
||||
[ "Build finished:", showTime $build->resultInfo->stoptime ],
|
||||
[ "Duration:", $build->resultInfo->stoptime - $build->resultInfo->starttime . "s" ],
|
||||
) if $build->resultInfo->starttime;
|
||||
[ "Build started:", showTime $build->starttime ],
|
||||
[ "Build finished:", showTime $build->stoptime ],
|
||||
[ "Duration:", $build->stoptime - $build->starttime . "s" ],
|
||||
) if $build->starttime;
|
||||
$infoTable->load(@lines);
|
||||
|
||||
my $inputsTable = Text::Table->new(
|
||||
|
@ -157,18 +157,18 @@ sub sendEmailNotification {
|
|||
$inputsTable->load(@lines);
|
||||
|
||||
my $loglines = 50;
|
||||
my $logfile = $build->resultInfo->logfile;
|
||||
my $logfile = $build->logfile;
|
||||
my $logtext = defined $logfile && -e $logfile ? `tail -$loglines $logfile` : "No logfile available.\n";
|
||||
$logtext = removeAsciiEscapes($logtext);
|
||||
|
||||
my $body = "Hi,\n"
|
||||
. "\n"
|
||||
. "This is to let you know that Hydra build " . $build->id
|
||||
. " of job " . $jobName . " " . (defined $prevBuild ? "has changed from '" . statusDescription($prevBuild->resultInfo->buildstatus) . "' to '$status'" : "is '$status'" ) .".\n"
|
||||
. " of job " . $jobName . " " . (defined $prevBuild ? "has changed from '" . statusDescription($prevBuild->buildstatus) . "' to '$status'" : "is '$status'" ) .".\n"
|
||||
. "\n"
|
||||
. "Complete build information can be found on this page: "
|
||||
. "$selfURI/build/" . $build->id . "\n"
|
||||
. ($build->resultInfo->buildstatus != 0 ? "\nThe last $loglines lines of the build log are shown at the bottom of this email.\n" : "")
|
||||
. ($build->buildstatus != 0 ? "\nThe last $loglines lines of the build log are shown at the bottom of this email.\n" : "")
|
||||
. "\n"
|
||||
. "A summary of the build information follows:\n"
|
||||
. "\n"
|
||||
|
@ -181,7 +181,7 @@ sub sendEmailNotification {
|
|||
. $inputsTable->body
|
||||
. "\n"
|
||||
. "Regards,\n\nThe Hydra build daemon.\n"
|
||||
. ($build->resultInfo->buildstatus != 0 ? "\n---\n$logtext" : "");
|
||||
. ($build->buildstatus != 0 ? "\n---\n$logtext" : "");
|
||||
|
||||
# stripping trailing spaces from lines
|
||||
$body =~ s/[\ ]+$//gm;
|
||||
|
@ -398,16 +398,16 @@ sub doBuild {
|
|||
}
|
||||
|
||||
txn_do($db, sub {
|
||||
$build->update({finished => 1, busy => 0, locker => '', logfile => '', timestamp => time});
|
||||
|
||||
my $releaseName = getReleaseName($outPath);
|
||||
|
||||
if ($buildStatus == 0 && -f "$outPath/nix-support/failed") {
|
||||
$buildStatus = 6;
|
||||
}
|
||||
$buildStatus = 6 if $buildStatus == 0 && -f "$outPath/nix-support/failed";
|
||||
|
||||
$db->resultset('BuildResultInfo')->create(
|
||||
{ id => $build->id
|
||||
$build->update(
|
||||
{ finished => 1
|
||||
, busy => 0
|
||||
, locker => ''
|
||||
, logfile => ''
|
||||
, timestamp => time # !!! Why change the timestamp?
|
||||
, iscachedbuild => $isCachedBuild
|
||||
, buildstatus => $buildStatus
|
||||
, starttime => $startTime
|
||||
|
@ -450,7 +450,7 @@ my $build;
|
|||
txn_do($db, sub {
|
||||
$build = $db->resultset('Builds')->find($buildId);
|
||||
die "build $buildId doesn't exist" unless defined $build;
|
||||
die "build $buildId already done" if defined $build->resultInfo;
|
||||
die "build $buildId already done" if $build->finished;
|
||||
if ($build->busy != 0 && $build->locker != getppid) {
|
||||
die "build $buildId is already being built";
|
||||
}
|
||||
|
|
|
@ -69,8 +69,7 @@ foreach my $project ($db->resultset('Projects')->all) {
|
|||
, buildStatus => 0 # == success
|
||||
, system => $system->system
|
||||
},
|
||||
{ join => 'resultInfo'
|
||||
, order_by => 'me.id DESC'
|
||||
{ order_by => 'me.id DESC'
|
||||
, rows => $keepnr
|
||||
});
|
||||
keepBuild $_ foreach @recentBuilds;
|
||||
|
@ -106,7 +105,7 @@ foreach my $project ($db->resultset('Projects')->all) {
|
|||
|
||||
# Keep all builds that have been marked as "keep".
|
||||
print STDERR "*** looking for kept builds\n";
|
||||
my @buildsToKeep = $db->resultset('Builds')->search({finished => 1, keep => 1}, {join => 'resultInfo'});
|
||||
my @buildsToKeep = $db->resultset('Builds')->search({finished => 1, keep => 1});
|
||||
keepBuild $_ foreach @buildsToKeep;
|
||||
|
||||
|
||||
|
|
|
@ -163,18 +163,10 @@ create table Builds (
|
|||
disabled integer not null default 0, -- !!! boolean
|
||||
|
||||
startTime integer, -- if busy, time we started
|
||||
stopTime integer,
|
||||
|
||||
foreign key (project) references Projects(name) on update cascade,
|
||||
foreign key (project, jobset) references Jobsets(project, name) on update cascade,
|
||||
foreign key (project, jobset, job) references Jobs(project, jobset, name) on update cascade
|
||||
);
|
||||
|
||||
|
||||
-- Info for a finished build.
|
||||
create table BuildResultInfo (
|
||||
id integer primary key not null,
|
||||
|
||||
isCachedBuild integer not null, -- boolean
|
||||
-- Information about finished builds.
|
||||
isCachedBuild integer, -- boolean
|
||||
|
||||
-- Status codes:
|
||||
-- 0 = succeeded
|
||||
|
@ -187,23 +179,17 @@ create table BuildResultInfo (
|
|||
|
||||
errorMsg text, -- error message in case of a Nix failure
|
||||
|
||||
startTime integer, -- in Unix time, 0 = used cached build result
|
||||
stopTime integer,
|
||||
|
||||
logfile text, -- the path of the logfile
|
||||
|
||||
logsize bigint not null default 0,
|
||||
size bigint not null default 0,
|
||||
closuresize bigint not null default 0,
|
||||
logSize bigint,
|
||||
size bigint,
|
||||
closureSize bigint,
|
||||
|
||||
releaseName text, -- e.g. "patchelf-0.5pre1234"
|
||||
|
||||
keep integer not null default 0, -- true means never garbage-collect the build output
|
||||
|
||||
failedDepBuild integer, -- obsolete
|
||||
failedDepStepNr integer, -- obsolete
|
||||
|
||||
foreign key (id) references Builds(id) on delete cascade
|
||||
foreign key (project) references Projects(name) on update cascade,
|
||||
foreign key (project, jobset) references Jobsets(project, name) on update cascade,
|
||||
foreign key (project, jobset, job) references Jobs(project, jobset, name) on update cascade
|
||||
);
|
||||
|
||||
|
||||
|
|
|
@ -4,12 +4,16 @@ alter table Builds
|
|||
add column locker text,
|
||||
add column logfile text,
|
||||
add column disabled integer not null default 0,
|
||||
add column startTime integer;
|
||||
|
||||
--alter table Builds
|
||||
-- add column isCachedBuild integer,
|
||||
-- add column buildStatus integer,
|
||||
-- add column errorMsg text;
|
||||
add column startTime integer,
|
||||
add column stopTime integer,
|
||||
add column isCachedBuild integer,
|
||||
add column buildStatus integer,
|
||||
add column errorMsg text,
|
||||
add column logSize bigint,
|
||||
add column size bigint,
|
||||
add column closureSize bigint,
|
||||
add column releaseName text,
|
||||
add column keep integer not null default 0;
|
||||
|
||||
update Builds b set
|
||||
priority = (select priority from BuildSchedulingInfo s where s.id = b.id),
|
||||
|
@ -21,6 +25,17 @@ update Builds b set
|
|||
|
||||
update Builds b set
|
||||
startTime = ((select startTime from BuildSchedulingInfo s where s.id = b.id) union (select startTime from BuildResultInfo r where r.id = b.id));
|
||||
-- isCachedBuild = (select isCachedBuild from BuildResultInfo r where r.id = b.id),
|
||||
-- buildStatus = (select buildStatus from BuildResultInfo r where r.id = b.id),
|
||||
-- errorMsg = (select errorMsg from BuildResultInfo r where r.id = b.id);
|
||||
|
||||
update Builds b set
|
||||
isCachedBuild = (select isCachedBuild from BuildResultInfo r where r.id = b.id),
|
||||
buildStatus = (select buildStatus from BuildResultInfo r where r.id = b.id),
|
||||
errorMsg = (select errorMsg from BuildResultInfo r where r.id = b.id),
|
||||
startTime = (select startTime from BuildResultInfo r where r.id = b.id),
|
||||
stopTime = (select stopTime from BuildResultInfo r where r.id = b.id),
|
||||
logfile = (select logfile from BuildResultInfo r where r.id = b.id),
|
||||
logSize = (select logsize from BuildResultInfo r where r.id = b.id),
|
||||
size = (select size from BuildResultInfo r where r.id = b.id),
|
||||
closureSize = (select closuresize from BuildResultInfo r where r.id = b.id),
|
||||
releaseName = (select releaseName from BuildResultInfo r where r.id = b.id),
|
||||
keep = (select keep from BuildResultInfo r where r.id = b.id)
|
||||
where exists (select 1 from BuildResultInfo r where r.id = b.id);
|
||||
|
|
Loading…
Reference in a new issue