diff --git a/flake.lock b/flake.lock index ddff55ec..3e403f6f 100644 --- a/flake.lock +++ b/flake.lock @@ -1,22 +1,13 @@ { "nodes": { "nix": { - "inputs": { - "flake-compat": [], - "flake-parts": [], - "git-hooks-nix": [], - "nixpkgs": [ - "nixpkgs" - ], - "nixpkgs-23-11": [], - "nixpkgs-regression": [] - }, + "flake": false, "locked": { - "lastModified": 1744030329, - "narHash": "sha256-r+psCOW77vTSTNbxTVrYHeh6OgB0QukbnyUVDwg8s4I=", + "lastModified": 1745420957, + "narHash": "sha256-ZbB3IH9OlJvo14GlQZbYHzJojf/HCDT38GzYTod8DaU=", "owner": "NixOS", "repo": "nix", - "rev": "a4962f73b5fc874d4b16baef47921daf349addfc", + "rev": "70921714cb3b5e6041b7413459541838651079f3", "type": "github" }, "original": { @@ -29,11 +20,11 @@ "nix-eval-jobs": { "flake": false, "locked": { - "lastModified": 1744018595, - "narHash": "sha256-v5n6t49X7MOpqS9j0FtI6TWOXvxuZMmGsp2OfUK5QfA=", + "lastModified": 1744370057, + "narHash": "sha256-n220U5pjzCtTtOJtbga4Xr/PyllowKw9anSevgCqJEw=", "owner": "nix-community", "repo": "nix-eval-jobs", - "rev": "cba718bafe5dc1607c2b6761ecf53c641a6f3b21", + "rev": "1260c6599d22dfd8c25fea6893c3d031996b20e1", "type": "github" }, "original": { @@ -44,11 +35,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1743987495, - "narHash": "sha256-46T2vMZ4/AfCK0Y2OjlFzJPxmdpP8GtsuEqSSJv3oe4=", + "lastModified": 1745408698, + "narHash": "sha256-JT1wMjLIypWJA0N2V27WpUw8feDmTok4Dwkb0oYXDS4=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "db8f4fe18ce772a9c8f3adf321416981c8fe9371", + "rev": "eea3403f7ca9f9942098f4f2756adab4ec924b2b", "type": "github" }, "original": { diff --git a/flake.nix b/flake.nix index dc1d1b8a..979bfcbd 100644 --- a/flake.nix +++ b/flake.nix @@ -5,14 +5,8 @@ inputs.nix = { url = "github:NixOS/nix/2.28-maintenance"; - inputs.nixpkgs.follows = "nixpkgs"; - - # hide nix dev tooling from our lock file - inputs.flake-parts.follows = ""; - inputs.git-hooks-nix.follows = ""; - inputs.nixpkgs-regression.follows = ""; - inputs.nixpkgs-23-11.follows = ""; - inputs.flake-compat.follows = ""; + # We want to control the deps precisely + flake = false; }; inputs.nix-eval-jobs = { @@ -30,10 +24,27 @@ # A Nixpkgs overlay that provides a 'hydra' package. overlays.default = final: prev: { - nix-eval-jobs = final.callPackage nix-eval-jobs {}; + nixDependenciesForHydra = final.lib.makeScope final.newScope + (import (nix + "/packaging/dependencies.nix") { + pkgs = final; + inherit (final) stdenv; + inputs = {}; + }); + nixComponentsForHydra = final.lib.makeScope final.nixDependenciesForHydra.newScope + (import (nix + "/packaging/components.nix") { + officialRelease = true; + inherit (final) lib; + pkgs = final; + src = nix; + maintainers = [ ]; + }); + nix-eval-jobs = final.callPackage nix-eval-jobs { + nixComponents = final.nixComponentsForHydra; + }; hydra = final.callPackage ./package.nix { - inherit (nixpkgs.lib) fileset; + inherit (final.lib) fileset; rawSrc = self; + nixComponents = final.nixComponentsForHydra; }; }; @@ -73,24 +84,26 @@ }); packages = forEachSystem (system: let - nixComponents = { - inherit (nix.packages.${system}) - nix-util - nix-store - nix-expr - nix-fetchers - nix-flake - nix-main - nix-cmd - nix-cli - nix-perl-bindings - ; - }; + inherit (nixpkgs) lib; + pkgs = nixpkgs.legacyPackages.${system}; + nixDependencies = lib.makeScope pkgs.newScope + (import (nix + "/packaging/dependencies.nix") { + inherit pkgs; + inherit (pkgs) stdenv; + inputs = {}; + }); + nixComponents = lib.makeScope nixDependencies.newScope + (import (nix + "/packaging/components.nix") { + officialRelease = true; + inherit lib pkgs; + src = nix; + maintainers = [ ]; + }); in { - nix-eval-jobs = nixpkgs.legacyPackages.${system}.callPackage nix-eval-jobs { + nix-eval-jobs = pkgs.callPackage nix-eval-jobs { inherit nixComponents; }; - hydra = nixpkgs.legacyPackages.${system}.callPackage ./package.nix { + hydra = pkgs.callPackage ./package.nix { inherit (nixpkgs.lib) fileset; inherit nixComponents; inherit (self.packages.${system}) nix-eval-jobs; diff --git a/package.nix b/package.nix index 4a7840c1..5c1a7860 100644 --- a/package.nix +++ b/package.nix @@ -277,5 +277,8 @@ stdenv.mkDerivation (finalAttrs: { dontStrip = true; meta.description = "Build of Hydra on ${stdenv.system}"; - passthru = { inherit perlDeps; }; + passthru = { + inherit perlDeps; + nix = nixComponents.nix-cli; + }; }) diff --git a/src/hydra-queue-runner/dispatcher.cc b/src/hydra-queue-runner/dispatcher.cc index d3e145de..ada25dc6 100644 --- a/src/hydra-queue-runner/dispatcher.cc +++ b/src/hydra-queue-runner/dispatcher.cc @@ -134,6 +134,8 @@ system_time State::doDispatch() comparator is a partial ordering (see MachineInfo). */ int highestGlobalPriority; int highestLocalPriority; + size_t numRequiredSystemFeatures; + size_t numRevDeps; BuildID lowestBuildID; StepInfo(Step::ptr step, Step::State & step_) : step(step) @@ -142,6 +144,8 @@ system_time State::doDispatch() lowestShareUsed = std::min(lowestShareUsed, jobset->shareUsed()); highestGlobalPriority = step_.highestGlobalPriority; highestLocalPriority = step_.highestLocalPriority; + numRequiredSystemFeatures = step->requiredSystemFeatures.size(); + numRevDeps = step_.rdeps.size(); lowestBuildID = step_.lowestBuildID; } }; @@ -194,6 +198,8 @@ system_time State::doDispatch() a.highestGlobalPriority != b.highestGlobalPriority ? a.highestGlobalPriority > b.highestGlobalPriority : a.lowestShareUsed != b.lowestShareUsed ? a.lowestShareUsed < b.lowestShareUsed : a.highestLocalPriority != b.highestLocalPriority ? a.highestLocalPriority > b.highestLocalPriority : + a.numRequiredSystemFeatures != b.numRequiredSystemFeatures ? a.numRequiredSystemFeatures > b.numRequiredSystemFeatures : + a.numRevDeps != b.numRevDeps ? a.numRevDeps > b.numRevDeps : a.lowestBuildID < b.lowestBuildID; }); diff --git a/src/hydra-queue-runner/hydra-queue-runner.cc b/src/hydra-queue-runner/hydra-queue-runner.cc index 05d7e263..ab146312 100644 --- a/src/hydra-queue-runner/hydra-queue-runner.cc +++ b/src/hydra-queue-runner/hydra-queue-runner.cc @@ -703,6 +703,7 @@ void State::dumpStatus(Connection & conn) : 0.0}, }; +#if NIX_WITH_S3_SUPPORT auto s3Store = dynamic_cast(&*store); if (s3Store) { auto & s3Stats = s3Store->getS3Stats(); @@ -728,6 +729,7 @@ void State::dumpStatus(Connection & conn) + s3Stats.getBytes / (1024.0 * 1024.0 * 1024.0) * 0.09}, }; } +#endif } { diff --git a/src/lib/Hydra/Controller/JobsetEval.pm b/src/lib/Hydra/Controller/JobsetEval.pm index 643a516c..77c01a84 100644 --- a/src/lib/Hydra/Controller/JobsetEval.pm +++ b/src/lib/Hydra/Controller/JobsetEval.pm @@ -76,7 +76,9 @@ sub view_GET { $c->stash->{removed} = $diff->{removed}; $c->stash->{unfinished} = $diff->{unfinished}; $c->stash->{aborted} = $diff->{aborted}; - $c->stash->{failed} = $diff->{failed}; + $c->stash->{totalAborted} = $diff->{totalAborted}; + $c->stash->{totalFailed} = $diff->{totalFailed}; + $c->stash->{totalQueued} = $diff->{totalQueued}; $c->stash->{full} = ($c->req->params->{full} || "0") eq "1"; diff --git a/src/lib/Hydra/Helper/BuildDiff.pm b/src/lib/Hydra/Helper/BuildDiff.pm index 65dad17c..be8525d6 100644 --- a/src/lib/Hydra/Helper/BuildDiff.pm +++ b/src/lib/Hydra/Helper/BuildDiff.pm @@ -32,7 +32,12 @@ sub buildDiff { removed => [], unfinished => [], aborted => [], - failed => [], + + # These summary counters cut across the categories to determine whether + # actions such as "Restart all failed" or "Bump queue" are available. + totalAborted => 0, + totalFailed => 0, + totalQueued => 0, }; my $n = 0; @@ -80,8 +85,15 @@ sub buildDiff { } else { push @{$ret->{new}}, $build if !$found; } - if (defined $build->buildstatus && $build->buildstatus != 0) { - push @{$ret->{failed}}, $build; + + if ($build->finished != 0 && $build->buildstatus != 0) { + if ($aborted) { + ++$ret->{totalAborted}; + } else { + ++$ret->{totalFailed}; + } + } elsif ($build->finished == 0) { + ++$ret->{totalQueued}; } } diff --git a/src/root/eval-error.tt b/src/root/eval-error.tt index c2ea28ec..7b6e702f 100644 --- a/src/root/eval-error.tt +++ b/src/root/eval-error.tt @@ -13,12 +13,12 @@
- [% IF jobset %] -

Errors occurred at [% INCLUDE renderDateTime timestamp=(jobset.errortime || jobset.lastcheckedtime) %].

-
[% HTML.escape(jobset.fetcherrormsg || jobset.errormsg) %]
- [% ELSIF eval %] + [% IF eval %]

Errors occurred at [% INCLUDE renderDateTime timestamp=(eval.evaluationerror.errortime || eval.timestamp) %].

[% HTML.escape(eval.evaluationerror.errormsg) %]
+ [% ELSIF jobset %] +

Errors occurred at [% INCLUDE renderDateTime timestamp=(jobset.errortime || jobset.lastcheckedtime) %].

+
[% HTML.escape(jobset.fetcherrormsg || jobset.errormsg) %]
[% END %]
diff --git a/src/root/jobset-eval.tt b/src/root/jobset-eval.tt index f0b92f97..12086d85 100644 --- a/src/root/jobset-eval.tt +++ b/src/root/jobset-eval.tt @@ -48,16 +48,16 @@ c.uri_for(c.controller('JobsetEval').action_for('view'), Actions diff --git a/src/root/machine-status.tt b/src/root/machine-status.tt index 07a2359d..725598eb 100644 --- a/src/root/machine-status.tt +++ b/src/root/machine-status.tt @@ -17,7 +17,7 @@ [% name = m.key ? stripSSHUser(m.key) : "localhost" %] - + [% INCLUDE renderMachineName machine=m.key %] [% IF m.value.systemTypes %] diff --git a/src/script/hydra-eval-jobset b/src/script/hydra-eval-jobset index cf3fa294..80f5d79c 100755 --- a/src/script/hydra-eval-jobset +++ b/src/script/hydra-eval-jobset @@ -372,6 +372,7 @@ sub evalJobs { or die "cannot find the input containing the job expression\n"; @cmd = ("nix-eval-jobs", + "--option", "restrict-eval", "true", "<" . $nixExprInputName . "/" . $nixExprPath . ">", inputsToArgs($inputInfo)); } diff --git a/t/Hydra/Helper/BuildDiff.t b/t/Hydra/Helper/BuildDiff.t index 243bb596..eef25a0f 100644 --- a/t/Hydra/Helper/BuildDiff.t +++ b/t/Hydra/Helper/BuildDiff.t @@ -25,7 +25,10 @@ subtest "empty diff" => sub { removed => [], unfinished => [], aborted => [], - failed => [], + + totalAborted => 0, + totalFailed => 0, + totalQueued => 0, }, "empty list of jobs returns empty diff" ); @@ -48,12 +51,7 @@ subtest "2 different jobs" => sub { "succeed_with_failed is a new job" ); - is(scalar(@{$ret->{failed}}), 1, "list of failed jobs is 1 element long"); - is( - $ret->{failed}[0]->get_column('id'), - $builds->{"succeed_with_failed"}->get_column('id'), - "succeed_with_failed is a failed job" - ); + is($ret->{totalFailed}, 1, "total failed jobs is 1"); is( $ret->{removed}, @@ -70,9 +68,9 @@ subtest "2 different jobs" => sub { subtest "failed job with no previous history" => sub { my $ret = buildDiff([$builds->{"fails"}], []); - is(scalar(@{$ret->{failed}}), 1, "list of failed jobs is 1 element long"); + is($ret->{totalFailed}, 1, "total failed jobs is 1"); is( - $ret->{failed}[0]->get_column('id'), + $ret->{new}[0]->get_column('id'), $builds->{"fails"}->get_column('id'), "fails is a failed job" ); @@ -93,7 +91,6 @@ subtest "not-yet-built job with no previous history" => sub { is($ret->{removed}, [], "removed"); is($ret->{unfinished}, [], "unfinished"); is($ret->{aborted}, [], "aborted"); - is($ret->{failed}, [], "failed"); is(scalar(@{$ret->{new}}), 1, "list of new jobs is 1 element long"); is(