feat(nix): add a dev shell and a checks output (task 0039)
`nix develop` now yields the toolchain the repository actually needs — Node, `git`, `tea`, and `curl` — giving a declarative answer to "what do I need to work on this", which the repository previously specified nowhere. The shell takes its Node from the package's `passthru` rather than naming `pkgs.nodejs` a second time, so development and the shipped artifact cannot drift onto different majors and cannot be set independently. `package.nix` declares that `passthru` as an interface rather than leaving the shell to read an incidental build attribute; it does not enter the derivation, so the store path is unchanged. The checks output aliases the package, so `nix flake check` builds it and thereby runs both its verification phases instead of being a silent no-op. No per-stage checks: the only stage adding coverage is the full typecheck, which spans `test/` and `bench/` and would drag the benchmark harness into the derivation's inputs, undoing the source filtering. It stays in CI. The shell deliberately omits `gitea-axi` itself. The benchmark's arm resolves that binary by name off PATH and must get the locally built `dist/main.js`, so supplying the packaged one would silently substitute the wrong artifact.
This commit was merged in pull request #48.
This commit is contained in:
@@ -16,8 +16,38 @@ The full typecheck stays in continuous integration, where it already runs.
|
||||
|
||||
## Acceptance criteria
|
||||
|
||||
- [ ] `nix develop` yields a shell with Node, `git`, and `tea` available.
|
||||
- [ ] The build, the fast tier, and the benchmark harness's runner all work from inside that shell.
|
||||
- [ ] The shell's Node and the package's Node come from one reference — changing it moves both, and they cannot be set independently.
|
||||
- [ ] `nix flake check` builds the package and runs its tests, and fails when the package fails.
|
||||
- [ ] No per-stage check derivations are added.
|
||||
- [x] `nix develop` yields a shell with Node, `git`, and `tea` available.
|
||||
- [x] The build, the fast tier, and the benchmark harness's runner all work from inside that shell.
|
||||
- [x] The shell's Node and the package's Node come from one reference — changing it moves both, and they cannot be set independently.
|
||||
- [x] `nix flake check` builds the package and runs its tests, and fails when the package fails.
|
||||
- [x] No per-stage check derivations are added.
|
||||
|
||||
## Implementation Notes
|
||||
|
||||
### The single Node reference is a `passthru`, not a second `pkgs.nodejs`
|
||||
|
||||
The shell takes `self.packages.${system}.gitea-axi.nodejs` rather than naming `pkgs.nodejs` again.
|
||||
Naming it twice would satisfy the criterion's letter while leaving two places to edit, which is the drift the criterion exists to prevent; reading it back off the derivation means there is genuinely one reference.
|
||||
|
||||
The first cut relied on `buildNpmPackage` incidentally surfacing its `nodejs` argument as a derivation attribute — which works, but only as a side effect of `inherit src nodejs`, with nothing marking it load-bearing.
|
||||
Review caught that: moving or dropping that `inherit` would have broken the shell silently at a distance.
|
||||
`package.nix` now declares `passthru = { inherit nodejs; };`, making it an interface with a comment saying what depends on it.
|
||||
`passthru` does not enter the derivation, so the store path is unchanged and the change costs no rebuild — verified: the drv hash before and after is identical.
|
||||
|
||||
### `curl` was a missing part of the toolchain
|
||||
|
||||
The benchmark's `raw-api` arm shells out to `curl` (`ARM_BINARY` in `bench/guard.ts`), so the shell carries it alongside Node, `git`, and `tea`.
|
||||
|
||||
### The shell deliberately does not supply `gitea-axi`
|
||||
|
||||
The criterion asks that the benchmark harness's runner work from inside the shell, and it does.
|
||||
A *live* arm run is a further step the shell cannot take: `provisionArmBin` resolves each arm's binary by name off `PATH`, and the `gitea-axi` arm's binary must be the locally built `dist/main.js` so a run measures the working tree rather than whatever the flake last packaged.
|
||||
Putting the packaged binary on `PATH` would satisfy the lookup with the wrong artifact — a silently misleading benchmark, worse than a missing one.
|
||||
|
||||
Exposing the *built* one was considered and rejected as well: `tsc` does not set an executable bit on `dist/main.js` (npm sets it at install time from the manifest's `bin` entry, which is what the packaging tier's bit assertion guards), so a `shellHook` would have had to `chmod +x` the build output on every shell entry — mutating build artifacts to work around a lookup that is the benchmark's own concern.
|
||||
Both the flake and the CLAUDE.md gotcha now state the boundary rather than implying the shell covers it.
|
||||
|
||||
### CLAUDE.md's toolchain gotcha was stale by construction
|
||||
|
||||
It read "the repository has no dev shell yet (task 0039 adds one)".
|
||||
This slice is that task, so the entry was rewritten to point at `nix develop --command`, keeping `nix shell nixpkgs#nodejs -c ...` only as the one-off outside the repository.
|
||||
|
||||
Reference in New Issue
Block a user