forked from lix-project/hydra
* Merged the Build and Job tables.
This commit is contained in:
parent
0f24c11292
commit
ecd0ba74e9
|
@ -29,12 +29,17 @@ sub getBuild {
|
||||||
sub index :Path :Args(0) {
|
sub index :Path :Args(0) {
|
||||||
my ( $self, $c ) = @_;
|
my ( $self, $c ) = @_;
|
||||||
$c->stash->{template} = 'index.tt';
|
$c->stash->{template} = 'index.tt';
|
||||||
$c->stash->{jobs} = [$c->model('DB::Jobs')->all];
|
|
||||||
$c->stash->{projects} = [$c->model('DB::Projects')->all];
|
$c->stash->{projects} = [$c->model('DB::Projects')->all];
|
||||||
$c->stash->{allBuilds} = [$c->model('DB::Builds')->search(undef, {order_by => "timestamp DESC"})];
|
$c->stash->{scheduled} = [$c->model('DB::Builds')->search(
|
||||||
# Get the latest build for each unique job.
|
{finished => 0}, {join => 'schedulingInfo'})]; # !!!
|
||||||
# select * from builds as x where timestamp == (select max(timestamp) from builds where jobName == x.jobName);
|
$c->stash->{allBuilds} = [$c->model('DB::Builds')->search(
|
||||||
$c->stash->{latestBuilds} = [$c->model('DB::Builds')->search(undef, {order_by => "project, attrName", where => "timestamp == (select max(timestamp) from builds where project == me.project and attrName == me.attrName)"})];
|
{finished => 1}, {order_by => "timestamp DESC"})];
|
||||||
|
# Get the latest finished build for each unique job.
|
||||||
|
$c->stash->{latestBuilds} = [$c->model('DB::Builds')->search(undef,
|
||||||
|
{ join => 'resultInfo'
|
||||||
|
, where => "finished != 0 and timestamp = (select max(timestamp) from Builds where project == me.project and attrName == me.attrName)"
|
||||||
|
, order_by => "project, attrname"
|
||||||
|
})];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -54,7 +59,9 @@ sub job :Local {
|
||||||
$c->stash->{template} = 'job.tt';
|
$c->stash->{template} = 'job.tt';
|
||||||
$c->stash->{projectName} = $project;
|
$c->stash->{projectName} = $project;
|
||||||
$c->stash->{jobName} = $jobName;
|
$c->stash->{jobName} = $jobName;
|
||||||
$c->stash->{builds} = [$c->model('DB::Builds')->search({project => $project, attrName => $jobName}, {order_by => "timestamp DESC"})];
|
$c->stash->{builds} = [$c->model('DB::Builds')->search(
|
||||||
|
{finished => 1, project => $project, attrName => $jobName},
|
||||||
|
{order_by => "timestamp DESC"})];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -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-10 14:25:07
|
# Created by DBIx::Class::Schema::Loader v0.04005 @ 2008-11-11 13:41:38
|
||||||
# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:dBO/r6lVlITiJ/HlltKcpQ
|
# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:1AgCf4sf5h2RU24Slo0sTA
|
||||||
|
|
||||||
|
|
||||||
# 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
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
package HydraFrontend::Schema::Inputs;
|
package HydraFrontend::Schema::Buildinputs;
|
||||||
|
|
||||||
use strict;
|
use strict;
|
||||||
use warnings;
|
use warnings;
|
||||||
|
@ -6,14 +6,12 @@ use warnings;
|
||||||
use base 'DBIx::Class';
|
use base 'DBIx::Class';
|
||||||
|
|
||||||
__PACKAGE__->load_components("Core");
|
__PACKAGE__->load_components("Core");
|
||||||
__PACKAGE__->table("inputs");
|
__PACKAGE__->table("BuildInputs");
|
||||||
__PACKAGE__->add_columns(
|
__PACKAGE__->add_columns(
|
||||||
"id",
|
"id",
|
||||||
{ data_type => "integer", is_nullable => 0, size => undef },
|
{ data_type => "integer", is_nullable => 0, size => undef },
|
||||||
"build",
|
"build",
|
||||||
{ data_type => "integer", is_nullable => 0, size => undef },
|
{ data_type => "integer", is_nullable => 0, size => undef },
|
||||||
"job",
|
|
||||||
{ data_type => "integer", is_nullable => 0, size => undef },
|
|
||||||
"name",
|
"name",
|
||||||
{ data_type => "text", is_nullable => 0, size => undef },
|
{ data_type => "text", is_nullable => 0, size => undef },
|
||||||
"type",
|
"type",
|
||||||
|
@ -33,11 +31,16 @@ __PACKAGE__->add_columns(
|
||||||
);
|
);
|
||||||
__PACKAGE__->set_primary_key("id");
|
__PACKAGE__->set_primary_key("id");
|
||||||
__PACKAGE__->belongs_to("build", "HydraFrontend::Schema::Builds", { id => "build" });
|
__PACKAGE__->belongs_to("build", "HydraFrontend::Schema::Builds", { id => "build" });
|
||||||
|
__PACKAGE__->belongs_to(
|
||||||
|
"dependency",
|
||||||
|
"HydraFrontend::Schema::Builds",
|
||||||
|
{ id => "dependency" },
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
# Created by DBIx::Class::Schema::Loader v0.04005 @ 2008-11-10 14:25:07
|
# Created by DBIx::Class::Schema::Loader v0.04005 @ 2008-11-11 13:41:38
|
||||||
# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:A3Is4VTFkTl2DzrYjzdrZA
|
# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:dKMSSomUN+gJX57Z5e295w
|
||||||
|
|
||||||
__PACKAGE__->belongs_to("dependency", "HydraFrontend::Schema::Builds", { id => "dependency" });
|
|
||||||
|
|
||||||
|
# You can replace this text with custom content, and it will be preserved on regeneration
|
||||||
1;
|
1;
|
|
@ -6,7 +6,7 @@ use warnings;
|
||||||
use base 'DBIx::Class';
|
use base 'DBIx::Class';
|
||||||
|
|
||||||
__PACKAGE__->load_components("Core");
|
__PACKAGE__->load_components("Core");
|
||||||
__PACKAGE__->table("buildLogs");
|
__PACKAGE__->table("BuildLogs");
|
||||||
__PACKAGE__->add_columns(
|
__PACKAGE__->add_columns(
|
||||||
"build",
|
"build",
|
||||||
{ data_type => "integer", is_nullable => 0, size => undef },
|
{ data_type => "integer", is_nullable => 0, size => undef },
|
||||||
|
@ -21,8 +21,8 @@ __PACKAGE__->set_primary_key("build", "logphase");
|
||||||
__PACKAGE__->belongs_to("build", "HydraFrontend::Schema::Builds", { id => "build" });
|
__PACKAGE__->belongs_to("build", "HydraFrontend::Schema::Builds", { id => "build" });
|
||||||
|
|
||||||
|
|
||||||
# Created by DBIx::Class::Schema::Loader v0.04005 @ 2008-11-10 14:25:07
|
# Created by DBIx::Class::Schema::Loader v0.04005 @ 2008-11-11 13:41:38
|
||||||
# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:eMNna7u2l0ec+OYuvtGRpg
|
# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:ZOxJeT+ltgyc/zuDl9aEDQ
|
||||||
|
|
||||||
|
|
||||||
# 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
|
||||||
|
|
|
@ -6,7 +6,7 @@ use warnings;
|
||||||
use base 'DBIx::Class';
|
use base 'DBIx::Class';
|
||||||
|
|
||||||
__PACKAGE__->load_components("Core");
|
__PACKAGE__->load_components("Core");
|
||||||
__PACKAGE__->table("buildProducts");
|
__PACKAGE__->table("BuildProducts");
|
||||||
__PACKAGE__->add_columns(
|
__PACKAGE__->add_columns(
|
||||||
"build",
|
"build",
|
||||||
{ data_type => "integer", is_nullable => 0, size => undef },
|
{ data_type => "integer", is_nullable => 0, size => undef },
|
||||||
|
@ -21,8 +21,8 @@ __PACKAGE__->set_primary_key("build", "path");
|
||||||
__PACKAGE__->belongs_to("build", "HydraFrontend::Schema::Builds", { id => "build" });
|
__PACKAGE__->belongs_to("build", "HydraFrontend::Schema::Builds", { id => "build" });
|
||||||
|
|
||||||
|
|
||||||
# Created by DBIx::Class::Schema::Loader v0.04005 @ 2008-11-10 14:25:07
|
# Created by DBIx::Class::Schema::Loader v0.04005 @ 2008-11-11 13:41:38
|
||||||
# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:LaXQ4zxxvzdKFBRVcjMdMQ
|
# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:rZPTilX/PAiIoxffxc0nJw
|
||||||
|
|
||||||
|
|
||||||
# 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
|
||||||
|
|
|
@ -0,0 +1,33 @@
|
||||||
|
package HydraFrontend::Schema::Buildresultinfo;
|
||||||
|
|
||||||
|
use strict;
|
||||||
|
use warnings;
|
||||||
|
|
||||||
|
use base 'DBIx::Class';
|
||||||
|
|
||||||
|
__PACKAGE__->load_components("Core");
|
||||||
|
__PACKAGE__->table("BuildResultInfo");
|
||||||
|
__PACKAGE__->add_columns(
|
||||||
|
"id",
|
||||||
|
{ data_type => "integer", is_nullable => 0, size => undef },
|
||||||
|
"iscachedbuild",
|
||||||
|
{ data_type => "integer", is_nullable => 0, size => undef },
|
||||||
|
"buildstatus",
|
||||||
|
{ data_type => "integer", is_nullable => 0, size => undef },
|
||||||
|
"errormsg",
|
||||||
|
{ data_type => "text", is_nullable => 0, size => undef },
|
||||||
|
"starttime",
|
||||||
|
{ data_type => "integer", is_nullable => 0, size => undef },
|
||||||
|
"stoptime",
|
||||||
|
{ data_type => "integer", is_nullable => 0, size => undef },
|
||||||
|
);
|
||||||
|
__PACKAGE__->set_primary_key("id");
|
||||||
|
__PACKAGE__->belongs_to("id", "HydraFrontend::Schema::Builds", { id => "id" });
|
||||||
|
|
||||||
|
|
||||||
|
# Created by DBIx::Class::Schema::Loader v0.04005 @ 2008-11-11 13:41:38
|
||||||
|
# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:2Vfqs9RUhbDrje18yZb3AA
|
||||||
|
|
||||||
|
|
||||||
|
# You can replace this text with custom content, and it will be preserved on regeneration
|
||||||
|
1;
|
|
@ -6,10 +6,12 @@ use warnings;
|
||||||
use base 'DBIx::Class';
|
use base 'DBIx::Class';
|
||||||
|
|
||||||
__PACKAGE__->load_components("Core");
|
__PACKAGE__->load_components("Core");
|
||||||
__PACKAGE__->table("builds");
|
__PACKAGE__->table("Builds");
|
||||||
__PACKAGE__->add_columns(
|
__PACKAGE__->add_columns(
|
||||||
"id",
|
"id",
|
||||||
{ data_type => "integer", is_nullable => 0, size => undef },
|
{ data_type => "integer", is_nullable => 0, size => undef },
|
||||||
|
"finished",
|
||||||
|
{ data_type => "integer", is_nullable => 0, size => undef },
|
||||||
"timestamp",
|
"timestamp",
|
||||||
{ data_type => "integer", is_nullable => 0, size => undef },
|
{ data_type => "integer", is_nullable => 0, size => undef },
|
||||||
"project",
|
"project",
|
||||||
|
@ -24,16 +26,6 @@ __PACKAGE__->add_columns(
|
||||||
{ data_type => "text", is_nullable => 0, size => undef },
|
{ data_type => "text", is_nullable => 0, size => undef },
|
||||||
"outpath",
|
"outpath",
|
||||||
{ data_type => "text", is_nullable => 0, size => undef },
|
{ data_type => "text", is_nullable => 0, size => undef },
|
||||||
"iscachedbuild",
|
|
||||||
{ data_type => "integer", is_nullable => 0, size => undef },
|
|
||||||
"buildstatus",
|
|
||||||
{ data_type => "integer", is_nullable => 0, size => undef },
|
|
||||||
"errormsg",
|
|
||||||
{ data_type => "text", is_nullable => 0, size => undef },
|
|
||||||
"starttime",
|
|
||||||
{ data_type => "integer", is_nullable => 0, size => undef },
|
|
||||||
"stoptime",
|
|
||||||
{ data_type => "integer", is_nullable => 0, size => undef },
|
|
||||||
"system",
|
"system",
|
||||||
{ data_type => "text", is_nullable => 0, size => undef },
|
{ data_type => "text", is_nullable => 0, size => undef },
|
||||||
);
|
);
|
||||||
|
@ -49,10 +41,25 @@ __PACKAGE__->belongs_to(
|
||||||
{ name => "jobset", project => "project" },
|
{ name => "jobset", project => "project" },
|
||||||
);
|
);
|
||||||
__PACKAGE__->has_many(
|
__PACKAGE__->has_many(
|
||||||
"inputs",
|
"buildschedulinginfoes",
|
||||||
"HydraFrontend::Schema::Inputs",
|
"HydraFrontend::Schema::Buildschedulinginfo",
|
||||||
|
{ "foreign.id" => "self.id" },
|
||||||
|
);
|
||||||
|
__PACKAGE__->has_many(
|
||||||
|
"buildresultinfoes",
|
||||||
|
"HydraFrontend::Schema::Buildresultinfo",
|
||||||
|
{ "foreign.id" => "self.id" },
|
||||||
|
);
|
||||||
|
__PACKAGE__->has_many(
|
||||||
|
"buildinputs_builds",
|
||||||
|
"HydraFrontend::Schema::Buildinputs",
|
||||||
{ "foreign.build" => "self.id" },
|
{ "foreign.build" => "self.id" },
|
||||||
);
|
);
|
||||||
|
__PACKAGE__->has_many(
|
||||||
|
"buildinputs_dependencies",
|
||||||
|
"HydraFrontend::Schema::Buildinputs",
|
||||||
|
{ "foreign.dependency" => "self.id" },
|
||||||
|
);
|
||||||
__PACKAGE__->has_many(
|
__PACKAGE__->has_many(
|
||||||
"buildproducts",
|
"buildproducts",
|
||||||
"HydraFrontend::Schema::Buildproducts",
|
"HydraFrontend::Schema::Buildproducts",
|
||||||
|
@ -65,9 +72,23 @@ __PACKAGE__->has_many(
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
# Created by DBIx::Class::Schema::Loader v0.04005 @ 2008-11-10 14:25:07
|
# Created by DBIx::Class::Schema::Loader v0.04005 @ 2008-11-11 13:41:38
|
||||||
# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:C1XPkCXQImyXduKER0Dllg
|
# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:1GZeB3YVr064AZrGargmFg
|
||||||
|
|
||||||
__PACKAGE__->has_many(dependents => 'HydraFrontend::Schema::Inputs', 'dependency');
|
__PACKAGE__->has_many(dependents => 'HydraFrontend::Schema::Buildinputs', 'dependency');
|
||||||
|
|
||||||
|
__PACKAGE__->has_many(inputs => 'HydraFrontend::Schema::Buildinputs', 'build');
|
||||||
|
|
||||||
|
__PACKAGE__->belongs_to(
|
||||||
|
"schedulingInfo",
|
||||||
|
"HydraFrontend::Schema::Buildschedulinginfo",
|
||||||
|
{ id => "id" },
|
||||||
|
);
|
||||||
|
|
||||||
|
__PACKAGE__->belongs_to(
|
||||||
|
"resultInfo",
|
||||||
|
"HydraFrontend::Schema::Buildresultinfo",
|
||||||
|
{ id => "id" },
|
||||||
|
);
|
||||||
|
|
||||||
1;
|
1;
|
||||||
|
|
|
@ -0,0 +1,31 @@
|
||||||
|
package HydraFrontend::Schema::Buildschedulinginfo;
|
||||||
|
|
||||||
|
use strict;
|
||||||
|
use warnings;
|
||||||
|
|
||||||
|
use base 'DBIx::Class';
|
||||||
|
|
||||||
|
__PACKAGE__->load_components("Core");
|
||||||
|
__PACKAGE__->table("BuildSchedulingInfo");
|
||||||
|
__PACKAGE__->add_columns(
|
||||||
|
"id",
|
||||||
|
{ 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 },
|
||||||
|
"logfile",
|
||||||
|
{ data_type => "text", is_nullable => 0, size => undef },
|
||||||
|
);
|
||||||
|
__PACKAGE__->set_primary_key("id");
|
||||||
|
__PACKAGE__->belongs_to("id", "HydraFrontend::Schema::Builds", { id => "id" });
|
||||||
|
|
||||||
|
|
||||||
|
# Created by DBIx::Class::Schema::Loader v0.04005 @ 2008-11-11 13:41:38
|
||||||
|
# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:rN7v2+MnC8TkrEHUzt2Gqg
|
||||||
|
|
||||||
|
|
||||||
|
# You can replace this text with custom content, and it will be preserved on regeneration
|
||||||
|
1;
|
|
@ -1,58 +0,0 @@
|
||||||
package HydraFrontend::Schema::Jobs;
|
|
||||||
|
|
||||||
use strict;
|
|
||||||
use warnings;
|
|
||||||
|
|
||||||
use base 'DBIx::Class';
|
|
||||||
|
|
||||||
__PACKAGE__->load_components("Core");
|
|
||||||
__PACKAGE__->table("jobs");
|
|
||||||
__PACKAGE__->add_columns(
|
|
||||||
"id",
|
|
||||||
{ data_type => "integer", is_nullable => 0, size => undef },
|
|
||||||
"timestamp",
|
|
||||||
{ 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",
|
|
||||||
{ data_type => "text", is_nullable => 0, size => undef },
|
|
||||||
"attrname",
|
|
||||||
{ data_type => "text", is_nullable => 0, size => undef },
|
|
||||||
"description",
|
|
||||||
{ data_type => "text", is_nullable => 0, size => undef },
|
|
||||||
"drvpath",
|
|
||||||
{ data_type => "text", is_nullable => 0, size => undef },
|
|
||||||
"outpath",
|
|
||||||
{ data_type => "text", is_nullable => 0, size => undef },
|
|
||||||
"system",
|
|
||||||
{ 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-10 14:25:07
|
|
||||||
# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:ZF8UB1MtbPuOk7wTSFJR5Q
|
|
||||||
|
|
||||||
__PACKAGE__->has_many(
|
|
||||||
"inputs",
|
|
||||||
"HydraFrontend::Schema::Inputs",
|
|
||||||
{ "foreign.job" => "self.id" },
|
|
||||||
);
|
|
||||||
|
|
||||||
1;
|
|
|
@ -6,7 +6,7 @@ use warnings;
|
||||||
use base 'DBIx::Class';
|
use base 'DBIx::Class';
|
||||||
|
|
||||||
__PACKAGE__->load_components("Core");
|
__PACKAGE__->load_components("Core");
|
||||||
__PACKAGE__->table("jobsetInputAlts");
|
__PACKAGE__->table("JobsetInputAlts");
|
||||||
__PACKAGE__->add_columns(
|
__PACKAGE__->add_columns(
|
||||||
"project",
|
"project",
|
||||||
{ data_type => "text", is_nullable => 0, size => undef },
|
{ 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-10 14:25:07
|
# Created by DBIx::Class::Schema::Loader v0.04005 @ 2008-11-11 13:41:38
|
||||||
# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:ibTncC1AslPWt1eiTtwplA
|
# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:bvEulSFMDlAMs39sIyHgZQ
|
||||||
|
|
||||||
|
|
||||||
# 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
|
||||||
|
|
|
@ -6,7 +6,7 @@ use warnings;
|
||||||
use base 'DBIx::Class';
|
use base 'DBIx::Class';
|
||||||
|
|
||||||
__PACKAGE__->load_components("Core");
|
__PACKAGE__->load_components("Core");
|
||||||
__PACKAGE__->table("jobsetInputs");
|
__PACKAGE__->table("JobsetInputs");
|
||||||
__PACKAGE__->add_columns(
|
__PACKAGE__->add_columns(
|
||||||
"project",
|
"project",
|
||||||
{ data_type => "text", is_nullable => 0, size => undef },
|
{ 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-10 14:25:07
|
# Created by DBIx::Class::Schema::Loader v0.04005 @ 2008-11-11 13:41:38
|
||||||
# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:D1UzSZwPtwDmOI7q6g8uKQ
|
# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:54xK3D1D0Jm5oKgRelXN7Q
|
||||||
|
|
||||||
|
|
||||||
# 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
|
||||||
|
|
|
@ -6,7 +6,7 @@ use warnings;
|
||||||
use base 'DBIx::Class';
|
use base 'DBIx::Class';
|
||||||
|
|
||||||
__PACKAGE__->load_components("Core");
|
__PACKAGE__->load_components("Core");
|
||||||
__PACKAGE__->table("jobsets");
|
__PACKAGE__->table("Jobsets");
|
||||||
__PACKAGE__->add_columns(
|
__PACKAGE__->add_columns(
|
||||||
"name",
|
"name",
|
||||||
{ data_type => "text", is_nullable => 0, size => undef },
|
{ data_type => "text", is_nullable => 0, size => undef },
|
||||||
|
@ -46,18 +46,10 @@ __PACKAGE__->has_many(
|
||||||
"foreign.project" => "self.project",
|
"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-10 14:25:07
|
# Created by DBIx::Class::Schema::Loader v0.04005 @ 2008-11-11 13:41:38
|
||||||
# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:6Pyrgervmq03S5Nx8QfA1Q
|
# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:JHirlq7Jc8dQOy+Op/VflA
|
||||||
|
|
||||||
|
|
||||||
# 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
|
||||||
|
|
|
@ -6,7 +6,7 @@ use warnings;
|
||||||
use base 'DBIx::Class';
|
use base 'DBIx::Class';
|
||||||
|
|
||||||
__PACKAGE__->load_components("Core");
|
__PACKAGE__->load_components("Core");
|
||||||
__PACKAGE__->table("projects");
|
__PACKAGE__->table("Projects");
|
||||||
__PACKAGE__->add_columns(
|
__PACKAGE__->add_columns(
|
||||||
"name",
|
"name",
|
||||||
{ data_type => "text", is_nullable => 0, size => undef },
|
{ data_type => "text", is_nullable => 0, size => undef },
|
||||||
|
@ -22,15 +22,10 @@ __PACKAGE__->has_many(
|
||||||
"HydraFrontend::Schema::Jobsets",
|
"HydraFrontend::Schema::Jobsets",
|
||||||
{ "foreign.project" => "self.name" },
|
{ "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-10 14:25:07
|
# Created by DBIx::Class::Schema::Loader v0.04005 @ 2008-11-11 13:41:38
|
||||||
# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:p8LbF31qRl/JfMK5wfkeCg
|
# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:7Ag5ZfYVgfw3MJZkNUmBYw
|
||||||
|
|
||||||
|
|
||||||
# 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
|
||||||
|
|
|
@ -1,7 +1,12 @@
|
||||||
[% WRAPPER layout.tt title="Hydra Overview" %]
|
[% WRAPPER layout.tt title="Hydra Overview" %]
|
||||||
[% USE date %]
|
[% USE date %]
|
||||||
|
|
||||||
<h1>Job <tt>[% build.project.name %]:[% build.attrname %]</tt> build [% id %]</h1>
|
<h1>
|
||||||
|
Job <tt>[% build.project.name %]:[% build.attrname %]</tt> build [% id %]
|
||||||
|
[% IF !build.finished %]
|
||||||
|
(scheduled)
|
||||||
|
[% END %]
|
||||||
|
</h1>
|
||||||
|
|
||||||
|
|
||||||
<h2>Information</h2>
|
<h2>Information</h2>
|
||||||
|
@ -11,6 +16,10 @@
|
||||||
<th>Build ID:</th>
|
<th>Build ID:</th>
|
||||||
<td>[% build.id %]</td>
|
<td>[% build.id %]</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<th>Time added:</th>
|
||||||
|
<td>[% date.format(build.timestamp, '%Y-%m-%d %H:%M:%S') %]</td>
|
||||||
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<th>Project:</th>
|
<th>Project:</th>
|
||||||
<td><a href="[% c.uri_for('/project' build.project.name) %]"><tt>[% build.project.name %]</tt></a></td>
|
<td><a href="[% c.uri_for('/project' build.project.name) %]"><tt>[% build.project.name %]</tt></a></td>
|
||||||
|
@ -28,26 +37,8 @@
|
||||||
<td>[% build.description %]</td>
|
<td>[% build.description %]</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<th>Time added:</th>
|
<th>System:</th>
|
||||||
<td>[% date.format(build.timestamp, '%Y-%m-%d %H:%M:%S') %]</td>
|
<td><tt>[% build.system %]</tt></td>
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<th>Build started:</th>
|
|
||||||
<td>[% IF build.starttime %][% date.format(build.starttime, '%Y-%m-%d %H:%M:%S') %][% ELSE %]<em>(cached build)</em>[% END %]</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<th>Build finished:</th>
|
|
||||||
<td>[% IF build.stoptime %][% date.format(build.stoptime, '%Y-%m-%d %H:%M:%S') %][% ELSE %]<em>(cached build)</em>[% END %]</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<th>Duration (seconds):</th>
|
|
||||||
<td>
|
|
||||||
[% IF build.iscachedbuild %]
|
|
||||||
<em>(cached build)</em>
|
|
||||||
[% ELSE %]
|
|
||||||
[% build.stoptime - build.starttime %]
|
|
||||||
[% END %]
|
|
||||||
</td>
|
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<th>Derivation store path:</th>
|
<th>Derivation store path:</th>
|
||||||
|
@ -57,20 +48,41 @@
|
||||||
<th>Output store path:</th>
|
<th>Output store path:</th>
|
||||||
<td><tt>[% build.outpath %]</tt></td>
|
<td><tt>[% build.outpath %]</tt></td>
|
||||||
</tr>
|
</tr>
|
||||||
|
[% IF build.finished %]
|
||||||
<tr>
|
<tr>
|
||||||
<th>System:</th>
|
<th>Build started:</th>
|
||||||
<td><tt>[% build.system %]</tt></td>
|
<td>[% IF build.resultInfo.starttime %][% date.format(build.resultInfo.starttime, '%Y-%m-%d %H:%M:%S') %][% ELSE %]<em>(cached build)</em>[% END %]</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<th>Build finished:</th>
|
||||||
|
<td>[% IF build.resultInfo.stoptime %][% date.format(build.resultInfo.stoptime, '%Y-%m-%d %H:%M:%S') %][% ELSE %]<em>(cached build)</em>[% END %]</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<th>Duration (seconds):</th>
|
||||||
|
<td>
|
||||||
|
[% IF build.resultInfo.iscachedbuild %]
|
||||||
|
<em>(cached build)</em>
|
||||||
|
[% ELSE %]
|
||||||
|
[% build.resultInfo.stoptime - build.resultInfo.starttime %]
|
||||||
|
[% END %]
|
||||||
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<th>Status:</th>
|
<th>Status:</th>
|
||||||
<td>
|
<td>
|
||||||
[% IF build.buildstatus == 0 %]
|
[% IF build.resultInfo.buildstatus == 0 %]
|
||||||
<img src="/static/images/success.gif" />
|
<img src="/static/images/success.gif" />
|
||||||
[% ELSE %]
|
[% ELSE %]
|
||||||
<img src="/static/images/failure.gif" />
|
<img src="/static/images/failure.gif" />
|
||||||
[% END %]
|
[% END %]
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
[% ELSE %]
|
||||||
|
<tr>
|
||||||
|
<th>Priority:</th>
|
||||||
|
<td>[% build.schedulingInfo.priority %]</td>
|
||||||
|
</tr>
|
||||||
|
[% END %]
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
|
|
||||||
|
@ -101,6 +113,8 @@
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
|
|
||||||
|
[% IF build.finished %]
|
||||||
|
|
||||||
<h2>Build products</h2>
|
<h2>Build products</h2>
|
||||||
|
|
||||||
<ul class="productList">
|
<ul class="productList">
|
||||||
|
@ -167,3 +181,6 @@
|
||||||
|
|
||||||
[% END %]
|
[% END %]
|
||||||
|
|
||||||
|
|
||||||
|
[% END %]
|
||||||
|
|
||||||
|
|
|
@ -8,15 +8,15 @@
|
||||||
<tr><th>#</th><th>Priority</th><th>Project</th><th>Job</th><th>System</th><th>Timestamp</th><th>Description</th></tr>
|
<tr><th>#</th><th>Priority</th><th>Project</th><th>Job</th><th>System</th><th>Timestamp</th><th>Description</th></tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
[% FOREACH job IN jobs -%]
|
[% FOREACH build IN scheduled -%]
|
||||||
<tr [% IF job.busy %]class="runningJob"[% END %] >
|
<tr [% IF build.schedulingInfo.busy %]class="runningJob"[% END %] >
|
||||||
<td>[% job.id %]</td>
|
<td><a href="[% c.uri_for('/build' build.id) %]">[% build.id %]</a></td>
|
||||||
<td>[% job.priority %]</td>
|
<td>[% build.schedulingInfo.priority %]</td>
|
||||||
<td><tt>[% job.project.name %]</tt></td>
|
<td><tt>[% build.project.name %]</tt></td>
|
||||||
<td><tt>[% job.jobset.name %]</tt></td>
|
<td><tt>[% build.jobset.name %]</tt></td>
|
||||||
<td><tt>[% job.system %]</tt></td>
|
<td><tt>[% build.system %]</tt></td>
|
||||||
<td>[% date.format(job.timestamp, '%Y-%m-%d %H:%M:%S') %]</td>
|
<td>[% date.format(build.timestamp, '%Y-%m-%d %H:%M:%S') %]</td>
|
||||||
<td>[% job.description %]</td>
|
<td>[% build.description %]</td>
|
||||||
</tr>
|
</tr>
|
||||||
[% END -%]
|
[% END -%]
|
||||||
</tbody>
|
</tbody>
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
<td>
|
<td>
|
||||||
[% IF build.buildstatus == 0 %]
|
[% IF build.resultInfo.buildstatus == 0 %]
|
||||||
<img src="/static/images/success.gif" />
|
<img src="/static/images/success.gif" />
|
||||||
[% ELSE %]
|
[% ELSE %]
|
||||||
<img src="/static/images/failure.gif" />
|
<img src="/static/images/failure.gif" />
|
||||||
|
|
77
src/build.pl
77
src/build.pl
|
@ -16,11 +16,11 @@ sub isValidPath {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
sub buildJob {
|
sub doBuild {
|
||||||
my ($job) = @_;
|
my ($build) = @_;
|
||||||
|
|
||||||
my $drvPath = $job->drvpath;
|
my $drvPath = $build->drvpath;
|
||||||
my $outPath = $job->outpath;
|
my $outPath = $build->outpath;
|
||||||
|
|
||||||
my $isCachedBuild = 1;
|
my $isCachedBuild = 1;
|
||||||
my $outputCreated = 1; # i.e., the Nix build succeeded (but it could be a positive failure)
|
my $outputCreated = 1; # i.e., the Nix build succeeded (but it could be a positive failure)
|
||||||
|
@ -52,27 +52,17 @@ sub buildJob {
|
||||||
}
|
}
|
||||||
|
|
||||||
$db->txn_do(sub {
|
$db->txn_do(sub {
|
||||||
my $build = $db->resultset('Builds')->create(
|
$build->finished(1);
|
||||||
{ timestamp => time()
|
$build->timestamp(time());
|
||||||
, project => $job->project->name
|
$build->update;
|
||||||
, jobset => $job->jobset->name
|
|
||||||
, attrname => $job->attrname
|
$db->resultset('Buildresultinfo')->create(
|
||||||
, description => $job->description
|
{ id => $build->id
|
||||||
, drvpath => $drvPath
|
|
||||||
, outpath => $outPath
|
|
||||||
, iscachedbuild => $isCachedBuild
|
, iscachedbuild => $isCachedBuild
|
||||||
, buildstatus => $buildStatus
|
, buildstatus => $buildStatus
|
||||||
, starttime => $startTime
|
, starttime => $startTime
|
||||||
, stoptime => $stopTime
|
, stoptime => $stopTime
|
||||||
, system => $job->system
|
|
||||||
});
|
});
|
||||||
print " build ID = ", $build->id, "\n";
|
|
||||||
|
|
||||||
foreach my $input ($job->inputs) {
|
|
||||||
$input->job(undef);
|
|
||||||
$input->build($build->id);
|
|
||||||
$input->update;
|
|
||||||
}
|
|
||||||
|
|
||||||
my $logPath = "/nix/var/log/nix/drvs/" . basename $drvPath;
|
my $logPath = "/nix/var/log/nix/drvs/" . basename $drvPath;
|
||||||
if (-e $logPath) {
|
if (-e $logPath) {
|
||||||
|
@ -125,47 +115,44 @@ sub buildJob {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$job->delete;
|
$build->schedulingInfo->delete;
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
print "STOP ", time, "\n";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
my $jobId = $ARGV[0] or die;
|
my $buildId = $ARGV[0] or die;
|
||||||
print "building job $jobId\n";
|
print "performing build $buildId\n";
|
||||||
|
|
||||||
# Lock the job. If necessary, steal the lock from the parent process
|
# Lock the build. If necessary, steal the lock from the parent
|
||||||
# (runner.pl). This is so that if the runner dies, the children
|
# process (runner.pl). This is so that if the runner dies, the
|
||||||
# (i.e. the job builders) can continue to run and won't have the lock
|
# children (i.e. the build.pl instances) can continue to run and won't
|
||||||
# taken away.
|
# have the lock taken away.
|
||||||
my $job;
|
my $build;
|
||||||
$db->txn_do(sub {
|
$db->txn_do(sub {
|
||||||
($job) = $db->resultset('Jobs')->search({ id => $jobId });
|
($build) = $db->resultset('Builds')->search({id => $buildId});
|
||||||
die "job $jobId doesn't exist" unless defined $job;
|
die "build $buildId doesn't exist" unless defined $build;
|
||||||
if ($job->busy != 0 && $job->locker != getppid) {
|
if ($build->schedulingInfo->busy != 0 && $build->schedulingInfo->locker != getppid) {
|
||||||
die "job $jobId is already being built";
|
die "build $buildId is already being built";
|
||||||
}
|
}
|
||||||
$job->busy(1);
|
$build->schedulingInfo->busy(1);
|
||||||
$job->locker($$);
|
$build->schedulingInfo->locker($$);
|
||||||
$job->update;
|
$build->schedulingInfo->update;
|
||||||
});
|
});
|
||||||
|
|
||||||
die unless $job;
|
die unless $build;
|
||||||
|
|
||||||
# Build the job. If it throws an error, unlock the job so that it can
|
# Do the build. If it throws an error, unlock the build so that it
|
||||||
# be retried.
|
# can be retried.
|
||||||
eval {
|
eval {
|
||||||
print "BUILD\n";
|
print "BUILD\n";
|
||||||
buildJob $job;
|
doBuild $build;
|
||||||
print "DONE\n";
|
print "DONE\n";
|
||||||
};
|
};
|
||||||
if ($@) {
|
if ($@) {
|
||||||
warn $@;
|
warn $@;
|
||||||
$db->txn_do(sub {
|
$db->txn_do(sub {
|
||||||
$job->busy(0);
|
$build->schedulingInfo->busy(0);
|
||||||
$job->locker($$);
|
$build->schedulingInfo->locker($$);
|
||||||
$job->update;
|
$build->schedulingInfo->update;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
125
src/hydra.sql
125
src/hydra.sql
|
@ -1,6 +1,15 @@
|
||||||
create table builds (
|
-- This table contains all builds, either scheduled or finished. For
|
||||||
|
-- scheduled builds, additional info (such as the priority) can be
|
||||||
|
-- found in the BuildSchedulingInfo table. For finished builds,
|
||||||
|
-- additional info (such as the logs, build products, etc.) can be
|
||||||
|
-- found in several tables, such as BuildResultInfo, BuildLogs and
|
||||||
|
-- BuildProducts.
|
||||||
|
create table Builds (
|
||||||
id integer primary key autoincrement not null,
|
id integer primary key autoincrement not null,
|
||||||
timestamp integer not null, -- time this build was added to the db (in Unix time)
|
|
||||||
|
finished integer not null, -- 0 = scheduled, 1 = finished
|
||||||
|
|
||||||
|
timestamp integer not null, -- time this build was scheduled / finished building
|
||||||
|
|
||||||
-- Info about the inputs.
|
-- Info about the inputs.
|
||||||
project text not null, -- !!! foreign key
|
project text not null, -- !!! foreign key
|
||||||
|
@ -11,25 +20,51 @@ create table builds (
|
||||||
description text,
|
description text,
|
||||||
drvPath text not null,
|
drvPath text not null,
|
||||||
outPath text not null,
|
outPath text not null,
|
||||||
isCachedBuild integer not null, -- boolean
|
|
||||||
buildStatus integer, -- 0 = succeeded, 1 = Nix build failure, 2 = positive build failure
|
|
||||||
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) references Projects(name), -- ignored by sqlite
|
||||||
foreign key (project, jobset) references jobsets(project, name) -- ignored by sqlite
|
foreign key (project, jobset) references Jobsets(project, name) -- ignored by sqlite
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
-- Inputs of jobs/builds.
|
-- Info for a scheduled build.
|
||||||
create table inputs (
|
create table BuildSchedulingInfo (
|
||||||
|
id integer primary key not null,
|
||||||
|
|
||||||
|
priority integer not null default 0,
|
||||||
|
|
||||||
|
busy integer not null default 0, -- true means someone is building this job now
|
||||||
|
locker text not null default '', -- !!! hostname/pid of the process building this job?
|
||||||
|
|
||||||
|
logfile text, -- if busy, the path of the logfile
|
||||||
|
|
||||||
|
foreign key (id) references Builds(id) on delete cascade -- ignored by sqlite
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
-- Info for a finished build.
|
||||||
|
create table BuildResultInfo (
|
||||||
|
id integer primary key not null,
|
||||||
|
|
||||||
|
isCachedBuild integer not null, -- boolean
|
||||||
|
|
||||||
|
buildStatus integer, -- 0 = succeeded, 1 = Nix build failure, 2 = positive build failure
|
||||||
|
|
||||||
|
errorMsg text, -- error message in case of a Nix failure
|
||||||
|
|
||||||
|
startTime integer, -- in Unix time, 0 = used cached build result
|
||||||
|
stopTime integer,
|
||||||
|
|
||||||
|
foreign key (id) references Builds(id) on delete cascade -- ignored by sqlite
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
-- Inputs of builds.
|
||||||
|
create table BuildInputs (
|
||||||
id integer primary key autoincrement not null,
|
id integer primary key autoincrement not null,
|
||||||
|
|
||||||
-- Which job or build this input belongs to. Exactly one must be non-null.
|
-- Which build this input belongs to.
|
||||||
build integer,
|
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,
|
name text not null,
|
||||||
|
@ -42,29 +77,28 @@ create table inputs (
|
||||||
|
|
||||||
path text,
|
path text,
|
||||||
|
|
||||||
foreign key (build) references builds(id) -- ignored by sqlite
|
foreign key (build) references Builds(id) on delete cascade, -- ignored by sqlite
|
||||||
foreign key (job) references jobs(id) -- ignored by sqlite
|
foreign key (dependency) references Builds(id) -- ignored by sqlite
|
||||||
foreign key (dependency) references builds(id) -- ignored by sqlite
|
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
create table buildProducts (
|
create table BuildProducts (
|
||||||
build integer not null,
|
build integer not null,
|
||||||
path text not null,
|
path text not null,
|
||||||
type text not null, -- "nix-build", "file", "doc", "report", ...
|
type text not null, -- "nix-build", "file", "doc", "report", ...
|
||||||
subtype text not null, -- "source-dist", "rpm", ...
|
subtype text not null, -- "source-dist", "rpm", ...
|
||||||
primary key (build, path),
|
primary key (build, path),
|
||||||
foreign key (build) references builds(id) on delete cascade -- ignored by sqlite
|
foreign key (build) references Builds(id) on delete cascade -- ignored by sqlite
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
create table buildLogs (
|
create table BuildLogs (
|
||||||
build integer not null,
|
build integer not null,
|
||||||
logPhase text not null,
|
logPhase text not null,
|
||||||
path text not null,
|
path text not null,
|
||||||
type text not null,
|
type text not null,
|
||||||
primary key (build, logPhase),
|
primary key (build, logPhase),
|
||||||
foreign key (build) references builds(id) on delete cascade -- ignored by sqlite
|
foreign key (build) references Builds(id) on delete cascade -- ignored by sqlite
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
|
@ -72,13 +106,15 @@ create table buildLogs (
|
||||||
create trigger cascadeBuildDeletion
|
create trigger cascadeBuildDeletion
|
||||||
before delete on builds
|
before delete on builds
|
||||||
for each row begin
|
for each row begin
|
||||||
--delete from buildInputs where build = old.id;
|
delete from BuildSchedulingInfo where id = old.id;
|
||||||
delete from buildLogs where build = old.id;
|
delete from BuildResultInfo where id = old.id;
|
||||||
delete from buildProducts where build = old.id;
|
delete from BuildInputs where build = old.id;
|
||||||
|
delete from BuildLogs where build = old.id;
|
||||||
|
delete from BuildProducts where build = old.id;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
||||||
create table projects (
|
create table Projects (
|
||||||
name text primary key not null
|
name text primary key not null
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -86,29 +122,29 @@ create table projects (
|
||||||
-- A jobset consists of a set of inputs (e.g. SVN repositories), one
|
-- A jobset consists of a set of inputs (e.g. SVN repositories), one
|
||||||
-- of which contains a Nix expression containing an attribute set
|
-- of which contains a Nix expression containing an attribute set
|
||||||
-- describing build jobs.
|
-- describing build jobs.
|
||||||
create table jobsets (
|
create table Jobsets (
|
||||||
name text not null,
|
name text not null,
|
||||||
project text not null,
|
project text not null,
|
||||||
description text,
|
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
|
nixExprPath text not null, -- relative path of the Nix expression
|
||||||
primary key (project, name),
|
primary key (project, name),
|
||||||
foreign key (project) references projects(name) on delete cascade, -- ignored by sqlite
|
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,
|
project text not null,
|
||||||
jobset text not null,
|
jobset text not null,
|
||||||
name text not null,
|
name text not null,
|
||||||
type text not null, -- "svn", "cvs", "path", "file", "string"
|
type text not null, -- "svn", "cvs", "path", "file", "string"
|
||||||
primary key (project, jobset, name),
|
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,
|
project text not null,
|
||||||
jobset text not null,
|
jobset text not null,
|
||||||
input text not null,
|
input text not null,
|
||||||
|
@ -121,30 +157,5 @@ create table jobsetInputAlts (
|
||||||
value text, -- for type == 'string'
|
value text, -- for type == 'string'
|
||||||
|
|
||||||
primary key (project, jobset, input, altnr),
|
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
|
||||||
);
|
|
||||||
|
|
||||||
|
|
||||||
create table jobs (
|
|
||||||
id integer primary key autoincrement not null,
|
|
||||||
timestamp integer not null, -- time this build was added to the db (in Unix time)
|
|
||||||
|
|
||||||
priority integer not null default 0,
|
|
||||||
|
|
||||||
busy integer not null default 0, -- true means someone is building this job now
|
|
||||||
locker text not null default '', -- !!! hostname/pid of the process building this job?
|
|
||||||
|
|
||||||
-- Info about the inputs.
|
|
||||||
project 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,
|
|
||||||
|
|
||||||
foreign key (project) references projects(name), -- ignored by sqlite
|
|
||||||
foreign key (project, jobset) references jobsets(project, name) -- ignored by sqlite
|
|
||||||
);
|
);
|
||||||
|
|
|
@ -12,14 +12,16 @@ $db->storage->dbh->do("PRAGMA synchronous = OFF;");
|
||||||
|
|
||||||
# Unlock jobs whose building process has died.
|
# Unlock jobs whose building process has died.
|
||||||
$db->txn_do(sub {
|
$db->txn_do(sub {
|
||||||
my @jobs = $db->resultset('Jobs')->search({ busy => 1 });
|
my @jobs = $db->resultset('Builds')->search(
|
||||||
|
{finished => 0, busy => 1}, {join => 'schedulingInfo'});
|
||||||
foreach my $job (@jobs) {
|
foreach my $job (@jobs) {
|
||||||
my $pid = $job->locker;
|
print $job, "\n";
|
||||||
|
my $pid = $job->schedulingInfo->locker;
|
||||||
if (kill(0, $pid) != 1) { # see if we can signal the process
|
if (kill(0, $pid) != 1) { # see if we can signal the process
|
||||||
print "job ", $job->id, " pid $pid died, unlocking\n";
|
print "job ", $job->id, " pid $pid died, unlocking\n";
|
||||||
$job->busy(0);
|
$job->schedulingInfo->busy(0);
|
||||||
$job->locker("");
|
$job->schedulingInfo->locker("");
|
||||||
$job->update;
|
$job->schedulingInfo->update;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -32,15 +34,17 @@ sub checkJobs {
|
||||||
|
|
||||||
$db->txn_do(sub {
|
$db->txn_do(sub {
|
||||||
|
|
||||||
my @jobs = $db->resultset('Jobs')->search({ busy => 0 }, {order_by => ["priority", "timestamp"]});
|
my @jobs = $db->resultset('Builds')->search(
|
||||||
|
{finished => 0, busy => 0},
|
||||||
|
{join => 'schedulingInfo', order_by => ["priority", "timestamp"]});
|
||||||
|
|
||||||
print "# of available jobs: ", scalar(@jobs), "\n";
|
print "# of available jobs: ", scalar(@jobs), "\n";
|
||||||
|
|
||||||
if (scalar @jobs > 0) {
|
if (scalar @jobs > 0) {
|
||||||
$job = $jobs[0];
|
$job = $jobs[0];
|
||||||
$job->busy(1);
|
$job->schedulingInfo->busy(1);
|
||||||
$job->locker($$);
|
$job->schedulingInfo->locker($$);
|
||||||
$job->update;
|
$job->schedulingInfo->update;
|
||||||
}
|
}
|
||||||
|
|
||||||
});
|
});
|
||||||
|
@ -66,9 +70,9 @@ sub checkJobs {
|
||||||
if ($@) {
|
if ($@) {
|
||||||
warn $@;
|
warn $@;
|
||||||
$db->txn_do(sub {
|
$db->txn_do(sub {
|
||||||
$job->busy(0);
|
$job->schedulingInfo->busy(0);
|
||||||
$job->locker($$);
|
$job->schedulingInfo->locker($$);
|
||||||
$job->update;
|
$job->schedulingInfo->update;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -67,24 +67,15 @@ sub checkJob {
|
||||||
{ project => $project->name, jobset => $jobset->name
|
{ project => $project->name, jobset => $jobset->name
|
||||||
, attrname => $jobName, outPath => $outPath })) > 0)
|
, attrname => $jobName, outPath => $outPath })) > 0)
|
||||||
{
|
{
|
||||||
print " already done\n";
|
print " already scheduled/done\n";
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (scalar($db->resultset('Jobs')->search(
|
|
||||||
{ project => $project->name, jobset => $jobset->name
|
|
||||||
, attrname => $jobName, outPath => $outPath })) > 0)
|
|
||||||
{
|
|
||||||
print " already queued\n";
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
print " adding to queue\n";
|
print " adding to queue\n";
|
||||||
my $job = $db->resultset('Jobs')->create(
|
|
||||||
{ timestamp => time()
|
my $build = $db->resultset('Builds')->create(
|
||||||
, priority => 0
|
{ finished => 0
|
||||||
, busy => 0
|
, timestamp => time()
|
||||||
, locker => ""
|
|
||||||
, project => $project->name
|
, project => $project->name
|
||||||
, jobset => $jobset->name
|
, jobset => $jobset->name
|
||||||
, attrname => $jobName
|
, attrname => $jobName
|
||||||
|
@ -94,10 +85,17 @@ sub checkJob {
|
||||||
, system => $job->{system}
|
, system => $job->{system}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
$db->resultset('Buildschedulinginfo')->create(
|
||||||
|
{ id => $build->id
|
||||||
|
, priority => 0
|
||||||
|
, busy => 0
|
||||||
|
, locker => ""
|
||||||
|
});
|
||||||
|
|
||||||
foreach my $inputName (keys %{$inputInfo}) {
|
foreach my $inputName (keys %{$inputInfo}) {
|
||||||
my $input = $inputInfo->{$inputName};
|
my $input = $inputInfo->{$inputName};
|
||||||
$db->resultset('Inputs')->create(
|
$db->resultset('Buildinputs')->create(
|
||||||
{ job => $job->id
|
{ build => $build->id
|
||||||
, name => $inputName
|
, name => $inputName
|
||||||
, type => $input->{type}
|
, type => $input->{type}
|
||||||
, uri => $input->{uri}
|
, uri => $input->{uri}
|
||||||
|
@ -151,8 +149,8 @@ sub checkJobAlternatives {
|
||||||
else {
|
else {
|
||||||
|
|
||||||
(my $prevBuild) = $db->resultset('Builds')->search(
|
(my $prevBuild) = $db->resultset('Builds')->search(
|
||||||
{project => $project->name, jobset => $jobset->name, attrname => $argName, buildStatus => 0},
|
{finished => 1, project => $project->name, jobset => $jobset->name, attrname => $argName, buildStatus => 0},
|
||||||
{order_by => "timestamp DESC", rows => 1});
|
{join => 'resultInfo', order_by => "timestamp DESC", rows => 1});
|
||||||
|
|
||||||
if (!defined $prevBuild) {
|
if (!defined $prevBuild) {
|
||||||
# !!! reschedule?
|
# !!! reschedule?
|
||||||
|
|
Loading…
Reference in a new issue