* Basic release management: releases are now dynamically computed as
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.
This commit is contained in:
parent
24923ed09a
commit
98c53156e6
|
@ -41,7 +41,7 @@ sub trim {
|
||||||
|
|
||||||
sub getBuild {
|
sub getBuild {
|
||||||
my ($c, $id) = @_;
|
my ($c, $id) = @_;
|
||||||
(my $build) = $c->model('DB::Builds')->search({ id => $id });
|
my $build = $c->model('DB::Builds')->find($id);
|
||||||
return $build;
|
return $build;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -168,6 +168,84 @@ sub all :Local {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
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];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
sub updateProject {
|
sub updateProject {
|
||||||
my ($c, $project) = @_;
|
my ($c, $project) = @_;
|
||||||
my $projectName = trim $c->request->params->{name};
|
my $projectName = trim $c->request->params->{name};
|
||||||
|
@ -296,7 +374,7 @@ sub project :Local {
|
||||||
my ($self, $c, $projectName, $subcommand, $arg) = @_;
|
my ($self, $c, $projectName, $subcommand, $arg) = @_;
|
||||||
$c->stash->{template} = 'project.tt';
|
$c->stash->{template} = 'project.tt';
|
||||||
|
|
||||||
(my $project) = $c->model('DB::Projects')->search({ name => $projectName });
|
my $project = $c->model('DB::Projects')->find($projectName);
|
||||||
return error($c, "Project $projectName doesn't exist.") if !defined $project;
|
return error($c, "Project $projectName doesn't exist.") if !defined $project;
|
||||||
|
|
||||||
my $isPosted = $c->request->method eq "POST";
|
my $isPosted = $c->request->method eq "POST";
|
||||||
|
@ -386,7 +464,7 @@ sub job :Local {
|
||||||
my ($self, $c, $projectName, $jobName) = @_;
|
my ($self, $c, $projectName, $jobName) = @_;
|
||||||
$c->stash->{template} = 'job.tt';
|
$c->stash->{template} = 'job.tt';
|
||||||
|
|
||||||
(my $project) = $c->model('DB::Projects')->search({ name => $projectName });
|
my $project = $c->model('DB::Projects')->find($projectName);
|
||||||
return error($c, "Project $projectName doesn't exist.") if !defined $project;
|
return error($c, "Project $projectName doesn't exist.") if !defined $project;
|
||||||
$c->stash->{curProject} = $project;
|
$c->stash->{curProject} = $project;
|
||||||
|
|
||||||
|
|
|
@ -8,8 +8,8 @@ use base 'DBIx::Class::Schema';
|
||||||
__PACKAGE__->load_classes;
|
__PACKAGE__->load_classes;
|
||||||
|
|
||||||
|
|
||||||
# Created by DBIx::Class::Schema::Loader v0.04005 @ 2008-11-27 03:26:23
|
# Created by DBIx::Class::Schema::Loader v0.04005 @ 2008-11-27 14:48:09
|
||||||
# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:yXQEjv8/1aoKNW095xSR/Q
|
# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:jJnmW70e1RDsSt5ClahomQ
|
||||||
|
|
||||||
|
|
||||||
# You can replace this text with custom content, and it will be preserved on regeneration
|
# You can replace this text with custom content, and it will be preserved on regeneration
|
||||||
|
|
|
@ -36,8 +36,8 @@ __PACKAGE__->belongs_to("build", "Hydra::Schema::Builds", { id => "build" });
|
||||||
__PACKAGE__->belongs_to("dependency", "Hydra::Schema::Builds", { id => "dependency" });
|
__PACKAGE__->belongs_to("dependency", "Hydra::Schema::Builds", { id => "dependency" });
|
||||||
|
|
||||||
|
|
||||||
# Created by DBIx::Class::Schema::Loader v0.04005 @ 2008-11-27 03:26:23
|
# Created by DBIx::Class::Schema::Loader v0.04005 @ 2008-11-27 14:48:09
|
||||||
# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:uaNcxZMTbF9WDLgf2G1Klw
|
# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:R1F2JbVygktvK55xmY8mcg
|
||||||
|
|
||||||
|
|
||||||
# You can replace this text with custom content, and it will be preserved on regeneration
|
# You can replace this text with custom content, and it will be preserved on regeneration
|
||||||
|
|
|
@ -33,8 +33,8 @@ __PACKAGE__->set_primary_key("build", "productnr");
|
||||||
__PACKAGE__->belongs_to("build", "Hydra::Schema::Builds", { id => "build" });
|
__PACKAGE__->belongs_to("build", "Hydra::Schema::Builds", { id => "build" });
|
||||||
|
|
||||||
|
|
||||||
# Created by DBIx::Class::Schema::Loader v0.04005 @ 2008-11-27 03:26:23
|
# Created by DBIx::Class::Schema::Loader v0.04005 @ 2008-11-27 14:48:09
|
||||||
# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:btk6BJGE0Hj9qTO4qChpfw
|
# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:aZuZd+oUAO1c8GvSbgn7Fw
|
||||||
|
|
||||||
|
|
||||||
# You can replace this text with custom content, and it will be preserved on regeneration
|
# You can replace this text with custom content, and it will be preserved on regeneration
|
||||||
|
|
|
@ -29,8 +29,8 @@ __PACKAGE__->set_primary_key("id");
|
||||||
__PACKAGE__->belongs_to("id", "Hydra::Schema::Builds", { id => "id" });
|
__PACKAGE__->belongs_to("id", "Hydra::Schema::Builds", { id => "id" });
|
||||||
|
|
||||||
|
|
||||||
# Created by DBIx::Class::Schema::Loader v0.04005 @ 2008-11-27 03:26:23
|
# Created by DBIx::Class::Schema::Loader v0.04005 @ 2008-11-27 14:48:09
|
||||||
# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:Cn7vCpqfbTiq1/JF48BG2Q
|
# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:QahlwGdZKC7mL7fvwNxWjA
|
||||||
|
|
||||||
|
|
||||||
# You can replace this text with custom content, and it will be preserved on regeneration
|
# You can replace this text with custom content, and it will be preserved on regeneration
|
||||||
|
|
|
@ -70,11 +70,13 @@ __PACKAGE__->has_many(
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
# Created by DBIx::Class::Schema::Loader v0.04005 @ 2008-11-27 03:26:23
|
# Created by DBIx::Class::Schema::Loader v0.04005 @ 2008-11-27 14:48:09
|
||||||
# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:p67v2RE44sAk2yGFoTpPww
|
# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:uRSa4YkaRG0K6vK/qhGI9w
|
||||||
|
|
||||||
__PACKAGE__->has_many(dependents => 'Hydra::Schema::Buildinputs', 'dependency');
|
__PACKAGE__->has_many(dependents => 'Hydra::Schema::Buildinputs', 'dependency');
|
||||||
|
|
||||||
|
__PACKAGE__->many_to_many(dependentBuilds => 'dependents', 'build');
|
||||||
|
|
||||||
__PACKAGE__->has_many(inputs => 'Hydra::Schema::Buildinputs', 'build');
|
__PACKAGE__->has_many(inputs => 'Hydra::Schema::Buildinputs', 'build');
|
||||||
|
|
||||||
__PACKAGE__->belongs_to(
|
__PACKAGE__->belongs_to(
|
||||||
|
|
|
@ -25,8 +25,8 @@ __PACKAGE__->set_primary_key("id");
|
||||||
__PACKAGE__->belongs_to("id", "Hydra::Schema::Builds", { id => "id" });
|
__PACKAGE__->belongs_to("id", "Hydra::Schema::Builds", { id => "id" });
|
||||||
|
|
||||||
|
|
||||||
# Created by DBIx::Class::Schema::Loader v0.04005 @ 2008-11-27 03:26:23
|
# Created by DBIx::Class::Schema::Loader v0.04005 @ 2008-11-27 14:48:09
|
||||||
# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:hdFMzqZ1IIdypz+/KLoCIw
|
# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:xBocoeipFdRsWDhvtoXImA
|
||||||
|
|
||||||
|
|
||||||
# You can replace this text with custom content, and it will be preserved on regeneration
|
# You can replace this text with custom content, and it will be preserved on regeneration
|
||||||
|
|
|
@ -35,8 +35,8 @@ __PACKAGE__->set_primary_key("id", "stepnr");
|
||||||
__PACKAGE__->belongs_to("id", "Hydra::Schema::Builds", { id => "id" });
|
__PACKAGE__->belongs_to("id", "Hydra::Schema::Builds", { id => "id" });
|
||||||
|
|
||||||
|
|
||||||
# Created by DBIx::Class::Schema::Loader v0.04005 @ 2008-11-27 03:26:23
|
# Created by DBIx::Class::Schema::Loader v0.04005 @ 2008-11-27 14:48:09
|
||||||
# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:zFljaYEbDkYbHuCmcIJhOA
|
# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:04BankpQ6xo6T/ioMTdWkQ
|
||||||
|
|
||||||
|
|
||||||
# You can replace this text with custom content, and it will be preserved on regeneration
|
# You can replace this text with custom content, and it will be preserved on regeneration
|
||||||
|
|
|
@ -22,8 +22,8 @@ __PACKAGE__->add_columns(
|
||||||
__PACKAGE__->set_primary_key("srcpath", "sha256hash");
|
__PACKAGE__->set_primary_key("srcpath", "sha256hash");
|
||||||
|
|
||||||
|
|
||||||
# Created by DBIx::Class::Schema::Loader v0.04005 @ 2008-11-27 03:26:23
|
# Created by DBIx::Class::Schema::Loader v0.04005 @ 2008-11-27 14:48:09
|
||||||
# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:E9++anIBM/+OIi2UdhIZKA
|
# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:Nq3TpcRmpSRWNL4Q1hGGrA
|
||||||
|
|
||||||
|
|
||||||
# You can replace this text with custom content, and it will be preserved on regeneration
|
# You can replace this text with custom content, and it will be preserved on regeneration
|
||||||
|
|
|
@ -20,8 +20,8 @@ __PACKAGE__->add_columns(
|
||||||
__PACKAGE__->set_primary_key("uri", "revision");
|
__PACKAGE__->set_primary_key("uri", "revision");
|
||||||
|
|
||||||
|
|
||||||
# Created by DBIx::Class::Schema::Loader v0.04005 @ 2008-11-27 03:26:23
|
# Created by DBIx::Class::Schema::Loader v0.04005 @ 2008-11-27 14:48:09
|
||||||
# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:eKcfAgBW789dI2VFGh4baw
|
# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:CCbHomM+8BTBqHBeGOGcuA
|
||||||
|
|
||||||
|
|
||||||
# You can replace this text with custom content, and it will be preserved on regeneration
|
# You can replace this text with custom content, and it will be preserved on regeneration
|
||||||
|
|
|
@ -33,8 +33,8 @@ __PACKAGE__->belongs_to(
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
# Created by DBIx::Class::Schema::Loader v0.04005 @ 2008-11-27 03:26:23
|
# Created by DBIx::Class::Schema::Loader v0.04005 @ 2008-11-27 14:48:09
|
||||||
# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:vEw8HtMT848S/GEL1Y1MUg
|
# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:JPf4ozBKK6NQPJT2few40g
|
||||||
|
|
||||||
|
|
||||||
# You can replace this text with custom content, and it will be preserved on regeneration
|
# You can replace this text with custom content, and it will be preserved on regeneration
|
||||||
|
|
|
@ -43,8 +43,8 @@ __PACKAGE__->has_many(
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
# Created by DBIx::Class::Schema::Loader v0.04005 @ 2008-11-27 03:26:23
|
# Created by DBIx::Class::Schema::Loader v0.04005 @ 2008-11-27 14:48:09
|
||||||
# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:JVmtu+NXI6P/GD5q7+YTDA
|
# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:S8z1W0kjUX9VN5HPjyGAzA
|
||||||
|
|
||||||
|
|
||||||
# You can replace this text with custom content, and it will be preserved on regeneration
|
# You can replace this text with custom content, and it will be preserved on regeneration
|
||||||
|
|
|
@ -50,8 +50,8 @@ __PACKAGE__->has_many(
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
# Created by DBIx::Class::Schema::Loader v0.04005 @ 2008-11-27 03:26:23
|
# Created by DBIx::Class::Schema::Loader v0.04005 @ 2008-11-27 14:48:09
|
||||||
# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:e1BZx0WYj1b6iIov6KvCqA
|
# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:ebblUCTW7I1wGhVlPfNd3Q
|
||||||
|
|
||||||
|
|
||||||
# You can replace this text with custom content, and it will be preserved on regeneration
|
# You can replace this text with custom content, and it will be preserved on regeneration
|
||||||
|
|
|
@ -30,10 +30,20 @@ __PACKAGE__->has_many(
|
||||||
"Hydra::Schema::Jobsets",
|
"Hydra::Schema::Jobsets",
|
||||||
{ "foreign.project" => "self.name" },
|
{ "foreign.project" => "self.name" },
|
||||||
);
|
);
|
||||||
|
__PACKAGE__->has_many(
|
||||||
|
"releasesets",
|
||||||
|
"Hydra::Schema::Releasesets",
|
||||||
|
{ "foreign.project" => "self.name" },
|
||||||
|
);
|
||||||
|
__PACKAGE__->has_many(
|
||||||
|
"releasesetjobs",
|
||||||
|
"Hydra::Schema::Releasesetjobs",
|
||||||
|
{ "foreign.project" => "self.name" },
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
# Created by DBIx::Class::Schema::Loader v0.04005 @ 2008-11-27 03:26:23
|
# Created by DBIx::Class::Schema::Loader v0.04005 @ 2008-11-27 14:48:09
|
||||||
# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:BHYbrizctvmbAJyTKSu89g
|
# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:70/Br6966ZZ+p8n6lF1hcw
|
||||||
|
|
||||||
|
|
||||||
# You can replace this text with custom content, and it will be preserved on regeneration
|
# You can replace this text with custom content, and it will be preserved on regeneration
|
||||||
|
|
40
src/Hydra/lib/Hydra/Schema/Releasesetjobs.pm
Normal file
40
src/Hydra/lib/Hydra/Schema/Releasesetjobs.pm
Normal file
|
@ -0,0 +1,40 @@
|
||||||
|
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;
|
37
src/Hydra/lib/Hydra/Schema/Releasesets.pm
Normal file
37
src/Hydra/lib/Hydra/Schema/Releasesets.pm
Normal file
|
@ -0,0 +1,37 @@
|
||||||
|
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;
|
|
@ -16,8 +16,8 @@ __PACKAGE__->add_columns(
|
||||||
__PACKAGE__->set_primary_key("system");
|
__PACKAGE__->set_primary_key("system");
|
||||||
|
|
||||||
|
|
||||||
# Created by DBIx::Class::Schema::Loader v0.04005 @ 2008-11-27 03:26:23
|
# Created by DBIx::Class::Schema::Loader v0.04005 @ 2008-11-27 14:48:09
|
||||||
# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:90X5M27CbmJcZ7YnciHVMA
|
# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:WeoKp84cptljEdtD+5l7Ug
|
||||||
|
|
||||||
|
|
||||||
# You can replace this text with custom content, and it will be preserved on regeneration
|
# You can replace this text with custom content, and it will be preserved on regeneration
|
||||||
|
|
|
@ -17,8 +17,8 @@ __PACKAGE__->set_primary_key("username", "role");
|
||||||
__PACKAGE__->belongs_to("username", "Hydra::Schema::Users", { username => "username" });
|
__PACKAGE__->belongs_to("username", "Hydra::Schema::Users", { username => "username" });
|
||||||
|
|
||||||
|
|
||||||
# Created by DBIx::Class::Schema::Loader v0.04005 @ 2008-11-27 03:26:23
|
# Created by DBIx::Class::Schema::Loader v0.04005 @ 2008-11-27 14:48:09
|
||||||
# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:g2EVNE74pSi9teIFqIA92Q
|
# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:WxjgPLWPvXpQ3nmxmlU7Dw
|
||||||
|
|
||||||
|
|
||||||
# You can replace this text with custom content, and it will be preserved on regeneration
|
# You can replace this text with custom content, and it will be preserved on regeneration
|
||||||
|
|
|
@ -25,8 +25,8 @@ __PACKAGE__->has_many(
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
# Created by DBIx::Class::Schema::Loader v0.04005 @ 2008-11-27 03:26:23
|
# Created by DBIx::Class::Schema::Loader v0.04005 @ 2008-11-27 14:48:09
|
||||||
# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:gmqkPkkET+452wBlILgOsQ
|
# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:s+M14nuDVIMoRSgXodj3dw
|
||||||
|
|
||||||
|
|
||||||
# You can replace this text with custom content, and it will be preserved on regeneration
|
# You can replace this text with custom content, and it will be preserved on regeneration
|
||||||
|
|
|
@ -276,7 +276,7 @@ print STDERR "performing build $buildId\n";
|
||||||
# have the lock taken away.
|
# have the lock taken away.
|
||||||
my $build;
|
my $build;
|
||||||
$db->txn_do(sub {
|
$db->txn_do(sub {
|
||||||
($build) = $db->resultset('Builds')->search({id => $buildId});
|
$build = $db->resultset('Builds')->find($buildId);
|
||||||
die "build $buildId doesn't exist" unless defined $build;
|
die "build $buildId doesn't exist" unless defined $build;
|
||||||
if ($build->schedulingInfo->busy != 0 && $build->schedulingInfo->locker != getppid) {
|
if ($build->schedulingInfo->busy != 0 && $build->schedulingInfo->locker != getppid) {
|
||||||
die "build $buildId is already being built";
|
die "build $buildId is already being built";
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
[% WRAPPER layout.tt title="Job Status" %]
|
[% WRAPPER layout.tt title="Job Status" %]
|
||||||
[% PROCESS common.tt %]
|
[% PROCESS common.tt %]
|
||||||
|
|
||||||
<h1>Job Status[% IF curProject %] in Project <tt>[% curProject.name %]</tt>[% END %]</h1>
|
<h1>Job Status[% IF curProject %] of Project <tt>[% curProject.name %]</tt>[% END %]</h1>
|
||||||
|
|
||||||
<p>Below are the latest builds for each job.</p>
|
<p>Below are the latest builds for each job.</p>
|
||||||
|
|
||||||
|
|
|
@ -99,9 +99,9 @@
|
||||||
<div class="title"><a href="[% c.uri_for('/project' project.name) %]">[% HTML.escape(project.displayname) %]</a></div>
|
<div class="title"><a href="[% c.uri_for('/project' project.name) %]">[% HTML.escape(project.displayname) %]</a></div>
|
||||||
[% IF curProject.name == project.name %]
|
[% IF curProject.name == project.name %]
|
||||||
<ul class="subsubmenu">
|
<ul class="subsubmenu">
|
||||||
[% INCLUDE makeLink uri = c.uri_for('/project' project.name 'edit') title = "Edit" %]
|
|
||||||
[% INCLUDE makeLink uri = c.uri_for('/project' project.name 'jobstatus') title = "Job status" %]
|
[% INCLUDE makeLink uri = c.uri_for('/project' project.name 'jobstatus') title = "Job status" %]
|
||||||
[% INCLUDE makeLink uri = c.uri_for('/project' project.name 'all') title = "All builds" %]
|
[% INCLUDE makeLink uri = c.uri_for('/project' project.name 'all') title = "All builds" %]
|
||||||
|
[% INCLUDE makeLink uri = c.uri_for('/project' project.name 'edit') title = "Edit" %]
|
||||||
</ul>
|
</ul>
|
||||||
[% END %]
|
[% END %]
|
||||||
</li>
|
</li>
|
||||||
|
|
|
@ -96,7 +96,11 @@
|
||||||
<tr>
|
<tr>
|
||||||
<th>Last checked:</th>
|
<th>Last checked:</th>
|
||||||
<td>
|
<td>
|
||||||
[% PROCESS renderDateTime timestamp = jobset.lastcheckedtime %]
|
[% IF jobset.lastcheckedtime %]
|
||||||
|
[% PROCESS renderDateTime timestamp = jobset.lastcheckedtime %]
|
||||||
|
[% ELSE %]
|
||||||
|
<em>never</em>
|
||||||
|
[% END %]
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
[% END %]
|
[% END %]
|
||||||
|
|
60
src/Hydra/root/releases.tt
Normal file
60
src/Hydra/root/releases.tt
Normal file
|
@ -0,0 +1,60 @@
|
||||||
|
[% 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 %]
|
14
src/Hydra/root/releasesets.tt
Normal file
14
src/Hydra/root/releasesets.tt
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
[% 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 %]
|
BIN
src/Hydra/root/static/images/question-mark.png
Normal file
BIN
src/Hydra/root/static/images/question-mark.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 586 B |
|
@ -168,6 +168,8 @@ create trigger cascadeProjectUpdate
|
||||||
update JobsetInputs set project = new.name where project = old.name;
|
update JobsetInputs set project = new.name where project = old.name;
|
||||||
update JobsetInputAlts set project = new.name where project = old.name;
|
update JobsetInputAlts set project = new.name where project = old.name;
|
||||||
update Builds set project = new.name where project = old.name;
|
update Builds set project = new.name where project = old.name;
|
||||||
|
update ReleaseSets set project = new.name where project = old.name;
|
||||||
|
update ReleaseSetJobs set project = new.name where project = old.name;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
@ -288,3 +290,64 @@ create trigger cascadeUserDelete
|
||||||
for each row begin
|
for each row begin
|
||||||
delete from UserRoles where userName = old.userName;
|
delete from UserRoles where userName = old.userName;
|
||||||
end;
|
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
|
||||||
|
);
|
||||||
|
|
Loading…
Reference in a new issue