Skip to content

fix: install dependencies added on the other lane during lane merge - #10579

Open
davidfirst wants to merge 2 commits into
masterfrom
fix/lane-merge-install-new-deps
Open

fix: install dependencies added on the other lane during lane merge#10579
davidfirst wants to merge 2 commits into
masterfrom
fix/lane-merge-install-new-deps

Conversation

@davidfirst

Copy link
Copy Markdown
Member

Problem

When you merge a lane, and the incoming side added a new package dependency, the install step does not install the new package. The package manager shows "Lockfile is up to date, resolution step is skipped". The auto-snap that follows fails with a "missing packages" error.

Cause

The merge flow loads the components before it writes the merged files and the merged config. The install step that runs after the merge uses this stale cache. As a result, the install manifest does not contain the new dependency, and the package manager skips the resolution step.

The config-merger records the new dependency correctly in the unmerged-components store. Only the stale cache prevents the install from using it.

Fix

Clear the workspace cache before the install step of the merge. The install then loads the components with the merged state, and the new dependency enters the install manifest.

Added an e2e test that reproduces the failure and verifies the fix.

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

Copy link
Copy Markdown

PR Summary by Qodo

Fix lane-merge installs for dependencies added on the other lane

🐞 Bug fix 🧪 Tests 🕐 20-40 Minutes

Grey Divider

AI Description

• Clear workspace component cache before merge-triggered dependency installation.
• Ensure install manifest reflects merged dependencies so auto-snap doesn’t fail.
• Add e2e coverage for main→lane merge introducing a new package dependency.
Diagram

graph TD
  A["Lane merge flow"] --> B["Components loaded & cached"] --> C["Write merged files/config"] --> D["workspace.clearCache()"] --> E["Dependency install"] --> F["Install manifest"] --> G["Package manager resolve"] --> H["Auto-snap"]
Loading
High-Level Assessment

The following are alternative approaches to this PR:

1. Delay component loading until after merged files/config are written
  • ➕ Avoids relying on cache invalidation as a corrective step
  • ➕ Reduces risk of other merge steps reading stale component state
  • ➖ Higher refactor risk: merge flow may currently depend on preloaded components
  • ➖ Could increase merge latency if loading is needed multiple times
2. Invalidate only dependency-related component cache entries
  • ➕ More targeted than clearing the entire workspace cache
  • ➕ Potentially faster for large workspaces
  • ➖ Harder to implement correctly without deep cache semantics knowledge
  • ➖ Higher chance of missing another stale derived artifact impacting install

Recommendation: Clearing the workspace cache immediately before the merge-triggered install is a pragmatic, low-risk fix that directly addresses the stale-state cause and is now covered by an e2e regression test. Consider the more structural alternative (load-after-write) only if additional stale-cache issues appear in the merge pipeline.

Files changed (2) +45 / -0

Bug fix (1) +5 / -0
merging.main.runtime.tsClear workspace cache before install during lane merge +5/-0

Clear workspace cache before install during lane merge

• Before running dependency installation in the merge flow, clears the workspace cache to prevent the install from using pre-merge component state. This ensures newly introduced dependencies from the other lane enter the install manifest and are resolved by the package manager.

scopes/component/merging/merging.main.runtime.ts

Tests (1) +40 / -0
merge-lanes-main.e2e.tsAdd regression test for main→lane merge introducing a new dependency +40/-0

Add regression test for main→lane merge introducing a new dependency

• Introduces an e2e scenario where main adds a new package dependency (is-positive) after a lane diverges with its own lockfile state. Verifies the merge completes auto-snap without missing packages and that the new dependency exists in node_modules.

e2e/harmony/lanes/merge-lanes-main.e2e.ts

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

qodo-free-for-open-source-projects Bot commented Aug 7, 2026

Copy link
Copy Markdown

Code Review by Qodo

🐞 Bugs (1) 📘 Rule violations (0) 📜 Skill insights (0)

Grey Divider


Remediation recommended

1. Unverified test precondition 🐞 Bug ☼ Reliability ⭐ New
Description
The new e2e test claims the lane lockfile “does not include is-positive” but never asserts that
is-positive is absent before the merge, so the test can pass without actually exercising the
regression it’s meant to catch.
Code

e2e/harmony/lanes/merge-lanes-main.e2e.ts[R337-340]

+      // create a lockfile that does not include is-positive
+      helper.command.install();
+      const laneWs = helper.scopeHelper.cloneWorkspace();
+      helper.command.switchLocalLane('main', '-x');
Evidence
The test explicitly states it created a lockfile that excludes is-positive, but it never checks
that state before proceeding. Other e2e tests in this repo do explicitly assert node_modules state
when it matters, demonstrating the preferred pattern for preventing false positives.

