release-please 14.12.0 → 14.13.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +14 -0
- package/README.md +3 -0
- package/build/src/github.d.ts +63 -5
- package/build/src/github.js +135 -2
- package/build/src/manifest.d.ts +1 -0
- package/build/src/manifest.js +45 -14
- package/build/src/util/pull-request-body.js +3 -0
- package/build/src/util/pull-request-overflow-handler.d.ts +54 -0
- package/build/src/util/pull-request-overflow-handler.js +78 -0
- package/package.json +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,20 @@
|
|
|
4
4
|
|
|
5
5
|
[1]: https://www.npmjs.com/package/release-please?activeTab=versions
|
|
6
6
|
|
|
7
|
+
## [14.13.1](https://github.com/googleapis/release-please/compare/v14.13.0...v14.13.1) (2022-10-14)
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
### Bug Fixes
|
|
11
|
+
|
|
12
|
+
* Updating a pull request uses overflow handler if body is too large ([#1702](https://github.com/googleapis/release-please/issues/1702)) ([f328511](https://github.com/googleapis/release-please/commit/f3285115a9c0e4a199f86038319bafd6d604d96a))
|
|
13
|
+
|
|
14
|
+
## [14.13.0](https://github.com/googleapis/release-please/compare/v14.12.0...v14.13.0) (2022-10-13)
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
### Features
|
|
18
|
+
|
|
19
|
+
* Handle extremely large pull request body fields ([#1689](https://github.com/googleapis/release-please/issues/1689)) ([ecc424d](https://github.com/googleapis/release-please/commit/ecc424db9a86e742eb6b4f6f9271a8eae13e4efc))
|
|
20
|
+
|
|
7
21
|
## [14.12.0](https://github.com/googleapis/release-please/compare/v14.11.2...v14.12.0) (2022-10-12)
|
|
8
22
|
|
|
9
23
|
|
package/README.md
CHANGED
|
@@ -12,6 +12,9 @@ It does so by parsing your
|
|
|
12
12
|
git history, looking for [Conventional Commit messages](https://www.conventionalcommits.org/),
|
|
13
13
|
and creating release PRs.
|
|
14
14
|
|
|
15
|
+
It does not handle publication to package managers or handle complex branch
|
|
16
|
+
management.
|
|
17
|
+
|
|
15
18
|
## What's a Release PR?
|
|
16
19
|
|
|
17
20
|
Rather than continuously releasing what's landed to your default branch,
|
package/build/src/github.d.ts
CHANGED
|
@@ -11,6 +11,7 @@ import { Update } from './update';
|
|
|
11
11
|
import { Release } from './release';
|
|
12
12
|
import { GitHubFileContents } from '@google-automations/git-file-utils';
|
|
13
13
|
import { Logger } from 'code-suggester/build/src/types';
|
|
14
|
+
import { PullRequestOverflowHandler } from './util/pull-request-overflow-handler';
|
|
14
15
|
declare type RequestBuilderType = typeof request;
|
|
15
16
|
declare type DefaultFunctionType = RequestBuilderType['defaults'];
|
|
16
17
|
declare type RequestFunctionType = ReturnType<DefaultFunctionType>;
|
|
@@ -73,6 +74,10 @@ interface FileDiff {
|
|
|
73
74
|
readonly originalContent: string | null;
|
|
74
75
|
}
|
|
75
76
|
export declare type ChangeSet = Map<string, FileDiff>;
|
|
77
|
+
interface CreatePullRequestOptions {
|
|
78
|
+
fork?: boolean;
|
|
79
|
+
draft?: boolean;
|
|
80
|
+
}
|
|
76
81
|
export declare class GitHub {
|
|
77
82
|
readonly repository: Repository;
|
|
78
83
|
private octokit;
|
|
@@ -226,6 +231,7 @@ export declare class GitHub {
|
|
|
226
231
|
* @param {string} path The path to the file in the repository
|
|
227
232
|
* @param {string} branch The branch to fetch from
|
|
228
233
|
* @returns {GitHubFileContents}
|
|
234
|
+
* @throws {FileNotFoundError} if the file cannot be found
|
|
229
235
|
* @throws {GitHubAPIError} on other API errors
|
|
230
236
|
*/
|
|
231
237
|
getFileContentsOnBranch(path: string, branch: string): Promise<GitHubFileContents>;
|
|
@@ -281,6 +287,8 @@ export declare class GitHub {
|
|
|
281
287
|
/**
|
|
282
288
|
* Open a pull request
|
|
283
289
|
*
|
|
290
|
+
* @deprecated This logic is handled by the Manifest class now as it
|
|
291
|
+
* can be more complicated if the release notes are too big
|
|
284
292
|
* @param {ReleasePullRequest} releasePullRequest Pull request data to update
|
|
285
293
|
* @param {string} targetBranch The base branch of the pull request
|
|
286
294
|
* @param {GitHubPR} options The pull request options
|
|
@@ -291,10 +299,17 @@ export declare class GitHub {
|
|
|
291
299
|
fork?: boolean;
|
|
292
300
|
skipLabeling?: boolean;
|
|
293
301
|
}): Promise<PullRequest>;
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
302
|
+
/**
|
|
303
|
+
* Open a pull request
|
|
304
|
+
*
|
|
305
|
+
* @param {PullRequest} pullRequest Pull request data to update
|
|
306
|
+
* @param {string} targetBranch The base branch of the pull request
|
|
307
|
+
* @param {string} message The commit message for the commit
|
|
308
|
+
* @param {Update[]} updates The files to update
|
|
309
|
+
* @param {CreatePullRequestOptions} options The pull request options
|
|
310
|
+
* @throws {GitHubAPIError} on an API error
|
|
311
|
+
*/
|
|
312
|
+
createPullRequest: (pullRequest: PullRequest, targetBranch: string, message: string, updates: Update[], options?: CreatePullRequestOptions | undefined) => Promise<PullRequest>;
|
|
298
313
|
/**
|
|
299
314
|
* Fetch a pull request given the pull number
|
|
300
315
|
* @param {number} number The pull request number
|
|
@@ -305,11 +320,17 @@ export declare class GitHub {
|
|
|
305
320
|
* Update a pull request's title and body.
|
|
306
321
|
* @param {number} number The pull request number
|
|
307
322
|
* @param {ReleasePullRequest} releasePullRequest Pull request data to update
|
|
308
|
-
* @param {}
|
|
323
|
+
* @param {string} targetBranch The target branch of the pull request
|
|
324
|
+
* @param {string} options.signoffUser Optional. Commit signoff message
|
|
325
|
+
* @param {boolean} options.fork Optional. Whether to open the pull request from
|
|
326
|
+
* a fork or not. Defaults to `false`
|
|
327
|
+
* @param {PullRequestOverflowHandler} options.pullRequestOverflowHandler Optional.
|
|
328
|
+
* Handles extra large pull request body messages.
|
|
309
329
|
*/
|
|
310
330
|
updatePullRequest: (number: number, releasePullRequest: ReleasePullRequest, targetBranch: string, options?: {
|
|
311
331
|
signoffUser?: string | undefined;
|
|
312
332
|
fork?: boolean | undefined;
|
|
333
|
+
pullRequestOverflowHandler?: PullRequestOverflowHandler | undefined;
|
|
313
334
|
} | undefined) => Promise<PullRequest>;
|
|
314
335
|
/**
|
|
315
336
|
* Given a set of proposed updates, build a changeset to suggest.
|
|
@@ -387,6 +408,43 @@ export declare class GitHub {
|
|
|
387
408
|
* @param {string} previousTag Optional. Name of previous tag to analyze commits since
|
|
388
409
|
*/
|
|
389
410
|
generateReleaseNotes(tagName: string, targetCommitish: string, previousTag?: string): Promise<string>;
|
|
411
|
+
/**
|
|
412
|
+
* Create a single file on a new branch based on an existing
|
|
413
|
+
* branch. This will force-push to that branch.
|
|
414
|
+
* @param {string} filename Filename with path in the repository
|
|
415
|
+
* @param {string} contents Contents of the file
|
|
416
|
+
* @param {string} newBranchName Name of the new branch
|
|
417
|
+
* @param {string} baseBranchName Name of the base branch (where
|
|
418
|
+
* new branch is forked from)
|
|
419
|
+
* @returns {string} HTML URL of the new file
|
|
420
|
+
*/
|
|
421
|
+
createFileOnNewBranch(filename: string, contents: string, newBranchName: string, baseBranchName: string): Promise<string>;
|
|
422
|
+
/**
|
|
423
|
+
* Helper to fetch the SHA of a branch
|
|
424
|
+
* @param {string} branchName The name of the branch
|
|
425
|
+
* @return {string | undefined} Returns the SHA of the branch
|
|
426
|
+
* or undefined if it can't be found.
|
|
427
|
+
*/
|
|
428
|
+
private getBranchSha;
|
|
429
|
+
/**
|
|
430
|
+
* Helper to fork a branch from an existing branch. Uses `force` so
|
|
431
|
+
* it will overwrite the contents of `targetBranchName` to match
|
|
432
|
+
* the current contents of `baseBranchName`.
|
|
433
|
+
*
|
|
434
|
+
* @param {string} targetBranchName The name of the new forked branch
|
|
435
|
+
* @param {string} baseBranchName The base branch from which to fork.
|
|
436
|
+
* @returns {string} The branch SHA
|
|
437
|
+
* @throws {ConfigurationError} if the base branch cannot be found.
|
|
438
|
+
*/
|
|
439
|
+
private forkBranch;
|
|
440
|
+
/**
|
|
441
|
+
* Helper to create a new branch from a given SHA.
|
|
442
|
+
* @param {string} branchName The new branch name
|
|
443
|
+
* @param {string} branchSha The SHA of the branch
|
|
444
|
+
* @returns {string} The SHA of the new branch
|
|
445
|
+
*/
|
|
446
|
+
private createNewBranch;
|
|
447
|
+
private updateBranchSha;
|
|
390
448
|
}
|
|
391
449
|
export declare const sleepInMs: (ms: number) => Promise<unknown>;
|
|
392
450
|
export {};
|
package/build/src/github.js
CHANGED
|
@@ -130,6 +130,16 @@ class GitHub {
|
|
|
130
130
|
this.logger.debug(`finding files by glob: ${glob}, ref: ${ref}, prefix: ${prefix}`);
|
|
131
131
|
return await this.fileCache.findFilesByGlob(glob, ref, prefix);
|
|
132
132
|
});
|
|
133
|
+
/**
|
|
134
|
+
* Open a pull request
|
|
135
|
+
*
|
|
136
|
+
* @param {PullRequest} pullRequest Pull request data to update
|
|
137
|
+
* @param {string} targetBranch The base branch of the pull request
|
|
138
|
+
* @param {string} message The commit message for the commit
|
|
139
|
+
* @param {Update[]} updates The files to update
|
|
140
|
+
* @param {CreatePullRequestOptions} options The pull request options
|
|
141
|
+
* @throws {GitHubAPIError} on an API error
|
|
142
|
+
*/
|
|
133
143
|
this.createPullRequest = wrapAsync(async (pullRequest, targetBranch, message, updates, options) => {
|
|
134
144
|
// Update the files for the release if not already supplied
|
|
135
145
|
const changes = await this.buildChangeSet(updates, targetBranch);
|
|
@@ -176,7 +186,12 @@ class GitHub {
|
|
|
176
186
|
* Update a pull request's title and body.
|
|
177
187
|
* @param {number} number The pull request number
|
|
178
188
|
* @param {ReleasePullRequest} releasePullRequest Pull request data to update
|
|
179
|
-
* @param {}
|
|
189
|
+
* @param {string} targetBranch The target branch of the pull request
|
|
190
|
+
* @param {string} options.signoffUser Optional. Commit signoff message
|
|
191
|
+
* @param {boolean} options.fork Optional. Whether to open the pull request from
|
|
192
|
+
* a fork or not. Defaults to `false`
|
|
193
|
+
* @param {PullRequestOverflowHandler} options.pullRequestOverflowHandler Optional.
|
|
194
|
+
* Handles extra large pull request body messages.
|
|
180
195
|
*/
|
|
181
196
|
this.updatePullRequest = wrapAsync(async (number, releasePullRequest, targetBranch, options) => {
|
|
182
197
|
// Update the files for the release if not already supplied
|
|
@@ -186,7 +201,9 @@ class GitHub {
|
|
|
186
201
|
message = (0, signoff_commit_message_1.signoffCommitMessage)(message, options.signoffUser);
|
|
187
202
|
}
|
|
188
203
|
const title = releasePullRequest.title.toString();
|
|
189
|
-
const body =
|
|
204
|
+
const body = ((options === null || options === void 0 ? void 0 : options.pullRequestOverflowHandler)
|
|
205
|
+
? await options.pullRequestOverflowHandler.handleOverflow(releasePullRequest)
|
|
206
|
+
: releasePullRequest.body)
|
|
190
207
|
.toString()
|
|
191
208
|
.slice(0, MAX_ISSUE_BODY_SIZE);
|
|
192
209
|
const prNumber = await (0, code_suggester_1.createPullRequest)(this.octokit, changes, {
|
|
@@ -914,6 +931,7 @@ class GitHub {
|
|
|
914
931
|
* @param {string} path The path to the file in the repository
|
|
915
932
|
* @param {string} branch The branch to fetch from
|
|
916
933
|
* @returns {GitHubFileContents}
|
|
934
|
+
* @throws {FileNotFoundError} if the file cannot be found
|
|
917
935
|
* @throws {GitHubAPIError} on other API errors
|
|
918
936
|
*/
|
|
919
937
|
async getFileContentsOnBranch(path, branch) {
|
|
@@ -963,6 +981,8 @@ class GitHub {
|
|
|
963
981
|
/**
|
|
964
982
|
* Open a pull request
|
|
965
983
|
*
|
|
984
|
+
* @deprecated This logic is handled by the Manifest class now as it
|
|
985
|
+
* can be more complicated if the release notes are too big
|
|
966
986
|
* @param {ReleasePullRequest} releasePullRequest Pull request data to update
|
|
967
987
|
* @param {string} targetBranch The base branch of the pull request
|
|
968
988
|
* @param {GitHubPR} options The pull request options
|
|
@@ -1060,6 +1080,119 @@ class GitHub {
|
|
|
1060
1080
|
});
|
|
1061
1081
|
return resp.data.body;
|
|
1062
1082
|
}
|
|
1083
|
+
/**
|
|
1084
|
+
* Create a single file on a new branch based on an existing
|
|
1085
|
+
* branch. This will force-push to that branch.
|
|
1086
|
+
* @param {string} filename Filename with path in the repository
|
|
1087
|
+
* @param {string} contents Contents of the file
|
|
1088
|
+
* @param {string} newBranchName Name of the new branch
|
|
1089
|
+
* @param {string} baseBranchName Name of the base branch (where
|
|
1090
|
+
* new branch is forked from)
|
|
1091
|
+
* @returns {string} HTML URL of the new file
|
|
1092
|
+
*/
|
|
1093
|
+
async createFileOnNewBranch(filename, contents, newBranchName, baseBranchName) {
|
|
1094
|
+
// create or update new branch to match base branch
|
|
1095
|
+
await this.forkBranch(newBranchName, baseBranchName);
|
|
1096
|
+
// use the single file upload API
|
|
1097
|
+
const { data: { content }, } = await this.octokit.repos.createOrUpdateFileContents({
|
|
1098
|
+
owner: this.repository.owner,
|
|
1099
|
+
repo: this.repository.repo,
|
|
1100
|
+
path: filename,
|
|
1101
|
+
// contents need to be base64 encoded
|
|
1102
|
+
content: Buffer.from(contents, 'binary').toString('base64'),
|
|
1103
|
+
message: 'Saving release notes',
|
|
1104
|
+
branch: newBranchName,
|
|
1105
|
+
});
|
|
1106
|
+
if (!(content === null || content === void 0 ? void 0 : content.html_url)) {
|
|
1107
|
+
throw new Error(`Failed to write to file: ${filename} on branch: ${newBranchName}`);
|
|
1108
|
+
}
|
|
1109
|
+
return content.html_url;
|
|
1110
|
+
}
|
|
1111
|
+
/**
|
|
1112
|
+
* Helper to fetch the SHA of a branch
|
|
1113
|
+
* @param {string} branchName The name of the branch
|
|
1114
|
+
* @return {string | undefined} Returns the SHA of the branch
|
|
1115
|
+
* or undefined if it can't be found.
|
|
1116
|
+
*/
|
|
1117
|
+
async getBranchSha(branchName) {
|
|
1118
|
+
this.logger.debug(`Looking up SHA for branch: ${branchName}`);
|
|
1119
|
+
try {
|
|
1120
|
+
const { data: { object: { sha }, }, } = await this.octokit.git.getRef({
|
|
1121
|
+
owner: this.repository.owner,
|
|
1122
|
+
repo: this.repository.repo,
|
|
1123
|
+
ref: `heads/${branchName}`,
|
|
1124
|
+
});
|
|
1125
|
+
this.logger.debug(`SHA for branch: ${sha}`);
|
|
1126
|
+
return sha;
|
|
1127
|
+
}
|
|
1128
|
+
catch (e) {
|
|
1129
|
+
if (e instanceof request_error_1.RequestError && e.status === 404) {
|
|
1130
|
+
this.logger.debug(`Branch: ${branchName} does not exist`);
|
|
1131
|
+
return undefined;
|
|
1132
|
+
}
|
|
1133
|
+
throw e;
|
|
1134
|
+
}
|
|
1135
|
+
}
|
|
1136
|
+
/**
|
|
1137
|
+
* Helper to fork a branch from an existing branch. Uses `force` so
|
|
1138
|
+
* it will overwrite the contents of `targetBranchName` to match
|
|
1139
|
+
* the current contents of `baseBranchName`.
|
|
1140
|
+
*
|
|
1141
|
+
* @param {string} targetBranchName The name of the new forked branch
|
|
1142
|
+
* @param {string} baseBranchName The base branch from which to fork.
|
|
1143
|
+
* @returns {string} The branch SHA
|
|
1144
|
+
* @throws {ConfigurationError} if the base branch cannot be found.
|
|
1145
|
+
*/
|
|
1146
|
+
async forkBranch(targetBranchName, baseBranchName) {
|
|
1147
|
+
const baseBranchSha = await this.getBranchSha(baseBranchName);
|
|
1148
|
+
if (!baseBranchSha) {
|
|
1149
|
+
// this is highly unlikely to be thrown as we will have
|
|
1150
|
+
// already attempted to read from the branch
|
|
1151
|
+
throw new errors_1.ConfigurationError(`Unable to find base branch: ${baseBranchName}`, 'core', `${this.repository.owner}/${this.repository.repo}`);
|
|
1152
|
+
}
|
|
1153
|
+
// see if newBranchName exists
|
|
1154
|
+
if (await this.getBranchSha(targetBranchName)) {
|
|
1155
|
+
// branch already exists, update it to the match the base branch
|
|
1156
|
+
const branchSha = await this.updateBranchSha(targetBranchName, baseBranchSha);
|
|
1157
|
+
this.logger.debug(`Updated ${targetBranchName} to match ${baseBranchName} at ${branchSha}`);
|
|
1158
|
+
return branchSha;
|
|
1159
|
+
}
|
|
1160
|
+
else {
|
|
1161
|
+
// branch does not exist, create a new branch from the base branch
|
|
1162
|
+
const branchSha = await this.createNewBranch(targetBranchName, baseBranchSha);
|
|
1163
|
+
this.logger.debug(`Forked ${targetBranchName} from ${baseBranchName} at ${branchSha}`);
|
|
1164
|
+
return branchSha;
|
|
1165
|
+
}
|
|
1166
|
+
}
|
|
1167
|
+
/**
|
|
1168
|
+
* Helper to create a new branch from a given SHA.
|
|
1169
|
+
* @param {string} branchName The new branch name
|
|
1170
|
+
* @param {string} branchSha The SHA of the branch
|
|
1171
|
+
* @returns {string} The SHA of the new branch
|
|
1172
|
+
*/
|
|
1173
|
+
async createNewBranch(branchName, branchSha) {
|
|
1174
|
+
this.logger.debug(`Creating new branch: ${branchName} at ${branchSha}`);
|
|
1175
|
+
const { data: { object: { sha }, }, } = await this.octokit.git.createRef({
|
|
1176
|
+
owner: this.repository.owner,
|
|
1177
|
+
repo: this.repository.repo,
|
|
1178
|
+
ref: `refs/heads/${branchName}`,
|
|
1179
|
+
sha: branchSha,
|
|
1180
|
+
});
|
|
1181
|
+
this.logger.debug(`New branch: ${branchName} at ${sha}`);
|
|
1182
|
+
return sha;
|
|
1183
|
+
}
|
|
1184
|
+
async updateBranchSha(branchName, branchSha) {
|
|
1185
|
+
this.logger.debug(`Updating branch ${branchName} to ${branchSha}`);
|
|
1186
|
+
const { data: { object: { sha }, }, } = await this.octokit.git.updateRef({
|
|
1187
|
+
owner: this.repository.owner,
|
|
1188
|
+
repo: this.repository.repo,
|
|
1189
|
+
ref: `heads/${branchName}`,
|
|
1190
|
+
sha: branchSha,
|
|
1191
|
+
force: true,
|
|
1192
|
+
});
|
|
1193
|
+
this.logger.debug(`Updated branch: ${branchName} to ${sha}`);
|
|
1194
|
+
return sha;
|
|
1195
|
+
}
|
|
1063
1196
|
}
|
|
1064
1197
|
exports.GitHub = GitHub;
|
|
1065
1198
|
/**
|
package/build/src/manifest.d.ts
CHANGED
|
@@ -211,6 +211,7 @@ export declare class Manifest {
|
|
|
211
211
|
readonly releaseSearchDepth: number;
|
|
212
212
|
readonly commitSearchDepth: number;
|
|
213
213
|
readonly logger: Logger;
|
|
214
|
+
private pullRequestOverflowHandler;
|
|
214
215
|
/**
|
|
215
216
|
* Create a Manifest from explicit config in code. This assumes that the
|
|
216
217
|
* repository has a single component at the root path.
|
package/build/src/manifest.js
CHANGED
|
@@ -21,10 +21,11 @@ const tag_name_1 = require("./util/tag-name");
|
|
|
21
21
|
const branch_name_1 = require("./util/branch-name");
|
|
22
22
|
const pull_request_title_1 = require("./util/pull-request-title");
|
|
23
23
|
const factory_1 = require("./factory");
|
|
24
|
-
const pull_request_body_1 = require("./util/pull-request-body");
|
|
25
24
|
const merge_1 = require("./plugins/merge");
|
|
26
25
|
const release_please_manifest_1 = require("./updaters/release-please-manifest");
|
|
27
26
|
const errors_1 = require("./errors");
|
|
27
|
+
const pull_request_overflow_handler_1 = require("./util/pull-request-overflow-handler");
|
|
28
|
+
const signoff_commit_message_1 = require("./util/signoff-commit-message");
|
|
28
29
|
exports.DEFAULT_RELEASE_PLEASE_CONFIG = 'release-please-config.json';
|
|
29
30
|
exports.DEFAULT_RELEASE_PLEASE_MANIFEST = '.release-please-manifest.json';
|
|
30
31
|
exports.ROOT_PROJECT_PATH = '.';
|
|
@@ -100,6 +101,7 @@ class Manifest {
|
|
|
100
101
|
repositoryConfig: this.repositoryConfig,
|
|
101
102
|
manifestPath: this.manifestPath,
|
|
102
103
|
}));
|
|
104
|
+
this.pullRequestOverflowHandler = new pull_request_overflow_handler_1.FilePullRequestOverflowHandler(this.github, this.logger);
|
|
103
105
|
}
|
|
104
106
|
/**
|
|
105
107
|
* Create a Manifest from config files in the repository.
|
|
@@ -451,11 +453,16 @@ class Manifest {
|
|
|
451
453
|
const openPullRequests = [];
|
|
452
454
|
const generator = this.github.pullRequestIterator(this.targetBranch, 'OPEN', Number.MAX_SAFE_INTEGER, false);
|
|
453
455
|
for await (const openPullRequest of generator) {
|
|
454
|
-
if (
|
|
455
|
-
hasAllLabels(this.snapshotLabels, openPullRequest.labels))
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
456
|
+
if (hasAllLabels(this.labels, openPullRequest.labels) ||
|
|
457
|
+
hasAllLabels(this.snapshotLabels, openPullRequest.labels)) {
|
|
458
|
+
const body = await this.pullRequestOverflowHandler.parseOverflow(openPullRequest);
|
|
459
|
+
if (body) {
|
|
460
|
+
// maybe replace with overflow body
|
|
461
|
+
openPullRequests.push({
|
|
462
|
+
...openPullRequest,
|
|
463
|
+
body: body.toString(),
|
|
464
|
+
});
|
|
465
|
+
}
|
|
459
466
|
}
|
|
460
467
|
}
|
|
461
468
|
this.logger.info(`found ${openPullRequests.length} open release pull requests.`);
|
|
@@ -467,9 +474,15 @@ class Manifest {
|
|
|
467
474
|
const closedGenerator = this.github.pullRequestIterator(this.targetBranch, 'CLOSED', 200, false);
|
|
468
475
|
for await (const closedPullRequest of closedGenerator) {
|
|
469
476
|
if (hasAllLabels([exports.SNOOZE_LABEL], closedPullRequest.labels) &&
|
|
470
|
-
branch_name_1.BranchName.parse(closedPullRequest.headBranchName, this.logger)
|
|
471
|
-
|
|
472
|
-
|
|
477
|
+
branch_name_1.BranchName.parse(closedPullRequest.headBranchName, this.logger)) {
|
|
478
|
+
const body = await this.pullRequestOverflowHandler.parseOverflow(closedPullRequest);
|
|
479
|
+
if (body) {
|
|
480
|
+
// maybe replace with overflow body
|
|
481
|
+
snoozedPullRequests.push({
|
|
482
|
+
...closedPullRequest,
|
|
483
|
+
body: body.toString(),
|
|
484
|
+
});
|
|
485
|
+
}
|
|
473
486
|
}
|
|
474
487
|
}
|
|
475
488
|
this.logger.info(`found ${snoozedPullRequests.length} snoozed release pull requests.`);
|
|
@@ -486,10 +499,21 @@ class Manifest {
|
|
|
486
499
|
if (snoozed) {
|
|
487
500
|
return await this.maybeUpdateSnoozedPullRequest(snoozed, pullRequest);
|
|
488
501
|
}
|
|
489
|
-
const
|
|
502
|
+
const body = await this.pullRequestOverflowHandler.handleOverflow(pullRequest);
|
|
503
|
+
const message = this.signoffUser
|
|
504
|
+
? (0, signoff_commit_message_1.signoffCommitMessage)(pullRequest.title.toString(), this.signoffUser)
|
|
505
|
+
: pullRequest.title.toString();
|
|
506
|
+
const newPullRequest = await this.github.createPullRequest({
|
|
507
|
+
headBranchName: pullRequest.headRefName,
|
|
508
|
+
baseBranchName: this.targetBranch,
|
|
509
|
+
number: -1,
|
|
510
|
+
title: pullRequest.title.toString(),
|
|
511
|
+
body,
|
|
512
|
+
labels: this.skipLabeling ? [] : pullRequest.labels,
|
|
513
|
+
files: [],
|
|
514
|
+
}, this.targetBranch, message, pullRequest.updates, {
|
|
490
515
|
fork: this.fork,
|
|
491
|
-
|
|
492
|
-
skipLabeling: this.skipLabeling,
|
|
516
|
+
draft: pullRequest.draft,
|
|
493
517
|
});
|
|
494
518
|
return newPullRequest;
|
|
495
519
|
}
|
|
@@ -503,6 +527,7 @@ class Manifest {
|
|
|
503
527
|
const updatedPullRequest = await this.github.updatePullRequest(existing.number, pullRequest, this.targetBranch, {
|
|
504
528
|
fork: this.fork,
|
|
505
529
|
signoffUser: this.signoffUser,
|
|
530
|
+
pullRequestOverflowHandler: this.pullRequestOverflowHandler,
|
|
506
531
|
});
|
|
507
532
|
return updatedPullRequest;
|
|
508
533
|
}
|
|
@@ -516,6 +541,7 @@ class Manifest {
|
|
|
516
541
|
const updatedPullRequest = await this.github.updatePullRequest(snoozed.number, pullRequest, this.targetBranch, {
|
|
517
542
|
fork: this.fork,
|
|
518
543
|
signoffUser: this.signoffUser,
|
|
544
|
+
pullRequestOverflowHandler: this.pullRequestOverflowHandler,
|
|
519
545
|
});
|
|
520
546
|
// TODO: consider leaving the snooze label
|
|
521
547
|
await this.github.removeIssueLabels([exports.SNOOZE_LABEL], snoozed.number);
|
|
@@ -529,12 +555,17 @@ class Manifest {
|
|
|
529
555
|
continue;
|
|
530
556
|
}
|
|
531
557
|
this.logger.debug(`Found pull request #${pullRequest.number}: '${pullRequest.title}'`);
|
|
532
|
-
|
|
558
|
+
// if the pull request body overflows, handle it
|
|
559
|
+
const pullRequestBody = await this.pullRequestOverflowHandler.parseOverflow(pullRequest);
|
|
533
560
|
if (!pullRequestBody) {
|
|
534
561
|
this.logger.debug('could not parse pull request body as a release PR');
|
|
535
562
|
continue;
|
|
536
563
|
}
|
|
537
|
-
|
|
564
|
+
// replace with the complete fetched body
|
|
565
|
+
yield {
|
|
566
|
+
...pullRequest,
|
|
567
|
+
body: pullRequestBody.toString(),
|
|
568
|
+
};
|
|
538
569
|
}
|
|
539
570
|
}
|
|
540
571
|
/**
|
|
@@ -36,8 +36,10 @@ class PullRequestBody {
|
|
|
36
36
|
return undefined;
|
|
37
37
|
}
|
|
38
38
|
let data = extractMultipleReleases(parts.content, logger);
|
|
39
|
+
let useComponents = true;
|
|
39
40
|
if (data.length === 0) {
|
|
40
41
|
data = extractSingleRelease(parts.content, logger);
|
|
42
|
+
useComponents = false;
|
|
41
43
|
if (data.length === 0) {
|
|
42
44
|
logger.warn('Failed to parse releases.');
|
|
43
45
|
}
|
|
@@ -45,6 +47,7 @@ class PullRequestBody {
|
|
|
45
47
|
return new PullRequestBody(data, {
|
|
46
48
|
header: parts.header,
|
|
47
49
|
footer: parts.footer,
|
|
50
|
+
useComponents,
|
|
48
51
|
});
|
|
49
52
|
}
|
|
50
53
|
notes() {
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { PullRequestBody } from './pull-request-body';
|
|
2
|
+
import { GitHub } from '../github';
|
|
3
|
+
import { PullRequest } from '../pull-request';
|
|
4
|
+
import { Logger } from './logger';
|
|
5
|
+
import { ReleasePullRequest } from '../release-pull-request';
|
|
6
|
+
/**
|
|
7
|
+
* Interface for managing the pull request body contents when the content
|
|
8
|
+
* is too large to fit into a pull request.
|
|
9
|
+
*/
|
|
10
|
+
export interface PullRequestOverflowHandler {
|
|
11
|
+
/**
|
|
12
|
+
* If a pull request's body is too big, store it somewhere and return
|
|
13
|
+
* a new pull request body with information about the new location.
|
|
14
|
+
* @param {ReleasePullRequest} pullRequest The candidate release pull request
|
|
15
|
+
* @returns {string} The new pull request body which may contain a link to
|
|
16
|
+
* the full content.
|
|
17
|
+
*/
|
|
18
|
+
handleOverflow(pullRequest: ReleasePullRequest, maxSize?: number): Promise<string>;
|
|
19
|
+
/**
|
|
20
|
+
* Given a pull request, parse the pull request body from the pull request
|
|
21
|
+
* or storage if the body was too big to store in the pull request body.
|
|
22
|
+
* @param {PullRequest} pullRequest The pull request from GitHub
|
|
23
|
+
* @return {PullRequestBody} The parsed pull request body
|
|
24
|
+
*/
|
|
25
|
+
parseOverflow(pullRequest: PullRequest): Promise<PullRequestBody | undefined>;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* This implementation of PullRequestOverflowHandler stores the full release
|
|
29
|
+
* notes on a new git branch. The branch name is derived from the head branch
|
|
30
|
+
* name of the release pull request.
|
|
31
|
+
*/
|
|
32
|
+
export declare class FilePullRequestOverflowHandler implements PullRequestOverflowHandler {
|
|
33
|
+
private github;
|
|
34
|
+
private logger;
|
|
35
|
+
constructor(github: GitHub, logger?: Logger);
|
|
36
|
+
/**
|
|
37
|
+
* Optionally store the full release notes into `release-notes.md` file
|
|
38
|
+
* on a new branch if they do not fit into the body of a pull request.
|
|
39
|
+
*
|
|
40
|
+
* The new release notes will have a link to the GitHub UI for that file
|
|
41
|
+
* which should render the release notes nicely.
|
|
42
|
+
* @param {ReleasePullRequest} pullRequest The candidate release pull request
|
|
43
|
+
* @returns {string} The new pull request body which contains a link to
|
|
44
|
+
* the full content.
|
|
45
|
+
*/
|
|
46
|
+
handleOverflow(pullRequest: ReleasePullRequest, maxSize?: number): Promise<string>;
|
|
47
|
+
/**
|
|
48
|
+
* Given a pull request, retrieve the full release notes from the stored
|
|
49
|
+
* file if the body was too big to store in the pull request body.
|
|
50
|
+
* @param {PullRequest} pullRequest The pull request from GitHub
|
|
51
|
+
* @return {PullRequestBody} The parsed pull request body
|
|
52
|
+
*/
|
|
53
|
+
parseOverflow(pullRequest: PullRequest): Promise<PullRequestBody | undefined>;
|
|
54
|
+
}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// Copyright 2022 Google LLC
|
|
3
|
+
//
|
|
4
|
+
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
// you may not use this file except in compliance with the License.
|
|
6
|
+
// You may obtain a copy of the License at
|
|
7
|
+
//
|
|
8
|
+
// http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
//
|
|
10
|
+
// Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
// See the License for the specific language governing permissions and
|
|
14
|
+
// limitations under the License.
|
|
15
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
16
|
+
exports.FilePullRequestOverflowHandler = void 0;
|
|
17
|
+
const pull_request_body_1 = require("./pull-request-body");
|
|
18
|
+
const logger_1 = require("./logger");
|
|
19
|
+
const url_1 = require("url");
|
|
20
|
+
const MAX_ISSUE_BODY_SIZE = 65536;
|
|
21
|
+
const OVERFLOW_MESSAGE = 'This release is too large to preview in the pull request body. View the full release notes here:';
|
|
22
|
+
const OVERFLOW_MESSAGE_REGEX = new RegExp(`${OVERFLOW_MESSAGE} (?<url>.*)`);
|
|
23
|
+
const RELEASE_NOTES_FILENAME = 'release-notes.md';
|
|
24
|
+
const FILE_PATH_REGEX = new RegExp(`blob/(?<branchName>.*)/${RELEASE_NOTES_FILENAME}`);
|
|
25
|
+
/**
|
|
26
|
+
* This implementation of PullRequestOverflowHandler stores the full release
|
|
27
|
+
* notes on a new git branch. The branch name is derived from the head branch
|
|
28
|
+
* name of the release pull request.
|
|
29
|
+
*/
|
|
30
|
+
class FilePullRequestOverflowHandler {
|
|
31
|
+
constructor(github, logger = logger_1.logger) {
|
|
32
|
+
this.github = github;
|
|
33
|
+
this.logger = logger;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Optionally store the full release notes into `release-notes.md` file
|
|
37
|
+
* on a new branch if they do not fit into the body of a pull request.
|
|
38
|
+
*
|
|
39
|
+
* The new release notes will have a link to the GitHub UI for that file
|
|
40
|
+
* which should render the release notes nicely.
|
|
41
|
+
* @param {ReleasePullRequest} pullRequest The candidate release pull request
|
|
42
|
+
* @returns {string} The new pull request body which contains a link to
|
|
43
|
+
* the full content.
|
|
44
|
+
*/
|
|
45
|
+
async handleOverflow(pullRequest, maxSize = MAX_ISSUE_BODY_SIZE) {
|
|
46
|
+
const notes = pullRequest.body.toString();
|
|
47
|
+
if (notes.length > maxSize) {
|
|
48
|
+
const notesBranchName = `${pullRequest.headRefName}--release-notes`;
|
|
49
|
+
const url = await this.github.createFileOnNewBranch(RELEASE_NOTES_FILENAME, notes, notesBranchName, this.github.repository.defaultBranch);
|
|
50
|
+
return `${OVERFLOW_MESSAGE} ${url}`;
|
|
51
|
+
}
|
|
52
|
+
return notes;
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Given a pull request, retrieve the full release notes from the stored
|
|
56
|
+
* file if the body was too big to store in the pull request body.
|
|
57
|
+
* @param {PullRequest} pullRequest The pull request from GitHub
|
|
58
|
+
* @return {PullRequestBody} The parsed pull request body
|
|
59
|
+
*/
|
|
60
|
+
async parseOverflow(pullRequest) {
|
|
61
|
+
var _a, _b;
|
|
62
|
+
const match = pullRequest.body.match(OVERFLOW_MESSAGE_REGEX);
|
|
63
|
+
if ((_a = match === null || match === void 0 ? void 0 : match.groups) === null || _a === void 0 ? void 0 : _a.url) {
|
|
64
|
+
this.logger.info(`Pull request body overflows, parsing full body from: ${match.groups.url}`);
|
|
65
|
+
const url = new url_1.URL(match.groups.url);
|
|
66
|
+
const pathMatch = url.pathname.match(FILE_PATH_REGEX);
|
|
67
|
+
if ((_b = pathMatch === null || pathMatch === void 0 ? void 0 : pathMatch.groups) === null || _b === void 0 ? void 0 : _b.branchName) {
|
|
68
|
+
const fileContents = await this.github.getFileContentsOnBranch(RELEASE_NOTES_FILENAME, pathMatch.groups.branchName);
|
|
69
|
+
return pull_request_body_1.PullRequestBody.parse(fileContents.parsedContent);
|
|
70
|
+
}
|
|
71
|
+
this.logger.warn(`Could not parse branch from ${match.groups.url}`);
|
|
72
|
+
return pull_request_body_1.PullRequestBody.parse(pullRequest.body, this.logger);
|
|
73
|
+
}
|
|
74
|
+
return pull_request_body_1.PullRequestBody.parse(pullRequest.body, this.logger);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
exports.FilePullRequestOverflowHandler = FilePullRequestOverflowHandler;
|
|
78
|
+
//# sourceMappingURL=pull-request-overflow-handler.js.map
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "release-please",
|
|
3
|
-
"version": "14.
|
|
3
|
+
"version": "14.13.1",
|
|
4
4
|
"description": "generate release PRs based on the conventionalcommits.org spec",
|
|
5
5
|
"main": "./build/src/index.js",
|
|
6
6
|
"bin": "./build/src/bin/release-please.js",
|
|
@@ -38,7 +38,7 @@
|
|
|
38
38
|
}
|
|
39
39
|
},
|
|
40
40
|
"devDependencies": {
|
|
41
|
-
"@octokit/types": "^
|
|
41
|
+
"@octokit/types": "^8.0.0",
|
|
42
42
|
"@types/chai": "^4.1.7",
|
|
43
43
|
"@types/diff": "^5.0.2",
|
|
44
44
|
"@types/iarna__toml": "^2.0.1",
|