From c84414a3192cca65da4469c7559460624446c898 Mon Sep 17 00:00:00 2001 From: Timothy Jones Date: Tue, 12 Dec 2023 05:26:13 +1100 Subject: [PATCH] fix(node-workspace): Add update-peer-dependencies option that also updates peer dependencies (#2094) * fix: Node workspace plugin now updates peer dependencies. Fixes #1943 * test: Remove obsolete snapshot * feat: Add update-peer-dependencies option to the node-workspace plugin * chore: Remove unused snapshot * test: Correct test for peerDependencies option Fixes #1943 --------- Co-authored-by: Jeff Ching --- __snapshots__/node-workspace.js | 33 +++++++++++++ docs/manifest-releaser.md | 11 +++++ schemas/config.json | 5 ++ src/factories/plugin-factory.ts | 1 + src/manifest.ts | 7 +++ src/plugins/node-workspace.ts | 6 +++ test/plugins/node-workspace.ts | 82 +++++++++++++++++++++++++++++++++ 7 files changed, 145 insertions(+) diff --git a/__snapshots__/node-workspace.js b/__snapshots__/node-workspace.js index f276d8689..fb38d0c84 100644 --- a/__snapshots__/node-workspace.js +++ b/__snapshots__/node-workspace.js @@ -207,3 +207,36 @@ Release notes for path: node4, releaseType: node --- This PR was generated with [Release Please](https://github.com/googleapis/release-please). See [documentation](https://github.com/googleapis/release-please#release-please). ` + +exports['NodeWorkspace plugin with updatePeerDependencies: true respects version prefix and updates peer dependencies 1'] = ` +{ + "name": "@here/plugin1", + "version": "4.4.4", + "peerDependencies": { + "@here/pkgA": "^2.2.2" + } +} +` + +exports['NodeWorkspace plugin with updatePeerDependencies: true should not ignore peer dependencies 1'] = ` +:robot: I have created a release *beep* *boop* +--- + + +
@here/pkgA: 3.3.4 + +Release notes for path: node1, releaseType: node +
+ +
@here/plugin1: 4.4.5 + +### Dependencies + +* The following workspace dependencies were updated + * peerDependencies + * @here/pkgA bumped from ^3.3.3 to ^3.3.4 +
+ +--- +This PR was generated with [Release Please](https://github.com/googleapis/release-please). See [documentation](https://github.com/googleapis/release-please#release-please). +` diff --git a/docs/manifest-releaser.md b/docs/manifest-releaser.md index 23f6f6e1e..e3b768325 100644 --- a/docs/manifest-releaser.md +++ b/docs/manifest-releaser.md @@ -207,6 +207,11 @@ defaults (those are documented in comments) // absence defaults to true "always-link-local": false, + // when using the `node-workspace` plugin, update peer dependency fields + // that reference bumped packages. + // absence defaults to false, and peer dependency fields are not updated. + "update-peer-dependencies": true, + // if true, create separate pull requests for each package instead of a // single manifest release pull request // absence defaults to false and one pull request will be raised @@ -495,6 +500,12 @@ your update pull request. If you don't agree with this behavior and would only l your local dependencies bumped if they are within the SemVer range, you can set the `"always-link-local"` option to `false` in your manifest config. +#### Linking peer dependencies + +By default, the `node-workspace` plugin doesn't modify `peerDependencies` fields in +package.json. If you would like version bumps to be also linked in `peerDependencies` +fields, set `"update-peer-dependencies"` to `true` in your manifest config. + ### cargo-workspace The `cargo-workspace` plugin operates similarly to the `node-workspace` plugin, diff --git a/schemas/config.json b/schemas/config.json index ee17c6f3d..a3e170e8b 100644 --- a/schemas/config.json +++ b/schemas/config.json @@ -248,6 +248,10 @@ "description": "When using the `node-workspace` plugin, force all local dependencies to be linked.", "type": "boolean" }, + "update-peer-dependencies": { + "description": "When using the `node-workspace` plugin, also bump peer dependency versions if they are modified.", + "type": "boolean" + }, "plugins": { "description": "Plugins to apply to pull requests. Plugins can be added to perform extra release processing that cannot be achieved by an individual release strategy.", "type": "array", @@ -383,6 +387,7 @@ "bootstrap-sha": true, "last-release-sha": true, "always-link-local": true, + "update-peer-dependencies": true, "plugins": true, "group-pull-request-title-pattern": true, "release-search-depth": true, diff --git a/src/factories/plugin-factory.ts b/src/factories/plugin-factory.ts index 46d38de7b..242346853 100644 --- a/src/factories/plugin-factory.ts +++ b/src/factories/plugin-factory.ts @@ -41,6 +41,7 @@ export interface PluginFactoryOptions { // node options alwaysLinkLocal?: boolean; + updatePeerDependencies?: boolean; // workspace options updateAllPackages?: boolean; diff --git a/src/manifest.ts b/src/manifest.ts index ef2976e77..77f979956 100644 --- a/src/manifest.ts +++ b/src/manifest.ts @@ -181,6 +181,7 @@ export interface ManifestOptions { bootstrapSha?: string; lastReleaseSha?: string; alwaysLinkLocal?: boolean; + updatePeerDependencies?: boolean; separatePullRequests?: boolean; plugins?: PluginType[]; fork?: boolean; @@ -242,6 +243,7 @@ export interface ManifestConfig extends ReleaserConfigJson { 'bootstrap-sha'?: string; 'last-release-sha'?: string; 'always-link-local'?: boolean; + 'update-peer-dependencies'?: boolean; plugins?: PluginType[]; 'group-pull-request-title-pattern'?: string; 'release-search-depth'?: number; @@ -317,6 +319,8 @@ export class Manifest { * as the point to consider commits after * @param {boolean} manifestOptions.alwaysLinkLocal Option for the node-workspace * plugin + * @param {boolean} manifestOptions.updatePeerDependencies Option for the node-workspace + * plugin * @param {boolean} manifestOptions.separatePullRequests If true, create separate pull * requests instead of a single manifest release pull request * @param {PluginType[]} manifestOptions.plugins Any plugins to use for this repository @@ -432,6 +436,8 @@ export class Manifest { * as the point to consider commits after * @param {boolean} manifestOptions.alwaysLinkLocal Option for the node-workspace * plugin + * @param {boolean} manifestOptions.updatePeerDependencies Option for the node-workspace + * plugin * @param {boolean} manifestOptions.separatePullRequests If true, create separate pull * requests instead of a single manifest release pull request * @param {PluginType[]} manifestOptions.plugins Any plugins to use for this repository @@ -1362,6 +1368,7 @@ async function parseConfig( bootstrapSha: config['bootstrap-sha'], lastReleaseSha: config['last-release-sha'], alwaysLinkLocal: config['always-link-local'], + updatePeerDependencies: config['update-peer-dependencies'], separatePullRequests: config['separate-pull-requests'], groupPullRequestTitlePattern: config['group-pull-request-title-pattern'], plugins: config['plugins'], diff --git a/src/plugins/node-workspace.ts b/src/plugins/node-workspace.ts index 5eab29efc..66827d111 100644 --- a/src/plugins/node-workspace.ts +++ b/src/plugins/node-workspace.ts @@ -55,6 +55,7 @@ interface Package { interface NodeWorkspaceOptions extends WorkspacePluginOptions { alwaysLinkLocal?: boolean; + updatePeerDependencies?: boolean; } /** @@ -66,6 +67,7 @@ interface NodeWorkspaceOptions extends WorkspacePluginOptions { */ export class NodeWorkspace extends WorkspacePlugin { private alwaysLinkLocal: boolean; + private updatePeerDependencies: boolean; constructor( github: GitHub, targetBranch: string, @@ -74,6 +76,7 @@ export class NodeWorkspace extends WorkspacePlugin { ) { super(github, targetBranch, repositoryConfig, options); this.alwaysLinkLocal = options.alwaysLinkLocal === false ? false : true; + this.updatePeerDependencies = options.updatePeerDependencies === true; } protected async buildAllPackages( candidates: CandidateReleasePullRequest[] @@ -342,6 +345,9 @@ export class NodeWorkspace extends WorkspacePlugin { ...(packageJson.dependencies ?? {}), ...(packageJson.devDependencies ?? {}), ...(packageJson.optionalDependencies ?? {}), + ...(this.updatePeerDependencies + ? packageJson.peerDependencies ?? {} + : {}), }; } } diff --git a/test/plugins/node-workspace.ts b/test/plugins/node-workspace.ts index 2daa6e501..5c7fe36dd 100644 --- a/test/plugins/node-workspace.ts +++ b/test/plugins/node-workspace.ts @@ -409,4 +409,86 @@ describe('NodeWorkspace plugin', () => { snapshot(dateSafe(nodeCandidate!.pullRequest.body.toString())); }); }); + describe('with updatePeerDependencies: true', () => { + const options = {updatePeerDependencies: true}; + it('should not ignore peer dependencies', async () => { + const candidates: CandidateReleasePullRequest[] = [ + buildMockCandidatePullRequest('node1', 'node', '3.3.4', { + component: '@here/pkgA', + updates: [ + buildMockPackageUpdate('node1/package.json', 'node1/package.json'), + ], + }), + ]; + stubFilesFromFixtures({ + sandbox, + github, + fixturePath: fixturesPath, + files: ['node1/package.json', 'plugin1/package.json'], + flatten: false, + targetBranch: 'main', + }); + plugin = new NodeWorkspace( + github, + 'main', + { + node1: { + releaseType: 'node', + }, + plugin1: { + releaseType: 'node', + }, + }, + options + ); + const newCandidates = await plugin.run(candidates); + expect(newCandidates).lengthOf(1); + const nodeCandidate = newCandidates.find( + candidate => candidate.config.releaseType === 'node' + ); + expect(nodeCandidate).to.not.be.undefined; + const updates = nodeCandidate!.pullRequest.updates; + assertHasUpdate(updates, 'node1/package.json'); + assertHasUpdate(updates, 'plugin1/package.json'); + snapshot(dateSafe(nodeCandidate!.pullRequest.body.toString())); + }); + + it('respects version prefix and updates peer dependencies', async () => { + const candidates: CandidateReleasePullRequest[] = [ + buildMockCandidatePullRequest('plugin1', 'node', '4.4.4', { + component: '@here/plugin1', + updates: [ + buildMockPackageUpdate( + 'plugin1/package.json', + 'plugin1/package.json' + ), + ], + }), + buildMockCandidatePullRequest('node1', 'node', '2.2.2', { + component: '@here/pkgA', + updates: [ + buildMockPackageUpdate('node1/package.json', 'node1/package.json'), + ], + }), + ]; + plugin = new NodeWorkspace( + github, + 'main', + { + plugin1: {releaseType: 'node'}, + node1: {releaseType: 'node'}, + }, + options + ); + const newCandidates = await plugin.run(candidates); + expect(newCandidates).lengthOf(1); + const nodeCandidate = newCandidates.find( + candidate => candidate.config.releaseType === 'node' + ); + expect(nodeCandidate).to.not.be.undefined; + const updates = nodeCandidate!.pullRequest.updates; + assertHasUpdate(updates, 'node1/package.json'); + snapshotUpdate(updates, 'plugin1/package.json'); + }); + }); });