e2e/harmony/lanes/merge-lanes-main.e2e.ts[321-348]
e2e/harmony/install.e2e.ts[303-319]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

### Issue description
The new e2e scenario documents that the lane workspace’s lockfile/node_modules should not contain `is-positive` before merging `main`, but it does not verify that assumption. If `is-positive` becomes present (e.g., fixture changes, transitive deps, or state leakage), the test may pass even if the merge/install behavior regresses.

### Issue Context
The setup runs `helper.command.install()` and immediately snapshots the workspace, but there is no assertion that `node_modules/is-positive` (and/or the lockfile) is actually absent at that moment.

### Fix Focus Areas
- e2e/harmony/lanes/merge-lanes-main.e2e.ts[337-347]

### Suggested fix
Add a precondition assertion right after the initial `helper.command.install()` (and before cloning/switching lanes), e.g.:
- Assert `node_modules/is-positive` does **not** exist.
- Optionally assert the lockfile does **not** mention `is-positive` (depending on the package-manager configured for these e2e runs).

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


2. Overbroad cache clear ✓ Resolved 🐞 Bug ➹ Performance
Description
MergingMain now calls workspace.clearCache() before running install, which also clears the
scope object repository cache and re-initializes it even though the stated need is only to reload
merged component state. This adds avoidable overhead to every lane merge that reaches the install
path and can be narrowed to component caches only.
Code

scopes/component/merging/merging.main.runtime.ts[R291-294]

+      // merged config (unmerged-components store). without clearing the cache, the install below
+      // reloads them with pre-merge dependencies, so a package newly introduced on the other side
+      // never enters the install manifest and the package manager skips it ("lockfile is up to date").
+      if (this.workspace) await this.workspace.clearCache();
Evidence
workspace.clearCache() calls into scope.clearCache() (which clears the legacy repository cache
and re-initializes it) in addition to clearing workspace component loaders; a narrower
clearAllComponentsCache() already exists and is used elsewhere after writing unmergedComponents
for similar “reload merged config” reasons.

scopes/component/merging/merging.main.runtime.ts[289-307]
scopes/workspace/workspace/workspace.ts[846-869]
scopes/scope/scope/scope.main.runtime.ts[436-440]
scopes/scope/objects/objects/repository.ts[469-473]
scopes/git/ci/ci.main.runtime.ts[589-594]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`workspace.clearCache()` clears more than needed (including scope object repository caches) to address a stale *workspace component* cache problem. This can add unnecessary I/O and time to merges that already run an install.
### Issue Context
The goal is to ensure `install` recalculates manifests using the merged component/config state written during the merge. That can be achieved by clearing the workspace component loaders/list, without re-initializing scope object caches.
### Fix Focus Areas
- scopes/component/merging/merging.main.runtime.ts[289-307]
- scopes/workspace/workspace/workspace.ts[846-869]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


3. Unpinned test dependency version ✓ Resolved 🐞 Bug ☼ Reliability
Description
The new e2e test runs bit install is-positive without a version, so it will resolve whatever the
latest registry version is at test time. This makes the test non-deterministic and can cause
unrelated future breakages if is-positive changes/unpublishes.
Code

e2e/harmony/lanes/merge-lanes-main.e2e.ts[R340-342]

+      helper.command.switchLocalLane('main', '-x');
+      helper.command.install('is-positive');
+      helper.fs.outputFile('comp1/index.js', `const isPositive = require('is-positive');\n${baseFile}`);
Evidence
The test explicitly installs is-positive without a version, while the install command supports
version suffixes and the same test file pins other package installs, indicating determinism is
expected.

e2e/harmony/lanes/merge-lanes-main.e2e.ts[321-347]
e2e/harmony/lanes/merge-lanes-main.e2e.ts[171-177]
scopes/workspace/install/install.cmd.tsx[40-45]
scopes/workspace/install/package-name-utils.ts[14-40]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The e2e installs an unversioned package (`is-positive`), which makes the test depend on the moving `latest` tag.
### Issue Context
Other tests in this file already pin external deps (e.g. lodash@^4.17.21), which avoids time-dependent failures.
### Fix Focus Areas
- e2e/harmony/lanes/merge-lanes-main.e2e.ts[321-357]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


To customize comments, go to the Qodo configuration screen, or learn more in the docs.

Previous review results

Review updated until commit 6568919 ⚖️ Balanced

Results up to commit f664879


🐞 Bugs (2) 📘 Rule violations (0) 📜 Skill insights (0)


