From af9f635a5a872b959f1b3eb19d95531fb0735ca8 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Wed, 27 May 2020 17:34:14 +0200 Subject: [PATCH 1/2] Use PostgreSQL 11 This is what we use for hydra.nixos.org. --- flake.nix | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/flake.nix b/flake.nix index 2611bd01..4f847bb8 100644 --- a/flake.nix +++ b/flake.nix @@ -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" From 8adb433e3b48638f3faaecc61ae5cb63efefff6e Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Wed, 27 May 2020 20:09:36 +0200 Subject: [PATCH 2/2] Remove the Jobs table This table has been superfluous for a long time. --- src/lib/Hydra/Controller/Build.pm | 2 +- src/lib/Hydra/Controller/Job.pm | 59 ++++--- src/lib/Hydra/Controller/Root.pm | 12 +- src/lib/Hydra/Controller/User.pm | 6 +- src/lib/Hydra/Helper/CatalystUtils.pm | 2 +- src/lib/Hydra/Schema/BuildMetrics.pm | 22 +-- src/lib/Hydra/Schema/Builds.pm | 22 +-- src/lib/Hydra/Schema/Jobs.pm | 216 -------------------------- src/lib/Hydra/Schema/JobsetEvals.pm | 4 +- src/lib/Hydra/Schema/Jobsets.pm | 37 +---- src/lib/Hydra/Schema/Projects.pm | 19 +-- src/lib/Hydra/Schema/StarredJobs.pm | 22 +-- src/lib/Hydra/View/TT.pm | 8 +- src/root/all.tt | 2 +- src/root/build.tt | 10 +- src/root/dashboard.tt | 2 +- src/root/job-metrics-tab.tt | 10 +- src/root/job.tt | 12 +- src/root/search.tt | 2 +- src/root/topbar.tt | 8 +- src/script/hydra-eval-jobset | 10 +- src/sql/hydra.sql | 22 +-- src/sql/update-dbix.pl | 1 - src/sql/upgrade-67.sql | 4 + tests/evaluation-tests.pl | 26 ++-- 25 files changed, 100 insertions(+), 440 deletions(-) delete mode 100644 src/lib/Hydra/Schema/Jobs.pm create mode 100644 src/sql/upgrade-67.sql diff --git a/src/lib/Hydra/Controller/Build.pm b/src/lib/Hydra/Controller/Build.pm index 75e3c0c5..827b8ac6 100644 --- a/src/lib/Hydra/Controller/Build.pm +++ b/src/lib/Hydra/Controller/Build.pm @@ -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 diff --git a/src/lib/Hydra/Controller/Job.pm b/src/lib/Hydra/Controller/Job.pm index 4013e31b..0487d574 100644 --- a/src/lib/Hydra/Controller/Job.pm +++ b/src/lib/Hydra/Controller/Job.pm @@ -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); diff --git a/src/lib/Hydra/Controller/Root.pm b/src/lib/Hydra/Controller/Root.pm index 32c841b0..a9b0d558 100644 --- a/src/lib/Hydra/Controller/Root.pm +++ b/src/lib/Hydra/Controller/Root.pm @@ -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( diff --git a/src/lib/Hydra/Controller/User.pm b/src/lib/Hydra/Controller/User.pm index 2f7d4c9f..18cc7b05 100644 --- a/src/lib/Hydra/Controller/User.pm +++ b/src/lib/Hydra/Controller/User.pm @@ -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] }; } } diff --git a/src/lib/Hydra/Helper/CatalystUtils.pm b/src/lib/Hydra/Helper/CatalystUtils.pm index d363f966..9121428b 100644 --- a/src/lib/Hydra/Helper/CatalystUtils.pm +++ b/src/lib/Hydra/Helper/CatalystUtils.pm @@ -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 } diff --git a/src/lib/Hydra/Schema/BuildMetrics.pm b/src/lib/Hydra/Schema/BuildMetrics.pm index 324d69e8..2e5d6c6a 100644 --- a/src/lib/Hydra/Schema/BuildMetrics.pm +++ b/src/lib/Hydra/Schema/BuildMetrics.pm @@ -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 - -=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'] }; diff --git a/src/lib/Hydra/Schema/Builds.pm b/src/lib/Hydra/Schema/Builds.pm index 0a21df44..d4334300 100644 --- a/src/lib/Hydra/Schema/Builds.pm +++ b/src/lib/Hydra/Schema/Builds.pm @@ -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 - -=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", diff --git a/src/lib/Hydra/Schema/Jobs.pm b/src/lib/Hydra/Schema/Jobs.pm deleted file mode 100644 index 714497f1..00000000 --- a/src/lib/Hydra/Schema/Jobs.pm +++ /dev/null @@ -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 - -=back - -=cut - -__PACKAGE__->load_components("+Hydra::Component::ToJSON"); - -=head1 TABLE: C - -=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 - -=item * L - -=item * L - -=back - -=cut - -__PACKAGE__->set_primary_key("project", "jobset", "name"); - -=head1 RELATIONS - -=head2 buildmetrics - -Type: has_many - -Related object: L - -=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 - -=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 - -=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 - -=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 - -=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 - -=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 - -=cut - -__PACKAGE__->has_many( - "builds", - "Hydra::Schema::Builds", - { - "foreign.job" => "self.name", - "foreign.jobset_id" => "self.jobset_id", - }, - undef, -); - -1; diff --git a/src/lib/Hydra/Schema/JobsetEvals.pm b/src/lib/Hydra/Schema/JobsetEvals.pm index 7e88c25e..44beb7fd 100644 --- a/src/lib/Hydra/Schema/JobsetEvals.pm +++ b/src/lib/Hydra/Schema/JobsetEvals.pm @@ -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", diff --git a/src/lib/Hydra/Schema/Jobsets.pm b/src/lib/Hydra/Schema/Jobsets.pm index 572b5642..2cf18aab 100644 --- a/src/lib/Hydra/Schema/Jobsets.pm +++ b/src/lib/Hydra/Schema/Jobsets.pm @@ -290,39 +290,6 @@ __PACKAGE__->has_many( undef, ); -=head2 jobs_jobset_ids - -Type: has_many - -Related object: L - -=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 - -=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 diff --git a/src/lib/Hydra/Schema/Projects.pm b/src/lib/Hydra/Schema/Projects.pm index f1c6c89e..0a529933 100644 --- a/src/lib/Hydra/Schema/Projects.pm +++ b/src/lib/Hydra/Schema/Projects.pm @@ -157,21 +157,6 @@ __PACKAGE__->has_many( undef, ); -=head2 jobs - -Type: has_many - -Related object: L - -=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 -> 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 => [ diff --git a/src/lib/Hydra/Schema/StarredJobs.pm b/src/lib/Hydra/Schema/StarredJobs.pm index 4114d65f..04c9df39 100644 --- a/src/lib/Hydra/Schema/StarredJobs.pm +++ b/src/lib/Hydra/Schema/StarredJobs.pm @@ -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 - -=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 diff --git a/src/lib/Hydra/View/TT.pm b/src/lib/Hydra/View/TT.pm index 567fa1d7..edaac447 100644 --- a/src/lib/Hydra/View/TT.pm +++ b/src/lib/Hydra/View/TT.pm @@ -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; diff --git a/src/root/all.tt b/src/root/all.tt index 0d065a1e..a4517349 100644 --- a/src/root/all.tt +++ b/src/root/all.tt @@ -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 %] diff --git a/src/root/build.tt b/src/root/build.tt index 63c11a5f..5a55844d 100644 --- a/src/root/build.tt +++ b/src/root/build.tt @@ -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;

