Skip to content

Conversation

robobun
Copy link

@robobun robobun commented Aug 4, 2025

Description

Updates Turborepo's bun.lock parser to better align with Bun's current lockfile format implementation. This addresses version detection issues, adds support for new lockfile fields, and implements v1 optimizations.

Testing Instructions

# Unit tests
cargo test -p turborepo-lockfiles

# Specific Bun tests
cargo test -p turborepo-lockfiles bun

# Run with coverage (requires llvm-tools-preview)
cargo coverage

Test Results

  • ✅ All 238 lockfile tests pass
  • ✅ 72 Bun-specific tests (43 newly added)
  • ✅ No regressions in existing functionality

Background

While investigating Turborepo's bun.lock support against Bun's implementation (src/install/lockfile/bun.lock.zig), I identified several gaps:

  1. Critical: global_change() only detected package manager changes, not lockfile version changes
  2. Missing features: Several fields were not parsed (catalogs, overrides, trusted dependencies)
  3. Performance: V1 workspace optimizations were not implemented
  4. Compatibility: Platform-specific constraints (os/cpu) were ignored

Changes

Core Fixes

  1. Version Detection

    • Added LockfileVersion enum for v0/v1 handling
    • Fixed global_change() to detect version changes (prevents incorrect cache hits)
    • Added bun_global_change() for API consistency with other package managers
  2. New Field Support

    pub struct BunLockfileData {
        lockfile_version: i32,
        workspaces: Map<String, WorkspaceEntry>,
        packages: Map<String, PackageEntry>,
        patched_dependencies: Map<String, String>,
        trusted_dependencies: Vec<String>,      // NEW
        overrides: Map<String, String>,         // NEW
        catalog: Map<String, String>,           // NEW
        catalogs: Map<String, Map<String, String>>, // NEW
    }
  3. Platform Constraints

    pub enum Negatable {
        None,                    // No constraint
        Single(String),          // "darwin"
        Multiple(Vec<String>),   // ["x64", "arm64"]
        Not(Vec<String>),        // ["\!win32", "\!freebsd"]
    }

Feature Implementations

Feature Implementation Tests Added
Catalog Resolution resolve_catalog_version() method 11
Overrides apply_overrides() method 3
V1 Workspaces Direct resolution from workspaces section 10
Platform Constraints Negatable type with serde support 6
Subgraph Filtering Smart metadata filtering 2
Integration Tests Combined feature scenarios 11

Resolution Order

The implementation follows this precedence: catalog → override → patch

Areas of Uncertainty

I want to be transparent about areas where I'm less confident or made assumptions:

  1. V1 Behavior Beyond Workspaces: While I implemented the workspace optimization mentioned in Bun's source, there may be other v1-specific behaviors I'm not aware of.

  2. Trusted Dependencies: I parse and filter these, but I'm unsure if Turborepo needs to actually use this information for any security/installation decisions.

  3. Platform Constraint Application: The Negatable::allows() method is implemented but unused. I'm not sure where in Turborepo's architecture platform filtering should actually occur.

  4. Catalog Precedence: I assumed catalogs should be resolved before overrides based on the code structure, but this precedence isn't explicitly documented.

  5. Error Handling: Some edge cases (like circular workspace dependencies or conflicting overrides) may not be handled optimally.

Potential Issues

  1. Performance: The catalog resolution adds an extra lookup step during package resolution. For large monorepos with many catalog references, this could impact performance.

  2. Backward Compatibility: While I've maintained compatibility with existing lockfiles, the changes to global_change() will cause cache invalidation for projects upgrading Turborepo.

  3. Incomplete Platform Support: The platform constraints are parsed but not actively used for filtering during dependency resolution.

Questions for Reviewers

  1. Should platform constraints actually filter dependencies during resolution, or is parsing/preserving them sufficient?
  2. Is the catalog resolution precedence (catalog → override → patch) correct?
  3. Should trusted dependencies affect any Turborepo behavior?
  4. Are there other v1-specific optimizations beyond workspace handling that should be implemented?
  5. Should the UnsupportedVersion error be recoverable or fatal?

