Merge pull request #770 from NixOS/remove-jobs

Remove the Jobs table
This commit is contained in:
Eelco Dolstra 2020-06-01 10:25:41 +02:00 committed by GitHub
commit 750e2e618a
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
26 changed files with 102 additions and 442 deletions

View file

@ -105,7 +105,7 @@
gitAndTools.topGit mercurial darcs subversion bazaar openssl bzip2 libxslt
perlDeps perl final.nix
boost
postgresql95
postgresql_11
(if lib.versionAtLeast lib.version "20.03pre"
then nlohmann_json
else nlohmann_json.override { multipleHeaders = true; })
@ -308,7 +308,7 @@
systemd.services.hydra-send-stats.enable = false;
services.postgresql.enable = true;
services.postgresql.package = pkgs.postgresql95;
services.postgresql.package = pkgs.postgresql_11;
# The following is to work around the following error from hydra-server:
# [error] Caught exception in engine "Cannot determine local time zone"

View file

@ -86,7 +86,7 @@ sub build_GET {
$c->stash->{prevBuilds} = [$c->model('DB::Builds')->search(
{ project => $c->stash->{project}->name
, jobset => $c->stash->{jobset}->name
, job => $c->stash->{job}->name
, job => $c->stash->{job}
, 'me.system' => $build->system
, finished => 1
, buildstatus => 0

View file

@ -24,18 +24,16 @@ sub job : Chained('/') PathPart('job') CaptureArgs(3) {
$c->detach;
}
$c->stash->{job} = $c->stash->{jobset}->jobs->find({ name => $jobName })
or notFound($c, "Job $projectName:$jobsetName:$jobName doesn't exist.");
$c->stash->{project} = $c->stash->{job}->project;
$c->stash->{job} = $jobName;
$c->stash->{project} = $c->stash->{jobset}->project;
}
sub prometheus : Chained('job') PathPart('prometheus') Args(0) {
my ($self, $c) = @_;
my $job = $c->stash->{job};
my $prometheus = Net::Prometheus->new;
my $lastBuild = $job->builds->find(
{ finished => 1 },
my $lastBuild = $c->stash->{jobset}->builds->find(
{ job => $c->stash->{job}, finished => 1 },
{ order_by => 'id DESC', rows => 1, columns => [@buildListColumns] }
);
@ -46,7 +44,7 @@ sub prometheus : Chained('job') PathPart('prometheus') Args(0) {
)->labels(
$c->stash->{project}->name,
$c->stash->{jobset}->name,
$c->stash->{job}->name,
$c->stash->{job},
)->inc($lastBuild->stoptime);
$prometheus->new_gauge(
@ -56,7 +54,7 @@ sub prometheus : Chained('job') PathPart('prometheus') Args(0) {
)->labels(
$c->stash->{project}->name,
$c->stash->{jobset}->name,
$c->stash->{job}->name,
$c->stash->{job},
)->inc($lastBuild->buildstatus > 0);
$c->stash->{'plain'} = { data => $prometheus->render };
@ -65,23 +63,22 @@ sub prometheus : Chained('job') PathPart('prometheus') Args(0) {
sub overview : Chained('job') PathPart('') Args(0) {
my ($self, $c) = @_;
my $job = $c->stash->{job};
$c->stash->{template} = 'job.tt';
$c->stash->{lastBuilds} =
[ $job->builds->search({ finished => 1 },
[ $c->stash->{jobset}->builds->search({ job => $c->stash->{job}, finished => 1 },
{ order_by => 'id DESC', rows => 10, columns => [@buildListColumns] }) ];
$c->stash->{queuedBuilds} = [
$job->builds->search(
{ finished => 0 },
$c->stash->{jobset}->builds->search(
{ job => $c->stash->{job}, finished => 0 },
{ order_by => ["priority DESC", "id"] }
) ];
# If this is an aggregate job, then get its constituents.
my @constituents = $c->model('DB::Builds')->search(
{ aggregate => { -in => $job->builds->search({}, { columns => ["id"], order_by => "id desc", rows => 15 })->as_query } },
{ aggregate => { -in => $c->stash->{jobset}->builds->search({ job => $c->stash->{job} }, { columns => ["id"], order_by => "id desc", rows => 15 })->as_query } },
{ join => 'aggregateconstituents_constituents',
columns => ['id', 'job', 'finished', 'buildstatus'],
+select => ['aggregateconstituents_constituents.aggregate'],
@ -91,10 +88,9 @@ sub overview : Chained('job') PathPart('') Args(0) {
my $aggregates = {};
my %constituentJobs;
foreach my $b (@constituents) {
my $jobName = $b->get_column('job');
$aggregates->{$b->get_column('aggregate')}->{constituents}->{$jobName} =
$aggregates->{$b->get_column('aggregate')}->{constituents}->{$b->job} =
{ id => $b->id, finished => $b->finished, buildstatus => $b->buildstatus };
$constituentJobs{$jobName} = 1;
$constituentJobs{$b->job} = 1;
}
foreach my $agg (keys %$aggregates) {
@ -109,24 +105,23 @@ sub overview : Chained('job') PathPart('') Args(0) {
$c->stash->{starred} = $c->user->starredjobs(
{ project => $c->stash->{project}->name
, jobset => $c->stash->{jobset}->name
, job => $c->stash->{job}->name
, job => $c->stash->{job}
})->count == 1 if $c->user_exists;
}
sub metrics_tab : Chained('job') PathPart('metrics-tab') Args(0) {
my ($self, $c) = @_;
my $job = $c->stash->{job};
$c->stash->{template} = 'job-metrics-tab.tt';
$c->stash->{metrics} = [ $job->buildmetrics->search(
{ }, { select => ["name"], distinct => 1, order_by => "name", }) ];
$c->stash->{metrics} = [ $c->stash->{jobset}->buildmetrics->search(
{ job => $c->stash->{job} }, { select => ["name"], distinct => 1, order_by => "name", }) ];
}
sub build_times : Chained('job') PathPart('build-times') Args(0) {
my ($self, $c) = @_;
my @res = $c->stash->{job}->builds->search(
{ finished => 1, buildstatus => 0, closuresize => { '!=', 0 } },
my @res = $c->stash->{jobset}->builds->search(
{ job => $c->stash->{job}, finished => 1, buildstatus => 0, closuresize => { '!=', 0 } },
{ join => "actualBuildStep"
, "+select" => ["actualBuildStep.stoptime - actualBuildStep.starttime"]
, "+as" => ["actualBuildTime"],
@ -137,8 +132,8 @@ sub build_times : Chained('job') PathPart('build-times') Args(0) {
sub closure_sizes : Chained('job') PathPart('closure-sizes') Args(0) {
my ($self, $c) = @_;
my @res = $c->stash->{job}->builds->search(
{ finished => 1, buildstatus => 0, closuresize => { '!=', 0 } },
my @res = $c->stash->{jobset}->builds->search(
{ job => $c->stash->{job}, finished => 1, buildstatus => 0, closuresize => { '!=', 0 } },
{ order_by => "id", columns => [ "id", "timestamp", "closuresize" ] });
$self->status_ok($c, entity => [ map { { id => $_->id, timestamp => $_ ->timestamp, value => $_->closuresize } } @res ]);
}
@ -146,8 +141,8 @@ sub closure_sizes : Chained('job') PathPart('closure-sizes') Args(0) {
sub output_sizes : Chained('job') PathPart('output-sizes') Args(0) {
my ($self, $c) = @_;
my @res = $c->stash->{job}->builds->search(
{ finished => 1, buildstatus => 0, size => { '!=', 0 } },
my @res = $c->stash->{jobset}->builds->search(
{ job => $c->stash->{job}, finished => 1, buildstatus => 0, size => { '!=', 0 } },
{ order_by => "id", columns => [ "id", "timestamp", "size" ] });
$self->status_ok($c, entity => [ map { { id => $_->id, timestamp => $_ ->timestamp, value => $_->size } } @res ]);
}
@ -159,8 +154,8 @@ sub metric : Chained('job') PathPart('metric') Args(1) {
$c->stash->{template} = 'metric.tt';
$c->stash->{metricName} = $metricName;
my @res = $c->stash->{job}->buildmetrics->search(
{ name => $metricName },
my @res = $c->stash->{jobset}->buildmetrics->search(
{ job => $c->stash->{job}, name => $metricName },
{ order_by => "timestamp", columns => [ "build", "name", "timestamp", "value", "unit" ] });
$self->status_ok($c, entity => [ map { { id => $_->get_column("build"), timestamp => $_ ->timestamp, value => $_->value, unit => $_->unit } } @res ]);
@ -170,11 +165,11 @@ sub metric : Chained('job') PathPart('metric') Args(1) {
# Hydra::Base::Controller::ListBuilds needs this.
sub get_builds : Chained('job') PathPart('') CaptureArgs(0) {
my ($self, $c) = @_;
$c->stash->{allBuilds} = $c->stash->{job}->builds;
$c->stash->{allBuilds} = $c->stash->{jobset}->builds->search({ job => $c->stash->{job} });
$c->stash->{latestSucceeded} = $c->model('DB')->resultset('LatestSucceededForJob')
->search({}, {bind => [$c->stash->{jobset}->id, $c->stash->{job}->name]});
->search({}, {bind => [$c->stash->{jobset}->id, $c->stash->{job}]});
$c->stash->{channelBaseName} =
$c->stash->{project}->name . "-" . $c->stash->{jobset}->name . "-" . $c->stash->{job}->name;
$c->stash->{project}->name . "-" . $c->stash->{jobset}->name . "-" . $c->stash->{job};
}
@ -185,7 +180,7 @@ sub star : Chained('job') PathPart('star') Args(0) {
my $args =
{ project => $c->stash->{project}->name
, jobset => $c->stash->{jobset}->name
, job => $c->stash->{job}->name
, job => $c->stash->{job}
};
if ($c->request->params->{star} eq "1") {
$c->user->starredjobs->update_or_create($args);

View file

@ -459,16 +459,16 @@ sub search :Local Args(0) {
},
{ order_by => ["project", "name"], join => ["project"] } ) ];
$c->stash->{jobs} = [ $c->model('DB::Jobs')->search(
{ "me.name" => { ilike => "%$query%" }
$c->stash->{jobs} = [ $c->model('DB::Builds')->search(
{ "job" => { ilike => "%$query%" }
, "project.hidden" => 0
, "jobset.hidden" => 0
, iscurrent => 1
},
{ order_by => ["enabled_ desc", "project", "jobset", "name"], join => ["project", "jobset"]
, "+select" => [\ "(project.enabled = 1 and jobset.enabled = 1 and exists (select 1 from Builds where project = project.name and jobset = jobset.name and job = me.name and iscurrent = 1)) as enabled_"]
, "+as" => ["enabled"]
{ order_by => ["project", "jobset", "job"], join => ["project", "jobset"]
, rows => $c->stash->{limit} + 1
} ) ];
} )
];
# Perform build search in separate queries to prevent seq scan on buildoutputs table.
$c->stash->{builds} = [ $c->model('DB::Builds')->search(

View file

@ -339,10 +339,10 @@ sub dashboard :Chained('dashboard_base') :PathPart('') :Args(0) {
# Get the N most recent builds for each starred job.
$c->stash->{starredJobs} = [];
foreach my $j ($c->stash->{user}->starredjobs->search({}, { order_by => ['project', 'jobset', 'job'] })) {
my @builds = $j->job->builds->search(
{ },
my @builds = $j->jobset->builds->search(
{ job => $j->job },
{ rows => 20, order_by => "id desc" });
push @{$c->stash->{starredJobs}}, { job => $j->job, builds => [@builds] };
push @{$c->stash->{starredJobs}}, { job => $j, builds => [@builds] };
}
}

View file

@ -46,7 +46,7 @@ sub getBuild {
sub getPreviousBuild {
my ($build) = @_;
return undef if !defined $build;
return $build->job->builds->search(
return $build->jobset->builds->search(
{ finished => 1
, system => $build->system
, 'me.id' => { '<' => $build->id }

View file

@ -71,7 +71,6 @@ __PACKAGE__->table("buildmetrics");
=head2 job
data_type: 'text'
is_foreign_key: 1
is_nullable: 0
=head2 timestamp
@ -95,7 +94,7 @@ __PACKAGE__->add_columns(
"jobset",
{ data_type => "text", is_foreign_key => 1, is_nullable => 0 },
"job",
{ data_type => "text", is_foreign_key => 1, is_nullable => 0 },
{ data_type => "text", is_nullable => 0 },
"timestamp",
{ data_type => "integer", is_nullable => 0 },
);
@ -131,21 +130,6 @@ __PACKAGE__->belongs_to(
{ is_deferrable => 0, on_delete => "CASCADE", on_update => "NO ACTION" },
);
=head2 job
Type: belongs_to
Related object: L<Hydra::Schema::Jobs>
=cut
__PACKAGE__->belongs_to(
"job",
"Hydra::Schema::Jobs",
{ jobset => "jobset", name => "job", project => "project" },
{ is_deferrable => 0, on_delete => "NO ACTION", on_update => "CASCADE" },
);
=head2 jobset
Type: belongs_to
@ -177,8 +161,8 @@ __PACKAGE__->belongs_to(
);
# Created by DBIx::Class::Schema::Loader v0.07049 @ 2020-02-06 12:22:36
# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:Roy7h/K9u7DQOzet4B1sbA
# Created by DBIx::Class::Schema::Loader v0.07049 @ 2020-05-27 17:40:41
# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:AYUVs6RdefFKw+g9Yxcu/A
sub json_hint {
return { columns => ['value', 'unit'] };

View file

@ -73,7 +73,6 @@ __PACKAGE__->table("builds");
=head2 job
data_type: 'text'
is_foreign_key: 1
is_nullable: 0
=head2 nixname
@ -224,7 +223,7 @@ __PACKAGE__->add_columns(
"jobset_id",
{ data_type => "integer", is_foreign_key => 1, is_nullable => 0 },
"job",
{ data_type => "text", is_foreign_key => 1, is_nullable => 0 },
{ data_type => "text", is_nullable => 0 },
"nixname",
{ data_type => "text", is_nullable => 1 },
"description",
@ -439,21 +438,6 @@ __PACKAGE__->has_many(
undef,
);
=head2 job
Type: belongs_to
Related object: L<Hydra::Schema::Jobs>
=cut
__PACKAGE__->belongs_to(
"job",
"Hydra::Schema::Jobs",
{ jobset => "jobset", name => "job", project => "project" },
{ is_deferrable => 0, on_delete => "NO ACTION", on_update => "CASCADE" },
);
=head2 jobset
Type: belongs_to
@ -558,8 +542,8 @@ __PACKAGE__->many_to_many(
);
# Created by DBIx::Class::Schema::Loader v0.07049 @ 2020-05-06 12:32:57
# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:3IyFj/9Zf/hvmhBY4U/IBQ
# Created by DBIx::Class::Schema::Loader v0.07049 @ 2020-05-27 17:40:41
# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:RIKKFfcKXFWIUeM8ma++iw
__PACKAGE__->has_many(
"dependents",

View file

@ -1,216 +0,0 @@
use utf8;
package Hydra::Schema::Jobs;
# Created by DBIx::Class::Schema::Loader
# DO NOT MODIFY THE FIRST PART OF THIS FILE
=head1 NAME
Hydra::Schema::Jobs
=cut
use strict;
use warnings;
use base 'DBIx::Class::Core';
=head1 COMPONENTS LOADED
=over 4
=item * L<Hydra::Component::ToJSON>
=back
=cut
__PACKAGE__->load_components("+Hydra::Component::ToJSON");
=head1 TABLE: C<jobs>
=cut
__PACKAGE__->table("jobs");
=head1 ACCESSORS
=head2 project
data_type: 'text'
is_foreign_key: 1
is_nullable: 0
=head2 jobset
data_type: 'text'
is_foreign_key: 1
is_nullable: 0
=head2 jobset_id
data_type: 'integer'
is_foreign_key: 1
is_nullable: 0
=head2 name
data_type: 'text'
is_nullable: 0
=cut
__PACKAGE__->add_columns(
"project",
{ data_type => "text", is_foreign_key => 1, is_nullable => 0 },
"jobset",
{ data_type => "text", is_foreign_key => 1, is_nullable => 0 },
"jobset_id",
{ data_type => "integer", is_foreign_key => 1, is_nullable => 0 },
"name",
{ data_type => "text", is_nullable => 0 },
);
=head1 PRIMARY KEY
=over 4
=item * L</project>
=item * L</jobset>
=item * L</name>
=back
=cut
__PACKAGE__->set_primary_key("project", "jobset", "name");
=head1 RELATIONS
=head2 buildmetrics
Type: has_many
Related object: L<Hydra::Schema::BuildMetrics>
=cut
__PACKAGE__->has_many(
"buildmetrics",
"Hydra::Schema::BuildMetrics",
{
"foreign.job" => "self.name",
"foreign.jobset" => "self.jobset",
"foreign.project" => "self.project",
},
undef,
);
=head2 builds
Type: has_many
Related object: L<Hydra::Schema::Builds>
=cut
__PACKAGE__->has_many(
"builds",
"Hydra::Schema::Builds",
{
"foreign.job" => "self.name",
"foreign.jobset" => "self.jobset",
"foreign.project" => "self.project",
},
undef,
);
=head2 jobset
Type: belongs_to
Related object: L<Hydra::Schema::Jobsets>
=cut
__PACKAGE__->belongs_to(
"jobset",
"Hydra::Schema::Jobsets",
{ id => "jobset_id" },
{ is_deferrable => 0, on_delete => "CASCADE", on_update => "NO ACTION" },
);
=head2 jobset_project_jobset
Type: belongs_to
Related object: L<Hydra::Schema::Jobsets>
=cut
__PACKAGE__->belongs_to(
"jobset_project_jobset",
"Hydra::Schema::Jobsets",
{ name => "jobset", project => "project" },
{ is_deferrable => 0, on_delete => "CASCADE", on_update => "CASCADE" },
);
=head2 project
Type: belongs_to
Related object: L<Hydra::Schema::Projects>
=cut
__PACKAGE__->belongs_to(
"project",
"Hydra::Schema::Projects",
{ name => "project" },
{ is_deferrable => 0, on_delete => "CASCADE", on_update => "CASCADE" },
);
=head2 starredjobs
Type: has_many
Related object: L<Hydra::Schema::StarredJobs>
=cut
__PACKAGE__->has_many(
"starredjobs",
"Hydra::Schema::StarredJobs",
{
"foreign.job" => "self.name",
"foreign.jobset" => "self.jobset",
"foreign.project" => "self.project",
},
undef,
);
# Created by DBIx::Class::Schema::Loader v0.07049 @ 2020-02-06 12:33:28
# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:C5Tyh8Ke4yC6q7KIFVOHcQ
=head2 builds
Type: has_many
Related object: L<Hydra::Sc2hema::Builds>
=cut
__PACKAGE__->has_many(
"builds",
"Hydra::Schema::Builds",
{
"foreign.job" => "self.name",
"foreign.jobset_id" => "self.jobset_id",
},
undef,
);
1;

View file

@ -201,8 +201,8 @@ __PACKAGE__->belongs_to(
);
# Created by DBIx::Class::Schema::Loader v0.07049 @ 2020-02-09 15:21:11
# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:Ar6GRni8AcAQmuZyg6tFKw
# Created by DBIx::Class::Schema::Loader v0.07049 @ 2020-05-27 17:40:41
# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:M61ikfnjORU7jDAH8P/j7w
__PACKAGE__->has_many(
"buildIds",

View file

@ -290,39 +290,6 @@ __PACKAGE__->has_many(
undef,
);
=head2 jobs_jobset_ids
Type: has_many
Related object: L<Hydra::Schema::Jobs>
=cut
__PACKAGE__->has_many(
"jobs_jobset_ids",
"Hydra::Schema::Jobs",
{ "foreign.jobset_id" => "self.id" },
undef,
);
=head2 jobs_project_jobsets
Type: has_many
Related object: L<Hydra::Schema::Jobs>
=cut
__PACKAGE__->has_many(
"jobs_project_jobsets",
"Hydra::Schema::Jobs",
{
"foreign.jobset" => "self.name",
"foreign.project" => "self.project",
},
undef,
);
=head2 jobsetevals
Type: has_many
@ -408,8 +375,8 @@ __PACKAGE__->has_many(
);
# Created by DBIx::Class::Schema::Loader v0.07049 @ 2020-02-09 15:32:17
# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:P8+t7rgpOqkGwRdM2b+3Bw
# Created by DBIx::Class::Schema::Loader v0.07049 @ 2020-05-27 17:40:41
# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:aDW78MCelU/ma953aTcHvA
=head2 builds

View file

@ -157,21 +157,6 @@ __PACKAGE__->has_many(
undef,
);
=head2 jobs
Type: has_many
Related object: L<Hydra::Schema::Jobs>
=cut
__PACKAGE__->has_many(
"jobs",
"Hydra::Schema::Jobs",
{ "foreign.project" => "self.name" },
undef,
);
=head2 jobsetevals
Type: has_many
@ -273,8 +258,8 @@ Composing rels: L</projectmembers> -> username
__PACKAGE__->many_to_many("usernames", "projectmembers", "username");
# Created by DBIx::Class::Schema::Loader v0.07049 @ 2020-05-06 12:32:57
# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:dEIVgrFGilPfITprs6nYuA
# Created by DBIx::Class::Schema::Loader v0.07049 @ 2020-05-27 17:40:41
# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:iBGJjFWiI9Wy9zwT7xGOEA
my %hint = (
columns => [

View file

@ -56,7 +56,6 @@ __PACKAGE__->table("starredjobs");
=head2 job
data_type: 'text'
is_foreign_key: 1
is_nullable: 0
=cut
@ -69,7 +68,7 @@ __PACKAGE__->add_columns(
"jobset",
{ data_type => "text", is_foreign_key => 1, is_nullable => 0 },
"job",
{ data_type => "text", is_foreign_key => 1, is_nullable => 0 },
{ data_type => "text", is_nullable => 0 },
);
=head1 PRIMARY KEY
@ -92,21 +91,6 @@ __PACKAGE__->set_primary_key("username", "project", "jobset", "job");
=head1 RELATIONS
=head2 job
Type: belongs_to
Related object: L<Hydra::Schema::Jobs>
=cut
__PACKAGE__->belongs_to(
"job",
"Hydra::Schema::Jobs",
{ jobset => "jobset", name => "job", project => "project" },
{ is_deferrable => 0, on_delete => "CASCADE", on_update => "CASCADE" },
);
=head2 jobset
Type: belongs_to
@ -153,8 +137,8 @@ __PACKAGE__->belongs_to(
);
# Created by DBIx::Class::Schema::Loader v0.07049 @ 2020-02-06 12:22:36
# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:fw4FfzmOhzDk0ZoSuNr2ww
# Created by DBIx::Class::Schema::Loader v0.07049 @ 2020-05-27 17:36:07
# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:RRDQ6UQL/bjXPD+HO1s5ug
# You can replace this text with custom code or comments, and it will be preserved on regeneration

View file

@ -37,12 +37,8 @@ sub stripSSHUser {
# Check whether the given job is a member of the most recent jobset
# evaluation.
sub jobExists {
my ($self, $c, $job) = @_;
my $latestEval = $job->jobset->jobsetevals->search(
{ hasnewbuilds => 1},
{ rows => 1, order_by => ["id desc"] })->single;
return 0 if !defined $latestEval; # can't happen
return scalar($latestEval->builds->search({ job => $job->name })) != 0;
my ($self, $c, $jobset, $jobName) = @_;
return defined $jobset->builds->search({ job => $jobName, iscurrent => 1 })->single;
}
1;

View file

@ -1,5 +1,5 @@
[% WRAPPER layout.tt title="Latest builds" _
(job ? " for job $project.name:$jobset.name:$job.name" :
(job ? " for job $project.name:$jobset.name:$job" :
jobset ? " for jobset $project.name:$jobset.name" :
project ? " for project $project.name" : "") %]
[% PROCESS common.tt %]

View file

@ -1,4 +1,4 @@
[% WRAPPER layout.tt title="Build $id of job $project.name:$jobset.name:$job.name" %]
[% WRAPPER layout.tt title="Build $id of job $project.name:$jobset.name:$job" %]
[% PROCESS common.tt %]
[% PROCESS "product-list.tt" %]
[% USE HTML %]
@ -258,7 +258,7 @@ END;
<p class="error">Note: this build is no longer available.</p>
[% END %]
[% INCLUDE renderProductList latestRoot=['/job' build.project.name build.jobset.name build.job.name 'latest'] %]
[% INCLUDE renderProductList latestRoot=['/job' build.project.name build.jobset.name build.job 'latest'] %]
[% END %]
@ -384,7 +384,7 @@ END;
<th>Output store paths:</th>
<td><tt>[% INCLUDE renderOutputs outputs=build.buildoutputs %]</tt></td>
</tr>
[% chartsURL = c.uri_for('/job' build.project.name build.jobset.name build.job.name) _ "#tabs-charts" %]
[% chartsURL = c.uri_for('/job' build.project.name build.jobset.name build.job) _ "#tabs-charts" %]
[% IF build.finished && build.closuresize %]
<tr>
<th>Closure size:</th>
@ -425,7 +425,7 @@ END;
<tbody>
[% FOREACH metric IN build.buildmetrics %]
<tr>
<td><tt><a class="row-link" [% HTML.attributes(href => c.uri_for('/job' project.name jobset.name job.name 'metric' metric.name)) %]">[%HTML.escape(metric.name)%]</a></tt></td>
<td><tt><a class="row-link" [% HTML.attributes(href => c.uri_for('/job' project.name jobset.name job 'metric' metric.name)) %]">[%HTML.escape(metric.name)%]</a></tt></td>
<td style="text-align: right">[%metric.value%]</td>
<td>[%metric.unit%]</td>
</tr>
@ -507,7 +507,7 @@ END;
running the following command:</p>
<pre>
<span class="shell-prompt"># </span>nix build [% HTML.escape(eval.flake) %]#hydraJobs.[% HTML.escape(job.name) %]
<span class="shell-prompt"># </span>nix build [% HTML.escape(eval.flake) %]#hydraJobs.[% HTML.escape(job) %]
</pre>
[% ELSE %]

View file

@ -22,7 +22,7 @@
<tdata>
[% FOREACH j IN starredJobs %]
<tr>
<td><span class="[% IF !jobExists(j.job) %]disabled-job[% END %]">[% INCLUDE renderFullJobName project=j.job.get_column('project') jobset=j.job.get_column('jobset') job=j.job.name %]</span></td>
<td><span class="[% IF !jobExists(j.job.jobset j.job.job) %]disabled-job[% END %]">[% INCLUDE renderFullJobName project=j.job.get_column('project') jobset=j.job.get_column('jobset') job=j.job.job %]</span></td>
[% FOREACH b IN j.builds %]
<td><a href="[% c.uri_for('/build' b.id) %]">[% INCLUDE renderBuildStatusIcon size=16 build=b %]</a></td>
[% END %]

View file

@ -4,23 +4,23 @@
<h3>Build time (in seconds)</h3>
[% INCLUDE createChart id="build-times" yaxis="sec" dataUrl=c.uri_for('/job' project.name jobset.name job.name 'build-times') %]
[% INCLUDE createChart id="build-times" yaxis="sec" dataUrl=c.uri_for('/job' project.name jobset.name job 'build-times') %]
<h3>Closure size (in MiB)</h3>
[% INCLUDE createChart id="closure-size" yaxis="mib" dataUrl=c.uri_for('/job' project.name jobset.name job.name 'closure-sizes') %]
[% INCLUDE createChart id="closure-size" yaxis="mib" dataUrl=c.uri_for('/job' project.name jobset.name job 'closure-sizes') %]
<h3>Output size (in MiB)</h3>
[% INCLUDE createChart id="output-size" yaxis="mib" dataUrl=c.uri_for('/job' project.name jobset.name job.name 'output-sizes') %]
[% INCLUDE createChart id="output-size" yaxis="mib" dataUrl=c.uri_for('/job' project.name jobset.name job 'output-sizes') %]
[% FOREACH metric IN metrics %]
<h3>Metric: <a [% HTML.attributes(href => c.uri_for('/job' project.name jobset.name job.name 'metric' metric.name)) %]><tt>[%HTML.escape(metric.name)%]</tt></a></h3>
<h3>Metric: <a [% HTML.attributes(href => c.uri_for('/job' project.name jobset.name job 'metric' metric.name)) %]><tt>[%HTML.escape(metric.name)%]</tt></a></h3>
[% id = "metric-" _ metric.name;
id = id.replace('\.', '_');
INCLUDE createChart dataUrl=c.uri_for('/job' project.name jobset.name job.name 'metric' metric.name); %]
INCLUDE createChart dataUrl=c.uri_for('/job' project.name jobset.name job 'metric' metric.name); %]
[% END %]

View file

@ -1,5 +1,5 @@
[% WRAPPER layout.tt
title="Job $project.name:$jobset.name:$job.name"
title="Job $project.name:$jobset.name:$job"
starUri=c.uri_for(c.controller('Job').action_for('star'), c.req.captures)
%]
[% PROCESS common.tt %]
@ -7,7 +7,7 @@
[% INCLUDE includeFlot %]
[% IF !jobExists(job) %]
[% IF !jobExists(jobset, job) %]
<div class="alert alert-warning">This job is not a member of the <a
href="[%c.uri_for('/jobset' project.name jobset.name
'evals')%]">latest evaluation</a> of its jobset. This means it was
@ -29,7 +29,7 @@ removed or had an evaluation error.</div>
[% IF lastBuilds.size != 0 %]
<h3>Latest builds</h3>
[% INCLUDE renderBuildList builds=lastBuilds
linkToAll=c.uri_for('/job' project.name jobset.name job.name 'all') %]
linkToAll=c.uri_for('/job' project.name jobset.name job 'all') %]
[% END %]
[% IF queuedBuilds.size != 0 %]
<h3>Queued builds</h3>
@ -84,12 +84,12 @@ removed or had an evaluation error.</div>
[% END %]
[% INCLUDE makeLazyTab tabName="tabs-charts" uri=c.uri_for('/job' project.name jobset.name job.name 'metrics-tab') %]
[% INCLUDE makeLazyTab tabName="tabs-charts" uri=c.uri_for('/job' project.name jobset.name job 'metrics-tab') %]
<div id="tabs-links" class="tab-pane">
<ul>
<li><a href="[% c.uri_for('/job' project.name jobset.name job.name 'latest') %]">Latest successful build</a></li>
<li><a href="[% c.uri_for('/job' project.name jobset.name job.name 'latest-finished') %]">Latest successful build from a finished evaluation</a></li>
<li><a href="[% c.uri_for('/job' project.name jobset.name job 'latest') %]">Latest successful build</a></li>
<li><a href="[% c.uri_for('/job' project.name jobset.name job 'latest-finished') %]">Latest successful build from a finished evaluation</a></li>
</ul>
</div>

View file

@ -67,7 +67,7 @@
<tbody>
[% FOREACH j IN jobs %]
<tr>
<td><span class="[% IF !j.get_column('enabled') %]disabled-job[% END %]">[% INCLUDE renderFullJobName project=j.get_column('project') jobset=j.get_column('jobset') job=j.name inRow=1 %]</span></td>
<td><span>[% INCLUDE renderFullJobName project=j.get_column('project') jobset=j.get_column('jobset') job=j.job inRow=1 %]</span></td>
</tr>
[% END %]
</tbody>

View file

@ -65,15 +65,15 @@
[% IF job %]
[% WRAPPER makeSubMenu title="Job" %]
<li class="nav-header">[% HTML.escape(job.name) %]</li>
<li class="nav-header">[% HTML.escape(job) %]</li>
<li class="divider"></li>
[% INCLUDE menuItem
uri = c.uri_for(c.controller('Job').action_for('overview'), [project.name, jobset.name, job.name])
uri = c.uri_for(c.controller('Job').action_for('overview'), [project.name, jobset.name, job])
title = "Overview" %]
[% INCLUDE menuItem
uri = c.uri_for(c.controller('Job').action_for('all'), [project.name, jobset.name, job.name])
uri = c.uri_for(c.controller('Job').action_for('all'), [project.name, jobset.name, job])
title = "Latest builds" %]
[% INCLUDE menuItem uri = c.uri_for('/job' project.name jobset.name job.name 'channel' 'latest') title = "Channel" %]
[% INCLUDE menuItem uri = c.uri_for('/job' project.name jobset.name job 'channel' 'latest') title = "Channel" %]
[% END %]
[% END %]

View file

@ -402,13 +402,6 @@ sub checkBuild {
my $build;
$db->txn_do(sub {
my $job = $jobset->jobs->update_or_create({
name => $jobName,
jobset_id => $jobset->id,
project => $jobset->project,
jobset => $jobset->name,
});
# Don't add a build that has already been scheduled for this
# job, or has been built but is still a "current" build for
# this job. Note that this means that if the sources of a job
@ -452,11 +445,12 @@ sub checkBuild {
}
# Add the build to the database.
$build = $job->builds->create(
$build = $jobset->builds->create(
{ timestamp => $time
, project => $jobset->project
, jobset => $jobset->name
, jobset_id => $jobset->id
, job => $jobName
, description => null($buildInfo->{description})
, license => null($buildInfo->{license})
, homepage => null($buildInfo->{homepage})

View file

@ -134,19 +134,6 @@ create table JobsetInputAlts (
);
create table Jobs (
project text not null,
jobset text not null,
jobset_id integer not null,
name text not null,
primary key (project, jobset, name),
foreign key (jobset_id) references Jobsets(id) on delete cascade,
foreign key (project) references Projects(name) on delete cascade on update cascade,
foreign key (project, jobset) references Jobsets(project, name) on delete cascade on update cascade
);
create table Builds (
id serial primary key not null,
@ -226,8 +213,7 @@ create table Builds (
foreign key (jobset_id) references Jobsets(id) on delete cascade,
foreign key (project) references Projects(name) on update cascade,
foreign key (project, jobset) references Jobsets(project, name) on update cascade,
foreign key (project, jobset, job) references Jobs(project, jobset, name) on update cascade
foreign key (project, jobset) references Jobsets(project, name) on update cascade
);
@ -371,8 +357,7 @@ create table BuildMetrics (
primary key (build, name),
foreign key (build) references Builds(id) on delete cascade,
foreign key (project) references Projects(name) on update cascade,
foreign key (project, jobset) references Jobsets(project, name) on update cascade,
foreign key (project, jobset, job) references Jobs(project, jobset, name) on update cascade
foreign key (project, jobset) references Jobsets(project, name) on update cascade
);
@ -545,8 +530,7 @@ create table StarredJobs (
primary key (userName, project, jobset, job),
foreign key (userName) references Users(userName) on update cascade on delete cascade,
foreign key (project) references Projects(name) on update cascade on delete cascade,
foreign key (project, jobset) references Jobsets(project, name) on update cascade on delete cascade,
foreign key (project, jobset, job) references Jobs(project, jobset, name) on update cascade on delete cascade
foreign key (project, jobset) references Jobsets(project, name) on update cascade on delete cascade
);

View file

@ -22,7 +22,6 @@ make_schema_at("Hydra::Schema", {
"cachedpathinputs" => "CachedPathInputs",
"cachedsubversioninputs" => "CachedSubversionInputs",
"failedpaths" => "FailedPaths",
"jobs" => "Jobs",
"jobsetevalinputs" => "JobsetEvalInputs",
"jobsetevalmembers" => "JobsetEvalMembers",
"jobsetevals" => "JobsetEvals",

4
src/sql/upgrade-67.sql Normal file
View file

@ -0,0 +1,4 @@
alter table Builds drop constraint builds_project_fkey2;
alter table BuildMetrics drop constraint buildmetrics_project_fkey2;
alter table StarredJobs drop constraint starredjobs_project_fkey2;
drop table Jobs;

View file

@ -25,10 +25,10 @@ ok(evalSucceeds($jobset), "Evaluating jobs/basic.nix should exi
ok(nrQueuedBuildsForJobset($jobset) == 3 , "Evaluating jobs/basic.nix should result in 3 builds");
for my $build (queuedBuildsForJobset($jobset)) {
ok(runBuild($build), "Build '".$build->job->name."' from jobs/basic.nix should exit with code 0");
ok(runBuild($build), "Build '".$build->job."' from jobs/basic.nix should exit with code 0");
my $newbuild = $db->resultset('Builds')->find($build->id);
my $expected = $build->job->name eq "fails" ? 1 : $build->job->name =~ /with_failed/ ? 6 : 0;
ok($newbuild->finished == 1 && $newbuild->buildstatus == $expected, "Build '".$build->job->name."' from jobs/basic.nix should have buildstatus $expected");
my $expected = $build->job eq "fails" ? 1 : $build->job =~ /with_failed/ ? 6 : 0;
ok($newbuild->finished == 1 && $newbuild->buildstatus == $expected, "Build '".$build->job."' from jobs/basic.nix should have buildstatus $expected");
}
# Test jobset with 2 jobs, one has parameter of succeeded build of the other
@ -37,17 +37,17 @@ $jobset = createJobsetWithOneInput("build-output-as-input", "build-output-as-inp
ok(evalSucceeds($jobset), "Evaluating jobs/build-output-as-input.nix should exit with return code 0");
ok(nrQueuedBuildsForJobset($jobset) == 1 , "Evaluating jobs/build-output-as-input.nix for first time should result in 1 build in queue");
for my $build (queuedBuildsForJobset($jobset)) {
ok(runBuild($build), "Build '".$build->job->name."' from jobs/basic.nix should exit with code 0");
ok(runBuild($build), "Build '".$build->job."' from jobs/basic.nix should exit with code 0");
my $newbuild = $db->resultset('Builds')->find($build->id);
ok($newbuild->finished == 1 && $newbuild->buildstatus == 0, "Build '".$build->job->name."' from jobs/basic.nix should have buildstatus 0");
ok($newbuild->finished == 1 && $newbuild->buildstatus == 0, "Build '".$build->job."' from jobs/basic.nix should have buildstatus 0");
}
ok(evalSucceeds($jobset), "Evaluating jobs/build-output-as-input.nix for second time should exit with return code 0");
ok(nrQueuedBuildsForJobset($jobset) == 1 , "Evaluating jobs/build-output-as-input.nix for second time after building build1 should result in 1 build in queue");
for my $build (queuedBuildsForJobset($jobset)) {
ok(runBuild($build), "Build '".$build->job->name."' from jobs/basic.nix should exit with code 0");
ok(runBuild($build), "Build '".$build->job."' from jobs/basic.nix should exit with code 0");
my $newbuild = $db->resultset('Builds')->find($build->id);
ok($newbuild->finished == 1 && $newbuild->buildstatus == 0, "Build '".$build->job->name."' from jobs/basic.nix should have buildstatus 0");
ok($newbuild->finished == 1 && $newbuild->buildstatus == 0, "Build '".$build->job."' from jobs/basic.nix should have buildstatus 0");
}
@ -158,16 +158,16 @@ ok(evalSucceeds($jobset), "Evaluating jobs/build-products.nix s
ok(nrQueuedBuildsForJobset($jobset) == 2 , "Evaluating jobs/build-products.nix should result in 2 builds");
for my $build (queuedBuildsForJobset($jobset)) {
ok(runBuild($build), "Build '".$build->job->name."' from jobs/build-products.nix should exit with code 0");
ok(runBuild($build), "Build '".$build->job."' from jobs/build-products.nix should exit with code 0");
my $newbuild = $db->resultset('Builds')->find($build->id);
ok($newbuild->finished == 1 && $newbuild->buildstatus == 0, "Build '".$build->job->name."' from jobs/build-products.nix should have buildstatus 0");
ok($newbuild->finished == 1 && $newbuild->buildstatus == 0, "Build '".$build->job."' from jobs/build-products.nix should have buildstatus 0");
my $buildproducts = $db->resultset('BuildProducts')->search({ build => $build->id });
my $buildproduct = $buildproducts->next;
if($build->job->name eq "simple") {
if($build->job eq "simple") {
ok($buildproduct->name eq "text.txt", "We should have text.txt, but found: ".$buildproduct->name."\n");
} elsif ($build->job->name eq "with_spaces") {
} elsif ($build->job eq "with_spaces") {
ok($buildproduct->name eq "some text.txt", "We should have: \"some text.txt\", but found: ".$buildproduct->name."\n");
}
}