Round 1 of #17174 hit `nix-lockfile-check` failure. Root cause was
NOT a stale hash — the primary `nix (ubuntu-latest)` and
`nix (macos-latest)` builds passed. GitHub's Magic Nix Cache returned
HTTP 418 (rate-limited / throttled) mid-run, so the rebuild bailed
with `some outputs of '/nix/store/...-npm-deps.drv' are not valid,
so checking is not possible` — no `got:` line for the script to
extract.
The script then incorrectly treated this as 'build failed with no
hash mismatch' and exited 1, breaking the lint on every PR whenever
the cache is throttled.
Now we recognize the throttling/cache-disabled signature and skip
that entry with a warning. A real stale hash still surfaces in the
primary `.#$ATTR` build (separate CI job), so we don't lose
coverage.
* ci(nix): auto-fix stale npm hashes on push to main
When a PR merges to main with updated package-lock.json or package.json
in ui-tui/ or web/, the new auto-fix-main job detects stale npmDepsHash
values and pushes a fix commit directly to main.
This eliminates the recurring manual hash-bump PRs (#15420, #15314,
#15272, #15244) by reusing the existing fix-lockfiles --apply pipeline.
The fix commit only touches nix/*.nix files, which are outside the push
path filter (package-lock.json / package.json), so it cannot re-trigger
itself.
Closes#15314
* fix(ci): use GitHub App token for auto-fix-main push
GITHUB_TOKEN commits are invisible to workflow triggers (GitHub's
infinite-loop prevention). The auto-fix-main job pushes directly to
main, so the fix commit never triggered downstream nix.yml verification.
Mint a short-lived token via the repo's GitHub App (daimon-nous, APP_ID
+ APP_PRIVATE_KEY secrets) so the push is treated as a real event and
nix.yml fires to verify the corrected hashes.
Tested via workflow_dispatch dry-run: app token minted successfully,
checkout with app token succeeded, fix job correctly gated.
Resolves review feedback from Bugbot (r3144569551).
* ci(nix): rename lockfile check job for required status check
Rename 'check' → 'nix-lockfile-check' so the status check name is
unambiguous when added as a required check on main.
* fix(ci): harden auto-fix-main against races, loops, and silent failures
Address adversarial review findings:
1. Race condition (#1): Job-level concurrency with cancel-in-progress
collapses back-to-back pushes; ref: main checkout always gets latest
branch state; explicit push target (origin HEAD:main).
2. Loop prevention (#2): File-whitelist check before commit aborts if
any file outside nix/{tui,web}.nix was modified, preventing
accidental self-triggering.
3. Silent infra failures (#8): nix-lockfile-check now fails explicitly
when fix-lockfiles exits without reporting stale status (catches nix
setup failures, network errors, script bugs that bypass continue-on-error).
4. Commit traceability (#11): Auto-fix commits include source SHA and
workflow run URL in the commit body.
5. Explicit push target (#12): git push origin HEAD:main instead of
bare git push.
---------
Co-authored-by: alt-glitch <alt-glitch@users.noreply.github.com>
* fix(nix): use --rebuild in fix-lockfiles to bypass cached FOD store paths
fix-lockfiles checked npm lockfile hashes by running
`nix build .#<attr>.npmDeps`, but fetchNpmDeps is a fixed-output
derivation — if the old store path exists locally, Nix returns it from
cache without re-fetching. This caused the script to report "ok" even
when hashes were stale, while CI (with no cache) failed with a hash
mismatch.
Adding --rebuild forces Nix to re-derive and verify the output hash
against the declared one, catching staleness regardless of local cache
state. Also updates the tui and web npm deps hashes that were stale.
* fix(nix): regenerate ui-tui lockfile to add missing @emnapi entries
npm ci was failing because @emnapi/core and @emnapi/runtime were
missing from ui-tui/package-lock.json despite being required as peer
deps by @napi-rs/wasm-runtime (via @rolldown/binding-wasm32-wasi).
Running npm install --package-lock-only adds the missing entries.
The npmDepsHash reverts to its previous value since fetchNpmDeps was
already fetching these packages as transitive dependencies.