Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
73 changes: 59 additions & 14 deletions nixos-tests.nix
Original file line number Diff line number Diff line change
Expand Up @@ -145,10 +145,18 @@ in
git -C /tmp/repo add .
git config --global user.email test@localhost
git config --global user.name test

# Create initial commit
git -C /tmp/repo commit -m 'Initial import'
git -C /tmp/repo remote add origin gitea@machine:root/repo
GIT_SSH_COMMAND='ssh -i $HOME/.ssh/privk -o StrictHostKeyChecking=no' \
git -C /tmp/repo push origin master
export GIT_SSH_COMMAND='ssh -i $HOME/.ssh/privk -o StrictHostKeyChecking=no'
git -C /tmp/repo push origin master
git -C /tmp/repo log >&2

# Create PR branch
git -C /tmp/repo checkout -b pr
git -C /tmp/repo commit --allow-empty -m 'Additional change'
git -C /tmp/repo push origin pr
git -C /tmp/repo log >&2
'';

Expand Down Expand Up @@ -185,7 +193,7 @@ in
cat >data.json <<EOF
{
"description": "Trivial",
"checkinterval": "60",
"checkinterval": "20",
"enabled": "1",
"visible": "1",
"keepnr": "1",
Expand All @@ -199,7 +207,12 @@ in
"gitea_repo_name": {"value": "repo", "type": "string"},
"gitea_repo_owner": {"value": "root", "type": "string"},
"gitea_status_repo": {"value": "git", "type": "string"},
"gitea_http_url": {"value": "http://localhost:3001", "type": "string"}
"gitea_http_url": {"value": "http://localhost:3001", "type": "string"},
"pulls": {
"type": "giteapulls",
"value": "localhost:3001 root repo http",
"emailresponsible": false
}
}
}
EOF
Expand Down Expand Up @@ -227,15 +240,31 @@ in
};

smallDrv = pkgs.writeText "jobset.nix" ''
{ trivial = builtins.derivation {
name = "trivial";
system = "${system}";
builder = "/bin/sh";
allowSubstitutes = false;
preferLocalBuild = true;
args = ["-c" "echo success > $out; exit 0"];
{ pulls, ... }:

let
genDrv = name: builtins.derivation {
inherit name;
system = "${system}";
builder = "/bin/sh";
allowSubstitutes = false;
preferLocalBuild = true;
args = ["-c" "echo success > $out; exit 0"];
};
}

prs = builtins.fromJSON (builtins.readFile pulls);
prJobNames = map (n: "pr-''${n}") (builtins.attrNames prs);
prJobset = builtins.listToAttrs (
map (
name: {
inherit name;
value = genDrv name;
}
) prJobNames
);
in {
trivial = genDrv "trivial";
} // prJobset
'';
in
''
Expand Down Expand Up @@ -279,18 +308,34 @@ in
+ '| jq .buildstatus | xargs test 0 -eq'
)

machine.sleep(3)

data = machine.succeed(
'curl -Lf -s "http://localhost:3001/api/v1/repos/root/repo/statuses/$(cd /tmp/repo && git show | head -n1 | awk "{print \\$2}")" '
'curl -Lf -s "http://localhost:3001/api/v1/repos/root/repo/statuses/$(cd /tmp/repo && git show master | head -n1 | awk "{print \\$2}")?sort=leastindex" '
+ "-H 'Accept: application/json' -H 'Content-Type: application/json' "
+ f"-H 'Authorization: token ${api_token}'"
)

response = json.loads(data)

assert len(response) == 2, "Expected exactly three status updates for latest commit (queued, finished)!"
assert len(response) == 2, "Expected exactly two status updates for latest commit (queued, finished)!"
assert response[0]['status'] == "success", "Expected finished status to be success!"
assert response[1]['status'] == "pending", "Expected queued status to be pending!"

# giteapulls test

machine.succeed(
"curl --fail -X POST http://localhost:3001/api/v1/repos/root/repo/pulls "
+ "-H 'Accept: application/json' -H 'Content-Type: application/json' "
+ f"-H 'Authorization: token ${api_token}'"
+ ' -d \'{"title":"Test PR", "base":"master", "head": "pr"}\'''
)

machine.wait_until_succeeds(
'curl -Lf -s http://localhost:3000/build/2 -H "Accept: application/json" '
+ '| jq .buildstatus | xargs test 0 -eq'
)

machine.shutdown()
'';
});
Expand Down
84 changes: 84 additions & 0 deletions src/lib/Hydra/Plugin/GiteaPulls.pm
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
# Allow building based on Gitea pull requests.
#
# Example input:
# "pulls": {
# "type": "giteapulls",
# "value": "example.com alice repo"
# "emailresponsible": false
# }

package Hydra::Plugin::GiteaPulls;

use strict;
use warnings;
use parent 'Hydra::Plugin';
use HTTP::Request;
use LWP::UserAgent;
use JSON::MaybeXS;
use Hydra::Helper::CatalystUtils;
use File::Temp;
use POSIX qw(strftime);

sub supportedInputTypes {
my ($self, $inputTypes) = @_;
$inputTypes->{'giteapulls'} = 'Open Gitea Pull Requests';
}

sub _iterate {
my ($url, $auth, $pulls, $ua) = @_;

my $req = HTTP::Request->new('GET', $url);
$req->header('Authorization' => 'token ' . $auth) if defined $auth;

my $res = $ua->request($req);
my $content = $res->decoded_content;
die "Error pulling from the gitea pulls API: $content\n"
unless $res->is_success;

my $pulls_list = decode_json $content;

foreach my $pull (@$pulls_list) {
$pulls->{$pull->{number}} = $pull;
}

# TODO Make Link header parsing more robust!!!
my @links = split ',', ($res->header("Link") // "");
my $next = "";
foreach my $link (@links) {
my ($url, $rel) = split ";", $link;
if (trim($rel) eq 'rel="next"') {
$next = substr trim($url), 1, -1;
last;
}
}
_iterate($next, $auth, $pulls, $ua) unless $next eq "";
}

sub fetchInput {
my ($self, $type, $name, $value, $project, $jobset) = @_;
return undef if $type ne "giteapulls";

my ($baseUrl, $owner, $repo, $proto) = split ' ', $value;
if (not defined $proto) { # the protocol handler is exposed as an option in order to do integration testing
$proto = "https"
}
my $auth = $self->{config}->{gitea_authorization}->{$owner};

my $ua = LWP::UserAgent->new();
my %pulls;
_iterate("$proto://$baseUrl/api/v1/repos/$owner/$repo/pulls?limit=100", $auth, \%pulls, $ua);

my $tempdir = File::Temp->newdir("gitea-pulls" . "XXXXX", TMPDIR => 1);
my $filename = "$tempdir/gitea-pulls.json";
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is this json already sorted?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

context: #1522

open(my $fh, ">", $filename) or die "Cannot open $filename for writing: $!";
print $fh encode_json \%pulls;
close $fh;

my $storePath = trim(`nix-store --add "$filename"`
or die "cannot copy path $filename to the Nix store.\n");
chomp $storePath;
my $timestamp = time;
return { storePath => $storePath, revision => strftime "%Y%m%d%H%M%S", gmtime($timestamp) };
}

1;