From 0d0b925af1e4ffcfc6a561ca505abb22746b6580 Mon Sep 17 00:00:00 2001 From: Shea Levy Date: Sat, 12 Mar 2016 11:03:05 -0500 Subject: [PATCH] Add a plugin to interact with the github status API. Mutliple sections are possible: * jobs: regexp for jobs to match * inputs: the input which corresponds to the github repo/rev whose status we want to report. Can be repeated * authorization: Verbatim contents of the Authorization header. See https://developer.github.com/v3/#authentication. --- src/lib/Hydra/Helper/PluginHooks.pm | 2 +- src/lib/Hydra/Plugin/GithubStatus.pm | 76 ++++++++++++++++++++++++++++ 2 files changed, 77 insertions(+), 1 deletion(-) create mode 100644 src/lib/Hydra/Plugin/GithubStatus.pm diff --git a/src/lib/Hydra/Helper/PluginHooks.pm b/src/lib/Hydra/Helper/PluginHooks.pm index 2813ac65..8ff59bd2 100644 --- a/src/lib/Hydra/Helper/PluginHooks.pm +++ b/src/lib/Hydra/Helper/PluginHooks.pm @@ -15,7 +15,7 @@ sub notifyBuildStarted { $plugin->buildStarted($build); }; if ($@) { - print STDERR "$plugin->buildStarted: $@\n": + print STDERR "$plugin->buildStarted: $@\n"; } } } diff --git a/src/lib/Hydra/Plugin/GithubStatus.pm b/src/lib/Hydra/Plugin/GithubStatus.pm new file mode 100644 index 00000000..e84cec3d --- /dev/null +++ b/src/lib/Hydra/Plugin/GithubStatus.pm @@ -0,0 +1,76 @@ +package Hydra::Plugin::GithubStatus; + +use strict; +use parent 'Hydra::Plugin'; +use HTTP::Request; +use JSON; +use LWP::UserAgent; +use Hydra::Helper::CatalystUtils; + +sub toGithubState { + my ($buildStatus) = @_; + if ($buildStatus == 0) { + return "success"; + } elsif ($buildStatus == 3 || $buildStatus == 4 || $buildStatus == 8 || $buildStatus == 10 || $buildStatus == 11) { + return "error"; + } else { + return "failure"; + } +} + +sub common { + my ($self, $build, $dependents, $finished) = @_; + my $cfg = $self->{config}->{githubstatus}; + my @config = defined $cfg ? ref $cfg eq "ARRAY" ? @$cfg : ($cfg) : (); + my $baseurl = $self->{config}->{'base_uri'} || "http://localhost:3000"; + + # Find matching configs + foreach my $b ($build, @{$dependents}) { + my $jobName = showJobName $b; + my $evals = $build->jobsetevals; + my $ua = LWP::UserAgent->new(); + my $body = encode_json( + { + state => $finished ? toGithubState($b->buildstatus) : "pending", + target_url => "$baseurl/build/" . $b->id, + description => "Hydra build #" . $b->id . " of $jobName", + context => "continuous-integration/hydra" + }); + foreach my $conf (@config) { + next unless $jobName =~ /^$conf->{jobs}$/; + + my $inputs_cfg = $conf->{inputs}; + my @inputs = defined $inputs_cfg ? ref $inputs_cfg eq "ARRAY" ? @$inputs_cfg : ($inputs_cfg) : (); + my %seen = map { $_ => {} } @inputs; + while (my $eval = $evals->next) { + foreach my $input (@inputs) { + my $i = $eval->jobsetevalinputs->find({ name => $input, altnr => 0 }); + next unless defined $i; + my $uri = $i->uri; + my $rev = $i->revision; + my $key = $uri . "-" . $rev; + next if exists $seen{$input}->{$key}; + $seen{$input}->{$key} = 1; + $uri =~ m![:/]([^/]+)/([^/]+?)(?:.git)?$!; + my $req = HTTP::Request->new('POST', "https://api.github.com/repos/$1/$2/statuses/$rev"); + $req->header('Content-Type' => 'application/json'); + $req->header('Accept' => 'application/vnd.github.v3+json'); + $req->header('Authorization' => $conf->{authorization}); + $req->content($body); + my $res = $ua->request($req); + print STDERR $res->status_line, ": ", $res->decoded_content, "\n" unless $res->is_success; + } + } + } + } +} + +sub buildStarted { + common(@_, [], 0); +} + +sub buildFinished { + common(@_, 1); +} + +1;