diff --git a/src/factories/plugin-factory.ts b/src/factories/plugin-factory.ts index fc7754912..ebf575111 100644 --- a/src/factories/plugin-factory.ts +++ b/src/factories/plugin-factory.ts @@ -39,6 +39,7 @@ export interface PluginFactoryOptions { repositoryConfig: RepositoryConfig; manifestPath: string; separatePullRequests?: boolean; + labels?: string[]; // node options alwaysLinkLocal?: boolean; diff --git a/src/manifest.ts b/src/manifest.ts index 18343780b..c05355709 100644 --- a/src/manifest.ts +++ b/src/manifest.ts @@ -414,6 +414,7 @@ export class Manifest { repositoryConfig: this.repositoryConfig, manifestPath: this.manifestPath, separatePullRequests: this.separatePullRequests, + labels: this.labels, }) ); this.pullRequestOverflowHandler = new FilePullRequestOverflowHandler( diff --git a/src/plugins/workspace.ts b/src/plugins/workspace.ts index 5e58b73b7..166213e95 100644 --- a/src/plugins/workspace.ts +++ b/src/plugins/workspace.ts @@ -35,6 +35,7 @@ export interface WorkspacePluginOptions { manifestPath?: string; updateAllPackages?: boolean; merge?: boolean; + labels?: string[]; logger?: Logger; } @@ -58,6 +59,7 @@ export abstract class WorkspacePlugin extends ManifestPlugin { private updateAllPackages: boolean; private manifestPath: string; private merge: boolean; + private labels: string[]; constructor( github: Scm, targetBranch: string, @@ -68,6 +70,7 @@ export abstract class WorkspacePlugin extends ManifestPlugin { this.manifestPath = options.manifestPath ?? DEFAULT_RELEASE_PLEASE_MANIFEST; this.updateAllPackages = options.updateAllPackages ?? false; this.merge = options.merge ?? true; + this.labels = options.labels ?? []; } async run( candidates: CandidateReleasePullRequest[] @@ -161,6 +164,11 @@ export abstract class WorkspacePlugin extends ManifestPlugin { ); } else { newCandidatePaths.add(newCandidate.path); + for (const label of this.labels) { + if (!newCandidate.pullRequest.labels.includes(label)) { + newCandidate.pullRequest.labels.push(label); + } + } newCandidates.push(newCandidate); } } @@ -176,15 +184,31 @@ export abstract class WorkspacePlugin extends ManifestPlugin { newCandidates = await mergePlugin.run(newCandidates); } - const newUpdates = newCandidates[0].pullRequest.updates; - newUpdates.push({ - path: this.manifestPath, - createIfMissing: false, - updater: new ReleasePleaseManifest({ - version: newCandidates[0].pullRequest.version!, - versionsMap: updatedPathVersions, - }), - }); + if (this.merge) { + const candidate = newCandidates[0]; + candidate.pullRequest.updates.push({ + path: this.manifestPath, + createIfMissing: false, + updater: new ReleasePleaseManifest({ + version: candidate.pullRequest.version!, + versionsMap: updatedPathVersions, + }), + }); + } else { + for (const candidate of newCandidates) { + const version = updatedPathVersions.get(candidate.path); + if (version) { + candidate.pullRequest.updates.push({ + path: this.manifestPath, + createIfMissing: false, + updater: new ReleasePleaseManifest({ + version: candidate.pullRequest.version!, + versionsMap: new Map([[candidate.path, version]]), + }), + }); + } + } + } this.logger.info( `Post-processing ${newCandidates.length} in-scope candidates` diff --git a/test/plugins/node-workspace.ts b/test/plugins/node-workspace.ts index 197232f64..08f4afc10 100644 --- a/test/plugins/node-workspace.ts +++ b/test/plugins/node-workspace.ts @@ -315,6 +315,77 @@ describe('NodeWorkspace plugin', () => { expect(updater.versionsMap?.get('node5')?.toString()).to.eql('1.0.1'); snapshot(dateSafe(nodeCandidate!.pullRequest.body.toString())); }); + it('adds separate manifest updates and labels to new candidates', 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', + 'node2/package.json', + 'node5/package.json', + ], + flatten: false, + targetBranch: 'main', + }); + plugin = new NodeWorkspace( + github, + 'main', + { + node1: {releaseType: 'node'}, + node2: {releaseType: 'node'}, + node5: {releaseType: 'node'}, + }, + { + merge: false, + labels: ['autorelease: pending'], + } + ); + + const newCandidates = await plugin.run(candidates); + expect(newCandidates).lengthOf(3); + + const node1Candidate = newCandidates.find( + candidate => candidate.path === 'node1' + )!; + const node2Candidate = newCandidates.find( + candidate => candidate.path === 'node2' + )!; + const node5Candidate = newCandidates.find( + candidate => candidate.path === 'node5' + )!; + + assertNoHasUpdate( + node1Candidate.pullRequest.updates, + '.release-please-manifest.json' + ); + const node2Manifest = assertHasUpdate( + node2Candidate.pullRequest.updates, + '.release-please-manifest.json', + ReleasePleaseManifest + ).updater as ReleasePleaseManifest; + expect(Array.from(node2Manifest.versionsMap!.keys())).to.eql(['node2']); + const node5Manifest = assertHasUpdate( + node5Candidate.pullRequest.updates, + '.release-please-manifest.json', + ReleasePleaseManifest + ).updater as ReleasePleaseManifest; + expect(Array.from(node5Manifest.versionsMap!.keys())).to.eql(['node5']); + expect(node2Candidate.pullRequest.labels).to.include( + 'autorelease: pending' + ); + expect(node5Candidate.pullRequest.labels).to.include( + 'autorelease: pending' + ); + }); it('walks dependency tree and updates previously untouched packages (prerelease)', async () => { const candidates: CandidateReleasePullRequest[] = [ buildMockCandidatePullRequest('node1', 'node', '3.3.4-beta', {