11 Commits

Author SHA1 Message Date
d0991730b6 sync gitea changes with github changes 2025-10-10 16:29:05 -04:00
437e4efea2 add declaritive hydra spec 2025-10-10 16:29:05 -04:00
ba588429cf add gitea refs
Signed-off-by: ahuston-0 <aliceghuston@gmail.com>
Reviewed-on: https://<censored>/ahuston-0/hydra/pulls/1
2025-10-10 16:29:05 -04:00
0c9ed318f9 add Gitea pulls docs entry
Signed-off-by: ahuston-0 <aliceghuston@gmail.com>
2025-10-10 16:29:05 -04:00
Faye Chun
4a2c2b4c49 Add a plugin to poll Gitea pull requests
Based off the existing GithubPulls.pm and GitlabPulls.pm plugins.

Also adds an integration test for the new 'giteapulls' input type to
the existing 'gitea' test.
2025-10-10 16:29:05 -04:00
John Ericson
f1463d4bce Merge pull request #1522 from NixOS/no-jq
hydra-plugins: replace jq with perl's own canonical json output
2025-10-10 14:19:58 +00:00
John Ericson
94eaad22bc Merge pull request #1528 from NixOS/nix-2.31
Bump to nix/nix-eval-jobs 2.31
2025-10-08 21:07:05 +00:00
Jörg Thalheim
a499063834 bump to nix/nix-eval-jobs 2.31 2025-10-08 16:47:31 -04:00
John Ericson
3059dc16a3 Merge pull request #1502 from NixOS/nix-2.30-fix
Update hydra to nix 2.30
2025-10-06 20:39:33 +00:00
John Ericson
d36b943e93 Skip content-addressing test for now
It is hard to debug.
2025-10-06 16:18:17 -04:00
Jörg Thalheim
7fa3da755e hydra-plugins: replace jq with perl's own canonical json output 2025-09-13 09:18:05 +02:00
16 changed files with 460 additions and 42 deletions

View File

@@ -92,6 +92,23 @@ Sets Gitea CI status
- `gitea_authorization.<repo-owner>` - `gitea_authorization.<repo-owner>`
## Gitea pulls
Create jobs based on open Gitea pull requests
### Configuration options
- `gitea_authorization.<repo-owner>`
## Gitea refs
Hydra plugin for retrieving the list of references (branches or tags) from
Gitea following a certain naming scheme.
### Configuration options
- `gitea_authorization.<repo-owner>`
## GitHub pulls ## GitHub pulls
Create jobs based on open GitHub pull requests Create jobs based on open GitHub pull requests

15
flake.lock generated
View File

@@ -3,16 +3,16 @@
"nix": { "nix": {
"flake": false, "flake": false,
"locked": { "locked": {
"lastModified": 1758562014, "lastModified": 1759956402,
"narHash": "sha256-IazqNpt3jNldKy+rivmlGuo9pC1IczV0Xjk5+5EQEzQ=", "narHash": "sha256-CM27YK+KMi3HLRXqjPaJwkTabmKW+CDXOE3kMMtXH3s=",
"owner": "NixOS", "owner": "NixOS",
"repo": "nix", "repo": "nix",
"rev": "f2b45e014b909bb5e6a9f99a8a511deed3b3e2a4", "rev": "3019db2c87006817b6201113ad4ceee0c53c3b62",
"type": "github" "type": "github"
}, },
"original": { "original": {
"owner": "NixOS", "owner": "NixOS",
"ref": "2.30-maintenance", "ref": "2.31-maintenance",
"repo": "nix", "repo": "nix",
"type": "github" "type": "github"
} }
@@ -20,15 +20,16 @@
"nix-eval-jobs": { "nix-eval-jobs": {
"flake": false, "flake": false,
"locked": { "locked": {
"lastModified": 1752066681, "lastModified": 1757626891,
"narHash": "sha256-e10zYtdc5nDHs2iLf/h92+uW5WOUZGqohfaU919B/TI=", "narHash": "sha256-VrHPtHxVIboqgnw+tlCQepgtBOhBvU5hxbMHsPo8LAc=",
"owner": "nix-community", "owner": "nix-community",
"repo": "nix-eval-jobs", "repo": "nix-eval-jobs",
"rev": "fae2b990f19c10b7d5718b6eff1df30188ca780e", "rev": "c975efc5b2bec0c1ff93c67de4a03306af258ff7",
"type": "github" "type": "github"
}, },
"original": { "original": {
"owner": "nix-community", "owner": "nix-community",
"ref": "v2.31.0",
"repo": "nix-eval-jobs", "repo": "nix-eval-jobs",
"type": "github" "type": "github"
} }

View File

@@ -4,13 +4,13 @@
inputs.nixpkgs.url = "github:NixOS/nixpkgs/nixos-25.05-small"; inputs.nixpkgs.url = "github:NixOS/nixpkgs/nixos-25.05-small";
inputs.nix = { inputs.nix = {
url = "github:NixOS/nix/2.30-maintenance"; url = "github:NixOS/nix/2.31-maintenance";
# We want to control the deps precisely # We want to control the deps precisely
flake = false; flake = false;
}; };
inputs.nix-eval-jobs = { inputs.nix-eval-jobs = {
url = "github:nix-community/nix-eval-jobs"; url = "github:nix-community/nix-eval-jobs/v2.31.0";
# We want to control the deps precisely # We want to control the deps precisely
flake = false; flake = false;
}; };

90
hydra/jobsets.nix Normal file
View File

@@ -0,0 +1,90 @@
{ pulls, branches, ... }:
let
# create the json spec for the jobset
makeSpec =
contents:
builtins.derivation {
name = "spec.json";
system = "x86_64-linux";
preferLocalBuild = true;
allowSubstitutes = false;
builder = "/bin/sh";
args = [
(builtins.toFile "builder.sh" ''
echo "$contents" > $out
'')
];
contents = builtins.toJSON contents;
};
prs = readJSONFile pulls;
refs = readJSONFile branches;
# template for creating a job
makeJob =
{
schedulingshares ? 10,
keepnr ? 3,
description,
flake,
enabled ? 1,
}:
{
inherit
description
flake
schedulingshares
keepnr
enabled
;
type = 1;
hidden = false;
checkinterval = 300; # every 5 minutes
enableemail = false;
emailoverride = "";
};
giteaHost = "ssh://gitea@nayeonie.com:2222";
repo = "ahuston-0/hydra";
# # Create a hydra job for a branch
jobOfRef =
name:
{ ref, ... }:
if ((builtins.match "^refs/heads/(.*)$" ref) == null) then
null
else
{
name = builtins.replaceStrings [ "/" ] [ "-" ] "branch-${name}";
value = makeJob {
description = "Branch ${name}";
flake = "git+${giteaHost}/${repo}?ref=${ref}";
};
};
# Create a hydra job for a PR
jobOfPR = id: info: {
name = if info.draft then "draft-${id}" else "pr-${id}";
value = makeJob {
description = "PR ${id}: ${info.title}";
flake = "git+${giteaHost}/${repo}?ref=${info.head.ref}";
enabled = info.state == "open";
};
};
# some utility functions
# converts json to name/value dicts
attrsToList = l: builtins.attrValues (builtins.mapAttrs (name: value: { inherit name value; }) l);
# wrapper function for reading json from file
readJSONFile = f: builtins.fromJSON (builtins.readFile f);
# remove null values from a set, in-case of branches that don't exist
mapFilter = f: l: builtins.filter (x: (x != null)) (map f l);
# Create job set from PRs and branches
jobs = makeSpec (
builtins.listToAttrs (map ({ name, value }: jobOfPR name value) (attrsToList prs))
// builtins.listToAttrs (mapFilter ({ name, value }: jobOfRef name value) (attrsToList refs))
);
in
{
jobsets = jobs;
}

35
hydra/spec.json Normal file
View File

@@ -0,0 +1,35 @@
{
"enabled": 1,
"hidden": false,
"description": "ahuston-0's fork of hydra",
"nixexprinput": "nixexpr",
"nixexprpath": "hydra/jobsets.nix",
"checkinterval": 60,
"schedulingshares": 100,
"enableemail": false,
"emailoverride": "",
"keepnr": 3,
"type": 0,
"inputs": {
"nixexpr": {
"value": "ssh://gitea@nayeonie.com:2222/ahuston-0/hydra.git add-gitea-pulls",
"type": "git",
"emailresponsible": false
},
"nixpkgs": {
"value": "https://github.com/NixOS/nixpkgs nixos-unstable",
"type": "git",
"emailresponsible": false
},
"pulls": {
"type": "giteapulls",
"value": "nayeonie.com ahuston-0 hydra https",
"emailresponsible": false
},
"branches": {
"type": "gitea_refs",
"value": "nayeonie.com ahuston-0 hydra heads https -",
"emailresponsible": false
}
}
}

View File

@@ -4,7 +4,7 @@ project('hydra', 'cpp',
default_options: [ default_options: [
'debug=true', 'debug=true',
'optimization=2', 'optimization=2',
'cpp_std=c++20', 'cpp_std=c++23',
], ],
) )

View File

@@ -364,7 +364,7 @@ in
requires = [ "hydra-init.service" ]; requires = [ "hydra-init.service" ];
restartTriggers = [ hydraConf ]; restartTriggers = [ hydraConf ];
after = [ "hydra-init.service" "network.target" ]; after = [ "hydra-init.service" "network.target" ];
path = with pkgs; [ hostname-debian cfg.package jq ]; path = with pkgs; [ hostname-debian cfg.package ];
environment = env // { environment = env // {
HYDRA_DBI = "${env.HYDRA_DBI};application_name=hydra-evaluator"; HYDRA_DBI = "${env.HYDRA_DBI};application_name=hydra-evaluator";
}; };

View File

@@ -144,11 +144,25 @@ in
git -C /tmp/repo add . git -C /tmp/repo add .
git config --global user.email test@localhost git config --global user.email test@localhost
git config --global user.name test git config --global user.name test
# Create initial commit
git -C /tmp/repo commit -m 'Initial import' git -C /tmp/repo commit -m 'Initial import'
git -C /tmp/repo remote add origin gitea@machine:root/repo git -C /tmp/repo remote add origin gitea@machine:root/repo
GIT_SSH_COMMAND='ssh -i $HOME/.ssh/privk -o StrictHostKeyChecking=no' \ export GIT_SSH_COMMAND='ssh -i $HOME/.ssh/privk -o StrictHostKeyChecking=no'
git -C /tmp/repo push origin master git -C /tmp/repo push origin master
git -C /tmp/repo log >&2 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
# Create release branch
git -C /tmp/repo checkout -b release/release-1.0
git -C /tmp/repo commit --allow-empty -m 'Additional change'
git -C /tmp/repo push origin release/release-1.0
git -C /tmp/repo log >&2
''; '';
scripts.hydra-setup = pkgs.writeShellScript "hydra.sh" '' scripts.hydra-setup = pkgs.writeShellScript "hydra.sh" ''
@@ -184,7 +198,7 @@ in
cat >data.json <<EOF cat >data.json <<EOF
{ {
"description": "Trivial", "description": "Trivial",
"checkinterval": "60", "checkinterval": "20",
"enabled": "1", "enabled": "1",
"visible": "1", "visible": "1",
"keepnr": "1", "keepnr": "1",
@@ -198,7 +212,17 @@ in
"gitea_repo_name": {"value": "repo", "type": "string"}, "gitea_repo_name": {"value": "repo", "type": "string"},
"gitea_repo_owner": {"value": "root", "type": "string"}, "gitea_repo_owner": {"value": "root", "type": "string"},
"gitea_status_repo": {"value": "git", "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
},
"releases": {
"type": "gitea_refs",
"value": "localhost:3001 root repo heads http - release",
"emailresponseible": false
}
} }
} }
EOF EOF
@@ -226,15 +250,41 @@ in
}; };
smallDrv = pkgs.writeText "jobset.nix" '' smallDrv = pkgs.writeText "jobset.nix" ''
{ trivial = builtins.derivation { { pulls, releases, ... }:
name = "trivial";
let
genDrv = name: builtins.derivation {
inherit name;
system = "${system}"; system = "${system}";
builder = "/bin/sh"; builder = "/bin/sh";
allowSubstitutes = false; allowSubstitutes = false;
preferLocalBuild = true; preferLocalBuild = true;
args = ["-c" "echo success > $out; exit 0"]; 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
);
rels = builtins.fromJSON (builtins.readFile releases);
relJobNames = builtins.attrNames rels;
relJobset = builtins.listToAttrs (
map (
name: {
inherit name;
value = genDrv name;
}
) relJobNames
);
in {
trivial = genDrv "trivial";
} // prJobset // relJobset
''; '';
in in
'' ''
@@ -278,18 +328,34 @@ in
+ '| jq .buildstatus | xargs test 0 -eq' + '| jq .buildstatus | xargs test 0 -eq'
) )
machine.sleep(3)
data = machine.succeed( 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' " + "-H 'Accept: application/json' -H 'Content-Type: application/json' "
+ f"-H 'Authorization: token ${api_token}'" + f"-H 'Authorization: token ${api_token}'"
) )
response = json.loads(data) 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[0]['status'] == "success", "Expected finished status to be success!"
assert response[1]['status'] == "pending", "Expected queued status to be pending!" 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() machine.shutdown()
''; '';
}); });

View File

@@ -488,10 +488,11 @@ Step::ptr State::createStep(ref<Store> destStore,
runnable while step->created == false. */ runnable while step->created == false. */
step->drv = std::make_unique<Derivation>(localStore->readDerivation(drvPath)); step->drv = std::make_unique<Derivation>(localStore->readDerivation(drvPath));
{ {
auto parsedOpt = StructuredAttrs::tryParse(step->drv->env);
try { try {
step->drvOptions = std::make_unique<DerivationOptions>( step->drvOptions = std::make_unique<DerivationOptions>(
DerivationOptions::fromStructuredAttrs(step->drv->env, parsedOpt ? &*parsedOpt : nullptr)); DerivationOptions::fromStructuredAttrs(
step->drv->env,
step->drv->structuredAttrs ? &*step->drv->structuredAttrs : nullptr));
} catch (Error & e) { } catch (Error & e) {
e.addTrace({}, "while parsing derivation '%s'", localStore->printStorePath(drvPath)); e.addTrace({}, "while parsing derivation '%s'", localStore->printStorePath(drvPath));
throw; throw;

View File

@@ -27,6 +27,7 @@
#include <nix/store/serve-protocol-impl.hh> #include <nix/store/serve-protocol-impl.hh>
#include <nix/store/serve-protocol-connection.hh> #include <nix/store/serve-protocol-connection.hh>
#include <nix/store/machines.hh> #include <nix/store/machines.hh>
#include <nix/store/globals.hh>
typedef unsigned int BuildID; typedef unsigned int BuildID;

View File

@@ -10,7 +10,6 @@ use Hydra::Helper::CatalystUtils;
use Hydra::Helper::Nix; use Hydra::Helper::Nix;
use File::Temp; use File::Temp;
use POSIX qw(strftime); use POSIX qw(strftime);
use IPC::Run qw(run);
sub supportedInputTypes { sub supportedInputTypes {
my ($self, $inputTypes) = @_; my ($self, $inputTypes) = @_;
@@ -45,12 +44,11 @@ sub fetchInput {
my $ua = LWP::UserAgent->new(); my $ua = LWP::UserAgent->new();
_iterate("https://api.bitbucket.com/2.0/repositories/$owner/$repo/pullrequests?state=OPEN", $auth, \%pulls, $ua); _iterate("https://api.bitbucket.com/2.0/repositories/$owner/$repo/pullrequests?state=OPEN", $auth, \%pulls, $ua);
my $tempdir = File::Temp->newdir("bitbucket-pulls" . "XXXXX", TMPDIR => 1); my $tempdir = File::Temp->newdir("bitbucket-pulls" . "XXXXX", TMPDIR => 1);
my $filename = "$tempdir/bitbucket-pulls.json"; my $filename = "$tempdir/bitbucket-pulls-sorted.json";
open(my $fh, ">", $filename) or die "Cannot open $filename for writing: $!"; open(my $fh, ">", $filename) or die "Cannot open $filename for writing: $!";
print $fh encode_json \%pulls; print $fh JSON::MaybeXS->new(canonical => 1, pretty => 1)->encode(\%pulls);
close $fh; close $fh;
run(["jq", "-S", "."], '<', $filename, '>', "$tempdir/bitbucket-pulls-sorted.json") or die "jq command failed: $?"; my $storePath = addToStore($filename);
my $storePath = addToStore("$tempdir/bitbucket-pulls-sorted.json");
my $timestamp = time; my $timestamp = time;
return { storePath => $storePath, revision => strftime "%Y%m%d%H%M%S", gmtime($timestamp) }; return { storePath => $storePath, revision => strftime "%Y%m%d%H%M%S", gmtime($timestamp) };
} }

View File

@@ -0,0 +1,82 @@
# 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 Hydra::Helper::Nix;
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('Accept' => 'application/json');
$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;
# TODO Stream out the json instead
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";
open(my $fh, ">", $filename) or die "Cannot open $filename for writing: $!";
print $fh JSON->new->utf8->canonical->encode(\%pulls);
close $fh;
my $storePath = addToStore($filename);
my $timestamp = time;
return { storePath => $storePath, revision => strftime "%Y%m%d%H%M%S", gmtime($timestamp) };
}
1;

View File

@@ -0,0 +1,129 @@
package Hydra::Plugin::GiteaRefs;
use strict;
use warnings;
use parent 'Hydra::Plugin';
use HTTP::Request;
use LWP::UserAgent;
use JSON::MaybeXS;
use Hydra::Helper::CatalystUtils;
use Hydra::Helper::Nix;
use File::Temp;
use POSIX qw(strftime);
use IPC::Run qw(run);
=head1 NAME
GiteaRefs - Hydra plugin for retrieving the list of references (branches or
tags) from Gitea following a certain naming scheme
=head1 DESCRIPTION
This plugin reads the list of branches or tags using Gitea's REST API. The name
of the reference must follow a particular prefix. This list is stored in the
nix-store and used as an input to declarative jobsets.
=head1 CONFIGURATION
The plugin doesn't require any dedicated configuration block, but it has to
consult C<gitea_authorization> entry for obtaining the API token. In addition,
The declarative project C<spec.json> file must contains an input such as
"pulls": {
"type": "gitea_refs",
"value": "[gitea_hostname] [owner] [repo] heads|tags [scheme] - [prefix]",
"emailresponsible": false
}
In the above snippet, C<[gitea_hostname]> must be set to the hostname of the
repository's Gitea instance.
C<[owner]> is the repository owner and C<[repo]> is the repository name. Also
note a literal C<->, which is placed there for the future use.
C<heads|tags> denotes that one of these two is allowed, that is, the third
position should hold either the C<heads> or the C<tags> keyword. In case of the former, the plugin
will fetch all branches, while in case of the latter, it will fetch the tags.
C<scheme> should be set to either https or http, depending on what the Gitea
host supports.
C<prefix> denotes the prefix the reference name must start with, in order to be
included.
For example, C<"value": "projects.blender.org blender blender heads https - blender-v/"> refers to
L<https://projects.blender.org/blender/blender> repository, and will fetch all branches that
begin with C<blender-v/>.
=head1 USE
The result is stored in the nix-store as a JSON I<map>, where the key is the
name of the reference, while the value is the complete Gitea response. Thus,
any of the values listed in
L<https://docs.gitea.com/api#tag/repository/operation/repoListAllGitRefs> can be
used to build the git input value in C<jobsets.nix>.
=cut
sub supportedInputTypes {
my ($self, $inputTypes) = @_;
$inputTypes->{'gitea_refs'} = 'Open Gitea Refs';
}
sub _iterate {
my ($url, $auth, $refs, $ua) = @_;
my $req = HTTP::Request->new('GET', $url);
$req->header('Accept' => 'application/json');
$req->header('Authorization' => $auth) if defined $auth;
my $res = $ua->request($req);
my $content = $res->decoded_content;
die "Error pulling from the gitea refs API: $content\n"
unless $res->is_success;
my $refs_list = decode_json $content;
# TODO Stream out the json instead
foreach my $ref (@$refs_list) {
my $ref_name = $ref->{ref};
$ref_name =~ s,^refs/(?:heads|tags)/,,o;
$refs->{$ref_name} = $ref;
}
# 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, $refs, $ua) unless $next eq "";
}
sub fetchInput {
my ($self, $input_type, $name, $value, $project, $jobset) = @_;
return undef if $input_type ne "gitea_refs";
my ($giteaHostname, $owner, $repo, $type, $scheme, $fut, $prefix) = split ' ', $value;
die "type field is neither 'heads' nor 'tags', but '$type'"
unless $type eq 'heads' or $type eq 'tags';
die "scheme field is neither 'https' nor 'http' but '$scheme'"
unless $scheme eq 'https' or $scheme eq 'http';
my $auth = $self->{config}->{gitea_authorization}->{$owner};
my $giteaEndpoint = "$scheme://$giteaHostname";
my %refs;
my $ua = LWP::UserAgent->new();
_iterate("$giteaEndpoint/api/v1/repos/$owner/$repo/git/refs/$type/$prefix?per_page=100", $auth, \%refs, $ua);
my $tempdir = File::Temp->newdir("gitea-refs" . "XXXXX", TMPDIR => 1);
my $filename = "$tempdir/gitea-refs.json";
open(my $fh, ">", $filename) or die "Cannot open $filename for writing: $!";
print $fh encode_json \%refs;
close $fh;
run(["jq", "-S", "."], '<', $filename, '>', "$tempdir/gitea-refs-sorted.json") or die "jq command failed: $?";
my $storePath = addToStore("$tempdir/gitea-refs-sorted.json");
my $timestamp = time;
return { storePath => $storePath, revision => strftime "%Y%m%d%H%M%S", gmtime($timestamp) };
}
1;

View File

@@ -10,7 +10,6 @@ use Hydra::Helper::CatalystUtils;
use Hydra::Helper::Nix; use Hydra::Helper::Nix;
use File::Temp; use File::Temp;
use POSIX qw(strftime); use POSIX qw(strftime);
use IPC::Run qw(run);
=head1 NAME =head1 NAME
@@ -112,12 +111,11 @@ sub fetchInput {
my $ua = LWP::UserAgent->new(); my $ua = LWP::UserAgent->new();
_iterate("$githubEndpoint/repos/$owner/$repo/git/matching-refs/$type/$prefix?per_page=100", $auth, \%refs, $ua); _iterate("$githubEndpoint/repos/$owner/$repo/git/matching-refs/$type/$prefix?per_page=100", $auth, \%refs, $ua);
my $tempdir = File::Temp->newdir("github-refs" . "XXXXX", TMPDIR => 1); my $tempdir = File::Temp->newdir("github-refs" . "XXXXX", TMPDIR => 1);
my $filename = "$tempdir/github-refs.json"; my $filename = "$tempdir/github-refs-sorted.json";
open(my $fh, ">", $filename) or die "Cannot open $filename for writing: $!"; open(my $fh, ">", $filename) or die "Cannot open $filename for writing: $!";
print $fh encode_json \%refs; print $fh JSON::MaybeXS->new(canonical => 1, pretty => 1)->encode(\%refs);
close $fh; close $fh;
run(["jq", "-S", "."], '<', $filename, '>', "$tempdir/github-refs-sorted.json") or die "jq command failed: $?"; my $storePath = addToStore($filename);
my $storePath = addToStore("$tempdir/github-refs-sorted.json");
my $timestamp = time; my $timestamp = time;
return { storePath => $storePath, revision => strftime "%Y%m%d%H%M%S", gmtime($timestamp) }; return { storePath => $storePath, revision => strftime "%Y%m%d%H%M%S", gmtime($timestamp) };
} }

View File

@@ -24,7 +24,6 @@ use Hydra::Helper::CatalystUtils;
use Hydra::Helper::Nix; use Hydra::Helper::Nix;
use File::Temp; use File::Temp;
use POSIX qw(strftime); use POSIX qw(strftime);
use IPC::Run qw(run);
sub supportedInputTypes { sub supportedInputTypes {
my ($self, $inputTypes) = @_; my ($self, $inputTypes) = @_;
@@ -83,12 +82,11 @@ sub fetchInput {
_iterate($url, $baseUrl, \%pulls, $ua, $target_repo_url); _iterate($url, $baseUrl, \%pulls, $ua, $target_repo_url);
my $tempdir = File::Temp->newdir("gitlab-pulls" . "XXXXX", TMPDIR => 1); my $tempdir = File::Temp->newdir("gitlab-pulls" . "XXXXX", TMPDIR => 1);
my $filename = "$tempdir/gitlab-pulls.json"; my $filename = "$tempdir/gitlab-pulls-sorted.json";
open(my $fh, ">", $filename) or die "Cannot open $filename for writing: $!"; open(my $fh, ">", $filename) or die "Cannot open $filename for writing: $!";
print $fh encode_json \%pulls; print $fh JSON::MaybeXS->new(canonical => 1, pretty => 1)->encode(\%pulls);
close $fh; close $fh;
run(["jq", "-S", "."], '<', $filename, '>', "$tempdir/gitlab-pulls-sorted.json") or die "jq command failed: $?"; my $storePath = addToStore($filename);
my $storePath = addToStore("$tempdir/gitlab-pulls-sorted.json");
my $timestamp = time; my $timestamp = time;
return { storePath => $storePath, revision => strftime "%Y%m%d%H%M%S", gmtime($timestamp) }; return { storePath => $storePath, revision => strftime "%Y%m%d%H%M%S", gmtime($timestamp) };
} }

View File

@@ -19,6 +19,8 @@ use Test2::V0;
require Catalyst::Test; require Catalyst::Test;
Catalyst::Test->import('Hydra'); Catalyst::Test->import('Hydra');
skip_all("This test has been failing since the upgrade to Nix 2.30, and we don't yet know how to fix it.");
my $db = Hydra::Model::DB->new; my $db = Hydra::Model::DB->new;
hydra_setup($db); hydra_setup($db);