Skip to content

Commit de4088b

Browse files
feat(node-workspace): use configured strategies to build new dependent version bumps (#2112)
Co-authored-by: Jeff Ching <[email protected]>
1 parent 611db3d commit de4088b

File tree

10 files changed

+318
-20
lines changed

10 files changed

+318
-20
lines changed

__snapshots__/node-workspace.js

+76
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,82 @@ Release notes for path: node1, releaseType: node
138138
This PR was generated with [Release Please](https://github.com/googleapis/release-please). See [documentation](https://github.com/googleapis/release-please#release-please).
139139
`
140140

141+
exports['NodeWorkspace plugin run includes headers for packages with configured strategies 1'] = `
142+
:robot: I have created a release *beep* *boop*
143+
---
144+
145+
146+
<details><summary>@here/pkgA: 3.3.4</summary>
147+
148+
Release notes for path: node1, releaseType: node
149+
</details>
150+
151+
<details><summary>pkgB: 2.2.3</summary>
152+
153+
## [2.2.3](https://github.com/googleapis/node-test-repo/compare/pkgB-v2.2.2...pkgB-v2.2.3) (1983-10-10)
154+
155+
156+
### Dependencies
157+
158+
* The following workspace dependencies were updated
159+
* dependencies
160+
* @here/pkgA bumped from 3.3.3 to 3.3.4
161+
</details>
162+
163+
<details><summary>pkgC: 1.1.2</summary>
164+
165+
## 1.1.2 (1983-10-10)
166+
167+
168+
### Dependencies
169+
170+
* The following workspace dependencies were updated
171+
* dependencies
172+
* @here/pkgB bumped from 2.2.2 to 2.2.3
173+
</details>
174+
175+
<details><summary>pkgE: 1.0.1</summary>
176+
177+
## 1.0.1 (1983-10-10)
178+
179+
180+
### Dependencies
181+
182+
* The following workspace dependencies were updated
183+
* dependencies
184+
* @here/pkgA bumped to 3.3.4
185+
</details>
186+
187+
---
188+
This PR was generated with [Release Please](https://github.com/googleapis/release-please). See [documentation](https://github.com/googleapis/release-please#release-please).
189+
`
190+
191+
exports['NodeWorkspace plugin run includes headers for packages with configured strategies 2'] = `
192+
other notes
193+
`
194+
195+
exports['NodeWorkspace plugin run includes headers for packages with configured strategies 3'] = `
196+
## [2.2.3](https://github.com/googleapis/node-test-repo/compare/pkgB-v2.2.2...pkgB-v2.2.3) (1983-10-10)
197+
198+
199+
### Dependencies
200+
201+
* The following workspace dependencies were updated
202+
* dependencies
203+
* @here/pkgA bumped from 3.3.3 to 3.3.4
204+
`
205+
206+
exports['NodeWorkspace plugin run includes headers for packages with configured strategies 4'] = `
207+
## 1.1.2 (1983-10-10)
208+
209+
210+
### Dependencies
211+
212+
* The following workspace dependencies were updated
213+
* dependencies
214+
* @here/pkgB bumped from 2.2.2 to 2.2.3
215+
`
216+
141217
exports['NodeWorkspace plugin run respects version prefix 1'] = `
142218
{
143219
"name": "@here/plugin1",

src/plugins/cargo-workspace.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -233,10 +233,10 @@ export class CargoWorkspace extends WorkspacePlugin<CrateInfo> {
233233
return existingCandidate;
234234
}
235235

236-
protected newCandidate(
236+
protected async newCandidate(
237237
pkg: CrateInfo,
238238
updatedVersions: VersionsMap
239-
): CandidateReleasePullRequest {
239+
): Promise<CandidateReleasePullRequest> {
240240
const version = updatedVersions.get(pkg.name);
241241
if (!version) {
242242
throw new Error(`Didn't find updated version for ${pkg.name}`);

src/plugins/maven-workspace.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -394,10 +394,10 @@ export class MavenWorkspace extends WorkspacePlugin<MavenArtifact> {
394394
}
395395
return existingCandidate;
396396
}
397-
protected newCandidate(
397+
protected async newCandidate(
398398
artifact: MavenArtifact,
399399
updatedVersions: VersionsMap
400-
): CandidateReleasePullRequest {
400+
): Promise<CandidateReleasePullRequest> {
401401
const version = updatedVersions.get(artifact.name);
402402
if (!version) {
403403
throw new Error(`Didn't find updated version for ${artifact.name}`);

src/plugins/node-workspace.ts

+45-2
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,9 @@ import {
2929
addPath,
3030
} from './workspace';
3131
import {PatchVersionUpdate} from '../versioning-strategy';
32+
import {Strategy} from '../strategy';
33+
import {Commit} from '../commit';
34+
import {Release} from '../release';
3235
import {CompositeUpdater} from '../updaters/composite';
3336
import {PackageJson, newVersionWithRange} from '../updaters/node/package-json';
3437
import {Logger} from '../util/logger';
@@ -67,6 +70,10 @@ interface NodeWorkspaceOptions extends WorkspacePluginOptions {
6770
*/
6871
export class NodeWorkspace extends WorkspacePlugin<Package> {
6972
private alwaysLinkLocal: boolean;
73+
74+
private strategiesByPath: Record<string, Strategy> = {};
75+
private releasesByPath: Record<string, Release> = {};
76+
7077
readonly updatePeerDependencies: boolean;
7178
constructor(
7279
github: GitHub,
@@ -230,10 +237,10 @@ export class NodeWorkspace extends WorkspacePlugin<Package> {
230237
}
231238
return existingCandidate;
232239
}
233-
protected newCandidate(
240+
protected async newCandidate(
234241
pkg: Package,
235242
updatedVersions: VersionsMap
236-
): CandidateReleasePullRequest {
243+
): Promise<CandidateReleasePullRequest> {
237244
// Update version of the package
238245
const newVersion = updatedVersions.get(pkg.name);
239246
if (!newVersion) {
@@ -250,6 +257,30 @@ export class NodeWorkspace extends WorkspacePlugin<Package> {
250257
updatedVersions,
251258
this.logger
252259
);
260+
261+
const strategy = this.strategiesByPath[updatedPackage.path];
262+
const latestRelease = this.releasesByPath[updatedPackage.path];
263+
264+
const basePullRequest = strategy
265+
? await strategy.buildReleasePullRequest([], latestRelease, false, [], {
266+
newVersion,
267+
})
268+
: undefined;
269+
270+
if (basePullRequest) {
271+
return this.updateCandidate(
272+
{
273+
path: pkg.path,
274+
pullRequest: basePullRequest,
275+
config: {
276+
releaseType: 'node',
277+
},
278+
},
279+
pkg,
280+
updatedVersions
281+
);
282+
}
283+
253284
const pullRequest: ReleasePullRequest = {
254285
title: PullRequestTitle.ofTargetBranch(this.targetBranch),
255286
body: new PullRequestBody([
@@ -350,6 +381,18 @@ export class NodeWorkspace extends WorkspacePlugin<Package> {
350381
: {}),
351382
};
352383
}
384+
385+
async preconfigure(
386+
strategiesByPath: Record<string, Strategy>,
387+
_commitsByPath: Record<string, Commit[]>,
388+
_releasesByPath: Record<string, Release>
389+
): Promise<Record<string, Strategy>> {
390+
// Using preconfigure to siphon releases and strategies.
391+
this.strategiesByPath = strategiesByPath;
392+
this.releasesByPath = _releasesByPath;
393+
394+
return strategiesByPath;
395+
}
353396
}
354397

355398
function getChangelogDepsNotes(

src/plugins/workspace.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -154,7 +154,7 @@ export abstract class WorkspacePlugin<T> extends ManifestPlugin {
154154
pkg
155155
)}`
156156
);
157-
const newCandidate = this.newCandidate(pkg, updatedVersions);
157+
const newCandidate = await this.newCandidate(pkg, updatedVersions);
158158
if (newCandidatePaths.has(newCandidate.path)) {
159159
this.logger.info(
160160
`Already created new candidate for path: ${newCandidate.path}`
@@ -320,7 +320,7 @@ export abstract class WorkspacePlugin<T> extends ManifestPlugin {
320320
protected abstract newCandidate(
321321
pkg: T,
322322
updatedVersions: VersionsMap
323-
): CandidateReleasePullRequest;
323+
): Promise<CandidateReleasePullRequest>;
324324

325325
/**
326326
* Collect all packages being managed in this workspace.

src/strategies/base.ts

+8-8
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
// See the License for the specific language governing permissions and
1313
// limitations under the License.
1414

15-
import {Strategy, BuildReleaseOptions} from '../strategy';
15+
import {Strategy, BuildReleaseOptions, BumpReleaseOptions} from '../strategy';
1616
import {GitHub} from '../github';
1717
import {VersioningStrategy} from '../versioning-strategy';
1818
import {Repository} from '../repository';
@@ -261,19 +261,19 @@ export abstract class BaseStrategy implements Strategy {
261261
commits: ConventionalCommit[],
262262
latestRelease?: Release,
263263
draft?: boolean,
264-
labels: string[] = []
264+
labels: string[] = [],
265+
bumpOnlyOptions?: BumpReleaseOptions
265266
): Promise<ReleasePullRequest | undefined> {
266267
const conventionalCommits = await this.postProcessCommits(commits);
267268
this.logger.info(`Considering: ${conventionalCommits.length} commits`);
268-
if (conventionalCommits.length === 0) {
269+
if (!bumpOnlyOptions && conventionalCommits.length === 0) {
269270
this.logger.info(`No commits for path: ${this.path}, skipping`);
270271
return undefined;
271272
}
272273

273-
const newVersion = await this.buildNewVersion(
274-
conventionalCommits,
275-
latestRelease
276-
);
274+
const newVersion =
275+
bumpOnlyOptions?.newVersion ??
276+
(await this.buildNewVersion(conventionalCommits, latestRelease));
277277
const versionsMap = await this.updateVersionsMap(
278278
await this.buildVersionsMap(conventionalCommits),
279279
conventionalCommits,
@@ -309,7 +309,7 @@ export abstract class BaseStrategy implements Strategy {
309309
latestRelease,
310310
commits
311311
);
312-
if (this.changelogEmpty(releaseNotesBody)) {
312+
if (!bumpOnlyOptions && this.changelogEmpty(releaseNotesBody)) {
313313
this.logger.info(
314314
`No user facing commits found since ${
315315
latestRelease ? latestRelease.sha : 'beginning of time'

src/strategies/java.ts

+3-1
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ import {DEFAULT_SNAPSHOT_LABELS} from '../manifest';
3030
import {JavaReleased} from '../updaters/java/java-released';
3131
import {mergeUpdates} from '../updaters/composite';
3232
import {logger as defaultLogger} from '../util/logger';
33+
import {BumpReleaseOptions} from '../strategy';
3334

3435
const CHANGELOG_SECTIONS = [
3536
{type: 'feat', section: 'Features'},
@@ -77,7 +78,8 @@ export class Java extends BaseStrategy {
7778
commits: ConventionalCommit[],
7879
latestRelease?: Release,
7980
draft?: boolean,
80-
labels: string[] = []
81+
labels: string[] = [],
82+
_bumpOnlyOptions?: BumpReleaseOptions
8183
): Promise<ReleasePullRequest | undefined> {
8284
if (await this.needsSnapshot(commits, latestRelease)) {
8385
this.logger.info('Repository needs a snapshot bump.');

src/strategies/php-yoshi.ts

+4-2
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ import {BranchName} from '../util/branch-name';
2929
import {PullRequestBody} from '../util/pull-request-body';
3030
import {GitHubFileContents} from '@google-automations/git-file-utils';
3131
import {FileNotFoundError} from '../errors';
32+
import {BumpReleaseOptions} from '../strategy';
3233

3334
const CHANGELOG_SECTIONS = [
3435
{type: 'feat', section: 'Features'},
@@ -68,12 +69,13 @@ export class PHPYoshi extends BaseStrategy {
6869
commits: Commit[],
6970
latestRelease?: Release,
7071
draft?: boolean,
71-
labels: string[] = []
72+
labels: string[] = [],
73+
bumpOnlyOptions?: BumpReleaseOptions
7274
): Promise<ReleasePullRequest | undefined> {
7375
const conventionalCommits = await this.postProcessCommits(
7476
parseConventionalCommits(commits, this.logger)
7577
);
76-
if (conventionalCommits.length === 0) {
78+
if (!bumpOnlyOptions && conventionalCommits.length === 0) {
7779
this.logger.info(`No commits for path: ${this.path}, skipping`);
7880
return undefined;
7981
}

src/strategy.ts

+10-1
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,10 @@ export interface BuildReleaseOptions {
2424
groupPullRequestTitlePattern?: string;
2525
}
2626

27+
export interface BumpReleaseOptions {
28+
newVersion: Version;
29+
}
30+
2731
/**
2832
* A strategy is responsible for determining which files are
2933
* necessary to update in a release pull request.
@@ -39,6 +43,10 @@ export interface Strategy {
3943
* component if available.
4044
* @param {boolean} draft Optional. Whether or not to create the pull
4145
* request as a draft. Defaults to `false`.
46+
* @param {BumpReleaseOptions} bumpOnlyOptions Optional. Options, that when
47+
* present, indicate a release should be created even if there are no
48+
* conventional commits. This is used when a release is required for
49+
* a dependency update with a workspace plugin.
4250
* @returns {ReleasePullRequest | undefined} The release pull request to
4351
* open for this path/component. Returns undefined if we should not
4452
* open a pull request.
@@ -47,7 +55,8 @@ export interface Strategy {
4755
commits: Commit[],
4856
latestRelease?: Release,
4957
draft?: boolean,
50-
labels?: string[]
58+
labels?: string[],
59+
bumpOnlyOptions?: BumpReleaseOptions
5160
): Promise<ReleasePullRequest | undefined>;
5261

5362
/**

0 commit comments

Comments
 (0)