Skip to content

Commit a3fac52

Browse files
fix: allow configuring multiple, separate linked-versions plugins (#1961)
* test: failing test for configuring multiple, separate linked-versions plugins * fix: allow configuring multiple, separate linked-versions plugins * test: failing test for having separate branch names * fix: grouped pull requests should have different branch names * chore: remove debugging logs * 🦉 Updates from OwlBot post-processor See https://github.com/googleapis/repo-automation-bots/blob/main/packages/owl-bot/README.md --------- Co-authored-by: Owl Bot <gcf-owl-bot[bot]@users.noreply.github.com>
1 parent a0ccd92 commit a3fac52

6 files changed

Lines changed: 203 additions & 13 deletions

File tree

__snapshots__/linked-versions.js

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,64 @@ exports['LinkedVersions plugin can skip grouping pull requests 3'] = `
4646
This PR was generated with [Release Please](https://github.com/googleapis/release-please). See [documentation](https://github.com/googleapis/release-please#release-please).
4747
`
4848

49+
exports['LinkedVersions plugin should allow multiple groups of linked versions 1'] = `
50+
:robot: I have created a release *beep* *boop*
51+
---
52+
53+
54+
<details><summary>pkg1: 1.0.1</summary>
55+
56+
## [1.0.1](https://github.com/fake-owner/fake-repo/compare/pkg1-v1.0.0...pkg1-v1.0.1) (1983-10-10)
57+
58+
59+
### Bug Fixes
60+
61+
* some bugfix ([aaaaaa](https://github.com/fake-owner/fake-repo/commit/aaaaaa))
62+
</details>
63+
64+
<details><summary>pkg4: 1.0.1</summary>
65+
66+
## [1.0.1](https://github.com/fake-owner/fake-repo/compare/pkg4-v1.0.0...pkg4-v1.0.1) (1983-10-10)
67+
68+
69+
### Miscellaneous Chores
70+
71+
* **pkg4:** Synchronize second group name versions
72+
</details>
73+
74+
---
75+
This PR was generated with [Release Please](https://github.com/googleapis/release-please). See [documentation](https://github.com/googleapis/release-please#release-please).
76+
`
77+
78+
exports['LinkedVersions plugin should allow multiple groups of linked versions 2'] = `
79+
:robot: I have created a release *beep* *boop*
80+
---
81+
82+
83+
<details><summary>pkg2: 0.2.4</summary>
84+
85+
## [0.2.4](https://github.com/fake-owner/fake-repo/compare/pkg2-v0.2.3...pkg2-v0.2.4) (1983-10-10)
86+
87+
88+
### Bug Fixes
89+
90+
* some bugfix ([bbbbbb](https://github.com/fake-owner/fake-repo/commit/bbbbbb))
91+
</details>
92+
93+
<details><summary>pkg3: 0.2.4</summary>
94+
95+
## [0.2.4](https://github.com/fake-owner/fake-repo/compare/pkg3-v0.2.3...pkg3-v0.2.4) (1983-10-10)
96+
97+
98+
### Miscellaneous Chores
99+
100+
* **pkg3:** Synchronize group name versions
101+
</details>
102+
103+
---
104+
This PR was generated with [Release Please](https://github.com/googleapis/release-please). See [documentation](https://github.com/googleapis/release-please#release-please).
105+
`
106+
49107
exports['LinkedVersions plugin should group pull requests 1'] = `
50108
:robot: I have created a release *beep* *boop*
51109
---

src/manifest.ts

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -746,12 +746,9 @@ export class Manifest {
746746
// pull requests
747747
if (!this.separatePullRequests) {
748748
this.plugins.push(
749-
new Merge(
750-
this.github,
751-
this.targetBranch,
752-
this.repositoryConfig,
753-
this.groupPullRequestTitlePattern
754-
)
749+
new Merge(this.github, this.targetBranch, this.repositoryConfig, {
750+
pullRequestTitlePattern: this.groupPullRequestTitlePattern,
751+
})
755752
);
756753
}
757754

src/plugins/linked-versions.ts

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import {Release} from '../release';
2222
import {Version} from '../version';
2323
import {buildStrategy} from '../factory';
2424
import {Merge} from './merge';
25+
import {BranchName} from '../util/branch-name';
2526

2627
interface LinkedVersionsPluginOptions {
2728
merge?: boolean;
@@ -154,6 +155,7 @@ export class LinkedVersions extends ManifestPlugin {
154155
(collection, candidate) => {
155156
if (!candidate.pullRequest.version) {
156157
this.logger.warn('pull request missing version', candidate);
158+
collection[1].push(candidate);
157159
return collection;
158160
}
159161
if (this.components.has(candidate.config.component || '')) {
@@ -175,7 +177,14 @@ export class LinkedVersions extends ManifestPlugin {
175177
this.github,
176178
this.targetBranch,
177179
this.repositoryConfig,
178-
`chore\${scope}: release ${this.groupName} libraries`
180+
{
181+
pullRequestTitlePattern: `chore\${scope}: release ${this.groupName} libraries`,
182+
forceMerge: true,
183+
headBranchName: BranchName.ofGroupTargetBranch(
184+
this.groupName,
185+
this.targetBranch
186+
).toString(),
187+
}
179188
);
180189
const merged = await merge.run(inScopeCandidates);
181190
outOfScopeCandidates.push(...merged);

src/plugins/merge.ts

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,13 @@ import {Update} from '../update';
2626
import {mergeUpdates} from '../updaters/composite';
2727
import {GitHub} from '../github';
2828

29+
interface MergeOptions {
30+
pullRequestTitlePattern?: string;
31+
pullRequestHeader?: string;
32+
headBranchName?: string;
33+
forceMerge?: boolean;
34+
}
35+
2936
/**
3037
* This plugin merges multiple pull requests into a single
3138
* release pull request.
@@ -35,18 +42,21 @@ import {GitHub} from '../github';
3542
export class Merge extends ManifestPlugin {
3643
private pullRequestTitlePattern?: string;
3744
private pullRequestHeader?: string;
45+
private headBranchName?: string;
46+
private forceMerge: boolean;
3847

3948
constructor(
4049
github: GitHub,
4150
targetBranch: string,
4251
repositoryConfig: RepositoryConfig,
43-
pullRequestTitlePattern?: string,
44-
pullRequestHeader?: string
52+
options: MergeOptions = {}
4553
) {
4654
super(github, targetBranch, repositoryConfig);
4755
this.pullRequestTitlePattern =
48-
pullRequestTitlePattern || MANIFEST_PULL_REQUEST_TITLE_PATTERN;
49-
this.pullRequestHeader = pullRequestHeader;
56+
options.pullRequestTitlePattern ?? MANIFEST_PULL_REQUEST_TITLE_PATTERN;
57+
this.pullRequestHeader = options.pullRequestHeader;
58+
this.headBranchName = options.headBranchName;
59+
this.forceMerge = options.forceMerge ?? false;
5060
}
5161

5262
async run(
@@ -61,7 +71,7 @@ export class Merge extends ManifestPlugin {
6171
Array<Array<CandidateReleasePullRequest>>
6272
>(
6373
(collection, candidate) => {
64-
if (candidate.config.separatePullRequests) {
74+
if (candidate.config.separatePullRequests && !this.forceMerge) {
6575
collection[1].push(candidate);
6676
} else {
6777
collection[0].push(candidate);
@@ -101,7 +111,9 @@ export class Merge extends ManifestPlugin {
101111
}),
102112
updates,
103113
labels: Array.from(labels),
104-
headRefName: BranchName.ofTargetBranch(this.targetBranch).toString(),
114+
headRefName:
115+
this.headBranchName ??
116+
BranchName.ofTargetBranch(this.targetBranch).toString(),
105117
draft: !candidates.some(candidate => !candidate.pullRequest.draft),
106118
};
107119

src/util/branch-name.ts

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ function getAllResourceNames(): BranchNameType[] {
2828
return [
2929
AutoreleaseBranchName,
3030
ComponentBranchName,
31+
GroupBranchName,
3132
DefaultBranchName,
3233
V12ComponentBranchName,
3334
V12DefaultBranchName,
@@ -78,6 +79,13 @@ export class BranchName {
7879
`${RELEASE_PLEASE}--branches--${targetBranch}--components--${component}`
7980
);
8081
}
82+
static ofGroupTargetBranch(group: string, targetBranch: string): BranchName {
83+
return new GroupBranchName(
84+
`${RELEASE_PLEASE}--branches--${targetBranch}--groups--${safeBranchName(
85+
group
86+
)}`
87+
);
88+
}
8189
constructor(_branchName: string) {}
8290

8391
static matches(_branchName: string): boolean {
@@ -211,3 +219,28 @@ class ComponentBranchName extends BranchName {
211219
return `${RELEASE_PLEASE}--branches--${this.targetBranch}--components--${this.component}`;
212220
}
213221
}
222+
223+
const GROUP_PATTERN = `^${RELEASE_PLEASE}--branches--(?<branch>.+)--groups--(?<group>.+)$`;
224+
class GroupBranchName extends BranchName {
225+
static matches(branchName: string): boolean {
226+
return !!branchName.match(GROUP_PATTERN);
227+
}
228+
constructor(branchName: string) {
229+
super(branchName);
230+
const match = branchName.match(GROUP_PATTERN);
231+
if (match?.groups) {
232+
this.targetBranch = match.groups['branch'];
233+
this.component = match.groups['group'];
234+
}
235+
}
236+
toString(): string {
237+
return `${RELEASE_PLEASE}--branches--${this.targetBranch}--groups--${this.component}`;
238+
}
239+
}
240+
241+
function safeBranchName(branchName: string): string {
242+
// convert disallowed characters in branch names, replacing them with '-'.
243+
// replace multiple consecutive '-' with a single '-' to avoid interfering with
244+
// our regexes for parsing the branch names
245+
return branchName.replace(/[^\w\d]/g, '-').replace(/-+/g, '-');
246+
}

test/plugins/linked-versions.ts

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,12 @@ describe('LinkedVersions plugin', () => {
7575
tagName: 'pkg3-v0.2.3',
7676
url: 'https://github.com/fake-owner/fake-repo/releases/tag/pkg3-v0.2.3',
7777
},
78+
{
79+
id: 4,
80+
sha: 'abc123',
81+
tagName: 'pkg4-v1.0.0',
82+
url: 'https://github.com/fake-owner/fake-repo/releases/tag/pkg1-v1.0.0',
83+
},
7884
]);
7985
mockCommits(sandbox, github, [
8086
{
@@ -265,4 +271,79 @@ describe('LinkedVersions plugin', () => {
265271
safeSnapshot(pullRequest.body.toString());
266272
}
267273
});
274+
it('should allow multiple groups of linked versions', async () => {
275+
const manifest = new Manifest(
276+
github,
277+
'target-branch',
278+
{
279+
'path/a': {
280+
releaseType: 'simple',
281+
component: 'pkg1',
282+
},
283+
'path/b': {
284+
releaseType: 'simple',
285+
component: 'pkg2',
286+
},
287+
'path/c': {
288+
releaseType: 'simple',
289+
component: 'pkg3',
290+
},
291+
'path/d': {
292+
releaseType: 'simple',
293+
component: 'pkg4',
294+
},
295+
},
296+
{
297+
'path/a': Version.parse('1.0.0'),
298+
'path/b': Version.parse('0.2.3'),
299+
'path/c': Version.parse('0.2.3'),
300+
'path/d': Version.parse('1.0.0'),
301+
},
302+
{
303+
separatePullRequests: true,
304+
plugins: [
305+
{
306+
type: 'linked-versions',
307+
groupName: 'group name',
308+
components: ['pkg2', 'pkg3'],
309+
},
310+
{
311+
type: 'linked-versions',
312+
groupName: 'second group name',
313+
components: ['pkg1', 'pkg4'],
314+
},
315+
],
316+
}
317+
);
318+
const pullRequests = await manifest.buildPullRequests();
319+
expect(pullRequests).lengthOf(2);
320+
const groupPullRequest1 = pullRequests[1];
321+
const packageData1 = groupPullRequest1.body.releaseData.find(
322+
data => data.component === 'pkg1'
323+
);
324+
expect(packageData1).to.not.be.undefined;
325+
const packageData4 = groupPullRequest1.body.releaseData.find(
326+
data => data.component === 'pkg4'
327+
);
328+
expect(packageData4).to.not.be.undefined;
329+
safeSnapshot(groupPullRequest1.body.toString());
330+
331+
const groupPullRequest2 = pullRequests[0];
332+
const packageData2 = groupPullRequest2.body.releaseData.find(
333+
data => data.component === 'pkg2'
334+
);
335+
expect(packageData2).to.not.be.undefined;
336+
const packageData3 = groupPullRequest2.body.releaseData.find(
337+
data => data.component === 'pkg3'
338+
);
339+
expect(packageData3).to.not.be.undefined;
340+
expect(packageData2?.version).to.eql(packageData3?.version);
341+
safeSnapshot(groupPullRequest2.body.toString());
342+
343+
expect(groupPullRequest1.headRefName).not.to.eql(
344+
groupPullRequest2.headRefName
345+
);
346+
expect(groupPullRequest1.headRefName).to.not.include(' ');
347+
expect(groupPullRequest2.headRefName).to.not.include(' ');
348+
});
268349
});

0 commit comments

Comments
 (0)