forked from lix-project/hydra
commit
750e2e618a
|
@ -105,7 +105,7 @@
|
||||||
gitAndTools.topGit mercurial darcs subversion bazaar openssl bzip2 libxslt
|
gitAndTools.topGit mercurial darcs subversion bazaar openssl bzip2 libxslt
|
||||||
perlDeps perl final.nix
|
perlDeps perl final.nix
|
||||||
boost
|
boost
|
||||||
postgresql95
|
postgresql_11
|
||||||
(if lib.versionAtLeast lib.version "20.03pre"
|
(if lib.versionAtLeast lib.version "20.03pre"
|
||||||
then nlohmann_json
|
then nlohmann_json
|
||||||
else nlohmann_json.override { multipleHeaders = true; })
|
else nlohmann_json.override { multipleHeaders = true; })
|
||||||
|
@ -308,7 +308,7 @@
|
||||||
systemd.services.hydra-send-stats.enable = false;
|
systemd.services.hydra-send-stats.enable = false;
|
||||||
|
|
||||||
services.postgresql.enable = true;
|
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:
|
# The following is to work around the following error from hydra-server:
|
||||||
# [error] Caught exception in engine "Cannot determine local time zone"
|
# [error] Caught exception in engine "Cannot determine local time zone"
|
||||||
|
|
|
@ -86,7 +86,7 @@ sub build_GET {
|
||||||
$c->stash->{prevBuilds} = [$c->model('DB::Builds')->search(
|
$c->stash->{prevBuilds} = [$c->model('DB::Builds')->search(
|
||||||
{ project => $c->stash->{project}->name
|
{ project => $c->stash->{project}->name
|
||||||
, jobset => $c->stash->{jobset}->name
|
, jobset => $c->stash->{jobset}->name
|
||||||
, job => $c->stash->{job}->name
|
, job => $c->stash->{job}
|
||||||
, 'me.system' => $build->system
|
, 'me.system' => $build->system
|
||||||
, finished => 1
|
, finished => 1
|
||||||
, buildstatus => 0
|
, buildstatus => 0
|
||||||
|
|
|
@ -24,18 +24,16 @@ sub job : Chained('/') PathPart('job') CaptureArgs(3) {
|
||||||
$c->detach;
|
$c->detach;
|
||||||
}
|
}
|
||||||
|
|
||||||
$c->stash->{job} = $c->stash->{jobset}->jobs->find({ name => $jobName })
|
$c->stash->{job} = $jobName;
|
||||||
or notFound($c, "Job $projectName:$jobsetName:$jobName doesn't exist.");
|
$c->stash->{project} = $c->stash->{jobset}->project;
|
||||||
$c->stash->{project} = $c->stash->{job}->project;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
sub prometheus : Chained('job') PathPart('prometheus') Args(0) {
|
sub prometheus : Chained('job') PathPart('prometheus') Args(0) {
|
||||||
my ($self, $c) = @_;
|
my ($self, $c) = @_;
|
||||||
my $job = $c->stash->{job};
|
|
||||||
my $prometheus = Net::Prometheus->new;
|
my $prometheus = Net::Prometheus->new;
|
||||||
|
|
||||||
my $lastBuild = $job->builds->find(
|
my $lastBuild = $c->stash->{jobset}->builds->find(
|
||||||
{ finished => 1 },
|
{ job => $c->stash->{job}, finished => 1 },
|
||||||
{ order_by => 'id DESC', rows => 1, columns => [@buildListColumns] }
|
{ order_by => 'id DESC', rows => 1, columns => [@buildListColumns] }
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -46,7 +44,7 @@ sub prometheus : Chained('job') PathPart('prometheus') Args(0) {
|
||||||
)->labels(
|
)->labels(
|
||||||
$c->stash->{project}->name,
|
$c->stash->{project}->name,
|
||||||
$c->stash->{jobset}->name,
|
$c->stash->{jobset}->name,
|
||||||
$c->stash->{job}->name,
|
$c->stash->{job},
|
||||||
)->inc($lastBuild->stoptime);
|
)->inc($lastBuild->stoptime);
|
||||||
|
|
||||||
$prometheus->new_gauge(
|
$prometheus->new_gauge(
|
||||||
|
@ -56,7 +54,7 @@ sub prometheus : Chained('job') PathPart('prometheus') Args(0) {
|
||||||
)->labels(
|
)->labels(
|
||||||
$c->stash->{project}->name,
|
$c->stash->{project}->name,
|
||||||
$c->stash->{jobset}->name,
|
$c->stash->{jobset}->name,
|
||||||
$c->stash->{job}->name,
|
$c->stash->{job},
|
||||||
)->inc($lastBuild->buildstatus > 0);
|
)->inc($lastBuild->buildstatus > 0);
|
||||||
|
|
||||||
$c->stash->{'plain'} = { data => $prometheus->render };
|
$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) {
|
sub overview : Chained('job') PathPart('') Args(0) {
|
||||||
my ($self, $c) = @_;
|
my ($self, $c) = @_;
|
||||||
my $job = $c->stash->{job};
|
|
||||||
|
|
||||||
$c->stash->{template} = 'job.tt';
|
$c->stash->{template} = 'job.tt';
|
||||||
|
|
||||||
$c->stash->{lastBuilds} =
|
$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] }) ];
|
{ order_by => 'id DESC', rows => 10, columns => [@buildListColumns] }) ];
|
||||||
|
|
||||||
$c->stash->{queuedBuilds} = [
|
$c->stash->{queuedBuilds} = [
|
||||||
$job->builds->search(
|
$c->stash->{jobset}->builds->search(
|
||||||
{ finished => 0 },
|
{ job => $c->stash->{job}, finished => 0 },
|
||||||
{ order_by => ["priority DESC", "id"] }
|
{ order_by => ["priority DESC", "id"] }
|
||||||
) ];
|
) ];
|
||||||
|
|
||||||
# If this is an aggregate job, then get its constituents.
|
# If this is an aggregate job, then get its constituents.
|
||||||
my @constituents = $c->model('DB::Builds')->search(
|
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',
|
{ join => 'aggregateconstituents_constituents',
|
||||||
columns => ['id', 'job', 'finished', 'buildstatus'],
|
columns => ['id', 'job', 'finished', 'buildstatus'],
|
||||||
+select => ['aggregateconstituents_constituents.aggregate'],
|
+select => ['aggregateconstituents_constituents.aggregate'],
|
||||||
|
@ -91,10 +88,9 @@ sub overview : Chained('job') PathPart('') Args(0) {
|
||||||
my $aggregates = {};
|
my $aggregates = {};
|
||||||
my %constituentJobs;
|
my %constituentJobs;
|
||||||
foreach my $b (@constituents) {
|
foreach my $b (@constituents) {
|
||||||
my $jobName = $b->get_column('job');
|
$aggregates->{$b->get_column('aggregate')}->{constituents}->{$b->job} =
|
||||||
$aggregates->{$b->get_column('aggregate')}->{constituents}->{$jobName} =
|
|
||||||
{ id => $b->id, finished => $b->finished, buildstatus => $b->buildstatus };
|
{ id => $b->id, finished => $b->finished, buildstatus => $b->buildstatus };
|
||||||
$constituentJobs{$jobName} = 1;
|
$constituentJobs{$b->job} = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach my $agg (keys %$aggregates) {
|
foreach my $agg (keys %$aggregates) {
|
||||||
|
@ -109,24 +105,23 @@ sub overview : Chained('job') PathPart('') Args(0) {
|
||||||
$c->stash->{starred} = $c->user->starredjobs(
|
$c->stash->{starred} = $c->user->starredjobs(
|
||||||
{ project => $c->stash->{project}->name
|
{ project => $c->stash->{project}->name
|
||||||
, jobset => $c->stash->{jobset}->name
|
, jobset => $c->stash->{jobset}->name
|
||||||
, job => $c->stash->{job}->name
|
, job => $c->stash->{job}
|
||||||
})->count == 1 if $c->user_exists;
|
})->count == 1 if $c->user_exists;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
sub metrics_tab : Chained('job') PathPart('metrics-tab') Args(0) {
|
sub metrics_tab : Chained('job') PathPart('metrics-tab') Args(0) {
|
||||||
my ($self, $c) = @_;
|
my ($self, $c) = @_;
|
||||||
my $job = $c->stash->{job};
|
|
||||||
$c->stash->{template} = 'job-metrics-tab.tt';
|
$c->stash->{template} = 'job-metrics-tab.tt';
|
||||||
$c->stash->{metrics} = [ $job->buildmetrics->search(
|
$c->stash->{metrics} = [ $c->stash->{jobset}->buildmetrics->search(
|
||||||
{ }, { select => ["name"], distinct => 1, order_by => "name", }) ];
|
{ job => $c->stash->{job} }, { select => ["name"], distinct => 1, order_by => "name", }) ];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
sub build_times : Chained('job') PathPart('build-times') Args(0) {
|
sub build_times : Chained('job') PathPart('build-times') Args(0) {
|
||||||
my ($self, $c) = @_;
|
my ($self, $c) = @_;
|
||||||
my @res = $c->stash->{job}->builds->search(
|
my @res = $c->stash->{jobset}->builds->search(
|
||||||
{ finished => 1, buildstatus => 0, closuresize => { '!=', 0 } },
|
{ job => $c->stash->{job}, finished => 1, buildstatus => 0, closuresize => { '!=', 0 } },
|
||||||
{ join => "actualBuildStep"
|
{ join => "actualBuildStep"
|
||||||
, "+select" => ["actualBuildStep.stoptime - actualBuildStep.starttime"]
|
, "+select" => ["actualBuildStep.stoptime - actualBuildStep.starttime"]
|
||||||
, "+as" => ["actualBuildTime"],
|
, "+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) {
|
sub closure_sizes : Chained('job') PathPart('closure-sizes') Args(0) {
|
||||||
my ($self, $c) = @_;
|
my ($self, $c) = @_;
|
||||||
my @res = $c->stash->{job}->builds->search(
|
my @res = $c->stash->{jobset}->builds->search(
|
||||||
{ finished => 1, buildstatus => 0, closuresize => { '!=', 0 } },
|
{ job => $c->stash->{job}, finished => 1, buildstatus => 0, closuresize => { '!=', 0 } },
|
||||||
{ order_by => "id", columns => [ "id", "timestamp", "closuresize" ] });
|
{ order_by => "id", columns => [ "id", "timestamp", "closuresize" ] });
|
||||||
$self->status_ok($c, entity => [ map { { id => $_->id, timestamp => $_ ->timestamp, value => $_->closuresize } } @res ]);
|
$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) {
|
sub output_sizes : Chained('job') PathPart('output-sizes') Args(0) {
|
||||||
my ($self, $c) = @_;
|
my ($self, $c) = @_;
|
||||||
my @res = $c->stash->{job}->builds->search(
|
my @res = $c->stash->{jobset}->builds->search(
|
||||||
{ finished => 1, buildstatus => 0, size => { '!=', 0 } },
|
{ job => $c->stash->{job}, finished => 1, buildstatus => 0, size => { '!=', 0 } },
|
||||||
{ order_by => "id", columns => [ "id", "timestamp", "size" ] });
|
{ order_by => "id", columns => [ "id", "timestamp", "size" ] });
|
||||||
$self->status_ok($c, entity => [ map { { id => $_->id, timestamp => $_ ->timestamp, value => $_->size } } @res ]);
|
$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->{template} = 'metric.tt';
|
||||||
$c->stash->{metricName} = $metricName;
|
$c->stash->{metricName} = $metricName;
|
||||||
|
|
||||||
my @res = $c->stash->{job}->buildmetrics->search(
|
my @res = $c->stash->{jobset}->buildmetrics->search(
|
||||||
{ name => $metricName },
|
{ job => $c->stash->{job}, name => $metricName },
|
||||||
{ order_by => "timestamp", columns => [ "build", "name", "timestamp", "value", "unit" ] });
|
{ 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 ]);
|
$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.
|
# Hydra::Base::Controller::ListBuilds needs this.
|
||||||
sub get_builds : Chained('job') PathPart('') CaptureArgs(0) {
|
sub get_builds : Chained('job') PathPart('') CaptureArgs(0) {
|
||||||
my ($self, $c) = @_;
|
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')
|
$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->{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 =
|
my $args =
|
||||||
{ project => $c->stash->{project}->name
|
{ project => $c->stash->{project}->name
|
||||||
, jobset => $c->stash->{jobset}->name
|
, jobset => $c->stash->{jobset}->name
|
||||||
, job => $c->stash->{job}->name
|
, job => $c->stash->{job}
|
||||||
};
|
};
|
||||||
if ($c->request->params->{star} eq "1") {
|
if ($c->request->params->{star} eq "1") {
|
||||||
$c->user->starredjobs->update_or_create($args);
|
$c->user->starredjobs->update_or_create($args);
|
||||||
|
|
|
@ -459,16 +459,16 @@ sub search :Local Args(0) {
|
||||||
},
|
},
|
||||||
{ order_by => ["project", "name"], join => ["project"] } ) ];
|
{ order_by => ["project", "name"], join => ["project"] } ) ];
|
||||||
|
|
||||||
$c->stash->{jobs} = [ $c->model('DB::Jobs')->search(
|
$c->stash->{jobs} = [ $c->model('DB::Builds')->search(
|
||||||
{ "me.name" => { ilike => "%$query%" }
|
{ "job" => { ilike => "%$query%" }
|
||||||
, "project.hidden" => 0
|
, "project.hidden" => 0
|
||||||
, "jobset.hidden" => 0
|
, "jobset.hidden" => 0
|
||||||
|
, iscurrent => 1
|
||||||
},
|
},
|
||||||
{ order_by => ["enabled_ desc", "project", "jobset", "name"], join => ["project", "jobset"]
|
{ order_by => ["project", "jobset", "job"], 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"]
|
|
||||||
, rows => $c->stash->{limit} + 1
|
, rows => $c->stash->{limit} + 1
|
||||||
} ) ];
|
} )
|
||||||
|
];
|
||||||
|
|
||||||
# Perform build search in separate queries to prevent seq scan on buildoutputs table.
|
# Perform build search in separate queries to prevent seq scan on buildoutputs table.
|
||||||
$c->stash->{builds} = [ $c->model('DB::Builds')->search(
|
$c->stash->{builds} = [ $c->model('DB::Builds')->search(
|
||||||
|
|
|
@ -339,10 +339,10 @@ sub dashboard :Chained('dashboard_base') :PathPart('') :Args(0) {
|
||||||
# Get the N most recent builds for each starred job.
|
# Get the N most recent builds for each starred job.
|
||||||
$c->stash->{starredJobs} = [];
|
$c->stash->{starredJobs} = [];
|
||||||
foreach my $j ($c->stash->{user}->starredjobs->search({}, { order_by => ['project', 'jobset', 'job'] })) {
|
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" });
|
{ rows => 20, order_by => "id desc" });
|
||||||
push @{$c->stash->{starredJobs}}, { job => $j->job, builds => [@builds] };
|
push @{$c->stash->{starredJobs}}, { job => $j, builds => [@builds] };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -46,7 +46,7 @@ sub getBuild {
|
||||||
sub getPreviousBuild {
|
sub getPreviousBuild {
|
||||||
my ($build) = @_;
|
my ($build) = @_;
|
||||||
return undef if !defined $build;
|
return undef if !defined $build;
|
||||||
return $build->job->builds->search(
|
return $build->jobset->builds->search(
|
||||||
{ finished => 1
|
{ finished => 1
|
||||||
, system => $build->system
|
, system => $build->system
|
||||||
, 'me.id' => { '<' => $build->id }
|
, 'me.id' => { '<' => $build->id }
|
||||||
|
|
|
@ -71,7 +71,6 @@ __PACKAGE__->table("buildmetrics");
|
||||||
=head2 job
|
=head2 job
|
||||||
|
|
||||||
data_type: 'text'
|
data_type: 'text'
|
||||||
is_foreign_key: 1
|
|
||||||
is_nullable: 0
|
is_nullable: 0
|
||||||
|
|
||||||
=head2 timestamp
|
=head2 timestamp
|
||||||
|
@ -95,7 +94,7 @@ __PACKAGE__->add_columns(
|
||||||
"jobset",
|
"jobset",
|
||||||
{ data_type => "text", is_foreign_key => 1, is_nullable => 0 },
|
{ data_type => "text", is_foreign_key => 1, is_nullable => 0 },
|
||||||
"job",
|
"job",
|
||||||
{ data_type => "text", is_foreign_key => 1, is_nullable => 0 },
|
{ data_type => "text", is_nullable => 0 },
|
||||||
"timestamp",
|
"timestamp",
|
||||||
{ data_type => "integer", is_nullable => 0 },
|
{ data_type => "integer", is_nullable => 0 },
|
||||||
);
|
);
|
||||||
|
@ -131,21 +130,6 @@ __PACKAGE__->belongs_to(
|
||||||
{ is_deferrable => 0, on_delete => "CASCADE", on_update => "NO ACTION" },
|
{ 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
|
=head2 jobset
|
||||||
|
|
||||||
Type: belongs_to
|
Type: belongs_to
|
||||||
|
@ -177,8 +161,8 @@ __PACKAGE__->belongs_to(
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
# Created by DBIx::Class::Schema::Loader v0.07049 @ 2020-02-06 12:22:36
|
# Created by DBIx::Class::Schema::Loader v0.07049 @ 2020-05-27 17:40:41
|
||||||
# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:Roy7h/K9u7DQOzet4B1sbA
|
# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:AYUVs6RdefFKw+g9Yxcu/A
|
||||||
|
|
||||||
sub json_hint {
|
sub json_hint {
|
||||||
return { columns => ['value', 'unit'] };
|
return { columns => ['value', 'unit'] };
|
||||||
|
|
|
@ -73,7 +73,6 @@ __PACKAGE__->table("builds");
|
||||||
=head2 job
|
=head2 job
|
||||||
|
|
||||||
data_type: 'text'
|
data_type: 'text'
|
||||||
is_foreign_key: 1
|
|
||||||
is_nullable: 0
|
is_nullable: 0
|
||||||
|
|
||||||
=head2 nixname
|
=head2 nixname
|
||||||
|
@ -224,7 +223,7 @@ __PACKAGE__->add_columns(
|
||||||
"jobset_id",
|
"jobset_id",
|
||||||
{ data_type => "integer", is_foreign_key => 1, is_nullable => 0 },
|
{ data_type => "integer", is_foreign_key => 1, is_nullable => 0 },
|
||||||
"job",
|
"job",
|
||||||
{ data_type => "text", is_foreign_key => 1, is_nullable => 0 },
|
{ data_type => "text", is_nullable => 0 },
|
||||||
"nixname",
|
"nixname",
|
||||||
{ data_type => "text", is_nullable => 1 },
|
{ data_type => "text", is_nullable => 1 },
|
||||||
"description",
|
"description",
|
||||||
|
@ -439,21 +438,6 @@ __PACKAGE__->has_many(
|
||||||
undef,
|
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
|
=head2 jobset
|
||||||
|
|
||||||
Type: belongs_to
|
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
|
# Created by DBIx::Class::Schema::Loader v0.07049 @ 2020-05-27 17:40:41
|
||||||
# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:3IyFj/9Zf/hvmhBY4U/IBQ
|
# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:RIKKFfcKXFWIUeM8ma++iw
|
||||||
|
|
||||||
__PACKAGE__->has_many(
|
__PACKAGE__->has_many(
|
||||||
"dependents",
|
"dependents",
|
||||||
|
|
|
@ -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;
|
|
|
@ -201,8 +201,8 @@ __PACKAGE__->belongs_to(
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
# Created by DBIx::Class::Schema::Loader v0.07049 @ 2020-02-09 15:21:11
|
# Created by DBIx::Class::Schema::Loader v0.07049 @ 2020-05-27 17:40:41
|
||||||
# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:Ar6GRni8AcAQmuZyg6tFKw
|
# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:M61ikfnjORU7jDAH8P/j7w
|
||||||
|
|
||||||
__PACKAGE__->has_many(
|
__PACKAGE__->has_many(
|
||||||
"buildIds",
|
"buildIds",
|
||||||
|
|
|
@ -290,39 +290,6 @@ __PACKAGE__->has_many(
|
||||||
undef,
|
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
|
=head2 jobsetevals
|
||||||
|
|
||||||
Type: has_many
|
Type: has_many
|
||||||
|
@ -408,8 +375,8 @@ __PACKAGE__->has_many(
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
# Created by DBIx::Class::Schema::Loader v0.07049 @ 2020-02-09 15:32:17
|
# Created by DBIx::Class::Schema::Loader v0.07049 @ 2020-05-27 17:40:41
|
||||||
# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:P8+t7rgpOqkGwRdM2b+3Bw
|
# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:aDW78MCelU/ma953aTcHvA
|
||||||
|
|
||||||
|
|
||||||
=head2 builds
|
=head2 builds
|
||||||
|
|
|
@ -157,21 +157,6 @@ __PACKAGE__->has_many(
|
||||||
undef,
|
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
|
=head2 jobsetevals
|
||||||
|
|
||||||
Type: has_many
|
Type: has_many
|
||||||
|
@ -273,8 +258,8 @@ Composing rels: L</projectmembers> -> username
|
||||||
__PACKAGE__->many_to_many("usernames", "projectmembers", "username");
|
__PACKAGE__->many_to_many("usernames", "projectmembers", "username");
|
||||||
|
|
||||||
|
|
||||||
# Created by DBIx::Class::Schema::Loader v0.07049 @ 2020-05-06 12:32:57
|
# Created by DBIx::Class::Schema::Loader v0.07049 @ 2020-05-27 17:40:41
|
||||||
# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:dEIVgrFGilPfITprs6nYuA
|
# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:iBGJjFWiI9Wy9zwT7xGOEA
|
||||||
|
|
||||||
my %hint = (
|
my %hint = (
|
||||||
columns => [
|
columns => [
|
||||||
|
|
|
@ -56,7 +56,6 @@ __PACKAGE__->table("starredjobs");
|
||||||
=head2 job
|
=head2 job
|
||||||
|
|
||||||
data_type: 'text'
|
data_type: 'text'
|
||||||
is_foreign_key: 1
|
|
||||||
is_nullable: 0
|
is_nullable: 0
|
||||||
|
|
||||||
=cut
|
=cut
|
||||||
|
@ -69,7 +68,7 @@ __PACKAGE__->add_columns(
|
||||||
"jobset",
|
"jobset",
|
||||||
{ data_type => "text", is_foreign_key => 1, is_nullable => 0 },
|
{ data_type => "text", is_foreign_key => 1, is_nullable => 0 },
|
||||||
"job",
|
"job",
|
||||||
{ data_type => "text", is_foreign_key => 1, is_nullable => 0 },
|
{ data_type => "text", is_nullable => 0 },
|
||||||
);
|
);
|
||||||
|
|
||||||
=head1 PRIMARY KEY
|
=head1 PRIMARY KEY
|
||||||
|
@ -92,21 +91,6 @@ __PACKAGE__->set_primary_key("username", "project", "jobset", "job");
|
||||||
|
|
||||||
=head1 RELATIONS
|
=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
|
=head2 jobset
|
||||||
|
|
||||||
Type: belongs_to
|
Type: belongs_to
|
||||||
|
@ -153,8 +137,8 @@ __PACKAGE__->belongs_to(
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
# Created by DBIx::Class::Schema::Loader v0.07049 @ 2020-02-06 12:22:36
|
# Created by DBIx::Class::Schema::Loader v0.07049 @ 2020-05-27 17:36:07
|
||||||
# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:fw4FfzmOhzDk0ZoSuNr2ww
|
# 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
|
# You can replace this text with custom code or comments, and it will be preserved on regeneration
|
||||||
|
|
|
@ -37,12 +37,8 @@ sub stripSSHUser {
|
||||||
# Check whether the given job is a member of the most recent jobset
|
# Check whether the given job is a member of the most recent jobset
|
||||||
# evaluation.
|
# evaluation.
|
||||||
sub jobExists {
|
sub jobExists {
|
||||||
my ($self, $c, $job) = @_;
|
my ($self, $c, $jobset, $jobName) = @_;
|
||||||
my $latestEval = $job->jobset->jobsetevals->search(
|
return defined $jobset->builds->search({ job => $jobName, iscurrent => 1 })->single;
|
||||||
{ 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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
1;
|
1;
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
[% WRAPPER layout.tt title="Latest builds" _
|
[% 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" :
|
jobset ? " for jobset $project.name:$jobset.name" :
|
||||||
project ? " for project $project.name" : "") %]
|
project ? " for project $project.name" : "") %]
|
||||||
[% PROCESS common.tt %]
|
[% PROCESS common.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 common.tt %]
|
||||||
[% PROCESS "product-list.tt" %]
|
[% PROCESS "product-list.tt" %]
|
||||||
[% USE HTML %]
|
[% USE HTML %]
|
||||||
|
@ -258,7 +258,7 @@ END;
|
||||||
<p class="error">Note: this build is no longer available.</p>
|
<p class="error">Note: this build is no longer available.</p>
|
||||||
[% END %]
|
[% 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 %]
|
[% END %]
|
||||||
|
|
||||||
|
@ -384,7 +384,7 @@ END;
|
||||||
<th>Output store paths:</th>
|
<th>Output store paths:</th>
|
||||||
<td><tt>[% INCLUDE renderOutputs outputs=build.buildoutputs %]</tt></td>
|
<td><tt>[% INCLUDE renderOutputs outputs=build.buildoutputs %]</tt></td>
|
||||||
</tr>
|
</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 %]
|
[% IF build.finished && build.closuresize %]
|
||||||
<tr>
|
<tr>
|
||||||
<th>Closure size:</th>
|
<th>Closure size:</th>
|
||||||
|
@ -425,7 +425,7 @@ END;
|
||||||
<tbody>
|
<tbody>
|
||||||
[% FOREACH metric IN build.buildmetrics %]
|
[% FOREACH metric IN build.buildmetrics %]
|
||||||
<tr>
|
<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 style="text-align: right">[%metric.value%]</td>
|
||||||
<td>[%metric.unit%]</td>
|
<td>[%metric.unit%]</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
@ -507,7 +507,7 @@ END;
|
||||||
running the following command:</p>
|
running the following command:</p>
|
||||||
|
|
||||||
<pre>
|
<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>
|
</pre>
|
||||||
|
|
||||||
[% ELSE %]
|
[% ELSE %]
|
||||||
|
|
|
@ -22,7 +22,7 @@
|
||||||
<tdata>
|
<tdata>
|
||||||
[% FOREACH j IN starredJobs %]
|
[% FOREACH j IN starredJobs %]
|
||||||
<tr>
|
<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 %]
|
[% FOREACH b IN j.builds %]
|
||||||
<td><a href="[% c.uri_for('/build' b.id) %]">[% INCLUDE renderBuildStatusIcon size=16 build=b %]</a></td>
|
<td><a href="[% c.uri_for('/build' b.id) %]">[% INCLUDE renderBuildStatusIcon size=16 build=b %]</a></td>
|
||||||
[% END %]
|
[% END %]
|
||||||
|
|
|
@ -4,23 +4,23 @@
|
||||||
|
|
||||||
<h3>Build time (in seconds)</h3>
|
<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>
|
<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>
|
<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 %]
|
[% 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 = "metric-" _ metric.name;
|
||||||
id = id.replace('\.', '_');
|
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 %]
|
[% END %]
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
[% WRAPPER layout.tt
|
[% 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)
|
starUri=c.uri_for(c.controller('Job').action_for('star'), c.req.captures)
|
||||||
%]
|
%]
|
||||||
[% PROCESS common.tt %]
|
[% PROCESS common.tt %]
|
||||||
|
@ -7,7 +7,7 @@
|
||||||
|
|
||||||
[% INCLUDE includeFlot %]
|
[% INCLUDE includeFlot %]
|
||||||
|
|
||||||
[% IF !jobExists(job) %]
|
[% IF !jobExists(jobset, job) %]
|
||||||
<div class="alert alert-warning">This job is not a member of the <a
|
<div class="alert alert-warning">This job is not a member of the <a
|
||||||
href="[%c.uri_for('/jobset' project.name jobset.name
|
href="[%c.uri_for('/jobset' project.name jobset.name
|
||||||
'evals')%]">latest evaluation</a> of its jobset. This means it was
|
'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 %]
|
[% IF lastBuilds.size != 0 %]
|
||||||
<h3>Latest builds</h3>
|
<h3>Latest builds</h3>
|
||||||
[% INCLUDE renderBuildList builds=lastBuilds
|
[% 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 %]
|
[% END %]
|
||||||
[% IF queuedBuilds.size != 0 %]
|
[% IF queuedBuilds.size != 0 %]
|
||||||
<h3>Queued builds</h3>
|
<h3>Queued builds</h3>
|
||||||
|
@ -84,12 +84,12 @@ removed or had an evaluation error.</div>
|
||||||
|
|
||||||
[% END %]
|
[% 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">
|
<div id="tabs-links" class="tab-pane">
|
||||||
<ul>
|
<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 '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-finished') %]">Latest successful build from a finished evaluation</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
|
@ -67,7 +67,7 @@
|
||||||
<tbody>
|
<tbody>
|
||||||
[% FOREACH j IN jobs %]
|
[% FOREACH j IN jobs %]
|
||||||
<tr>
|
<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>
|
</tr>
|
||||||
[% END %]
|
[% END %]
|
||||||
</tbody>
|
</tbody>
|
||||||
|
|
|
@ -65,15 +65,15 @@
|
||||||
|
|
||||||
[% IF job %]
|
[% IF job %]
|
||||||
[% WRAPPER makeSubMenu title="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>
|
<li class="divider"></li>
|
||||||
[% INCLUDE menuItem
|
[% 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" %]
|
title = "Overview" %]
|
||||||
[% INCLUDE menuItem
|
[% 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" %]
|
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 %]
|
||||||
[% END %]
|
[% END %]
|
||||||
|
|
||||||
|
|
|
@ -402,13 +402,6 @@ sub checkBuild {
|
||||||
my $build;
|
my $build;
|
||||||
|
|
||||||
$db->txn_do(sub {
|
$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
|
# Don't add a build that has already been scheduled for this
|
||||||
# job, or has been built but is still a "current" build for
|
# 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
|
# 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.
|
# Add the build to the database.
|
||||||
$build = $job->builds->create(
|
$build = $jobset->builds->create(
|
||||||
{ timestamp => $time
|
{ timestamp => $time
|
||||||
, project => $jobset->project
|
, project => $jobset->project
|
||||||
, jobset => $jobset->name
|
, jobset => $jobset->name
|
||||||
, jobset_id => $jobset->id
|
, jobset_id => $jobset->id
|
||||||
|
, job => $jobName
|
||||||
, description => null($buildInfo->{description})
|
, description => null($buildInfo->{description})
|
||||||
, license => null($buildInfo->{license})
|
, license => null($buildInfo->{license})
|
||||||
, homepage => null($buildInfo->{homepage})
|
, homepage => null($buildInfo->{homepage})
|
||||||
|
|
|
@ -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 (
|
create table Builds (
|
||||||
id serial primary key not null,
|
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 (jobset_id) references Jobsets(id) on delete cascade,
|
||||||
foreign key (project) references Projects(name) on update 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) references Jobsets(project, name) on update cascade
|
||||||
foreign key (project, jobset, job) references Jobs(project, jobset, name) on update cascade
|
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
|
@ -371,8 +357,7 @@ create table BuildMetrics (
|
||||||
primary key (build, name),
|
primary key (build, name),
|
||||||
foreign key (build) references Builds(id) on delete cascade,
|
foreign key (build) references Builds(id) on delete cascade,
|
||||||
foreign key (project) references Projects(name) on update 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) references Jobsets(project, name) on update cascade
|
||||||
foreign key (project, jobset, job) references Jobs(project, jobset, name) on update cascade
|
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
|
@ -545,8 +530,7 @@ create table StarredJobs (
|
||||||
primary key (userName, project, jobset, job),
|
primary key (userName, project, jobset, job),
|
||||||
foreign key (userName) references Users(userName) on update cascade on delete cascade,
|
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) 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) 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
|
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -22,7 +22,6 @@ make_schema_at("Hydra::Schema", {
|
||||||
"cachedpathinputs" => "CachedPathInputs",
|
"cachedpathinputs" => "CachedPathInputs",
|
||||||
"cachedsubversioninputs" => "CachedSubversionInputs",
|
"cachedsubversioninputs" => "CachedSubversionInputs",
|
||||||
"failedpaths" => "FailedPaths",
|
"failedpaths" => "FailedPaths",
|
||||||
"jobs" => "Jobs",
|
|
||||||
"jobsetevalinputs" => "JobsetEvalInputs",
|
"jobsetevalinputs" => "JobsetEvalInputs",
|
||||||
"jobsetevalmembers" => "JobsetEvalMembers",
|
"jobsetevalmembers" => "JobsetEvalMembers",
|
||||||
"jobsetevals" => "JobsetEvals",
|
"jobsetevals" => "JobsetEvals",
|
||||||
|
|
4
src/sql/upgrade-67.sql
Normal file
4
src/sql/upgrade-67.sql
Normal 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;
|
|
@ -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");
|
ok(nrQueuedBuildsForJobset($jobset) == 3 , "Evaluating jobs/basic.nix should result in 3 builds");
|
||||||
|
|
||||||
for my $build (queuedBuildsForJobset($jobset)) {
|
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 $newbuild = $db->resultset('Builds')->find($build->id);
|
||||||
my $expected = $build->job->name eq "fails" ? 1 : $build->job->name =~ /with_failed/ ? 6 : 0;
|
my $expected = $build->job eq "fails" ? 1 : $build->job =~ /with_failed/ ? 6 : 0;
|
||||||
ok($newbuild->finished == 1 && $newbuild->buildstatus == $expected, "Build '".$build->job->name."' from jobs/basic.nix should have buildstatus $expected");
|
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
|
# 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(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");
|
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)) {
|
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 $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(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");
|
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)) {
|
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 $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");
|
ok(nrQueuedBuildsForJobset($jobset) == 2 , "Evaluating jobs/build-products.nix should result in 2 builds");
|
||||||
|
|
||||||
for my $build (queuedBuildsForJobset($jobset)) {
|
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);
|
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 $buildproducts = $db->resultset('BuildProducts')->search({ build => $build->id });
|
||||||
my $buildproduct = $buildproducts->next;
|
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");
|
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");
|
ok($buildproduct->name eq "some text.txt", "We should have: \"some text.txt\", but found: ".$buildproduct->name."\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue