Repository navigation
fix(deps): keep env.jsonc component peers after lane merge, support +^/+~ versions #10815
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
davidfirst
wants to merge
3
commits into
master
Choose a base branch
from
fix/env-jsonc-lane-peer-deps
base: master
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
+437
−49
Open
Changes from all commits
Commits
Show all changes
3 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
43 changes: 43 additions & 0 deletions
43
scopes/component/isolator/prepare-package-json-to-write.spec.ts
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,43 @@ | ||
| import { expect } from 'chai'; | ||
| import { ComponentID, ComponentIdList } from '@teambit/component-id'; | ||
| import { ExtensionDataList } from '@teambit/legacy.extension-data'; | ||
| import { IsolatorMain } from './isolator.main.runtime'; | ||
|
|
||
| const depId = ComponentID.fromString('my-scope/dep@0.0.2'); | ||
|
|
||
| function preparePackageJson(componentDepsToIgnore: ComponentIdList, includePeers: boolean) { | ||
| const isolator = Object.create(IsolatorMain.prototype); | ||
| isolator.logger = { debug: () => {} }; | ||
| isolator.dependencyResolver = { getComponentDependencies: () => [{ componentId: depId, versionRange: '+^' }] }; | ||
| const noDeps = { getAllIds: () => new ComponentIdList() }; | ||
| const legacyComp = { | ||
| id: ComponentID.fromString('my-scope/user@0.0.2'), | ||
| version: '0.0.2', | ||
| mainFile: 'index.js', | ||
| _getHomepage: () => undefined, | ||
| packageDependencies: {}, | ||
| devPackageDependencies: {}, | ||
| peerPackageDependencies: {}, | ||
| extensions: new ExtensionDataList(), | ||
| dependencies: noDeps, | ||
| devDependencies: noDeps, | ||
| peerDependencies: { getAllIds: () => ComponentIdList.fromArray([depId]) }, | ||
| }; | ||
| const component = { id: legacyComp.id, state: { _consumer: legacyComp } }; | ||
| return isolator.preparePackageJsonToWrite(component, '.', componentDepsToIgnore, includePeers).packageJsonObject; | ||
| } | ||
|
|
||
| describe('IsolatorMain.preparePackageJsonToWrite()', () => { | ||
| it('should write the component peers with their resolved version when asked to', () => { | ||
| const packageJson = preparePackageJson(new ComponentIdList(), true); | ||
| expect(Object.values(packageJson.peerDependencies)).to.deep.equal(['^0.0.2']); | ||
| }); | ||
| it('should not write the component peers by default', () => { | ||
| const packageJson = preparePackageJson(new ComponentIdList(), false); | ||
| expect(packageJson.peerDependencies).to.deep.equal({}); | ||
| }); | ||
| it('should not write a component peer that is part of the capsules', () => { | ||
| const packageJson = preparePackageJson(ComponentIdList.fromArray([depId]), true); | ||
| expect(packageJson.peerDependencies).to.deep.equal({}); | ||
| }); | ||
| }); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
26 changes: 26 additions & 0 deletions
26
scopes/dependencies/dependencies/dependencies-loader/apply-overrides.spec.ts
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,26 @@ | ||
| import { expect } from 'chai'; | ||
| import { ApplyOverrides } from './apply-overrides'; | ||
|
|
||
| function createApplyOverrides({ installed, inWorkspacePolicy }: { installed?: string; inWorkspacePolicy?: string }) { | ||
| const applyOverrides = Object.create(ApplyOverrides.prototype); | ||
| applyOverrides.depsResolver = { | ||
| getWorkspacePolicyManifest: () => ({ dependencies: inWorkspacePolicy ? { 'my-pkg': inWorkspacePolicy } : {} }), | ||
| }; | ||
| applyOverrides._resolvePackageData = () => (installed ? { concreteVersion: installed } : undefined); | ||
| return applyOverrides; | ||
| } | ||
|
|
||
| describe('ApplyOverrides.resolveEnvPeerDepVersion()', () => { | ||
| it('should prefer the installed version by default', () => { | ||
| const applyOverrides = createApplyOverrides({ installed: '2.0.0', inWorkspacePolicy: '3.0.1' }); | ||
| expect(applyOverrides.resolveEnvPeerDepVersion('my-pkg')).to.equal('2.0.0'); | ||
| }); | ||
| it('should prefer the workspace policy when asked to, as the installed version could be outdated', () => { | ||
| const applyOverrides = createApplyOverrides({ installed: '2.0.0', inWorkspacePolicy: '3.0.1' }); | ||
| expect(applyOverrides.resolveEnvPeerDepVersion('my-pkg', true)).to.equal('3.0.1'); | ||
| }); | ||
| it('should fall back to the installed version when the workspace policy does not have the package', () => { | ||
| const applyOverrides = createApplyOverrides({ installed: '2.0.0' }); | ||
| expect(applyOverrides.resolveEnvPeerDepVersion('my-pkg', true)).to.equal('2.0.0'); | ||
| }); | ||
| }); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -14,6 +14,7 @@ import type { ResolvedPackageData } from '../resolve-pkg-data'; | |
| import { resolvePackageData } from '../resolve-pkg-data'; | ||
| import type { Workspace } from '@teambit/workspace'; | ||
| import type { DependencyResolverMain } from '@teambit/dependency-resolver'; | ||
| import { isPlusVersion, resolvePlusVersion } from '@teambit/dependency-resolver'; | ||
| import type { Consumer } from '@teambit/legacy.consumer'; | ||
| import type { ComponentMap } from '@teambit/legacy.bit-map'; | ||
| import type { Logger } from '@teambit/logger'; | ||
|
|
@@ -716,7 +717,11 @@ export class ApplyOverrides { | |
| comp.versionRange = pkgVal; | ||
| this.allDependencies.peerDependencies.push(comp); | ||
| } else { | ||
| this.allPackagesDependencies[key][pkgName] = pkgVal; | ||
| // a package has no separate version and range, so a "+" placeholder is resolved here. | ||
| // a component dep keeps it in the versionRange, and it's resolved when generating the package.json | ||
| this.allPackagesDependencies[key][pkgName] = isPlusVersion(pkgVal) | ||
| ? resolvePlusVersion(pkgVal, this.resolveEnvPeerDepVersion(pkgName, true)) | ||
| : pkgVal; | ||
|
Comment on lines
+722
to
+724
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 2. A tilde peer setting turns into a caret range applyPackageVersion() now calls resolveEnvPeerDepVersion(pkgName, true), which returns the workspace.jsonc value first, and that value is usually a range such as ^18.0.0. resolvePlusVersion() adds the ^/~ prefix only to a plain tag and returns a range unchanged, so +~ (and also the "exact" +) becomes the workspace's ^18.0.0 instead of ~18.2.0 or 18.2.0. The component's saved package peer and its released package.json then get a different range than the one env.jsonc asked for. Agent Prompt
|
||
| } | ||
|
|
||
| if (existsInCompsPeerDeps) { | ||
|
|
@@ -750,11 +755,11 @@ export class ApplyOverrides { | |
| }); | ||
| const resolvedEnvPolicyManifest = Object.keys(envPolicyManifest).reduce((acc, pkgName) => { | ||
| const version = envPolicyManifest[pkgName]; | ||
| if (version !== '+') { | ||
| if (!isPlusVersion(version)) { | ||
| acc[pkgName] = version; | ||
| return acc; | ||
| } | ||
| acc[pkgName] = this.resolveEnvPeerDepVersion(pkgName); | ||
| acc[pkgName] = resolvePlusVersion(version, this.resolveEnvPeerDepVersion(pkgName)); | ||
|
qodo-free-for-open-source-projects[bot] marked this conversation as resolved.
|
||
| return acc; | ||
| }, {}); | ||
| // TODO: handle component deps once we support peers between components | ||
|
|
@@ -765,21 +770,27 @@ export class ApplyOverrides { | |
| } | ||
|
|
||
| /** | ||
| * in the env.jsonc file, a policy-peer package can have `+` sign in the version. it means that it should be resolved | ||
| * in the env.jsonc file, a policy-peer package can have `+` sign (or `+^`/`+~`) in the version. it means that it should be resolved | ||
| * from the workspace. whatever version is installed/imported in the workspace, it should be used here. | ||
| * in some cases, the package is not installed in the workspace, for example, the env is now imported without the | ||
| * dep. so the dep is not in the node_modules. | ||
| * strategy should be: .bitmap, workspace.jsonc, then model. | ||
| * it's not in .bitmap, otherwise, it was linked and `_resolvePackageData` would have found it. | ||
| * so either, it's in the workspace.jsonc or in the model. | ||
| * @param preferWorkspacePolicy check the workspace.jsonc before what's installed. needed for a package that the | ||
| * component gets with a plus version. what's installed for the component was installed according to the version it | ||
| * had before, so it doesn't follow an upgrade in the workspace.jsonc (e.g. by "bit update"). | ||
| */ | ||
| private resolveEnvPeerDepVersion(pkgName: string): string { | ||
| private resolveEnvPeerDepVersion(pkgName: string, preferWorkspacePolicy = false): string { | ||
| const wsPolicy = this.depsResolver.getWorkspacePolicyManifest(); | ||
| const wsVersion = wsPolicy?.dependencies?.[pkgName] || wsPolicy?.peerDependencies?.[pkgName]; | ||
| if (preferWorkspacePolicy && wsVersion) { | ||
| return wsVersion; | ||
| } | ||
| const resolved = this._resolvePackageData(pkgName); | ||
| if (resolved && resolved.concreteVersion) { | ||
| return resolved.concreteVersion; | ||
| } | ||
| const wsPolicy = this.depsResolver.getWorkspacePolicyManifest(); | ||
| const wsVersion = wsPolicy?.dependencies?.[pkgName] || wsPolicy?.peerDependencies?.[pkgName]; | ||
| if (wsVersion) { | ||
| return wsVersion; | ||
| } | ||
|
|
||
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
1. Hidden peer updates fail with an error
🐞 Bug≡ CorrectnessAgent Prompt
ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools