Compare commits

...

14 Commits

Author SHA1 Message Date
Jörg Thalheim
b254962aa8 make flake.nix test pure 2025-11-11 15:39:23 +01:00
Jörg Thalheim
281b49208c hydra-eval-jobs: use nix-eval-jobs's --select rather --expr
the current use of builtins.getFlake, mean we don't have pure evaluation
2025-11-11 15:12:42 +01:00
Jörg Thalheim
241ab71800 Merge pull request #1536 from NixOS/fix-1535
Revert "Deduplicate protocol code more with `ServeProto::BasicClientConnection`
2025-11-06 19:23:48 +00:00
Jörg Thalheim
78ed8d7aa5 Merge pull request #1533 from hacker1024/patch-3
GithubRefs: Allow arbitrary ref types
2025-11-06 09:38:05 +00:00
John Ericson
4bd941daa8 Revert "Deduplicate protocol code more with ServeProto::BasicClientConnection"
This reverts commit 58846b0a1c.
2025-10-30 14:01:38 -04:00
John Ericson
0414ae64eb Merge pull request #1531 from NixOS/nix-2.32
Bump Nix 2.32
2025-10-16 06:17:02 +00:00
John Ericson
449791b1c7 Upgrade Nix to 2.32 2025-10-16 01:58:08 -04:00
Joshua Leivenzon
d7b40c4233 GithubRefs: Allow arbitrary ref types
GitHub's reference list API does not actually restrict the specified type, so don't artificially restrict it.

The API does not actually make a distinction between the "type" and "prefix" at all, but this is maintained for backwards compatibility. The two are simply concatenated.
2025-10-16 16:35:31 +11:00
John Ericson
524b232032 Merge pull request #1532 from NixOS/proto-dedup
Deduplicate protocol code more with `ServeProto::BasicClientConnection`
2025-10-15 22:15:30 +00:00
John Ericson
58846b0a1c Deduplicate protocol code more with ServeProto::BasicClientConnection
I did this in Nix for this purpose, but didn't get around to actually
taking advantage of it here, until now.
2025-10-15 18:00:20 -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
Jörg Thalheim
7fa3da755e hydra-plugins: replace jq with perl's own canonical json output 2025-09-13 09:18:05 +02:00
15 changed files with 146 additions and 126 deletions

15
flake.lock generated
View File

