Support push notification of repository changes

External machines can now notify Hydra that it should check a
repository by sending a GET or PUSH request to /api/push, providing a
list of jobsets to be checked and/or a list of repository URLs.  In
the latter case, all jobsets that have any of the specified
repositories as an input will be checked.

For instance, you can configure GitHub or BitBucket to send a request
to the URL

  http://hydra.example.org/api/push?repos=git://github.com/NixOS/nixpkgs.git

to trigger evaluation of all jobsets that have
git://github.com/NixOS/nixpkgs.git as an input, or to the URL

  http://hydra.example.org/api/push?jobsets=patchelf:trunk,nixpkgs:trunk

to trigger evaluation of just the specified jobsets.
This commit is contained in:
Eelco Dolstra
2013-02-25 21:04:10 +01:00
parent ddcb9f1d5d
commit 42d2015357
8 changed files with 95 additions and 11 deletions

View File

@ -1,5 +1,6 @@
package Hydra::Controller::API;
use utf8;
use strict;
use warnings;
use base 'Catalyst::Controller';
@ -22,6 +23,16 @@ sub api : Chained('/') PathPart('api') CaptureArgs(0) {
}
sub end : ActionClass('RenderView') {
my ($self, $c) = @_;
if (scalar @{$c->error}) {
$c->stash->{json}->{error} = join "\n", @{$c->error};
$c->forward('View::JSON');
$c->clear_errors;
}
}
sub projectToHash {
my ($project) = @_;
return {
@ -274,4 +285,39 @@ sub logdiff : Chained('api') PathPart('logdiff') Args(2) {
}
sub triggerJobset {
my ($self, $c, $jobset) = @_;
txn_do($c->model('DB')->schema, sub {
$jobset->update({ triggertime => time });
});
push @{$c->{stash}->{json}->{jobsetsTriggered}}, $jobset->project->name . ":" . $jobset->name;
}
sub push : Chained('api') PathPart('push') Args(0) {
my ($self, $c) = @_;
$c->{stash}->{json}->{jobsetsTriggered} = [];
my @jobsets = split /,/, ($c->request->params->{jobsets} // "");
foreach my $s (@jobsets) {
my ($p, $j) = parseJobsetName($s);
my $jobset = $c->model('DB::Jobsets')->find($p, $j) or notFound($c, "Jobset $p:$j does not exist.");
next unless $jobset->project->enabled && $jobset->enabled;
triggerJobset($self, $c, $jobset);
}
my @repos = split /,/, ($c->request->params->{repos} // "");
foreach my $r (@repos) {
triggerJobset($self, $c, $_) foreach $c->model('DB::Jobsets')->search(
{ 'project.enabled' => 1, 'me.enabled' => 1 },
{ join => 'project'
, where => \ [ 'exists (select 1 from JobsetInputAlts where project = me.project and jobset = me.name and value = ?)', [ 'value', $r ] ]
});
}
$c->forward('View::JSON');
}
1;

View File

@ -563,11 +563,10 @@ sub clone_submit : Chained('build') PathPart('clone/submit') Args(0) {
sub get_info : Chained('build') PathPart('api/get-info') Args(0) {
my ($self, $c) = @_;
my $build = $c->stash->{build};
# !!! strip the json prefix
$c->stash->{jsonBuildId} = $build->id;
$c->stash->{jsonDrvPath} = $build->drvpath;
$c->stash->{json}->{buildId} = $build->id;
$c->stash->{json}->{drvPath} = $build->drvpath;
my $out = getMainOutput($build);
$c->stash->{jsonOutPath} = $out->path if defined $out;
$c->stash->{json}->{outPath} = $out->path if defined $out;
$c->forward('View::JSON');
}

View File

@ -13,6 +13,7 @@ our @EXPORT = qw(
requireLogin requireProjectOwner requireAdmin requirePost isAdmin isProjectOwner
trim
getLatestFinishedEval
parseJobsetName
$pathCompRE $relPathRE $relNameRE $projectNameRE $jobsetNameRE $jobNameRE $systemRE
@buildListColumns
);
@ -171,4 +172,11 @@ Readonly our $jobNameRE => "(?:$attrNameRE(?:\\.$attrNameRE)*)";
Readonly our $systemRE => "(?:[a-z0-9_]+-[a-z0-9_]+)";
sub parseJobsetName {
my ($s) = @_;
$s =~ /^($projectNameRE):($jobsetNameRE)$/ or die "invalid jobset specifier $s\n";
return ($1, $2);
}
1;

View File

@ -66,6 +66,11 @@ __PACKAGE__->table("Jobsets");
data_type: 'integer'
is_nullable: 1
=head2 triggertime
data_type: 'integer'
is_nullable: 1
=head2 enabled
data_type: 'integer'
@ -114,6 +119,8 @@ __PACKAGE__->add_columns(
{ data_type => "integer", is_nullable => 1 },
"lastcheckedtime",
{ data_type => "integer", is_nullable => 1 },
"triggertime",
{ data_type => "integer", is_nullable => 1 },
"enabled",
{ data_type => "integer", default_value => 1, is_nullable => 0 },
"enableemail",
@ -245,7 +252,7 @@ __PACKAGE__->belongs_to(
);
# Created by DBIx::Class::Schema::Loader v0.07033 @ 2013-01-22 13:29:36
# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:9smV/zbSSxQNLiBcnADFXA
# Created by DBIx::Class::Schema::Loader v0.07033 @ 2013-02-25 19:10:12
# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:SvBgR0iH9NjVH4jvBATYPA
1;