Skip to content

fix(isolator): don't isolate published-tag dependency-only cycles#10488

Merged
davidfirst merged 4 commits into
masterfrom
fix/isolator-skip-published-tag-dep-cycles
Jul 13, 2026
Merged

fix(isolator): don't isolate published-tag dependency-only cycles#10488
davidfirst merged 4 commits into
masterfrom
fix/isolator-skip-published-tag-dep-cycles

Conversation

@davidfirst

@davidfirst davidfirst commented Jul 11, 2026

Copy link
Copy Markdown
Member

Symptom

bit build can abort with EnvNotFound for a dependency's env — a component that is never built in this run, only pulled in as build context. When such a dependency carries an old/deprecated env that can't be loaded, resolving it fails the whole build, even though the dependency should simply be installed as a package.

Root cause

Since #10449 (isolate cyclic dependencies of seeders to avoid registry fetch), refined by #10453 (isolate & link snap-versioned cyclic deps during aspect isolation), getCyclicDependenciesOfSeeders pulls cyclic deps of seeders into the seeders-only isolation. #10453 added an onlySnaps guard but applied it only to aspect isolation — the build path runs with onlySnaps=false and therefore pulls in every member of every cycle found in the seeder's dependency closure, including cycles that exist purely among dependencies.

A published-tag, dependency-only cycle resolves fine from the registry and never needed a capsule. Isolating it needlessly pulls in large transitive graphs and force-loads each member's env — which aborts the build when a member has an env that can't be loaded.

Why it worked before those PRs: seeders-only isolation contained only the seeders — dependencies installed as packages, so their envs were never resolved.

Fix

Isolate a cyclic dependency only when the registry can't serve it: it's an unpublished snap, or it belongs to a cycle that includes a seeder (whose own package is unpublished, so a registry install of the member would try to fetch the seeder and fail). A published-tag, dependency-only cycle installs as a regular package again.

Behavior for the scenarios #10449/#10453 target is unchanged: cycles involving a seeder still pull in all their members, snap-versioned members are still isolated, and the aspect-isolation (onlySnaps) path is untouched.

Test

Added an e2e case (e2e/harmony/isolate-cyclic-deps.e2e.ts): when the seeder is outside a dependency-only cycle, bit capsule create <seeder> --seeders-only isolates only the seeder, not the cycle members — the inverse of the existing test that verifies a seeder-cycle is isolated.

When isolating seeders (bit build/sign), a cyclic dependency is now pulled into the isolation only when the registry can't serve it: an unpublished snap, or a member of a cycle that includes a seeder. A published-tag, dependency-only cycle installs as a regular package instead of a capsule, so its env is never loaded. This prevents build/sign from failing when such a dependency carries an old/deprecated env that can't be loaded, and avoids needlessly isolating (and installing) large transitive dependency graphs.
@qodo-free-for-open-source-projects

Copy link
Copy Markdown

PR Summary by Qodo

Fix isolator to skip published-tag dependency-only cyclic dependencies

🐞 Bug fix 🕐 10-20 Minutes

Grey Divider

AI Description

• Stop isolating dependency-only cycles that can be installed from the registry.
• Isolate cyclic deps only for snap versions or cycles involving a seeder.
• Prevent build/sign failures from loading deprecated envs for non-built dependencies.
Diagram

graph TD
  A["bit build/sign"] --> B["IsolatorMain"] --> C["Build dep graph"] --> D["Find cycles"] --> E{"Cycle member needs isolation?"}
  E -- "Yes (snap OR involves seeder)" --> F["Add to capsules"] --> G["Create/link capsules"]
  E -- "No (published-tag dep-only)" --> H[("Registry install")]
  subgraph Legend
    direction LR
    _proc["Process"] ~~~ _dec{"Decision"} ~~~ _reg[("Registry")]
  end
Loading
High-Level Assessment

The following are alternative approaches to this PR:

1. Filter cycles up-front (ignore dep-only cycles)
  • ➕ Avoids computing per-member filtering for cycles that will be entirely skipped
  • ➕ Makes intent clearer: only seeder-involving cycles matter for seeder isolation
  • ➖ Must still handle mixed cycles (some members already isolated, some snap)
  • ➖ Requires careful handling of versionless vs versioned IDs (same complexity, moved earlier)
2. Ask registry/host for publishability instead of inferring via snap/seeder
  • ➕ More direct definition of 'registry can serve it'
  • ➕ Could handle future non-snap unpublished cases
  • ➖ May require network calls or extra host APIs, slowing isolation
  • ➖ More moving parts than the current purely-graph-based check

Recommendation: Current approach is a good tradeoff: it keeps behavior unchanged for the targeted failure modes (snap members and seeder-involving cycles) while avoiding unnecessary capsule isolation for published-tag dependency-only cycles. The added seeder-involvement check (using versionless IDs) addresses the core correctness issue without introducing registry lookups or broader architectural changes.

Files changed (1) +20 / -3

Bug fix (1) +20 / -3
isolator.main.runtime.tsSkip isolating published-tag dependency-only cyclic dependencies +20/-3

Skip isolating published-tag dependency-only cyclic dependencies

• Refines seeder cyclic-dependency isolation to only add cycle members to capsules when they are snap-versioned or the cycle includes a seeder. Introduces a helper to detect seeder participation in a cycle using versionless ID comparison, preventing unnecessary capsule creation and env loading for registry-resolvable cycles.

scopes/component/isolator/isolator.main.runtime.ts

@qodo-free-for-open-source-projects

qodo-free-for-open-source-projects Bot commented Jul 11, 2026

Copy link
Copy Markdown

Code Review by Qodo

🐞 Bugs (0) 📘 Rule violations (0) 📎 Requirement gaps (0)

Grey Divider

Great, no issues found!

Qodo reviewed your code and found no material issues that require review

Grey Divider

Previous review results

Review updated until commit 8ade0b5

Results up to commit 3026074


🐞 Bugs (0) 📘 Rule violations (0) 📎 Requirement gaps (0)

Great, no issues found!

Qodo reviewed your code and found no material issues that require review
Results up to commit 4b29ef8


🐞 Bugs (0) 📘 Rule violations (0) 📎 Requirement gaps (0)

Great, no issues found!

Qodo reviewed your code and found no material issues that require review
Qodo Logo

Comment thread scopes/component/isolator/isolator.main.runtime.ts Outdated
@qodo-free-for-open-source-projects

Copy link
Copy Markdown

Code review by qodo was updated up to the latest commit beb55ec

@qodo-free-for-open-source-projects

Copy link
Copy Markdown

Code review by qodo was updated up to the latest commit 3026074

@davidfirst davidfirst enabled auto-merge (squash) July 13, 2026 14:07
@qodo-free-for-open-source-projects

Copy link
Copy Markdown

Code review by qodo was updated up to the latest commit 8ade0b5

@davidfirst davidfirst merged commit 68e094b into master Jul 13, 2026
13 checks passed
@davidfirst davidfirst deleted the fix/isolator-skip-published-tag-dep-cycles branch July 13, 2026 14:46
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.

2 participants