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; # = okayforeach 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 regeneration1;
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 regeneration1;
# 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 cascadeReleaseSetDeletebefore delete on ReleaseSetsfor each row begindelete 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 sqliteforeign key (project, release) references ReleaseSets(project, name) on delete cascade -- ignored by sqlite);