@@ -3,16 +3,16 @@
"nix": { "nix": {
"flake": false, "flake": false,
"locked": { "locked": {
"lastModified": 1758562014, "lastModified": 1760573252,
"narHash": "sha256-IazqNpt3jNldKy+rivmlGuo9pC1IczV0Xjk5+5EQEzQ=", "narHash": "sha256-mcvNeNdJP5R7huOc8Neg0qZESx/0DMg8Fq6lsdx0x8U=",
"owner": "NixOS", "owner": "NixOS",
"repo": "nix", "repo": "nix",
"rev": "f2b45e014b909bb5e6a9f99a8a511deed3b3e2a4", "rev": "3c39583e5512729f9c5a44c3b03b6467a2acd963",
"type": "github" "type": "github"
}, },
"original": { "original": {
"owner": "NixOS", "owner": "NixOS",
"ref": "2.30-maintenance", "ref": "2.32-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": 1760478325,
"narHash": "sha256-e10zYtdc5nDHs2iLf/h92+uW5WOUZGqohfaU919B/TI=", "narHash": "sha256-hA+NOH8KDcsuvH7vJqSwk74PyZP3MtvI/l+CggZcnTc=",
"owner": "nix-community", "owner": "nix-community",
"repo": "nix-eval-jobs", "repo": "nix-eval-jobs",
"rev": "fae2b990f19c10b7d5718b6eff1df30188ca780e", "rev": "daa42f9e9c84aeff1e325dd50fda321f53dfd02c",
"type": "github" "type": "github"
}, },
"original": { "original": {
"owner": "nix-community", "owner": "nix-community",
"ref": "v2.32.1",
"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.32-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.32.1";
# We want to control the deps precisely # We want to control the deps precisely
flake = false; flake = 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

@@ -14,6 +14,7 @@
#include <nix/util/current-process.hh> #include <nix/util/current-process.hh>
#include <nix/util/processes.hh> #include <nix/util/processes.hh>
#include <nix/util/util.hh> #include <nix/util/util.hh>
#include <nix/store/export-import.hh>
#include <nix/store/serve-protocol.hh> #include <nix/store/serve-protocol.hh>
#include <nix/store/serve-protocol-impl.hh> #include <nix/store/serve-protocol-impl.hh>
#include <nix/store/ssh.hh> #include <nix/store/ssh.hh>
@@ -104,7 +105,7 @@ static void copyClosureTo(
std::chrono::seconds(600)); std::chrono::seconds(600));
conn.to << ServeProto::Command::ImportPaths; conn.to << ServeProto::Command::ImportPaths;
destStore.exportPaths(missing, conn.to); exportPaths(destStore, missing, conn.to);
conn.to.flush(); conn.to.flush();
if (readInt(conn.from) != 1) if (readInt(conn.from) != 1)
@@ -262,16 +263,18 @@ static BuildResult performBuild(
// Since this a `BasicDerivation`, `staticOutputHashes` will not // Since this a `BasicDerivation`, `staticOutputHashes` will not
// do any real work. // do any real work.
auto outputHashes = staticOutputHashes(localStore, drv); auto outputHashes = staticOutputHashes(localStore, drv);
for (auto & [outputName, output] : drvOutputs) { if (auto * successP = result.tryGetSuccess()) {
auto outputPath = output.second; for (auto & [outputName, output] : drvOutputs) {
// Weve just asserted that the output paths of the derivation auto outputPath = output.second;
// were known // Weve just asserted that the output paths of the derivation
assert(outputPath); // were known
auto outputHash = outputHashes.at(outputName); assert(outputPath);
auto drvOutput = DrvOutput { outputHash, outputName }; auto outputHash = outputHashes.at(outputName);
result.builtOutputs.insert_or_assign( auto drvOutput = DrvOutput { outputHash, outputName };
std::move(outputName), successP->builtOutputs.insert_or_assign(
Realisation { drvOutput, *outputPath }); std::move(outputName),
Realisation { drvOutput, *outputPath });
}
} }
} }
@@ -336,54 +339,68 @@ void RemoteResult::updateWithBuildResult(const nix::BuildResult & buildResult)
startTime = buildResult.startTime; startTime = buildResult.startTime;
stopTime = buildResult.stopTime; stopTime = buildResult.stopTime;
timesBuilt = buildResult.timesBuilt; timesBuilt = buildResult.timesBuilt;
errorMsg = buildResult.errorMsg;
isNonDeterministic = buildResult.isNonDeterministic;
switch ((BuildResult::Status) buildResult.status) { std::visit(overloaded{
case BuildResult::Built: [&](const BuildResult::Success & success) {
stepStatus = bsSuccess; stepStatus = bsSuccess;
break; switch (success.status) {
case BuildResult::Substituted: case BuildResult::Success::Built:
case BuildResult::AlreadyValid: break;
stepStatus = bsSuccess; case BuildResult::Success::Substituted:
isCached = true; case BuildResult::Success::AlreadyValid:
break; case BuildResult::Success::ResolvesToAlreadyValid:
case BuildResult::PermanentFailure: isCached = true;
stepStatus = bsFailed; break;
canCache = true; default:
errorMsg = ""; assert(false);
break; }
case BuildResult::InputRejected: },
case BuildResult::OutputRejected: [&](const BuildResult::Failure & failure) {
stepStatus = bsFailed; errorMsg = failure.errorMsg;
canCache = true; isNonDeterministic = failure.isNonDeterministic;
break; switch (failure.status) {
case BuildResult::TransientFailure: case BuildResult::Failure::PermanentFailure:
stepStatus = bsFailed; stepStatus = bsFailed;
canRetry = true; canCache = true;
errorMsg = ""; errorMsg = "";
break; break;
case BuildResult::TimedOut: case BuildResult::Failure::InputRejected:
stepStatus = bsTimedOut; case BuildResult::Failure::OutputRejected:
errorMsg = ""; stepStatus = bsFailed;
break; canCache = true;
case BuildResult::MiscFailure: break;
stepStatus = bsAborted; case BuildResult::Failure::TransientFailure:
canRetry = true; stepStatus = bsFailed;
break; canRetry = true;
case BuildResult::LogLimitExceeded: errorMsg = "";
stepStatus = bsLogLimitExceeded; break;
break; case BuildResult::Failure::TimedOut:
case BuildResult::NotDeterministic: stepStatus = bsTimedOut;
stepStatus = bsNotDeterministic; errorMsg = "";
canRetry = false; break;
canCache = true; case BuildResult::Failure::MiscFailure:
break; stepStatus = bsAborted;
default: canRetry = true;
stepStatus = bsAborted; break;
break; case BuildResult::Failure::LogLimitExceeded:
} stepStatus = bsLogLimitExceeded;
break;
case BuildResult::Failure::NotDeterministic:
stepStatus = bsNotDeterministic;
canRetry = false;
canCache = true;
break;
case BuildResult::Failure::CachedFailure:
case BuildResult::Failure::DependencyFailed:
case BuildResult::Failure::NoSubstituters:
case BuildResult::Failure::HashMismatch:
stepStatus = bsAborted;
break;
default:
assert(false);
}
},
}, buildResult.inner);
} }
/* Utility guard object to auto-release a semaphore on destruction. */ /* Utility guard object to auto-release a semaphore on destruction. */
@@ -405,7 +422,7 @@ void State::buildRemote(ref<Store> destStore,
std::function<void(StepState)> updateStep, std::function<void(StepState)> updateStep,
NarMemberDatas & narMembers) NarMemberDatas & narMembers)
{ {
assert(BuildResult::TimedOut == 8); assert(BuildResult::Failure::TimedOut == 8);
auto [logFile, logFD] = build_remote::openLogFile(logDir, step->drvPath); auto [logFile, logFD] = build_remote::openLogFile(logDir, step->drvPath);
AutoDelete logFileDel(logFile, false); AutoDelete logFileDel(logFile, false);
@@ -514,7 +531,7 @@ void State::buildRemote(ref<Store> destStore,
updateStep(ssBuilding); updateStep(ssBuilding);
BuildResult buildResult = build_remote::performBuild( auto buildResult = build_remote::performBuild(
conn, conn,
*localStore, *localStore,
step->drvPath, step->drvPath,
@@ -556,8 +573,9 @@ void State::buildRemote(ref<Store> destStore,
wakeDispatcher(); wakeDispatcher();
StorePathSet outputs; StorePathSet outputs;
for (auto & [_, realisation] : buildResult.builtOutputs) if (auto * successP = buildResult.tryGetSuccess())
outputs.insert(realisation.outPath); for (auto & [_, realisation] : successP->builtOutputs)
outputs.insert(realisation.outPath);
/* Copy the output paths. */ /* Copy the output paths. */
if (!machine->isLocalhost() || localStore != std::shared_ptr<Store>(destStore)) { if (!machine->isLocalhost() || localStore != std::shared_ptr<Store>(destStore)) {
@@ -590,15 +608,17 @@ void State::buildRemote(ref<Store> destStore,
/* Register the outputs of the newly built drv */ /* Register the outputs of the newly built drv */
if (experimentalFeatureSettings.isEnabled(Xp::CaDerivations)) { if (experimentalFeatureSettings.isEnabled(Xp::CaDerivations)) {
auto outputHashes = staticOutputHashes(*localStore, *step->drv); auto outputHashes = staticOutputHashes(*localStore, *step->drv);
for (auto & [outputName, realisation] : buildResult.builtOutputs) { if (auto * successP = buildResult.tryGetSuccess()) {
// Register the resolved drv output for (auto & [outputName, realisation] : successP->builtOutputs) {
destStore->registerDrvOutput(realisation); // Register the resolved drv output
destStore->registerDrvOutput(realisation);
// Also register the unresolved one // Also register the unresolved one
auto unresolvedRealisation = realisation; auto unresolvedRealisation = realisation;
unresolvedRealisation.signatures.clear(); unresolvedRealisation.signatures.clear();
unresolvedRealisation.id.drvHash = outputHashes.at(outputName); unresolvedRealisation.id.drvHash = outputHashes.at(outputName);
destStore->registerDrvOutput(unresolvedRealisation); destStore->registerDrvOutput(unresolvedRealisation);
}
} }
} }

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

@@ -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
@@ -19,9 +18,8 @@ tags) from GitHub following a certain naming scheme
=head1 DESCRIPTION =head1 DESCRIPTION
This plugin reads the list of branches or tags using GitHub's REST API. The name This plugin reads the list of branches or tags using GitHub's REST API. This
of the reference must follow a particular prefix. This list is stored in the list is stored in the nix-store and used as an input to declarative jobsets.
nix-store and used as an input to declarative jobsets.
=head1 CONFIGURATION =head1 CONFIGURATION
@@ -35,7 +33,7 @@ The declarative project C<spec.json> file must contains an input such as
"pulls": { "pulls": {
"type": "github_refs", "type": "github_refs",
"value": "[owner] [repo] heads|tags - [prefix]", "value": "[owner] [repo] [type] - [prefix]",
"emailresponsible": false "emailresponsible": false
} }
@@ -43,12 +41,11 @@ In the above snippet, 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 repository name. Also note a literal C<->, which is placed there for the future
use. use.
C<heads|tags> denotes that one of these two is allowed, that is, the third C<[type]> is the type of ref to list. Typical values are "heads", "tags", and
position should hold either the C<heads> or the C<tags> keyword. In case of the former, the plugin "pull". "." will include all types.
will fetch all branches, while in case of the latter, it will fetch the tags.
C<prefix> denotes the prefix the reference name must start with, in order to be C<prefix> denotes the prefix the reference name must start with, in order to be
included. included. "." will include all references.
For example, C<"value": "nixos hydra heads - release/"> refers to For example, C<"value": "nixos hydra heads - release/"> refers to
L<https://github.com/nixos/hydra> repository, and will fetch all branches that L<https://github.com/nixos/hydra> repository, and will fetch all branches that
@@ -103,8 +100,6 @@ sub fetchInput {
return undef if $input_type ne "github_refs"; return undef if $input_type ne "github_refs";
my ($owner, $repo, $type, $fut, $prefix) = split ' ', $value; my ($owner, $repo, $type, $fut, $prefix) = split ' ', $value;
die "type field is neither 'heads' nor 'tags', but '$type'"
unless $type eq 'heads' or $type eq 'tags';
my $auth = $self->{config}->{github_authorization}->{$owner}; my $auth = $self->{config}->{github_authorization}->{$owner};
my $githubEndpoint = $self->{config}->{github_endpoint} // "https://api.github.com"; my $githubEndpoint = $self->{config}->{github_endpoint} // "https://api.github.com";
@@ -112,12 +107,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

@@ -358,21 +358,14 @@ sub evalJobs {
my @cmd; my @cmd;
if (defined $flakeRef) { if (defined $flakeRef) {
my $nix_expr =
"let " .
"flake = builtins.getFlake (toString \"$flakeRef\"); " .
"in " .
"flake.hydraJobs " .
"or flake.checks " .
"or (throw \"flake '$flakeRef' does not provide any Hydra jobs or checks\")";
@cmd = ("nix-eval-jobs", @cmd = ("nix-eval-jobs",
# Disable the eval cache to prevent SQLite database contention. # Disable the eval cache to prevent SQLite database contention.
# Since Hydra typically evaluates each revision only once, # Since Hydra typically evaluates each revision only once,
# parallel workers would compete for database locks without # parallel workers would compete for database locks without
# providing any benefit from caching. # providing any benefit from caching.
"--option", "eval-cache", "false", "--option", "eval-cache", "false",
"--expr", $nix_expr); "--flake", $flakeRef,
"--select", "flake: flake.outputs.hydraJobs or flake.outputs.checks or (throw \"flake '$flakeRef' does not provide any Hydra jobs or checks\")");
} else { } else {
my $nixExprInput = $inputInfo->{$nixExprInputName}->[0] my $nixExprInput = $inputInfo->{$nixExprInputName}->[0]
or die "cannot find the input containing the job expression\n"; or die "cannot find the input containing the job expression\n";

View File

@@ -1,4 +1,6 @@
with import ./config.nix; { system ? builtins.currentSystem }:
with import ./config.nix { inherit system; };
{ {
empty_dir = empty_dir =
mkDerivation { mkDerivation {

View File

@@ -1,9 +1,11 @@
{ system ? builtins.currentSystem }:
rec { rec {
path = "@testPath@"; path = "@testPath@";
mkDerivation = args: mkDerivation = args:
derivation ({ derivation ({
system = builtins.currentSystem; inherit system;
PATH = path; PATH = path;
} // args); } // args);
mkContentAddressedDerivation = args: mkDerivation ({ mkContentAddressedDerivation = args: mkDerivation ({

View File

@@ -1,6 +1,11 @@
{ {
outputs = { ... }: { outputs = { self, ... }:
checks = let
import ./basic.nix; systems = [ "x86_64-linux" "aarch64-linux" "x86_64-darwin" "aarch64-darwin" ];
}; forAllSystems = f: builtins.listToAttrs (map (system: { name = system; value = f system; }) systems);
in {
checks = forAllSystems (system:
import ./basic.nix { inherit system; }
);
};
} }

View File

@@ -1,6 +1,11 @@
{ {
outputs = { ... }: { outputs = { self, ... }:
hydraJobs = let
import ./basic.nix; systems = [ "x86_64-linux" "aarch64-linux" "x86_64-darwin" "aarch64-darwin" ];
}; forAllSystems = f: builtins.listToAttrs (map (system: { name = system; value = f system; }) systems);
in {
hydraJobs = forAllSystems (system:
import ./basic.nix { inherit system; }
);
};
} }