Note: this build is no longer available.

[% 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; Output store paths: [% INCLUDE renderOutputs outputs=build.buildoutputs %] - [% 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 %] Closure size: @@ -425,7 +425,7 @@ END; [% FOREACH metric IN build.buildmetrics %] - c.uri_for('/job' project.name jobset.name job.name 'metric' metric.name)) %]">[%HTML.escape(metric.name)%] + c.uri_for('/job' project.name jobset.name job 'metric' metric.name)) %]">[%HTML.escape(metric.name)%] [%metric.value%] [%metric.unit%] @@ -507,7 +507,7 @@ END; running the following command:

-# nix build [% HTML.escape(eval.flake) %]#hydraJobs.[% HTML.escape(job.name) %]
+# nix build [% HTML.escape(eval.flake) %]#hydraJobs.[% HTML.escape(job) %]
 
[% ELSE %] diff --git a/src/root/dashboard.tt b/src/root/dashboard.tt index efb35af1..5411652e 100644 --- a/src/root/dashboard.tt +++ b/src/root/dashboard.tt @@ -22,7 +22,7 @@ [% FOREACH j IN starredJobs %] - [% INCLUDE renderFullJobName project=j.job.get_column('project') jobset=j.job.get_column('jobset') job=j.job.name %] + [% INCLUDE renderFullJobName project=j.job.get_column('project') jobset=j.job.get_column('jobset') job=j.job.job %] [% FOREACH b IN j.builds %] [% INCLUDE renderBuildStatusIcon size=16 build=b %] [% END %] diff --git a/src/root/job-metrics-tab.tt b/src/root/job-metrics-tab.tt index 163046b7..23d8ffa3 100644 --- a/src/root/job-metrics-tab.tt +++ b/src/root/job-metrics-tab.tt @@ -4,23 +4,23 @@

