nova-cache 0.3.1.0 → 0.3.2.0
raw patch · 5 files changed
+43/−5 lines, 5 files
Files
- CHANGELOG.md +23/−0
- README.md +3/−3
- nova-cache.cabal +1/−1
- src/NovaCache/Validate.hs +7/−1
- test/Main.hs +9/−0
CHANGELOG.md view
@@ -1,5 +1,28 @@ # Changelog +## 0.3.2.0 — 2026-03-18++### Seed action fixes++- **Resolve runtime outputs, not derivations** — `nix-instantiate` replaced+ with `nix-build --no-out-link` so the cache stores actual binaries instead of+ `.drv` build recipes.+- **Filter uploads to diff-only** — `nix copy` exports transitive deps; uploads+ now filtered against the missing-hashes diff to avoid re-uploading cached paths.+- **Fix broken pipe** — `find | xargs` with `pipefail` caused spurious failures;+ now writes to intermediate files.+- **Fix xargs line-too-long** — large path lists passed via file instead of inline.+- **Diagnostic output** — upload failure HTTP codes now printed; `nix copy` errors+ no longer silenced.+- **Parallelism** — default reduced from 32 to 8; per-upload `--max-time` added.++### Server validation++- **Reject derivation narinfos** — `validateNarInfo` now rejects any narinfo+ where StorePath ends in `.drv` with a new `DerivationStorePath` error. Binary+ caches serve build outputs, not build recipes.+- 1 new test (75 total)+ ## 0.3.1.0 — 2026-03-07 ### Drop `memory` dependency, use `ram`
README.md view
@@ -295,7 +295,7 @@ ``` - **10 modules**, 8 pure + 2 at the IO boundary (Compression optional via flag)-- **74 core tests + 4 compression tests**, hand-rolled harness, no framework dependencies+- **75 core tests + 4 compression tests**, hand-rolled harness, no framework dependencies - **Zero partial functions** — total by construction - **Strict by default** — bang patterns on all data fields @@ -403,9 +403,9 @@ | `cache-url` | yes | Base URL of the nova-cache server | | `api-key` | yes | Bearer token for authenticating uploads | | `paths` | no | Explicit store paths (space-separated). Defaults to all paths from `shell.nix` / `default.nix` |-| `parallel` | no | Max concurrent uploads (default: 32) |+| `parallel` | no | Max concurrent uploads (default: 8) | -The action fetches `GET /narinfo-hashes` to determine which paths are already cached, exports only the missing paths, and uploads narinfo + NAR files in parallel. Falls back to uploading everything if the endpoint is unavailable (servers < 0.3.0.0). Works with any CI that has Nix installed.+The action resolves runtime store paths via `nix-build`, diffs against the server's `GET /narinfo-hashes`, exports only missing paths, and uploads narinfo + NAR files in parallel. Includes per-upload timeouts, failure diagnostics, and a round-trip validation check. Works with any CI that has Nix installed. ---
nova-cache.cabal view
@@ -1,6 +1,6 @@ cabal-version: 3.0 name: nova-cache-version: 0.3.1.0+version: 0.3.2.0 synopsis: Pure Nix binary cache protocol library description: A focused, minimal, pure-first library implementing the full Nix binary
src/NovaCache/Validate.hs view
@@ -15,6 +15,7 @@ import Data.ByteString (ByteString) import Data.Text (Text)+import qualified Data.Text as T import NovaCache.Hash (formatNixHash, hashBytes, parseNixHash) import NovaCache.NarInfo (NarInfo (..)) import NovaCache.Signing (PublicKey, verify)@@ -46,6 +47,8 @@ SignatureInvalid !Text | -- | The narinfo has zero signatures. NoSignatures+ | -- | StorePath is a derivation (.drv) — binary caches serve build outputs only.+ DerivationStorePath !Text deriving (Eq, Show) -- ---------------------------------------------------------------------------@@ -57,13 +60,16 @@ -- Returns the 'NarInfo' unchanged on success for composition. validateNarInfo :: NarInfo -> Either [ValidationError] NarInfo validateNarInfo ni =- case concat [sizeErrors, storePathErrors, fileHashErrors, narHashErrors, refErrors] of+ case concat [sizeErrors, drvErrors, storePathErrors, fileHashErrors, narHashErrors, refErrors] of [] -> Right ni errs -> Left errs where sizeErrors = [NegativeFileSize (niFileSize ni) | niFileSize ni < 0] ++ [NegativeNarSize (niNarSize ni) | niNarSize ni < 0]++ drvErrors =+ [DerivationStorePath (niStorePath ni) | ".drv" `T.isSuffixOf` niStorePath ni] storePathErrors = case parseStorePath defaultStoreDir (niStorePath ni) of Left err -> [InvalidStorePath (niStorePath ni) err]
test/Main.hs view
@@ -631,6 +631,15 @@ "negative narsize" (Left [Validate.NegativeNarSize (-1)]) (Validate.validateNarInfo ni),+ test "validateNarInfo derivation StorePath rejected" $+ let drvPath = "/nix/store/abc12345678901234567890123456789-foo.drv"+ ni = mkValidNarInfo {NarInfo.niStorePath = drvPath}+ in case Validate.validateNarInfo ni of+ Left [Validate.DerivationStorePath raw] ->+ assertEqual "raw value" drvPath raw+ other -> do+ putStrLn (" expected Left [DerivationStorePath ..], got: " ++ show other)+ pure False, test "validateNarInfo bad StorePath" $ let ni = mkValidNarInfo {NarInfo.niStorePath = "not-a-store-path"} in case Validate.validateNarInfo ni of