diff --git a/src/hydra-eval-jobs/hydra-eval-jobs.cc b/src/hydra-eval-jobs/hydra-eval-jobs.cc index acffe1d1..44a273a9 100644 --- a/src/hydra-eval-jobs/hydra-eval-jobs.cc +++ b/src/hydra-eval-jobs/hydra-eval-jobs.cc @@ -504,6 +504,17 @@ int main(int argc, char * * argv) job.erase("namedConstituents"); + /* Register the derivation as a GC root. !!! This + registers roots for jobs that we may have already + done. */ + auto localStore = store.dynamic_pointer_cast(); + if (gcRootsDir != "" && localStore) { + auto drvPath = job["drvPath"].get(); + Path root = gcRootsDir + "/" + std::string(baseNameOf(drvPath)); + if (!pathExists(root)) + localStore->addPermRoot(localStore->parseStorePath(drvPath), root); + } + if (!brokenJobs.empty()) { std::stringstream ss; for (const auto& [jobName, error] : brokenJobs) { diff --git a/t/evaluate-basic.t b/t/evaluator/evaluate-basic.t similarity index 100% rename from t/evaluate-basic.t rename to t/evaluator/evaluate-basic.t diff --git a/t/evaluator/evaluate-constituents-gc.t b/t/evaluator/evaluate-constituents-gc.t new file mode 100644 index 00000000..a9b23e6c --- /dev/null +++ b/t/evaluator/evaluate-constituents-gc.t @@ -0,0 +1,20 @@ +use strict; +use warnings; +use Setup; +use Test2::V0; + +my $ctx = test_context(); + +my $builds = $ctx->makeAndEvaluateJobset( + expression => 'constituents.nix', +); + +my $constituentA = $builds->{"constituentA"}; +my $directAggregate = $builds->{"direct_aggregate"}; +my $indirectAggregate = $builds->{"indirect_aggregate"}; + +is(system('nix-store', '--delete', $constituentA->drvpath), 256, "Deleting a constituent derivation fails"); +is(system('nix-store', '--delete', $directAggregate->drvpath), 256, "Deleting the direct aggregate derivation fails"); +is(system('nix-store', '--delete', $indirectAggregate->drvpath), 256, "Deleting the indirect aggregate derivation fails"); + +done_testing; diff --git a/t/evaluate-dependent-jobsets.t b/t/evaluator/evaluate-dependent-jobsets.t similarity index 100% rename from t/evaluate-dependent-jobsets.t rename to t/evaluator/evaluate-dependent-jobsets.t diff --git a/t/jobs/constituents.nix b/t/jobs/constituents.nix new file mode 100644 index 00000000..5b7106b9 --- /dev/null +++ b/t/jobs/constituents.nix @@ -0,0 +1,40 @@ +with import ./config.nix; +rec { + constituentA = mkDerivation { + name = "empty-dir-A"; + builder = ./empty-dir-builder.sh; + }; + + constituentB = mkDerivation { + name = "empty-dir-B"; + builder = ./empty-dir-builder.sh; + }; + + direct_aggregate = mkDerivation { + name = "direct_aggregate"; + _hydraAggregate = true; + constituents = [ + constituentA + ]; + builder = ./empty-dir-builder.sh; + }; + + indirect_aggregate = mkDerivation { + name = "indirect_aggregate"; + _hydraAggregate = true; + constituents = [ + "constituentA" + ]; + builder = ./empty-dir-builder.sh; + }; + + mixed_aggregate = mkDerivation { + name = "mixed_aggregate"; + _hydraAggregate = true; + constituents = [ + "constituentA" + constituentB + ]; + builder = ./empty-dir-builder.sh; + }; +} diff --git a/t/queue-runner/direct-indirect-constituents.t b/t/queue-runner/direct-indirect-constituents.t new file mode 100644 index 00000000..35370450 --- /dev/null +++ b/t/queue-runner/direct-indirect-constituents.t @@ -0,0 +1,35 @@ +use strict; +use warnings; +use Setup; +use Test2::V0; + +my $ctx = test_context(); + +my $builds = $ctx->makeAndEvaluateJobset( + expression => 'constituents.nix', +); + +my $constituentBuildA = $builds->{"constituentA"}; +my $constituentBuildB = $builds->{"constituentB"}; + +my $eval = $constituentBuildA->jobsetevals->first(); +is($eval->evaluationerror->errormsg, ""); + +subtest "Verifying the direct aggregate" => sub { + my $aggBuild = $builds->{"direct_aggregate"}; + is($aggBuild->constituents->first()->id, $constituentBuildA->id, "The ID of the constituent is correct"); +}; + +subtest "Verifying the indirect aggregate" => sub { + my $indirectBuild = $builds->{"indirect_aggregate"}; + is($indirectBuild->constituents->first()->id, $constituentBuildA->id, "The ID of the constituent is correct"); +}; + +subtest "Verifying a mix of direct and indirect aggregate references" => sub { + my $mixedBuild = $builds->{"mixed_aggregate"}; + my ($constituentA, $constituentB) = $mixedBuild->constituents()->search({}, {order_by => { -asc => "job"} }); + is($constituentA->id, $constituentBuildA->id, "The ID of the constituent is correct"); + is($constituentB->id, $constituentBuildB->id, "The ID of the constituent is correct"); +}; + +done_testing;