Build time (in seconds)

- [% 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') %]

Closure size (in MiB)

- [% 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') %]

Output size (in MiB)

- [% 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 %] -

Metric: c.uri_for('/job' project.name jobset.name job.name 'metric' metric.name)) %]>[%HTML.escape(metric.name)%]

+

Metric: c.uri_for('/job' project.name jobset.name job 'metric' metric.name)) %]>[%HTML.escape(metric.name)%]

[% 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 %] diff --git a/src/root/job.tt b/src/root/job.tt index 1bf7c499..0d398264 100644 --- a/src/root/job.tt +++ b/src/root/job.tt @@ -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) %]
This job is not a member of the latest evaluation of its jobset. This means it was @@ -29,7 +29,7 @@ removed or had an evaluation error.
[% IF lastBuilds.size != 0 %]

Latest builds

[% 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 %]

Queued builds

@@ -84,12 +84,12 @@ removed or had an evaluation error. [% 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') %] diff --git a/src/root/search.tt b/src/root/search.tt index 06f1e8ed..d2b2dece 100644 --- a/src/root/search.tt +++ b/src/root/search.tt @@ -67,7 +67,7 @@ [% FOREACH j IN jobs %] - [% INCLUDE renderFullJobName project=j.get_column('project') jobset=j.get_column('jobset') job=j.name inRow=1 %] + [% INCLUDE renderFullJobName project=j.get_column('project') jobset=j.get_column('jobset') job=j.job inRow=1 %] [% END %] diff --git a/src/root/topbar.tt b/src/root/topbar.tt index ee093f88..b9b839f9 100644 --- a/src/root/topbar.tt +++ b/src/root/topbar.tt @@ -65,15 +65,15 @@ [% IF job %] [% WRAPPER makeSubMenu title="Job" %] - +
  • [% 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 %] diff --git a/src/script/hydra-eval-jobset b/src/script/hydra-eval-jobset index 6e1841a2..9df87ac9 100755 --- a/src/script/hydra-eval-jobset +++ b/src/script/hydra-eval-jobset @@ -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}) diff --git a/src/sql/hydra.sql b/src/sql/hydra.sql index 4f3f0089..a0db622a 100644 --- a/src/sql/hydra.sql +++ b/src/sql/hydra.sql @@ -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 ); diff --git a/src/sql/update-dbix.pl b/src/sql/update-dbix.pl index 2d4f14fe..df6c0526 100644 --- a/src/sql/update-dbix.pl +++ b/src/sql/update-dbix.pl @@ -22,7 +22,6 @@ make_schema_at("Hydra::Schema", { "cachedpathinputs" => "CachedPathInputs", "cachedsubversioninputs" => "CachedSubversionInputs", "failedpaths" => "FailedPaths", - "jobs" => "Jobs", "jobsetevalinputs" => "JobsetEvalInputs", "jobsetevalmembers" => "JobsetEvalMembers", "jobsetevals" => "JobsetEvals", diff --git a/src/sql/upgrade-67.sql b/src/sql/upgrade-67.sql new file mode 100644 index 00000000..9c586823 --- /dev/null +++ b/src/sql/upgrade-67.sql @@ -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; diff --git a/tests/evaluation-tests.pl b/tests/evaluation-tests.pl index 45ebb452..1d4c37a5 100644 --- a/tests/evaluation-tests.pl +++ b/tests/evaluation-tests.pl @@ -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"); } }