database queries from a set of jobs that have to be in a release. E.g. a patchelf release might consist of the jobs "tarball", "build", and "rpm_fedora10i386". Here the first job ("tarball") is the primary job: all the others have it as an input. The primary job supplies the identity of the release.
FHF6IZJQPUQHY5QWQYRPZVDBRLHREWRHGNKVQDT7F3GQKKLZXJKQC
2AIIYGI54TEFYBCGWMUA7JG2DMJXBKMYUZ7CG6ETIXF4ENNP74CQC
R5D7DZPETNNQQ644CFC3LYTR4JX3LTNXHQSTMQENND7DARWIEAJAC
J5UVLXOK6EDIL5I7VKWH4V2QDS4DPD7FHRK6XBWSXFRQS4JKXFZQC
LQNBKF3DKVYK3NPDGK7OLOTIWIF4HR3EKLRYNLZJB4G3NMIVBCEAC
K5BEBWKMPMTXDZTZECMJ32LCL354WMOM3RPEFWGHJFB3QH7FH6WAC
JD27RBKM7ROBUKBEQDFSCPO3MDE2AFZ6DSSKFUPJ7IC2MCGDVFGAC
GCHNNFZPCYM3BPOCU5GASALJ6ONWMEVEEGVD7KKLTWC7YQKJ5KZAC
2AUODJBTW2UJ47UB3SREZ7O7UTTJDQ4AGUQMPZAI4F3Y6BUF6LUQC
PHX2HIVGHHKCAX6VNN2WXD4LRGSA74KQMJCCTMHK7HS6JPELVECAC
L2E6EVE2RVFVDCUNRJ4CZYSQNS2DZUA5DTBETHBDUQUV2KQQRAOQC
VCOSLZRPLRS3ITD2JIPKZPMTCEPHN4WEFKTE5TKH3RAZ7WJKMQ4AC
SHBLLAVHMMHOPCJ5NPGDZQPVRAMPMGXSFEMX7H7BETW6GTRGUUBAC
CLJQCY2XHIDNNMFBJ5PK3GQEN6RFALEFKXBJRWZPEIKR4PR5ZQ5AC
ZVTSOVHNQNQCRF3N44RKDQSL3UM7HSLTAXICMWEE6EIA6SWJXZCQC
M552HLIAP52D42AVXVC5SGROAYN2TBCEUZOXESWEMBBUX7G3U6TAC
X27GNHDV5KPZ5GSH6DCAJMNCEMZLCP7M43JWF2X3O5QWXMOX273AC
BVOPAMLSAU4UTV3DUX53OYDMXP2SETAQVUKAYE2OTCVVN4RD7LLQC
PKPWUHUXLGPQFQUTNHLVGWNT6AB3H2VMDCBKT6IPZDC53CEL4W7QC
TWVSALRLHGSY6SHLMLT53K2A5SUCPU3SNFPZ2KWYOLDQUJBSZ2OAC
RU7AQO7U4HCWJNQTR2KRGDLLG24WYD47MWIHREV6SIAPCPDQHAWQC
S66BOMVUACAUDSGSDWP7ZIXVMZSQHWXOZYVTB7ILUCWZ7DDFAKVAC
7YBYT2LQML2PKEO6UO4444AGSASS664UCDXW2YO3ALB7THQHCEBQC
YTSIRIMKV2EN6CMO6LFX5J3NBJJYWBJKYDU3Z53CGXCIWP3FYI2QC
HCKFTNQ6J62JYGWKRSO2523L67JXRKG64NFHUMTHDO2JXIDVUIHQC
3ZCEPLNOOWRHKM75FJJVQHHYIAHXAYKFF5SEKQGVSMLRAF4NOBIAC
US27ZTX5HCH53SQN2KFSCV2GL2625XL5J3WCDR7D5HLPA7ZSPX5AC
KFFNFE4D7OTXSHUI5W5FD4SZNZIUCOFNY44ZCQXG5SNAPHYQYQHAC
N22GPKYTOLZLBGTGDATQDVZ4R5APZEAOIA7L32X4UXBH4XNI7MWAC
}
sub releasesets :Local {
my ($self, $c, $projectName) = @_;
$c->stash->{template} = 'releasesets.tt';
my $project = $c->model('DB::Projects')->find($projectName);
return error($c, "Project $projectName doesn't exist.") if !defined $project;
$c->stash->{curProject} = $project;
$c->stash->{releaseSets} = [$project->releasesets->all];
}
sub releases :Local {
my ($self, $c, $projectName, $releaseName) = @_;
$c->stash->{template} = 'releases.tt';
my $project = $c->model('DB::Projects')->find($projectName);
return error($c, "Project $projectName doesn't exist.") if !defined $project;
$c->stash->{curProject} = $project;
(my $releaseSet) = $c->model('DB::Releasesets')->find($projectName, $releaseName);
return error($c, "Release set $releaseName doesn't exist.") if !defined $releaseSet;
$c->stash->{releaseSet} = $releaseSet;
(my $primaryJob) = $releaseSet->releasesetjobs->search({isprimary => 1});
return error($c, "Release set $releaseName doesn't have a primary job.") if !defined $primaryJob;
$c->stash->{jobs} = [$releaseSet->releasesetjobs->search({}, {order_by => "isprimary DESC"})];
my @primaryBuilds = $project->builds->search(
{ attrname => $primaryJob->job, finished => 1 },
{ join => 'resultInfo', order_by => "timestamp DESC", '+select' => ["resultInfo.releasename"], '+as' => ["releasename"] });
my @releases = ();
foreach my $primaryBuild (@primaryBuilds) {
my @jobs = ();
my $status = 0; # = okay
foreach my $job (@{$c->stash->{jobs}}) {
my $thisBuild;
if ($job->isprimary == 1) {
$thisBuild = $primaryBuild;
} else {
# Find a build of this job that had the primary build
# as input. If there are multiple, prefer successful
# ones, and then oldest. !!! order_by buildstatus is hacky
($thisBuild) = $primaryBuild->dependentBuilds->search(
{ attrname => $job->job, finished => 1 },
{ join => 'resultInfo', rows => 1
, order_by => ["buildstatus", "timestamp"] });
}
if ($job->mayfail != 1) {
if (!defined $thisBuild) {
$status = 2 if $status == 0; # = unfinished
} elsif ($thisBuild->resultInfo->buildstatus != 0) {
$status = 1; # = failed
}
}
push @jobs, { build => $thisBuild };
}
push @releases,
{ id => $primaryBuild->id
, releasename => $primaryBuild->get_column('releasename')
, jobs => [@jobs]
, status => $status
};
}
$c->stash->{releases} = [@releases];
# Created by DBIx::Class::Schema::Loader v0.04005 @ 2008-11-27 03:26:23
# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:uaNcxZMTbF9WDLgf2G1Klw
# Created by DBIx::Class::Schema::Loader v0.04005 @ 2008-11-27 14:48:09
# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:R1F2JbVygktvK55xmY8mcg
# Created by DBIx::Class::Schema::Loader v0.04005 @ 2008-11-27 03:26:23
# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:btk6BJGE0Hj9qTO4qChpfw
# Created by DBIx::Class::Schema::Loader v0.04005 @ 2008-11-27 14:48:09
# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:aZuZd+oUAO1c8GvSbgn7Fw
# Created by DBIx::Class::Schema::Loader v0.04005 @ 2008-11-27 03:26:23
# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:Cn7vCpqfbTiq1/JF48BG2Q
# Created by DBIx::Class::Schema::Loader v0.04005 @ 2008-11-27 14:48:09
# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:QahlwGdZKC7mL7fvwNxWjA
# Created by DBIx::Class::Schema::Loader v0.04005 @ 2008-11-27 03:26:23
# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:p67v2RE44sAk2yGFoTpPww
# Created by DBIx::Class::Schema::Loader v0.04005 @ 2008-11-27 14:48:09
# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:uRSa4YkaRG0K6vK/qhGI9w
# Created by DBIx::Class::Schema::Loader v0.04005 @ 2008-11-27 03:26:23
# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:hdFMzqZ1IIdypz+/KLoCIw
# Created by DBIx::Class::Schema::Loader v0.04005 @ 2008-11-27 14:48:09
# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:xBocoeipFdRsWDhvtoXImA
# Created by DBIx::Class::Schema::Loader v0.04005 @ 2008-11-27 03:26:23
# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:zFljaYEbDkYbHuCmcIJhOA
# Created by DBIx::Class::Schema::Loader v0.04005 @ 2008-11-27 14:48:09
# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:04BankpQ6xo6T/ioMTdWkQ
# Created by DBIx::Class::Schema::Loader v0.04005 @ 2008-11-27 03:26:23
# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:E9++anIBM/+OIi2UdhIZKA
# Created by DBIx::Class::Schema::Loader v0.04005 @ 2008-11-27 14:48:09
# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:Nq3TpcRmpSRWNL4Q1hGGrA
# Created by DBIx::Class::Schema::Loader v0.04005 @ 2008-11-27 03:26:23
# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:eKcfAgBW789dI2VFGh4baw
# Created by DBIx::Class::Schema::Loader v0.04005 @ 2008-11-27 14:48:09
# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:CCbHomM+8BTBqHBeGOGcuA
# Created by DBIx::Class::Schema::Loader v0.04005 @ 2008-11-27 03:26:23
# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:vEw8HtMT848S/GEL1Y1MUg
# Created by DBIx::Class::Schema::Loader v0.04005 @ 2008-11-27 14:48:09
# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:JPf4ozBKK6NQPJT2few40g
# Created by DBIx::Class::Schema::Loader v0.04005 @ 2008-11-27 03:26:23
# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:JVmtu+NXI6P/GD5q7+YTDA
# Created by DBIx::Class::Schema::Loader v0.04005 @ 2008-11-27 14:48:09
# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:S8z1W0kjUX9VN5HPjyGAzA
# Created by DBIx::Class::Schema::Loader v0.04005 @ 2008-11-27 03:26:23
# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:e1BZx0WYj1b6iIov6KvCqA
# Created by DBIx::Class::Schema::Loader v0.04005 @ 2008-11-27 14:48:09
# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:ebblUCTW7I1wGhVlPfNd3Q
# Created by DBIx::Class::Schema::Loader v0.04005 @ 2008-11-27 03:26:23
# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:BHYbrizctvmbAJyTKSu89g
# Created by DBIx::Class::Schema::Loader v0.04005 @ 2008-11-27 14:48:09
# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:70/Br6966ZZ+p8n6lF1hcw
package Hydra::Schema::Releasesetjobs;
use strict;
use warnings;
use base 'DBIx::Class';
__PACKAGE__->load_components("Core");
__PACKAGE__->table("ReleaseSetJobs");
__PACKAGE__->add_columns(
"project",
{ data_type => "text", is_nullable => 0, size => undef },
"release",
{ data_type => "text", is_nullable => 0, size => undef },
"job",
{ data_type => "text", is_nullable => 0, size => undef },
"attrs",
{ data_type => "text", is_nullable => 0, size => undef },
"isprimary",
{ data_type => "integer", is_nullable => 0, size => undef },
"mayfail",
{ data_type => "integer", is_nullable => 0, size => undef },
"description",
{ data_type => "text", is_nullable => 0, size => undef },
);
__PACKAGE__->set_primary_key("project", "release", "job", "attrs");
__PACKAGE__->belongs_to("project", "Hydra::Schema::Projects", { name => "project" });
__PACKAGE__->belongs_to(
"releaseset",
"Hydra::Schema::Releasesets",
{ name => "release", project => "project" },
);
# Created by DBIx::Class::Schema::Loader v0.04005 @ 2008-11-27 14:48:09
# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:t2ZI1kBn/GsKlY0e4+Wspg
# You can replace this text with custom content, and it will be preserved on regeneration
1;
package Hydra::Schema::Releasesets;
use strict;
use warnings;
use base 'DBIx::Class';
__PACKAGE__->load_components("Core");
__PACKAGE__->table("ReleaseSets");
__PACKAGE__->add_columns(
"project",
{ data_type => "text", is_nullable => 0, size => undef },
"name",
{ data_type => "text", is_nullable => 0, size => undef },
"description",
{ data_type => "text", is_nullable => 0, size => undef },
"keep",
{ data_type => "integer", is_nullable => 0, size => undef },
);
__PACKAGE__->set_primary_key("project", "name");
__PACKAGE__->belongs_to("project", "Hydra::Schema::Projects", { name => "project" });
__PACKAGE__->has_many(
"releasesetjobs",
"Hydra::Schema::Releasesetjobs",
{
"foreign.project" => "self.project",
"foreign.release" => "self.name",
},
);
# Created by DBIx::Class::Schema::Loader v0.04005 @ 2008-11-27 14:48:09
# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:pNqwNlXuENM/SsZ/utKhWw
# You can replace this text with custom content, and it will be preserved on regeneration
1;
# Created by DBIx::Class::Schema::Loader v0.04005 @ 2008-11-27 03:26:23
# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:90X5M27CbmJcZ7YnciHVMA
# Created by DBIx::Class::Schema::Loader v0.04005 @ 2008-11-27 14:48:09
# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:WeoKp84cptljEdtD+5l7Ug
# Created by DBIx::Class::Schema::Loader v0.04005 @ 2008-11-27 03:26:23
# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:g2EVNE74pSi9teIFqIA92Q
# Created by DBIx::Class::Schema::Loader v0.04005 @ 2008-11-27 14:48:09
# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:WxjgPLWPvXpQ3nmxmlU7Dw
# Created by DBIx::Class::Schema::Loader v0.04005 @ 2008-11-27 03:26:23
# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:gmqkPkkET+452wBlILgOsQ
# Created by DBIx::Class::Schema::Loader v0.04005 @ 2008-11-27 14:48:09
# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:s+M14nuDVIMoRSgXodj3dw
# Created by DBIx::Class::Schema::Loader v0.04005 @ 2008-11-27 03:26:23
# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:yXQEjv8/1aoKNW095xSR/Q
# Created by DBIx::Class::Schema::Loader v0.04005 @ 2008-11-27 14:48:09
# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:jJnmW70e1RDsSt5ClahomQ
[% WRAPPER layout.tt title="Releases" %]
[% PROCESS common.tt %]
[% USE HTML %]
<h1>Releases</h1>
<!-- <p>Description: [% releaseSet.description %]</p> -->
<table class="tablesorter">
<thead>
<tr>
<th></th>
<th>#</th>
<th>Release</th>
[% FOREACH job IN jobs %]
<th>[% IF job.description; HTML.escape(job.description); ELSE %]<tt>[% job.job %]</tt> ([% job.attrs %])[% END %]</th>
[% END %]
</tr>
</thead>
<tbody>
[% FOREACH release IN releases %]
<tr>
<td>
[% IF release.status == 0 %]
<img src="/static/images/success.gif" />
[% ELSIF release.status == 1 %]
<img src="/static/images/failure.gif" />
[% ELSIF release.status == 2 %]
<img src="/static/images/question-mark.png" />
[% END %]
</td>
<td>[% release.id %]</td>
<td>
[% IF release.releasename %]
<tt>[% release.releasename %]</tt>
[% ELSE %]
<em>No name</em>
[% END %]
</td>
[% FOREACH job IN release.jobs %]
<td>
[% IF job.build %]
<a href="[% c.uri_for('/build' job.build.id) %]">
[% IF job.build.resultInfo.buildstatus == 0 %]
<img src="/static/images/success.gif" />
[% ELSE %]
<img src="/static/images/failure.gif" />
[% END %]
[% job.build.id %]
</a>
[% END %]
</td>
[% END %]
</tr>
[% END %]
</tbody>
</table>
[% END %]
[% WRAPPER layout.tt title="Release Sets" %]
[% PROCESS common.tt %]
<h1>Release Sets</h1>
<p>Project <tt>[% curProject.name %]</tt> has the following release sets:</p>
<ul>
[% FOREACH releaseSet IN releaseSets %]
<li><a href="[% c.uri_for('/releases' curProject.name releaseSet.name) %]"><tt>[% releaseSet.name %]</tt></a></li>
[% END %]
</ul>
[% END %]
-- Release sets are a mechanism to automatically group related builds
-- together. A release set defines what an individual release
-- consists of, namely: a release consists of a build of some
-- "primary" job, plus all builds of the other jobs named in
-- ReleaseSetJobs that have that build as an input. If there are
-- multiple builds matching a ReleaseSetJob, then we take the *oldest*
-- successful build (for release stability), or the *newest*
-- unsuccessful build if there is no succesful build. A release is
-- itself considered successful if all builds (except those for jobs
-- that have mayFail set) are successful.
--
-- Note that individual releases aren't separately stored in the
-- database, so they're really just a dynamic view on the universe of
-- builds, defined by a ReleaseSet.
create table ReleaseSets (
project text not null,
name text not null,
description text,
-- If true, don't garbage-collect builds belonging to the releases
-- defined by this row.
keep integer not null default 0,
primary key (project, name),
foreign key (project) references Projects(name) on delete cascade -- ignored by sqlite
);
create trigger cascadeReleaseSetDelete
before delete on ReleaseSets
for each row begin
delete from ReleaseSetJobs where project = old.project and release = old.release;
end;
create table ReleaseSetJobs (
project text not null,
release text not null,
job text not null,
-- A constraint on the job consisting of `name=value' pairs,
-- e.g. "system=i686-linux officialRelease=true". Should really
-- be a separate table but I'm lazy.
attrs text not null,
-- If set, this is the primary job for the release. There can be
-- onlyt one such job per release set.
isPrimary integer not null default 0,
mayFail integer not null default 0,
description text,
primary key (project, release, job, attrs),
foreign key (project) references Projects(name) on delete cascade, -- ignored by sqlite
foreign key (project, release) references ReleaseSets(project, name) on delete cascade -- ignored by sqlite
);