Remediation recommended
1. Overbroad cache clear 🐞 Bug ➹ Performance
Description
MergingMain now calls workspace.clearCache() before running install, which also clears the
scope object repository cache and re-initializes it even though the stated need is only to reload
merged component state. This adds avoidable overhead to every lane merge that reaches the install
path and can be narrowed to component caches only.
Code

scopes/component/merging/merging.main.runtime.ts[R291-294]

+      // merged config (unmerged-components store). without clearing the cache, the install below
+      // reloads them with pre-merge dependencies, so a package newly introduced on the other side
+      // never enters the install manifest and the package manager skips it ("lockfile is up to date").
+      if (this.workspace) await this.workspace.clearCache();
Evidence
workspace.clearCache() calls into scope.clearCache() (which clears the legacy repository cache
and re-initializes it) in addition to clearing workspace component loaders; a narrower
clearAllComponentsCache() already exists and is used elsewhere after writing unmergedComponents
for similar “reload merged config” reasons.

scopes/component/merging/merging.main.runtime.ts[289-307]
scopes/workspace/workspace/workspace.ts[846-869]
scopes/scope/scope/scope.main.runtime.ts[436-440]
scopes/scope/objects/objects/repository.ts[469-473]
scopes/git/ci/ci.main.runtime.ts[589-594]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

### Issue description
`workspace.clearCache()` clears more than needed (including scope object repository caches) to address a stale *workspace component* cache problem. This can add unnecessary I/O and time to merges that already run an install.

### Issue Context
The goal is to ensure `install` recalculates manifests using the merged component/config state written during the merge. That can be achieved by clearing the workspace component loaders/list, without re-initializing scope object caches.

### Fix Focus Areas
- scopes/component/merging/merging.main.runtime.ts[289-307]
- scopes/workspace/workspace/workspace.ts[846-869]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


2. Unpinned test dependency version 🐞 Bug ☼ Reliability
Description
The new e2e test runs bit install is-positive without a version, so it will resolve whatever the
latest registry version is at test time. This makes the test non-deterministic and can cause
unrelated future breakages if is-positive changes/unpublishes.
Code

e2e/harmony/lanes/merge-lanes-main.e2e.ts[R340-342]

+      helper.command.switchLocalLane('main', '-x');
+      helper.command.install('is-positive');
+      helper.fs.outputFile('comp1/index.js', `const isPositive = require('is-positive');\n${baseFile}`);
Evidence
The test explicitly installs is-positive without a version, while the install command supports
version suffixes and the same test file pins other package installs, indicating determinism is
expected.

e2e/harmony/lanes/merge-lanes-main.e2e.ts[321-347]
e2e/harmony/lanes/merge-lanes-main.e2e.ts[171-177]
scopes/workspace/install/install.cmd.tsx[40-45]
scopes/workspace/install/package-name-utils.ts[14-40]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

### Issue description
The e2e installs an unversioned package (`is-positive`), which makes the test depend on the moving `latest` tag.

### Issue Context
Other tests in this file already pin external deps (e.g. lodash@^4.17.21), which avoids time-dependent failures.

### Fix Focus Areas
- e2e/harmony/lanes/merge-lanes-main.e2e.ts[321-357]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Qodo Logo

Comment thread scopes/component/merging/merging.main.runtime.ts Outdated
Comment thread e2e/harmony/lanes/merge-lanes-main.e2e.ts
Comment on lines +337 to +340
// create a lockfile that does not include is-positive
helper.command.install();
const laneWs = helper.scopeHelper.cloneWorkspace();
helper.command.switchLocalLane('main', '-x');

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Remediation recommended

1. Unverified test precondition 🐞 Bug ☼ Reliability

The new e2e test claims the lane lockfile “does not include is-positive” but never asserts that
is-positive is absent before the merge, so the test can pass without actually exercising the
regression it’s meant to catch.
Agent Prompt
### Issue description
The new e2e scenario documents that the lane workspace’s lockfile/node_modules should not contain `is-positive` before merging `main`, but it does not verify that assumption. If `is-positive` becomes present (e.g., fixture changes, transitive deps, or state leakage), the test may pass even if the merge/install behavior regresses.

### Issue Context
The setup runs `helper.command.install()` and immediately snapshots the workspace, but there is no assertion that `node_modules/is-positive` (and/or the lockfile) is actually absent at that moment.

### Fix Focus Areas
- e2e/harmony/lanes/merge-lanes-main.e2e.ts[337-347]

### Suggested fix
Add a precondition assertion right after the initial `helper.command.install()` (and before cloning/switching lanes), e.g.:
- Assert `node_modules/is-positive` does **not** exist.
- Optionally assert the lockfile does **not** mention `is-positive` (depending on the package-manager configured for these e2e runs).

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

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

Copy link
Copy Markdown

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

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