This commit is contained in:
Eelco Dolstra 2008-11-10 10:18:50 +00:00
parent f4a44db664
commit 8f42bf303f
16 changed files with 129 additions and 47 deletions

View file

@ -29,6 +29,7 @@ sub getBuild {
sub index :Path :Args(0) {
my ( $self, $c ) = @_;
$c->stash->{template} = 'index.tt';
$c->stash->{jobs} = [$c->model('DB::Jobs')->all];
$c->stash->{projects} = [$c->model('DB::Projects')->all];
$c->stash->{allBuilds} = [$c->model('DB::Builds')->search(undef, {order_by => "timestamp DESC"})];
# Get the latest build for each unique job.

View file

@ -8,8 +8,8 @@ use base 'DBIx::Class::Schema';
__PACKAGE__->load_classes;
# Created by DBIx::Class::Schema::Loader v0.04005 @ 2008-11-09 01:36:21
# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:G17vptu+2rEUXbsqVtoXzQ
# Created by DBIx::Class::Schema::Loader v0.04005 @ 2008-11-10 10:30:11
# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:xP97YDrN7Bm2B/BlbQJ7fQ
# You can replace this text with custom content, and it will be preserved on regeneration

View file

@ -21,8 +21,8 @@ __PACKAGE__->set_primary_key("build", "logphase");
__PACKAGE__->belongs_to("build", "HydraFrontend::Schema::Builds", { id => "build" });
# Created by DBIx::Class::Schema::Loader v0.04005 @ 2008-11-09 01:36:21
# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:xvWlrugDQD11vH+7f91K0A
# Created by DBIx::Class::Schema::Loader v0.04005 @ 2008-11-10 10:30:11
# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:pt0CJFX1pP9Z2TjqrTjTkw
# You can replace this text with custom content, and it will be preserved on regeneration

View file

@ -21,8 +21,8 @@ __PACKAGE__->set_primary_key("build", "path");
__PACKAGE__->belongs_to("build", "HydraFrontend::Schema::Builds", { id => "build" });
# Created by DBIx::Class::Schema::Loader v0.04005 @ 2008-11-09 01:36:21
# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:SMsT6htcybeWNHhv82+ilA
# Created by DBIx::Class::Schema::Loader v0.04005 @ 2008-11-10 10:30:11
# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:3NKUaF4u4H6ZmIRCeva8yA
# You can replace this text with custom content, and it will be preserved on regeneration

View file

@ -38,6 +38,16 @@ __PACKAGE__->add_columns(
{ data_type => "text", is_nullable => 0, size => undef },
);
__PACKAGE__->set_primary_key("id");
__PACKAGE__->belongs_to(
"project",
"HydraFrontend::Schema::Projects",
{ name => "project" },
);
__PACKAGE__->belongs_to(
"jobset",
"HydraFrontend::Schema::Jobsets",
{ name => "jobset", project => "project" },
);
__PACKAGE__->has_many(
"inputs",
"HydraFrontend::Schema::Inputs",
@ -55,8 +65,8 @@ __PACKAGE__->has_many(
);
# Created by DBIx::Class::Schema::Loader v0.04005 @ 2008-11-09 01:36:21
# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:nfVureYYGM1V/NHroQA5Tw
# Created by DBIx::Class::Schema::Loader v0.04005 @ 2008-11-10 10:30:11
# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:8s5Z03ugocOVb021EwGVag
__PACKAGE__->has_many(dependents => 'HydraFrontend::Schema::Inputs', 'dependency');

View file

@ -35,8 +35,8 @@ __PACKAGE__->set_primary_key("id");
__PACKAGE__->belongs_to("build", "HydraFrontend::Schema::Builds", { id => "build" });
# Created by DBIx::Class::Schema::Loader v0.04005 @ 2008-11-09 01:36:21
# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:3PAsUD+79bZk4vGeSyyACg
# Created by DBIx::Class::Schema::Loader v0.04005 @ 2008-11-10 10:30:11
# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:AzV6B/6CCrroPlO32n2p3A
__PACKAGE__->belongs_to("dependency", "HydraFrontend::Schema::Builds", { id => "dependency" });

View file

@ -14,6 +14,10 @@ __PACKAGE__->add_columns(
{ data_type => "integer", is_nullable => 0, size => undef },
"priority",
{ data_type => "integer", is_nullable => 0, size => undef },
"busy",
{ data_type => "integer", is_nullable => 0, size => undef },
"locker",
{ data_type => "text", is_nullable => 0, size => undef },
"project",
{ data_type => "text", is_nullable => 0, size => undef },
"jobset",
@ -30,10 +34,20 @@ __PACKAGE__->add_columns(
{ data_type => "text", is_nullable => 0, size => undef },
);
__PACKAGE__->set_primary_key("id");
__PACKAGE__->belongs_to(
"project",
"HydraFrontend::Schema::Projects",
{ name => "project" },
);
__PACKAGE__->belongs_to(
"jobset",
"HydraFrontend::Schema::Jobsets",
{ name => "jobset", project => "project" },
);
# Created by DBIx::Class::Schema::Loader v0.04005 @ 2008-11-09 01:36:21
# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:T8O0XTTOZXapWpJbzjKLTw
# Created by DBIx::Class::Schema::Loader v0.04005 @ 2008-11-10 10:30:11
# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:GubRofAmJ/sbJbjyV3aKSQ
# You can replace this text with custom content, and it will be preserved on regeneration

View file

@ -6,7 +6,7 @@ use warnings;
use base 'DBIx::Class';
__PACKAGE__->load_components("Core");
__PACKAGE__->table("jobSetInputAlts");
__PACKAGE__->table("jobsetInputAlts");
__PACKAGE__->add_columns(
"project",
{ data_type => "text", is_nullable => 0, size => undef },
@ -33,8 +33,8 @@ __PACKAGE__->belongs_to(
);
# Created by DBIx::Class::Schema::Loader v0.04005 @ 2008-11-09 01:36:21
# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:DzEHCDlnponciGmGASknlg
# Created by DBIx::Class::Schema::Loader v0.04005 @ 2008-11-10 10:30:11
# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:ZjjWLbAWExxOqsDz41A3KA
# You can replace this text with custom content, and it will be preserved on regeneration

View file

@ -6,7 +6,7 @@ use warnings;
use base 'DBIx::Class';
__PACKAGE__->load_components("Core");
__PACKAGE__->table("jobSetInputs");
__PACKAGE__->table("jobsetInputs");
__PACKAGE__->add_columns(
"project",
{ data_type => "text", is_nullable => 0, size => undef },
@ -43,8 +43,8 @@ __PACKAGE__->has_many(
);
# Created by DBIx::Class::Schema::Loader v0.04005 @ 2008-11-09 01:36:21
# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:Lm2oIWEUSHFICYMX2qmTfw
# Created by DBIx::Class::Schema::Loader v0.04005 @ 2008-11-10 10:30:11
# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:6hzbFjPWQ872UxFhhpxjFg
# You can replace this text with custom content, and it will be preserved on regeneration

View file

@ -6,7 +6,7 @@ use warnings;
use base 'DBIx::Class';
__PACKAGE__->load_components("Core");
__PACKAGE__->table("jobSets");
__PACKAGE__->table("jobsets");
__PACKAGE__->add_columns(
"name",
{ data_type => "text", is_nullable => 0, size => undef },
@ -20,6 +20,14 @@ __PACKAGE__->add_columns(
{ data_type => "text", is_nullable => 0, size => undef },
);
__PACKAGE__->set_primary_key("project", "name");
__PACKAGE__->has_many(
"builds",
"HydraFrontend::Schema::Builds",
{
"foreign.jobset" => "self.name",
"foreign.project" => "self.project",
},
);
__PACKAGE__->belongs_to(
"project",
"HydraFrontend::Schema::Projects",
@ -38,10 +46,18 @@ __PACKAGE__->has_many(
"foreign.project" => "self.project",
},
);
__PACKAGE__->has_many(
"jobs",
"HydraFrontend::Schema::Jobs",
{
"foreign.jobset" => "self.name",
"foreign.project" => "self.project",
},
);
# Created by DBIx::Class::Schema::Loader v0.04005 @ 2008-11-09 01:36:21
# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:EmATMMeNmMd2AI8lVzcLFA
# Created by DBIx::Class::Schema::Loader v0.04005 @ 2008-11-10 10:30:11
# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:oRV4yw0DWG5PI0agcM7QHA
# You can replace this text with custom content, and it will be preserved on regeneration

View file

@ -12,15 +12,25 @@ __PACKAGE__->add_columns(
{ data_type => "text", is_nullable => 0, size => undef },
);
__PACKAGE__->set_primary_key("name");
__PACKAGE__->has_many(
"builds",
"HydraFrontend::Schema::Builds",
{ "foreign.project" => "self.name" },
);
__PACKAGE__->has_many(
"jobsets",
"HydraFrontend::Schema::Jobsets",
{ "foreign.project" => "self.name" },
);
__PACKAGE__->has_many(
"jobs",
"HydraFrontend::Schema::Jobs",
{ "foreign.project" => "self.name" },
);
# Created by DBIx::Class::Schema::Loader v0.04005 @ 2008-11-09 01:36:21
# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:ZifQocKoHOPRrJQSPggZ+w
# Created by DBIx::Class::Schema::Loader v0.04005 @ 2008-11-10 10:30:11
# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:9SeEXSEOH1ocrdkoa7fx5Q
# You can replace this text with custom content, and it will be preserved on regeneration

View file

@ -1,7 +1,7 @@
[% WRAPPER layout.tt title="Hydra Overview" %]
[% USE date %]
<h1>Job <tt>[% build.project %]:[% build.attrname %]</tt> build [% id %]</h1>
<h1>Job <tt>[% build.project.name %]:[% build.attrname %]</tt> build [% id %]</h1>
<h2>Information</h2>
@ -13,11 +13,11 @@
</tr>
<tr>
<th>Project:</th>
<td><a href="[% c.uri_for('/project' build.project) %]"><tt>[% build.project %]</tt></a></td>
<td><a href="[% c.uri_for('/project' build.project.name) %]"><tt>[% build.project.name %]</tt></a></td>
</tr>
<tr>
<th>Jobset:</th>
<td><tt>[% build.jobset %]</tt></td>
<td><tt>[% build.jobset.name %]</tt></td>
</tr>
<tr>
<th>Job name:</th>
@ -87,7 +87,7 @@
<td><tt>[% input.type %]</tt></td>
<td>
[% IF input.type == "build" %]
<a href="[% c.uri_for('/build' input.dependency.id) %]">Job <tt>[% input.dependency.project %]:[% input.dependency.attrname %]</tt> build [% input.dependency.id %]</a>
<a href="[% c.uri_for('/build' input.dependency.id) %]">Job <tt>[% input.dependency.project.name %]:[% input.dependency.attrname %]</tt> build [% input.dependency.id %]</a>
[% ELSIF input.type == "string" %]
<tt>"[% input.value %]"</tt>
[% ELSE %]
@ -153,7 +153,7 @@
<tbody>
[% FOREACH input IN build.dependents -%]
<tr>
<td><a href="[% c.uri_for('/build' input.build.id) %]">Job <tt>[% input.build.project %]:[% input.build.attrname %]</tt> build [% input.build.id %]</a></td>
<td><a href="[% c.uri_for('/build' input.build.id) %]">Job <tt>[% input.build.project.name %]:[% input.build.attrname %]</tt> build [% input.build.id %]</a></td>
<td><tt>[% input.name %]</tt></td>
<td><tt>[% input.build.system %]</tt></td>
<td>[% date.format(input.build.timestamp, '%Y-%m-%d %H:%M:%S') %]</td>

View file

@ -1,4 +1,25 @@
[% WRAPPER layout.tt title="Hydra Overview" %]
[% USE date %]
<h1>Queue</h1>
<table class="tablesorter">
<thead>
<tr><th>Priority</th><th>Project</th><th>Job</th><th>System</th><th>Timestamp</th><th>Description</th></tr>
</thead>
<tbody>
[% FOREACH job IN jobs -%]
<tr>
<td>[% job.priority %]</td>
<td><tt>[% job.project.name %]</tt></td>
<td><tt>[% job.jobset.name %]</tt></td>
<td><tt>[% job.system %]</tt></td>
<td>[% date.format(job.timestamp, '%Y-%m-%d %H:%M:%S') %]</td>
<td>[% job.description %]</td>
</tr>
[% END -%]
</tbody>
</table>
<h1>Job status</h1>

View file

@ -9,8 +9,8 @@
[% END %]
</td>
<td><a href="[% c.uri_for('/build' build.id) %]">[% build.id %]</a></td>
<td><a href="[% c.uri_for('/project' build.project) %]"><tt>[% build.project %]</tt></a></td>
<td><a href="[% c.uri_for('/job' build.project build.attrname) %]"><tt>[% build.attrname %]</tt></a></td>
<td><a href="[% c.uri_for('/project' build.project.name) %]"><tt>[% build.project.name %]</tt></a></td>
<td><a href="[% c.uri_for('/job' build.project.name build.attrname) %]"><tt>[% build.attrname %]</tt></a></td>
<td><tt>[% build.system %]</tt></td>
<td>[% date.format(build.timestamp, '%Y-%m-%d %H:%M:%S') %]</td>
<td>[% build.description %]</td>

View file

@ -4,7 +4,7 @@ create table builds (
-- Info about the inputs.
project text not null, -- !!! foreign key
jobSet text not null, -- !!! foreign key
jobset text not null, -- !!! foreign key
attrName text not null,
-- Info about the build result.
@ -16,7 +16,10 @@ create table builds (
errorMsg text, -- error message in case of a Nix failure
startTime integer, -- in Unix time, 0 = used cached build result
stopTime integer,
system text not null
system text not null,
foreign key (project) references projects(name), -- ignored by sqlite
foreign key (project, jobset) references jobsets(project, name) -- ignored by sqlite
);
@ -28,7 +31,7 @@ create table inputs (
build integer,
job integer,
-- Copied from the jobSetInputs from which the build was created.
-- Copied from the jobsetinputs from which the build was created.
name text not null,
type text not null,
uri text,
@ -83,29 +86,29 @@ create table projects (
-- A jobset consists of a set of inputs (e.g. SVN repositories), one
-- of which contains a Nix expression containing an attribute set
-- describing build jobs.
create table jobSets (
create table jobsets (
name text not null,
project text not null,
description text,
nixExprInput text not null, -- name of the jobSetInput containing the Nix expression
nixExprInput text not null, -- name of the jobsetInput containing the Nix expression
nixExprPath text not null, -- relative path of the Nix expression
primary key (project, name),
foreign key (project) references projects(name) on delete cascade, -- ignored by sqlite
foreign key (project, name, nixExprInput) references jobSetInputs(project, job, name)
foreign key (project, name, nixExprInput) references jobsetInputs(project, job, name)
);
create table jobSetInputs (
create table jobsetInputs (
project text not null,
jobset text not null,
name text not null,
type text not null, -- "svn", "cvs", "path", "file", "string"
primary key (project, jobset, name),
foreign key (project, jobset) references jobSets(project, name) on delete cascade -- ignored by sqlite
foreign key (project, jobset) references jobsets(project, name) on delete cascade -- ignored by sqlite
);
create table jobSetInputAlts (
create table jobsetInputAlts (
project text not null,
jobset text not null,
input text not null,
@ -118,7 +121,7 @@ create table jobSetInputAlts (
value text, -- for type == 'string'
primary key (project, jobset, input, altnr),
foreign key (project, jobset, input) references jobSetInputs(project, jobset, name) on delete cascade -- ignored by sqlite
foreign key (project, jobset, input) references jobsetInputs(project, jobset, name) on delete cascade -- ignored by sqlite
);
@ -128,14 +131,20 @@ create table jobs (
priority integer not null,
busy integer not null, -- true means someone is building this job now
locker text not null, -- !!! hostname/pid of the process building this job?
-- Info about the inputs.
project text not null, -- !!! foreign key
jobSet text not null, -- !!! foreign key
jobset text not null, -- !!! foreign key
attrName text not null,
-- What this job will build.
description text,
drvPath text not null,
outPath text not null,
system text not null
system text not null,
foreign key (project) references projects(name), -- ignored by sqlite
foreign key (project, jobset) references jobsets(project, name) -- ignored by sqlite
);

View file

@ -16,7 +16,7 @@ sub isValidPath {
sub buildJob {
my ($project, $jobset, $jobName, $drvPath, $outPath, $usedInputs, $system) = @_;
my ($project, $jobset, $jobName, $description, $drvPath, $outPath, $usedInputs, $system) = @_;
if (scalar($db->resultset('Builds')->search({project => $project->name, jobset => $jobset->name, attrname => $jobName, outPath => $outPath})) > 0) {
print " already done\n";
@ -58,6 +58,7 @@ sub buildJob {
, project => $project->name
, jobset => $jobset->name
, attrname => $jobName
, description => $description
, drvpath => $drvPath
, outpath => $outPath
, iscachedbuild => $isCachedBuild
@ -175,17 +176,17 @@ sub checkJob {
my $infoXml = `nix-env -f $nixExprPath --query --available "*" --attr-path --out-path --drv-path --meta --xml --system-filter "*" --attr $jobName $extraArgs`
or die "cannot get information about the job: $?";
my $info = XMLin($infoXml, KeyAttr => ['attrPath', 'name'])
my $info = XMLin($infoXml, ForceArray => 1, KeyAttr => ['attrPath', 'name'])
or die "cannot parse XML output";
my $job = $info->{item};
die if !defined $job || $job->{attrPath} ne $jobName;
my $job = $info->{item}->{$jobName};
die if !defined $job;
my $description = defined $job->{meta}->{description} ? $job->{meta}->{description}->{value} : "";
die unless $job->{drvPath} eq $drvPath;
my $outPath = $job->{outPath};
buildJob($project, $jobset, $jobName, $drvPath, $outPath, $inputInfo, $job->{system});
buildJob($project, $jobset, $jobName, $description, $drvPath, $outPath, $inputInfo, $job->{system});
};