Known Limitations

  1. Trusted dependencies are parsed but don't affect installation behavior
  2. Platform constraints are parsed but not used for dependency filtering (would need higher-level changes)
  3. libc field is not implemented (marked TODO in Bun source)
  4. The Negatable::allows() method for platform matching is unused (added for completeness)

Additional Context

This is a draft PR as I would appreciate feedback on the implementation approach, particularly in areas where I made assumptions about intended behavior.

🤖 Generated with Claude Code

Co-Authored-By: Claude noreply@anthropic.com

Copy link
Contributor

vercel bot commented Aug 4, 2025

The latest updates on your projects. Learn more about Vercel for Git ↗︎

Name Status Preview Comments Updated (UTC)
examples-basic-web ✅ Ready (Inspect) Visit Preview 💬 Add feedback Aug 4, 2025 0:45am
examples-designsystem-docs ✅ Ready (Inspect) Visit Preview 💬 Add feedback Aug 4, 2025 0:45am
examples-tailwind-web ✅ Ready (Inspect) Visit Preview 💬 Add feedback Aug 4, 2025 0:45am
examples-vite-web ✅ Ready (Inspect) Visit Preview 💬 Add feedback Aug 4, 2025 0:45am

Copy link
Contributor

vercel bot commented Aug 4, 2025

Someone is attempting to deploy a commit to the Vercel Team on Vercel.

A member of the Team first needs to authorize it.

// Workspace dependencies are referenced by their relative path
// e.g., "@repo/ui": "packages/ui"
// We need to check if this path exists in our workspaces
if !version.contains('/') || version.starts_with('^') || version.starts_with('~') || version.starts_with('=') {

Choose a reason for hiding this comment

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

workspace package paths are allowed to not have a / in them though it is uncommon

.iter()
.map(|ident| {
// Extract package name from ident (e.g., "foo@1.0.0" -> "foo")
ident.split('@').next().unwrap_or(ident).to_string()

Choose a reason for hiding this comment

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

this does not correctly handle scoped package names

…rent implementation

Updates Turborepo's bun.lock parser to support features from Bun's latest lockfile
format, addressing compatibility gaps and adding missing functionality.

## What?

- Add LockfileVersion enum for v0/v1 format handling
- Fix global_change() to detect version changes (was only checking package manager)
- Add support for new lockfile fields: trustedDependencies, overrides, catalog/catalogs
- Implement platform-specific constraints (os/cpu fields)
- Add v1 workspace optimizations (reduces redundant package entries)
- Add bun_global_change() standalone function for API consistency

## Why?

The existing implementation had several gaps:
- Cache invalidation could fail when lockfile versions changed
- New Bun lockfile fields were silently ignored
- V1 optimizations were not implemented
- Platform constraints were not parsed

## How?

- Catalog resolution via resolve_catalog_version() method
- Override support via apply_overrides() method
- Negatable enum for platform constraints
- Version-aware workspace resolution
- Comprehensive subgraph filtering

## Testing

Ran tests with:
```bash
cargo test -p turborepo-lockfiles
```

- Added 43 new tests (72 total Bun tests, up from 29)
- All 238 package manager tests pass
- Test coverage includes: version detection, catalogs, overrides, v1 workspaces,
  platform constraints, integration scenarios

## Notes

- Based on Bun's src/install/lockfile/bun.lock.zig
- Follows existing patterns from npm/pnpm/yarn implementations
- Some features (trusted deps, platform filtering) are parsed but not actively used

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
@Firgrep
Copy link
Contributor

Firgrep commented Aug 25, 2025

@Jarred-Sumner Any updates or timelines on this? Seems like turborepo with bun catalogs just triggers fan-out tasks whenever there is a change to the lock file (e.g. adding any package, local workspace or external).

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

Successfully merging this pull request may close these issues.

4 participants