refactor(modules): extract shared customPackages overlay into flake.lib#166
refactor(modules): extract shared customPackages overlay into flake.lib#166
Conversation
|
Claude finished @Bad3r's task in 2m 4s —— View job ReviewThe refactor is sound and achieves its stated goal. Pre/post are byte-identical for both hosts (independently verified): the shared overlay defines exactly the union of the pre-refactor attributes minus All 22 The structural eliminations are exactly what the PR #165 review called out — there's no longer a duplicated overlay block where an upstream change can silently land in only one host file. ✓ Suggestions1. Namespace convention (minor) — Every other
This PR introduces 2. File-name asymmetry (very minor) The shared module is 3. Worth noting in the file header
Nits
Test coverageThe PR description lists thorough manual validation (drvPath equality on three representative packages, ✅ LGTM aside from the namespace placement nit — the refactor is correct, the equivalence reasoning checks out, and it eliminates a real recurring failure mode.
|
There was a problem hiding this comment.
Code Review
This pull request centralizes custom package definitions into a shared Nixpkgs overlay, reducing duplication across host-specific modules and resolving merge conflict markers in the tpnix configuration. Feedback suggests using the final fixpoint instead of prev for dependencies in package overrides to ensure consistency and allow other overlays to influence the package set.
…rlay Address claude-review nits on PR #166: 1. Namespace: move `flake.lib.customPackagesOverlay` -> `flake.lib.overlays.customPackages`. Aligns with the existing `flake.lib.<area>.<name>` convention used by `flake.lib.security.*`, `flake.lib.nixos.*`, `flake.lib.agents.*`, `flake.lib.meta.inputBranches`, `flake.lib.xdg.desktopFiles`. Leaves room for additional overlays under the same namespace. 2. Filename: rename `modules/base/custom-packages.nix` ->`modules/base/custom-packages-overlay.nix`. Mirrors the host-side filenames so the relationship is discoverable by name alone. 3. Header: clarify that the overlay is *defined* (not auto-applied) and that hosts opt in by composing it into `nixpkgs.overlays`. Prevents future readers from assuming `modules/base/` content is globally applied. Verified equivalent: `nix flake check --accept-flake-config --no-build` -> all checks passed; both host toplevel evals succeed.
Reply to automated review (run 25343941782)All three suggestions adopted in `36655dc5`: Adopted
Verification
The "Nits" section (use of `final:` and `:` patterns) and the "Test coverage" assessment required no action -- those are observations of existing correct style. No items rejected. |
|
Claude finished @Bad3r's task in 2m 16s —— View job ReviewThe latest commit (
Both host call-sites ( On the gemini-code-assist suggestion (
|
Adopt the gemini-code-assist suggestion on PR #166 (lines 63 / 73 of the shared overlay): switch dependency lookups inside the `librepods` and `marktext` `overrideAttrs` bodies from `prev.*` to `final.*`. The `prev.<pkg>.overrideAttrs` calls themselves stay on `prev` (they need to extend the unmodified upstream attrs), but the deps consumed inside the override bodies (`fetchFromGitHub`, `libpulseaudio`, `openssl`, `qt6.*`, `node-gyp`) now go through `final`. This is the standard Nixpkgs idiom: it lets a later overlay -- e.g. an `openssl` CVE patch overlay -- propagate into the librepods build instead of being silently bypassed. No `nixpkgs.overlays` consumer in either host closure currently rebinds any of these dependencies, so drvPaths are byte-identical pre and post: - `librepods.drvPath`: `/nix/store/4sjfa72q2kvpvf5ywm0168g1p370bynf-librepods-0.2.5.drv` - `marktext.drvPath`: `/nix/store/sw5869iqqarh41bwjlqhja5yl1yj6vnh-marktext-0.17.0-unstable-2025-11-19.drv` The change is purely defensive against future overlay composition, and brings these two overrides into alignment with the rest of the file (`wfuzz`, `brave-origin`, all in-tree `callPackage` lines, `monitor-query`) which already use `final`. Comments updated to record the rationale. Validated with `nix flake check --accept-flake-config --no-build` (all checks passed) and pre-commit hook chain green.
|
Claude finished @Bad3r's task in 1m 33s —— View job Review
Latest push (
drvPath equivalence sanity checkThe commit message lists byte-identical
So the "byte-identical pre/post" claim holds and the change is purely defensive against future overlay composition. ✓ Style consistencyThe override pattern in this file now matches itself end-to-end: Out-of-scope follow-up (do NOT fold into this PR)While verifying, I noticed Nits (non-blocking)
VerdictLGTM. The structural refactor is correct, naming follows the repo's Optional follow-up: extend the same |
Reply to second-round review (run 25344192340)`b4e24fc8` adopts the gemini-code-assist suggestions on `modules/base/custom-packages-overlay.nix` lines 63 (librepods) and 73 (marktext). Both review threads now resolved. Adopted (gemini-code-assist, also seconded by claude-review)
The `prev..overrideAttrs` calls themselves stay on `prev` -- that part was already correct (the override extends the unmodified upstream attrs). Acknowledged (no action needed)
Verification
The byte-identical drvPaths match claude-review's prediction: no overlay in either host closure currently rebinds the affected dependencies, so the change is purely defensive against future overlay composition. |
Reply to third-round review (run 25344427322)Thanks for the LGTM. Closing the loop on the noted out-of-scope follow-up. Acknowledged (no change in this PR)The observation about `modules/base/envfs.nix:13-34` reusing the same `prev.fetchFromGitHub` / `prev.rustPlatform.fetchCargoVendor` pattern is correct, and the same defensive reasoning applies. Per the reviewer's own framing ("do NOT fold into this PR" / "outside the stated scope") and to keep this diff minimal, that change is being handled in a separate PR rather than extending the scope here. Tracking PR will be opened immediately and linked back. Verified non-actionable
Net statusAll review threads on this PR are now resolved. Verdict from the third review iteration: ✅ LGTM, ready to merge. |
…167) * fix(tpnix): resolve unresolved merge conflict markers in overlay PR #160 squash-merged a state where `Merge branch 'main' into feat/csec-tools` (22973ff) left literal conflict markers in `modules/tpnix/custom-packages-overlay.nix:28,37,57`. The result is not valid Nix syntax: `nix-instantiate --parse` rejects the file, the `tpnix` host build is broken, and both the `wfuzz` (feat/csec-tools) and `librepods` (main) overrides are mutually exclusive in that state. Resolution mirrors the system76 sibling at `modules/system76/custom-packages-overlay.nix`, which was resolved correctly during the same merge: keep both blocks, since the wfuzz and librepods overrides are independent. Verified with `nix-instantiate --parse` and `nix flake check --accept-flake-config --no-build`. Reported by claude-code review on PR #160 (run 25340703466). * refactor(base): use final for dep lookups in envfs overlay override `modules/base/envfs.nix:13-34` pinned `envfs` to 1.2.0 with dependency lookups (`prev.fetchFromGitHub`, `prev.rustPlatform.fetchCargoVendor`) sourced from `prev`. Switch those to `final.*` so any later overlay -- e.g. a future `rustPlatform`/`fetchurl` patch overlay -- propagates into the override instead of silently linking against the un-modified upstream copy. The `prev.envfs.overrideAttrs` entry point itself stays on `prev` (it must extend the unmodified upstream attrs, not recurse through the fixpoint). This is the same shape applied to `librepods` and `marktext` in #166. Comment updated above the overlay to record the rationale. `envfs.drvPath` is byte-identical pre/post: `/nix/store/f6npid91mdh5dpyxxbrn5wyzcn9dxf11-envfs-1.2.0.drv` -- no overlay in either host closure currently rebinds `fetchFromGitHub` or `rustPlatform.fetchCargoVendor`, so the change is purely defensive against future overlay composition. Validated with `nix flake check --accept-flake-config --no-build` (all checks passed). Suggested as an out-of-scope follow-up by claude-review on PR #166 (run 25344427322). * docs(base): correct envfs overlay comment to not imply overlay order The comment above the `envfs` overlay said "any later overlay that rebinds them feeds into this build". That implied registration order mattered. Nixpkgs overlays are evaluated as a single fixed point, so any overlay (regardless of registration order) that rebinds the referenced deps is observed via `final`. Reword to "any other overlay" and add a parenthetical noting that ordering is irrelevant here. Suggested by claude-review on PR #167 (run 25344637086). * refactor(base): dedupe cargoDeps src in envfs overlay override The `cargoDeps.src` argument inside the `envfs` override was an exact duplicate of the outer `src` (same `owner` / `repo` / `rev` / `hash`). Bind once via a `let` block inside the `overrideAttrs` body and reuse via `inherit src;` at both call sites. The four-line drift risk -- a future bump touching only one of the two `src` literals -- is now structurally impossible. `envfs.drvPath` is byte-identical pre/post: `/nix/store/f6npid91mdh5dpyxxbrn5wyzcn9dxf11-envfs-1.2.0.drv`. Suggested by gemini-code-assist on PR #167 (line 30 of `envfs.nix`) and seconded by claude-review (run 25344831509).
Reply: round 4 review feedbackPulled and re-validated every reviewer suggestion across the three claude-bot reviews and the two gemini-code-assist inline threads. The only unaddressed item remaining was the out-of-scope follow-up flagged by the third claude review ( Adopted
Rationale for folding into this PR (rather than a tracking PR)The third review explicitly recommended punting this to a separate PR to keep the diff focused. Reconsidered because:
If the reviewer prefers the split, this commit can be cherry-picked back out and reissued as a follow-up PR -- but the unified shape reads more cleanly as one logical "use Validation
Status of prior review feedback (recap)
No items rejected. No outstanding suggestions remain across any reviewer thread. |
Correction to the previous replyThe prior reply (#issuecomment-4376405223) is partially incorrect. PR #167 (
Net status of PR 166 review feedbackAll reviewer suggestions across both gemini-code-assist threads and all three claude-bot reviews are now addressed -- the customPackages overlay polish in this PR plus the envfs polish in #167. Next stepRebasing the branch on
Will follow up once the rebase completes. |
`modules/system76/custom-packages-overlay.nix` and `modules/tpnix/custom-packages-overlay.nix` shared ~95% identical content (the entire `final: prev:` body apart from the `system76-power` SCSI patch). That duplication is what caused the merge in PR #160 to leave conflict markers in only one of the two files when an upstream change touched the shared region. Extract the common overlay into `modules/base/custom-packages.nix` as `config.flake.lib.customPackagesOverlay`, mirroring the established pattern used by `flake.lib.security.*` (see `modules/security/`). Hosts now compose the shared overlay with any host-specific extras: - `system76`: prepends the shared overlay, then layers a small overlay that adds the `system76-power` SCSI patch (hardware-specific). - `tpnix`: just consumes the shared overlay. Verified semantically equivalent to pre-refactor by comparing derivation paths for `brave-origin`, `system76-power`, `librepods` (all byte-identical), `system.activationScripts.binsh` (identical), and `environment.systemPackages` (only difference is `nixos-version`, which embeds `system.configurationRevision`; the dirty-tree suffix during validation accounts for the hash diff). Validated with: - `nix flake check --accept-flake-config --no-build`: all checks passed - `nix eval .#nixosConfigurations.{system76,tpnix}.config.system.build.toplevel.outPath`: both succeed - pre-commit hooks (deadnix, statix, nix-parse, treefmt, gitleaks, managed-files-drift): all pass Addresses the non-blocking observation from claude-review on PR #165 (run 25341374903): "lift the common attrset into a single shared `customPackages` overlay imported by both hosts -- would prevent the next merge from re-creating exactly this class of conflict."
…rlay Address claude-review nits on PR #166: 1. Namespace: move `flake.lib.customPackagesOverlay` -> `flake.lib.overlays.customPackages`. Aligns with the existing `flake.lib.<area>.<name>` convention used by `flake.lib.security.*`, `flake.lib.nixos.*`, `flake.lib.agents.*`, `flake.lib.meta.inputBranches`, `flake.lib.xdg.desktopFiles`. Leaves room for additional overlays under the same namespace. 2. Filename: rename `modules/base/custom-packages.nix` ->`modules/base/custom-packages-overlay.nix`. Mirrors the host-side filenames so the relationship is discoverable by name alone. 3. Header: clarify that the overlay is *defined* (not auto-applied) and that hosts opt in by composing it into `nixpkgs.overlays`. Prevents future readers from assuming `modules/base/` content is globally applied. Verified equivalent: `nix flake check --accept-flake-config --no-build` -> all checks passed; both host toplevel evals succeed.
Adopt the gemini-code-assist suggestion on PR #166 (lines 63 / 73 of the shared overlay): switch dependency lookups inside the `librepods` and `marktext` `overrideAttrs` bodies from `prev.*` to `final.*`. The `prev.<pkg>.overrideAttrs` calls themselves stay on `prev` (they need to extend the unmodified upstream attrs), but the deps consumed inside the override bodies (`fetchFromGitHub`, `libpulseaudio`, `openssl`, `qt6.*`, `node-gyp`) now go through `final`. This is the standard Nixpkgs idiom: it lets a later overlay -- e.g. an `openssl` CVE patch overlay -- propagate into the librepods build instead of being silently bypassed. No `nixpkgs.overlays` consumer in either host closure currently rebinds any of these dependencies, so drvPaths are byte-identical pre and post: - `librepods.drvPath`: `/nix/store/4sjfa72q2kvpvf5ywm0168g1p370bynf-librepods-0.2.5.drv` - `marktext.drvPath`: `/nix/store/sw5869iqqarh41bwjlqhja5yl1yj6vnh-marktext-0.17.0-unstable-2025-11-19.drv` The change is purely defensive against future overlay composition, and brings these two overrides into alignment with the rest of the file (`wfuzz`, `brave-origin`, all in-tree `callPackage` lines, `monitor-query`) which already use `final`. Comments updated to record the rationale. Validated with `nix flake check --accept-flake-config --no-build` (all checks passed) and pre-commit hook chain green.
8857e56 to
6d1a8d1
Compare
|
Claude finished @Bad3r's task in 1m 57s —— View job Status: PR already mergedThis PR was squash-merged into The rebase concern raised in the prior comment (envfs duplication via Retrospective review of merged contentFor posterity, since the review was requested. What landed (
|
| File | Δ | Role |
|---|---|---|
modules/base/custom-packages-overlay.nix |
+84 (new) | Defines flake.lib.overlays.customPackages |
modules/system76/custom-packages-overlay.nix |
+4 / -70 | Composes shared overlay + system76-power SCSI patch |
modules/tpnix/custom-packages-overlay.nix |
+3 / -70 | Just consumes the shared overlay |
Net: +91 / -140 across 3 files. Eliminates ~95% identical duplication that was the structural cause of the PR #165 conflict-marker class of bug.
Verdict: ✅ Correctly merged
- Namespacing —
flake.lib.overlays.customPackages(custom-packages-overlay.nix:12) follows the repo convention (flake.lib.security.*,flake.lib.agents.*,flake.lib.nixos.*,flake.lib.meta.*,flake.lib.xdg.*) and reserves theoverlaysnamespace for future shared overlays. - Filename symmetry — shared and host files all named
custom-packages-overlay.nix; producer/consumer relationship is discoverable. - Header documentation (
custom-packages-overlay.nix:1-10) — explicitly states the module defines the overlay (not auto-applied), points readers at a host composition example, and documents thefinal.callPackage(in-tree) vs.prev.<pkg>.overrideAttrs(upstream-patch) split. Good level of clarity for amodules/base/shared library. - Fixpoint discipline — every dep lookup inside an override body uses
final(lines 51, 57–63, 72, 74, 75); only the legitimateprev.<pkg>.overrideAttrsentry points (lines 49, 70) useprev. Matches Nixpkgs idiom and stays robust against future overlay composition. - Composition order —
system76correctly prepends the shared overlay then layers thesystem76-powerpatch (modules/system76/custom-packages-overlay.nix:4-17); since the shared overlay doesn't definesystem76-power, layering order is irrelevant for that attribute, so drvPaths are preserved. - Negative-space comment preserved (line 82): documents why
toggle-logseqlives inmodules/apps/i3wm/config.nixrather than here.
Items worth keeping in mind for future overlay work
These aren't issues with the merged code — they're observations from this review thread that may apply elsewhere:
- The
finalvsprevdiscipline applied here is now also in place formodules/base/envfs.nix(via refactor(base): use final for dep lookups in envfs overlay override #167). Any new overlay that overridesprev.<pkg>should follow the same shape: keepprev.<pkg>.overrideAttrsonprev, but resolve dep lookups (fetchFromGitHub,buildInputs,nativeBuildInputs, toolchain refs) throughfinal. - The
flake.lib.overlays.*namespace is now established. If a future shared overlay emerges (e.g. aflake.lib.overlays.csecfor cybersec tooling), this PR's pattern is the template.
Todos
- Sync with origin/main and inspect rebase state
- Read the current PR diff vs origin/main
- Review
modules/base/custom-packages-overlay.nix(shared overlay) - Review host call-sites (
system76,tpnix) - Cross-check
finalvsprevdiscipline and overlay composition - Verify the rebase concern from the latest comment (8857e56 / d0bca28 — not on branch tip; no issue)
- Post review
No file changes were made (PR is already merged; nothing to push).
• Merged commit: 4d7cb2f • Branch: refactor/dedup-host-overlays
Summary
modules/system76/custom-packages-overlay.nixandmodules/tpnix/custom-packages-overlay.nixinto a singleconfig.flake.lib.customPackagesOverlaydefined inmodules/base/custom-packages.nix. Hosts now compose the shared overlay with any host-specific extras (e.g.,system76-powerSCSI patch on system76).flake.lib.<namespace>convention already used bymodules/security/sops-helpers.nix,modules/security/usbguard-lib.nix, andmodules/meta/nixos-app-helpers.nix.<<<<<<</=======/>>>>>>>markers in only one of the two host files when an upstream change touched the shared region).This addresses the non-blocking observation from claude-review on PR #165 (run 25341374903): "lift the common attrset into a single shared customPackages overlay imported by both hosts — would prevent the next merge from re-creating exactly this class of conflict."
Stacked on top of #165 (
fix/tpnix-merge-conflict-markers); rebases cleanly onmainonce that lands.Test plan
nix flake check --accept-flake-config --no-buildreportsall checks passed!nix eval .#nixosConfigurations.system76.config.system.build.toplevel.outPathsucceedsnix eval .#nixosConfigurations.tpnix.config.system.build.toplevel.outPathsucceedsbrave-origin,system76-power,librepods(all byte-identical)system.activationScripts.binshbyte-identical pre/post-refactorenvironment.systemPackagesdiffers only onnixos-version, which embedssystem.configurationRevision(dirty-tree suffix accounts for the hash diff during local validation)deadnix,statix,nix-parse,treefmt,gitleaks,managed-files-drift)Diff overview