Skip to content

fix(image-spec): discover transitive nix flake path deps from flake.lock#46

Open
sammiphone6 wants to merge 2 commits intomasterfrom
devin/1772169940-fix-transitive-nix-flake-path-deps
Open

fix(image-spec): discover transitive nix flake path deps from flake.lock#46
sammiphone6 wants to merge 2 commits intomasterfrom
devin/1772169940-fix-transitive-nix-flake-path-deps

Conversation

@sammiphone6
Copy link

@sammiphone6 sammiphone6 commented Feb 27, 2026

Why are the changes needed?

When a direct nix flake path input (e.g. minos2_rust) itself depends on another path input (e.g. rust-exautils), that transitive dependency only appears in flake.lock, not in the top-level flake.nix. The builder previously only scanned flake.nix for url = "path:..." patterns, so transitive path deps were never copied into the Docker build context. This caused Docker/nix builds to fail with errors like:

error: path '/build/local_packages/rust/shared/exautils/flake.nix' does not exist

What changes were proposed in this pull request?

  1. New function discover_nix_flake_lock_path_inputs() in image_spec.py: Scans flake.lock JSON for all nodes with "type": "path" in their locked field, deduplicating against already-discovered direct inputs.

  2. Updated _copy_local_packages_and_update_lock() in default_builder.py:

    • After discovering direct path inputs from flake.nix, also discovers transitive ones from flake.lock.
    • Direct inputs: copied into local_packages/ AND paths rewritten in both flake.nix and flake.lock.
    • Transitive inputs: only copied into local_packages/ — their paths in flake.lock are not rewritten. This is because nix resolves transitive dep paths relative to the parent input, not the root flake. Since both parent and child are copied preserving their git-root-relative structure under local_packages/, the relative paths between them remain correct.
    • Copy logic refactored into _copy_nix_input() helper.
  3. Updated tag hash computation in ImageSpec.tag: Includes transitive path deps in the content hash so image tags change when transitive deps change.

How was this patch tested?

Manually verified against the exa_ml flake which has the dependency chain exa_ml → minos2_rust → rust-exautils where rust-exautils is a transitive path dep that was previously missed.

Initial version rewrote transitive dep paths in the top-level flake.lock, which caused nix to resolve them relative to the parent input's new location, producing incorrect paths like:

/build/local_packages/python/minos2/minos2_rust/local_packages/rust/shared/exautils/flake.nix

Fixed by not rewriting transitive dep paths — the relative structure is preserved by the copy layout.

No unit tests added yet.

Human review checklist

  • Transitive path resolution assumption: The fix assumes nix resolves transitive dep paths relative to the parent input directory. Verify this holds for all nix flake path resolution scenarios (e.g. deeply nested transitive deps, absolute path inputs).
  • Silent skip of non-existent transitive deps: discover_nix_flake_lock_path_inputs silently skips paths that don't exist on disk, while direct inputs in the builder raise ValueError. Is this asymmetry intentional/acceptable?
  • already_discovered set mutation: The function mutates the caller's set as a side effect. Acceptable here but worth noting.
  • Relative structure preservation: The fix relies on both direct and transitive inputs being copied under local_packages/ preserving their original git-root-relative paths. If a transitive dep lives outside the git root, this could break.
  • Missing unit tests: Both discover_nix_flake_lock_path_inputs and the copy-without-rewrite behavior for transitive deps should have test coverage.

Check all the applicable boxes

  • I updated the documentation accordingly.
  • All new and existing tests passed.
  • All commits are signed-off.

Link to Devin run: https://app.devin.ai/sessions/ca581679e9554604bfc845afc7f50f97
Requested by: @sammiphone6

When a direct flake path input (e.g. minos2_rust) depends on another
path input (e.g. rust-exautils), that transitive dependency only appears
in flake.lock, not in the top-level flake.nix. The builder previously
only scanned flake.nix for path inputs, causing Docker builds to fail
with missing flake.nix errors for transitive deps.

Add discover_nix_flake_lock_path_inputs() to scan flake.lock for all
nodes with type=path, deduplicating against already-discovered direct
inputs. Both the builder copy logic and the tag hash computation now
include transitive path deps.

Co-Authored-By: Samuel Mitchell <sammiphone6@gmail.com>
@devin-ai-integration
Copy link

🤖 Devin AI Engineer

I'll be helping with this pull request! Here's what you should know:

✅ I will automatically:

  • Address comments on this PR. Add '(aside)' to your comment to have me ignore it.
  • Look at CI failures and help fix them

Note: I can only respond to comments from users who have write access to this repository.

⚙️ Control Options:

  • Disable automatic comment and CI monitoring

Nix resolves transitive dep paths relative to the parent input, not
the root flake. Since all inputs are copied preserving their git-root-
relative structure under local_packages/, the relative paths between
parent and child inputs remain correct. Only direct inputs (from
flake.nix) need path rewriting.

Refactor copy logic into _copy_nix_input() helper for clarity.

Co-Authored-By: Samuel Mitchell <sammiphone6@gmail.com>
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