Skip to content

Comments

fix(nix): use lock-driven Bun dependency fetching for frontend builds#198

Open
skulldogged wants to merge 4 commits intospacedriveapp:mainfrom
skulldogged:chore/frontend-bun2nix-lock
Open

fix(nix): use lock-driven Bun dependency fetching for frontend builds#198
skulldogged wants to merge 4 commits intospacedriveapp:mainfrom
skulldogged:chore/frontend-bun2nix-lock

Conversation

@skulldogged
Copy link
Contributor

@skulldogged skulldogged commented Feb 24, 2026

Summary

  • replace the fixed-output node_modules hash flow in nix/default.nix with a Bun-native dependency flow driven directly from interface/bun.lock
  • add bun2nix as a flake input and wire fetchBunDeps + bun2nix.hook into the frontend build
  • add frontendLockIntegrityCheck in flake.nix to fail when bun.lock contains empty integrity entries
  • regenerate and normalize interface/bun.lock so it is compatible with frozen installs in the same linker mode used by the Nix build (--linker=hoisted)

Why

  • removes manual frontend dependency hash churn in Nix when dependencies change
  • keeps frontend dependency resolution Bun-based and reproducible from the lockfile
  • ensures frozen lockfile installs in Nix do not attempt lockfile edits during build

Why the lockfile regeneration is needed

  • the previous lockfile format/metadata was not fully compatible with the Bun install mode used by the Nix hook
  • in Nix, installs run with --frozen-lockfile, so any lockfile delta causes a hard failure
  • normalizing the lock once (with the same linker expectations) makes lock-driven, frozen installs deterministic going forward

Validation

  • nix build .#frontend
  • nix build .#checks.x86_64-linux.frontendLockIntegrityCheck

Note

Automated Summary

This PR replaces Spacebot's frontend dependency management with a lock-file-driven Nix build that reads directly from bun.lock via bun2nix. The changes integrate the fetchBunDeps hook and add a lockfile integrity check to prevent empty entries. The bun.lock has been regenerated with --linker=hoisted to ensure frozen installs work correctly in Nix builds. This eliminates manual hash management in Nix when dependencies change while maintaining reproducibility.

Written by Tembo for commit 39830fb. This will update automatically on new commits.

Replace the fixed-output node_modules hash flow with bun2nix lock ingestion so frontend dependency updates no longer require manual Nix hash edits. Add a lock integrity check to fail when bun.lock contains empty integrity entries.
Regenerate the frontend Bun lockfile using the hoisted linker mode used by the Nix bun2nix hook so frozen installs do not attempt lockfile edits during builds.
@coderabbitai
Copy link

coderabbitai bot commented Feb 24, 2026

Walkthrough

Adds bun2nix to the flake and wiring in nix/default.nix to replace in-tree Bun handling with bun2nix-generated Bun derivations; exposes bun2nix in spacebotPackages and adds a frontend lock integrity check that inspects bun.lock and fails on empty integrities.

Changes

Cohort / File(s) Summary
Flake changes
flake.nix
Added bun2nix input and re-exported it under outputs; propagated bun2nix into spacebotPackages and added frontendLockIntegrityCheck to the checks set.
Frontend / Nix build
nix/default.nix
Added bun2nix parameter and integrated bun2nix.hook into nativeBuildInputs; introduced generatedFrontendBunNix, frontendBunDeps, and frontendInstallFlags; replaced previous platform-specific bun install derivations and lifecycle scripts with bun2nix-driven dependency generation and bun-based install/build flow.

Sequence Diagram(s)

sequenceDiagram
  participant Flake as flake.nix
  participant Bun2Nix as bun2nix (flake input)
  participant Generator as generatedFrontendBunNix
  participant Fetcher as frontendBunDeps
  participant Frontend as frontend derivation
  participant Check as frontendLockIntegrityCheck

  Flake->>Bun2Nix: expose bun2nix in outputs
  Bun2Nix->>Generator: generate Nix expr from bun.lock
  Generator->>Fetcher: produce bunDeps derivation
  Fetcher->>Frontend: provide bunDeps + bunInstallFlags
  Frontend->>Frontend: run bun install (with bunDeps) and bun run build
  Check->>Frontend: read bun.lock and run integrity check
  Check-->>Flake: report pass/fail
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Poem

🐰 I nibbled locks and spun a fix,

bun2nix hopped in to do the tricks,
Dependencies tidy, checks in tow,
Builds that bounce and tests that glow,
🥕— a little rabbit's Nix-powered show

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The PR title clearly describes the main change: switching to lock-driven Bun dependency fetching via bun2nix for frontend builds, which aligns with the primary objective.
Description check ✅ Passed The PR description is directly related to the changeset, detailing the rationale, implementation approach, and validation steps for the Bun dependency management refactor.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

skulldogged and others added 2 commits February 24, 2026 04:19
Co-authored-by: tembo[bot] <208362400+tembo[bot]@users.noreply.github.com>
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
flake.nix (1)

92-100: Defensive improvements for the integrity check: consider handling missing fields and better error reporting.

While the current code works correctly for the existing bun.lock (all 850 packages have valid SHA512 hashes at index 3), it's worth adding a defensive check for missing integrity fields and logging affected package names for faster debugging.

Suggested improvement
-            const packageEntries = Object.values(lock.packages ?? {})
-            const emptyIntegrities = packageEntries.filter(
-              (entry) => Array.isArray(entry) && entry[3] === ""
+            const packageMap = lock.packages ?? {}
+            const emptyIntegrities = Object.entries(packageMap).filter(
+              ([, entry]) => Array.isArray(entry) && (!entry[3] || entry[3] === "")
             )

             if (emptyIntegrities.length > 0) {
-              console.error("bun.lock has " + emptyIntegrities.length + " packages with empty integrity hashes")
+              console.error("bun.lock has " + emptyIntegrities.length + " packages with empty/missing integrity hashes:")
+              emptyIntegrities.forEach(([name]) => console.error("  - " + name))
               process.exit(1)
             }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@flake.nix` around lines 92 - 100, The integrity check currently uses
packageEntries = Object.values(lock.packages ?? {}) and only filters Array
entries with entry[3] === "", which misses entries with missing fields and
doesn't report package names; change to iterate Object.entries(lock.packages ??
{}) so you have both packageName and entry, treat non-array entries or
entries.length <= 3 or entry[3] falsy as failures, collect the package names
into a list (e.g., badPackages) and update the console.error to include the
count and the affected package names (and then process.exit(1) as before) so
failures are clearly identified for debugging; reference the variables
packageEntries, lock.packages, emptyIntegrities and the exit behavior.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@flake.nix`:
- Around line 92-100: The integrity check currently uses packageEntries =
Object.values(lock.packages ?? {}) and only filters Array entries with entry[3]
=== "", which misses entries with missing fields and doesn't report package
names; change to iterate Object.entries(lock.packages ?? {}) so you have both
packageName and entry, treat non-array entries or entries.length <= 3 or
entry[3] falsy as failures, collect the package names into a list (e.g.,
badPackages) and update the console.error to include the count and the affected
package names (and then process.exit(1) as before) so failures are clearly
identified for debugging; reference the variables packageEntries, lock.packages,
emptyIntegrities and the exit behavior.

ℹ️ Review info

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 39830fb and f9249f2.

📒 Files selected for processing (1)
  • flake.nix

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant