release-please 17.4.1 → 17.5.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/build/src/bin/release-please.js +39 -10
- package/build/src/bootstrapper.d.ts +2 -2
- package/build/src/changelog-notes/default.js +9 -1
- package/build/src/changelog-notes/github.d.ts +2 -2
- package/build/src/changelog-notes.d.ts +1 -0
- package/build/src/commit.d.ts +6 -0
- package/build/src/factories/changelog-notes-factory.d.ts +2 -2
- package/build/src/factories/plugin-factory.d.ts +2 -2
- package/build/src/factories/versioning-strategy-factory.d.ts +2 -2
- package/build/src/factory.d.ts +2 -2
- package/build/src/github-api.d.ts +260 -0
- package/build/src/github-api.js +701 -0
- package/build/src/github.d.ts +21 -171
- package/build/src/github.js +154 -699
- package/build/src/index.d.ts +2 -2
- package/build/src/index.js +1 -1
- package/build/src/local-github.d.ts +271 -0
- package/build/src/local-github.js +778 -0
- package/build/src/manifest.d.ts +7 -5
- package/build/src/manifest.js +28 -26
- package/build/src/plugin.d.ts +3 -3
- package/build/src/plugins/group-priority.d.ts +2 -2
- package/build/src/plugins/linked-versions.d.ts +2 -2
- package/build/src/plugins/maven-workspace.d.ts +2 -2
- package/build/src/plugins/merge.d.ts +2 -2
- package/build/src/plugins/node-workspace.d.ts +2 -2
- package/build/src/plugins/sentence-case.d.ts +2 -2
- package/build/src/plugins/workspace.d.ts +2 -2
- package/build/src/scm.d.ts +80 -0
- package/build/src/scm.js +16 -0
- package/build/src/strategies/base.d.ts +5 -3
- package/build/src/strategies/base.js +2 -0
- package/build/src/util/pull-request-overflow-handler.d.ts +2 -2
- package/package.json +2 -2
package/build/src/github.js
CHANGED
|
@@ -13,23 +13,17 @@
|
|
|
13
13
|
// See the License for the specific language governing permissions and
|
|
14
14
|
// limitations under the License.
|
|
15
15
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
16
|
-
exports.sleepInMs = exports.GitHub =
|
|
17
|
-
const code_suggester_1 = require("code-suggester");
|
|
18
|
-
const rest_1 = require("@octokit/rest");
|
|
19
|
-
const request_1 = require("@octokit/request");
|
|
20
|
-
const graphql_1 = require("@octokit/graphql");
|
|
16
|
+
exports.sleepInMs = exports.GitHub = void 0;
|
|
21
17
|
const request_error_1 = require("@octokit/request-error");
|
|
18
|
+
const code_suggester_1 = require("code-suggester");
|
|
22
19
|
const errors_1 = require("./errors");
|
|
23
20
|
const MAX_ISSUE_BODY_SIZE = 65536;
|
|
24
21
|
const MAX_SLEEP_SECONDS = 20;
|
|
25
|
-
exports.GH_API_URL = 'https://api.github.com';
|
|
26
|
-
exports.GH_GRAPHQL_URL = 'https://api.github.com';
|
|
27
22
|
const logger_1 = require("./util/logger");
|
|
28
23
|
const manifest_1 = require("./manifest");
|
|
24
|
+
const github_api_1 = require("./github-api");
|
|
29
25
|
const signoff_commit_message_1 = require("./util/signoff-commit-message");
|
|
30
26
|
const git_file_utils_1 = require("@google-automations/git-file-utils");
|
|
31
|
-
const https_proxy_agent_1 = require("https-proxy-agent");
|
|
32
|
-
const http_proxy_agent_1 = require("http-proxy-agent");
|
|
33
27
|
const composite_1 = require("./updaters/composite");
|
|
34
28
|
class GitHub {
|
|
35
29
|
constructor(options) {
|
|
@@ -133,130 +127,6 @@ class GitHub {
|
|
|
133
127
|
this.logger.debug(`finding files by glob: ${glob}, ref: ${ref}, prefix: ${prefix}`);
|
|
134
128
|
return await this.fileCache.findFilesByGlob(glob, ref, prefix);
|
|
135
129
|
});
|
|
136
|
-
/**
|
|
137
|
-
* Open a pull request
|
|
138
|
-
*
|
|
139
|
-
* @param {PullRequest} pullRequest Pull request data to update
|
|
140
|
-
* @param {string} targetBranch The base branch of the pull request
|
|
141
|
-
* @param {string} message The commit message for the commit
|
|
142
|
-
* @param {Update[]} updates The files to update
|
|
143
|
-
* @param {CreatePullRequestOptions} options The pull request options
|
|
144
|
-
* @throws {GitHubAPIError} on an API error
|
|
145
|
-
*/
|
|
146
|
-
this.createPullRequest = wrapAsync(async (pullRequest, targetBranch, message, updates, options) => {
|
|
147
|
-
// Update the files for the release if not already supplied
|
|
148
|
-
const changes = await this.buildChangeSet(updates, targetBranch);
|
|
149
|
-
const prNumber = await (0, code_suggester_1.createPullRequest)(this.octokit, changes, {
|
|
150
|
-
upstreamOwner: this.repository.owner,
|
|
151
|
-
upstreamRepo: this.repository.repo,
|
|
152
|
-
title: pullRequest.title,
|
|
153
|
-
branch: pullRequest.headBranchName,
|
|
154
|
-
description: pullRequest.body,
|
|
155
|
-
primary: targetBranch,
|
|
156
|
-
force: true,
|
|
157
|
-
fork: !!(options === null || options === void 0 ? void 0 : options.fork),
|
|
158
|
-
message,
|
|
159
|
-
logger: this.logger,
|
|
160
|
-
draft: !!(options === null || options === void 0 ? void 0 : options.draft),
|
|
161
|
-
labels: pullRequest.labels,
|
|
162
|
-
});
|
|
163
|
-
if (prNumber === 0) {
|
|
164
|
-
this.logger.warn('no code changes detected, skipping pull request creation');
|
|
165
|
-
return {
|
|
166
|
-
headBranchName: pullRequest.headBranchName,
|
|
167
|
-
baseBranchName: targetBranch,
|
|
168
|
-
number: 0,
|
|
169
|
-
title: pullRequest.title,
|
|
170
|
-
body: pullRequest.body,
|
|
171
|
-
labels: pullRequest.labels,
|
|
172
|
-
files: [],
|
|
173
|
-
};
|
|
174
|
-
}
|
|
175
|
-
return await this.getPullRequest(prNumber);
|
|
176
|
-
});
|
|
177
|
-
/**
|
|
178
|
-
* Fetch a pull request given the pull number
|
|
179
|
-
* @param {number} number The pull request number
|
|
180
|
-
* @returns {PullRequest}
|
|
181
|
-
*/
|
|
182
|
-
this.getPullRequest = wrapAsync(async (number) => {
|
|
183
|
-
const response = await this.octokit.pulls.get({
|
|
184
|
-
owner: this.repository.owner,
|
|
185
|
-
repo: this.repository.repo,
|
|
186
|
-
pull_number: number,
|
|
187
|
-
});
|
|
188
|
-
return {
|
|
189
|
-
headBranchName: response.data.head.ref,
|
|
190
|
-
baseBranchName: response.data.base.ref,
|
|
191
|
-
number: response.data.number,
|
|
192
|
-
title: response.data.title,
|
|
193
|
-
body: response.data.body || '',
|
|
194
|
-
files: [],
|
|
195
|
-
labels: response.data.labels
|
|
196
|
-
.map(label => label.name)
|
|
197
|
-
.filter(name => !!name),
|
|
198
|
-
};
|
|
199
|
-
});
|
|
200
|
-
/**
|
|
201
|
-
* Update a pull request's title and body.
|
|
202
|
-
* @param {number} number The pull request number
|
|
203
|
-
* @param {ReleasePullRequest} releasePullRequest Pull request data to update
|
|
204
|
-
* @param {string} targetBranch The target branch of the pull request
|
|
205
|
-
* @param {string} options.signoffUser Optional. Commit signoff message
|
|
206
|
-
* @param {boolean} options.fork Optional. Whether to open the pull request from
|
|
207
|
-
* a fork or not. Defaults to `false`
|
|
208
|
-
* @param {PullRequestOverflowHandler} options.pullRequestOverflowHandler Optional.
|
|
209
|
-
* Handles extra large pull request body messages.
|
|
210
|
-
*/
|
|
211
|
-
this.updatePullRequest = wrapAsync(async (number, releasePullRequest, targetBranch, options) => {
|
|
212
|
-
// Update the files for the release if not already supplied
|
|
213
|
-
const changes = await this.buildChangeSet(releasePullRequest.updates, targetBranch);
|
|
214
|
-
let message = releasePullRequest.title.toString();
|
|
215
|
-
if (options === null || options === void 0 ? void 0 : options.signoffUser) {
|
|
216
|
-
message = (0, signoff_commit_message_1.signoffCommitMessage)(message, options.signoffUser);
|
|
217
|
-
}
|
|
218
|
-
const title = releasePullRequest.title.toString();
|
|
219
|
-
const body = ((options === null || options === void 0 ? void 0 : options.pullRequestOverflowHandler)
|
|
220
|
-
? await options.pullRequestOverflowHandler.handleOverflow(releasePullRequest)
|
|
221
|
-
: releasePullRequest.body)
|
|
222
|
-
.toString()
|
|
223
|
-
.slice(0, MAX_ISSUE_BODY_SIZE);
|
|
224
|
-
const prNumber = await (0, code_suggester_1.createPullRequest)(this.octokit, changes, {
|
|
225
|
-
upstreamOwner: this.repository.owner,
|
|
226
|
-
upstreamRepo: this.repository.repo,
|
|
227
|
-
title,
|
|
228
|
-
branch: releasePullRequest.headRefName,
|
|
229
|
-
description: body,
|
|
230
|
-
primary: targetBranch,
|
|
231
|
-
force: true,
|
|
232
|
-
fork: (options === null || options === void 0 ? void 0 : options.fork) === false ? false : true,
|
|
233
|
-
message,
|
|
234
|
-
logger: this.logger,
|
|
235
|
-
draft: releasePullRequest.draft,
|
|
236
|
-
});
|
|
237
|
-
if (prNumber !== number) {
|
|
238
|
-
this.logger.warn(`updated code for ${prNumber}, but update requested for ${number}`);
|
|
239
|
-
}
|
|
240
|
-
const response = await this.octokit.pulls.update({
|
|
241
|
-
owner: this.repository.owner,
|
|
242
|
-
repo: this.repository.repo,
|
|
243
|
-
pull_number: number,
|
|
244
|
-
title: releasePullRequest.title.toString(),
|
|
245
|
-
body,
|
|
246
|
-
state: 'open',
|
|
247
|
-
});
|
|
248
|
-
return {
|
|
249
|
-
headBranchName: response.data.head.ref,
|
|
250
|
-
baseBranchName: response.data.base.ref,
|
|
251
|
-
number: response.data.number,
|
|
252
|
-
title: response.data.title,
|
|
253
|
-
body: response.data.body || '',
|
|
254
|
-
files: [],
|
|
255
|
-
labels: response.data.labels
|
|
256
|
-
.map(label => label.name)
|
|
257
|
-
.filter(name => !!name),
|
|
258
|
-
};
|
|
259
|
-
});
|
|
260
130
|
/**
|
|
261
131
|
* Returns a list of paths to all files with a given file
|
|
262
132
|
* extension.
|
|
@@ -277,213 +147,27 @@ class GitHub {
|
|
|
277
147
|
}
|
|
278
148
|
return this.fileCache.findFilesByExtension(extension, ref, prefix);
|
|
279
149
|
});
|
|
280
|
-
/**
|
|
281
|
-
* Create a GitHub release
|
|
282
|
-
*
|
|
283
|
-
* @param {Release} release Release parameters
|
|
284
|
-
* @param {ReleaseOptions} options Release option parameters
|
|
285
|
-
* @throws {DuplicateReleaseError} if the release tag already exists
|
|
286
|
-
* @throws {GitHubAPIError} on other API errors
|
|
287
|
-
*/
|
|
288
|
-
this.createRelease = wrapAsync(async (release, options = {}) => {
|
|
289
|
-
if (options.forceTag) {
|
|
290
|
-
try {
|
|
291
|
-
await this.octokit.git.createRef({
|
|
292
|
-
owner: this.repository.owner,
|
|
293
|
-
repo: this.repository.repo,
|
|
294
|
-
ref: `refs/tags/${release.tag.toString()}`,
|
|
295
|
-
sha: release.sha,
|
|
296
|
-
});
|
|
297
|
-
}
|
|
298
|
-
catch (err) {
|
|
299
|
-
// ignore if tag already exists
|
|
300
|
-
if (err.status === 422) {
|
|
301
|
-
this.logger.debug(`Tag ${release.tag.toString()} already exists, skipping tag creation`);
|
|
302
|
-
}
|
|
303
|
-
else {
|
|
304
|
-
throw err;
|
|
305
|
-
}
|
|
306
|
-
}
|
|
307
|
-
}
|
|
308
|
-
const resp = await this.octokit.repos.createRelease({
|
|
309
|
-
name: release.name,
|
|
310
|
-
owner: this.repository.owner,
|
|
311
|
-
repo: this.repository.repo,
|
|
312
|
-
tag_name: release.tag.toString(),
|
|
313
|
-
body: release.notes,
|
|
314
|
-
draft: !!options.draft,
|
|
315
|
-
prerelease: !!options.prerelease,
|
|
316
|
-
target_commitish: release.sha,
|
|
317
|
-
});
|
|
318
|
-
return {
|
|
319
|
-
id: resp.data.id,
|
|
320
|
-
name: resp.data.name || undefined,
|
|
321
|
-
tagName: resp.data.tag_name,
|
|
322
|
-
sha: resp.data.target_commitish,
|
|
323
|
-
notes: resp.data.body_text ||
|
|
324
|
-
resp.data.body ||
|
|
325
|
-
resp.data.body_html ||
|
|
326
|
-
undefined,
|
|
327
|
-
url: resp.data.html_url,
|
|
328
|
-
draft: resp.data.draft,
|
|
329
|
-
uploadUrl: resp.data.upload_url,
|
|
330
|
-
};
|
|
331
|
-
}, e => {
|
|
332
|
-
if (e instanceof request_error_1.RequestError) {
|
|
333
|
-
if (e.status === 422 &&
|
|
334
|
-
errors_1.GitHubAPIError.parseErrors(e).some(error => {
|
|
335
|
-
return error.code === 'already_exists';
|
|
336
|
-
})) {
|
|
337
|
-
throw new errors_1.DuplicateReleaseError(e, 'tagName');
|
|
338
|
-
}
|
|
339
|
-
}
|
|
340
|
-
});
|
|
341
|
-
/**
|
|
342
|
-
* Makes a comment on a issue/pull request.
|
|
343
|
-
*
|
|
344
|
-
* @param {string} comment - The body of the comment to post.
|
|
345
|
-
* @param {number} number - The issue or pull request number.
|
|
346
|
-
* @throws {GitHubAPIError} on an API error
|
|
347
|
-
*/
|
|
348
|
-
this.commentOnIssue = wrapAsync(async (comment, number) => {
|
|
349
|
-
this.logger.debug(`adding comment to https://github.com/${this.repository.owner}/${this.repository.repo}/issues/${number}`);
|
|
350
|
-
const resp = await this.octokit.issues.createComment({
|
|
351
|
-
owner: this.repository.owner,
|
|
352
|
-
repo: this.repository.repo,
|
|
353
|
-
issue_number: number,
|
|
354
|
-
body: comment,
|
|
355
|
-
});
|
|
356
|
-
return resp.data.html_url;
|
|
357
|
-
});
|
|
358
|
-
/**
|
|
359
|
-
* Removes labels from an issue/pull request.
|
|
360
|
-
*
|
|
361
|
-
* @param {string[]} labels The labels to remove.
|
|
362
|
-
* @param {number} number The issue/pull request number.
|
|
363
|
-
*/
|
|
364
|
-
this.removeIssueLabels = wrapAsync(async (labels, number) => {
|
|
365
|
-
if (labels.length === 0) {
|
|
366
|
-
return;
|
|
367
|
-
}
|
|
368
|
-
this.logger.debug(`removing labels: ${labels} from issue/pull ${number}`);
|
|
369
|
-
await Promise.all(labels.map(label => this.octokit.issues.removeLabel({
|
|
370
|
-
owner: this.repository.owner,
|
|
371
|
-
repo: this.repository.repo,
|
|
372
|
-
issue_number: number,
|
|
373
|
-
name: label,
|
|
374
|
-
})));
|
|
375
|
-
});
|
|
376
|
-
/**
|
|
377
|
-
* Adds label to an issue/pull request.
|
|
378
|
-
*
|
|
379
|
-
* @param {string[]} labels The labels to add.
|
|
380
|
-
* @param {number} number The issue/pull request number.
|
|
381
|
-
*/
|
|
382
|
-
this.addIssueLabels = wrapAsync(async (labels, number) => {
|
|
383
|
-
if (labels.length === 0) {
|
|
384
|
-
return;
|
|
385
|
-
}
|
|
386
|
-
this.logger.debug(`adding labels: ${labels} from issue/pull ${number}`);
|
|
387
|
-
await this.octokit.issues.addLabels({
|
|
388
|
-
owner: this.repository.owner,
|
|
389
|
-
repo: this.repository.repo,
|
|
390
|
-
issue_number: number,
|
|
391
|
-
labels,
|
|
392
|
-
});
|
|
393
|
-
});
|
|
394
150
|
this.repository = options.repository;
|
|
395
151
|
this.octokit = options.octokitAPIs.octokit;
|
|
396
|
-
this.request = options.octokitAPIs.request;
|
|
397
152
|
this.graphql = options.octokitAPIs.graphql;
|
|
398
153
|
this.fileCache = new git_file_utils_1.RepositoryFileCache(this.octokit, this.repository);
|
|
399
154
|
this.logger = (_a = options.logger) !== null && _a !== void 0 ? _a : logger_1.logger;
|
|
155
|
+
this.gitHubApi = new github_api_1.GitHubApi({
|
|
156
|
+
repository: this.repository,
|
|
157
|
+
octokitAPIs: options.octokitAPIs,
|
|
158
|
+
logger: this.logger,
|
|
159
|
+
});
|
|
400
160
|
}
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
return undefined;
|
|
404
|
-
}
|
|
405
|
-
const { host, port } = defaultProxy;
|
|
406
|
-
if (new URL(baseUrl).protocol.replace(':', '') === 'http') {
|
|
407
|
-
return new http_proxy_agent_1.HttpProxyAgent(`http://${host}:${port}`);
|
|
408
|
-
}
|
|
409
|
-
else {
|
|
410
|
-
return new https_proxy_agent_1.HttpsProxyAgent(`https://${host}:${port}`);
|
|
411
|
-
}
|
|
161
|
+
getGitHubApi() {
|
|
162
|
+
return this.gitHubApi;
|
|
412
163
|
}
|
|
413
|
-
/**
|
|
414
|
-
* Build a new GitHub client with auto-detected default branch.
|
|
415
|
-
*
|
|
416
|
-
* @param {GitHubCreateOptions} options Configuration options
|
|
417
|
-
* @param {string} options.owner The repository owner.
|
|
418
|
-
* @param {string} options.repo The repository name.
|
|
419
|
-
* @param {string} options.defaultBranch Optional. The repository's default branch.
|
|
420
|
-
* Defaults to the value fetched via the API.
|
|
421
|
-
* @param {string} options.apiUrl Optional. The base url of the GitHub API.
|
|
422
|
-
* @param {string} options.graphqlUrl Optional. The base url of the GraphQL API.
|
|
423
|
-
* @param {OctokitAPISs} options.octokitAPIs Optional. Override the internal
|
|
424
|
-
* client instances with a pre-authenticated instance.
|
|
425
|
-
* @param {string} token Optional. A GitHub API token used for authentication.
|
|
426
|
-
*/
|
|
427
164
|
static async create(options) {
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
const apis = (_c = options.octokitAPIs) !== null && _c !== void 0 ? _c : {
|
|
433
|
-
octokit: new rest_1.Octokit({
|
|
434
|
-
baseUrl: apiUrl,
|
|
435
|
-
auth: options.token,
|
|
436
|
-
request: {
|
|
437
|
-
agent: this.createDefaultAgent(apiUrl, options.proxy),
|
|
438
|
-
fetch: options.fetch,
|
|
439
|
-
},
|
|
440
|
-
}),
|
|
441
|
-
request: request_1.request.defaults({
|
|
442
|
-
baseUrl: apiUrl,
|
|
443
|
-
headers: {
|
|
444
|
-
'user-agent': `release-please/${releasePleaseVersion}`,
|
|
445
|
-
Authorization: `token ${options.token}`,
|
|
446
|
-
},
|
|
447
|
-
fetch: options.fetch,
|
|
448
|
-
}),
|
|
449
|
-
graphql: graphql_1.graphql.defaults({
|
|
450
|
-
baseUrl: graphqlUrl,
|
|
451
|
-
request: {
|
|
452
|
-
agent: this.createDefaultAgent(graphqlUrl, options.proxy),
|
|
453
|
-
fetch: options.fetch,
|
|
454
|
-
},
|
|
455
|
-
headers: {
|
|
456
|
-
'user-agent': `release-please/${releasePleaseVersion}`,
|
|
457
|
-
Authorization: `token ${options.token}`,
|
|
458
|
-
'content-type': 'application/vnd.github.v3+json',
|
|
459
|
-
},
|
|
460
|
-
}),
|
|
461
|
-
};
|
|
462
|
-
const opts = {
|
|
463
|
-
repository: {
|
|
464
|
-
owner: options.owner,
|
|
465
|
-
repo: options.repo,
|
|
466
|
-
defaultBranch: (_d = options.defaultBranch) !== null && _d !== void 0 ? _d : (await GitHub.defaultBranch(options.owner, options.repo, apis.octokit)),
|
|
467
|
-
},
|
|
468
|
-
octokitAPIs: apis,
|
|
165
|
+
const gitHubApi = await github_api_1.GitHubApi.create(options);
|
|
166
|
+
return new GitHub({
|
|
167
|
+
repository: gitHubApi.repository,
|
|
168
|
+
octokitAPIs: gitHubApi.octokitAPIs,
|
|
469
169
|
logger: options.logger,
|
|
470
|
-
};
|
|
471
|
-
return new GitHub(opts);
|
|
472
|
-
}
|
|
473
|
-
/**
|
|
474
|
-
* Returns the default branch for a given repository.
|
|
475
|
-
*
|
|
476
|
-
* @param {string} owner The GitHub repository owner
|
|
477
|
-
* @param {string} repo The GitHub repository name
|
|
478
|
-
* @param {OctokitType} octokit An authenticated octokit instance
|
|
479
|
-
* @returns {string} Name of the default branch
|
|
480
|
-
*/
|
|
481
|
-
static async defaultBranch(owner, repo, octokit) {
|
|
482
|
-
const { data } = await octokit.repos.get({
|
|
483
|
-
repo,
|
|
484
|
-
owner,
|
|
485
170
|
});
|
|
486
|
-
return data.default_branch;
|
|
487
171
|
}
|
|
488
172
|
/**
|
|
489
173
|
* Returns the list of commits to the default branch after the provided filter
|
|
@@ -545,8 +229,8 @@ class GitHub {
|
|
|
545
229
|
}
|
|
546
230
|
}
|
|
547
231
|
async mergeCommitsGraphQL(targetBranch, cursor, options = {}) {
|
|
548
|
-
var _a, _b, _c, _d, _e, _f, _g, _h, _j;
|
|
549
|
-
var
|
|
232
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k;
|
|
233
|
+
var _l;
|
|
550
234
|
this.logger.debug(`Fetching merge commits on branch ${targetBranch} with cursor: ${cursor}`);
|
|
551
235
|
const query = `query pullRequestsSince($owner: String!, $repo: String!, $num: Int!, $maxFilesChanged: Int, $targetBranch: String!, $cursor: String) {
|
|
552
236
|
repository(owner: $owner, name: $repo) {
|
|
@@ -583,6 +267,13 @@ class GitHub {
|
|
|
583
267
|
}
|
|
584
268
|
sha: oid
|
|
585
269
|
message
|
|
270
|
+
author {
|
|
271
|
+
name
|
|
272
|
+
email
|
|
273
|
+
user {
|
|
274
|
+
login
|
|
275
|
+
}
|
|
276
|
+
}
|
|
586
277
|
}
|
|
587
278
|
pageInfo {
|
|
588
279
|
hasNextPage
|
|
@@ -624,7 +315,7 @@ class GitHub {
|
|
|
624
315
|
for (const commit of commits) {
|
|
625
316
|
for (const pr of commit.associatedPullRequests.nodes) {
|
|
626
317
|
if ((_c = pr.mergeCommit) === null || _c === void 0 ? void 0 : _c.oid) {
|
|
627
|
-
(_d = mergeCommitCount[
|
|
318
|
+
(_d = mergeCommitCount[_l = pr.mergeCommit.oid]) !== null && _d !== void 0 ? _d : (mergeCommitCount[_l] = 0);
|
|
628
319
|
mergeCommitCount[pr.mergeCommit.oid]++;
|
|
629
320
|
}
|
|
630
321
|
}
|
|
@@ -634,6 +325,13 @@ class GitHub {
|
|
|
634
325
|
const commit = {
|
|
635
326
|
sha: graphCommit.sha,
|
|
636
327
|
message: graphCommit.message,
|
|
328
|
+
author: graphCommit.author
|
|
329
|
+
? {
|
|
330
|
+
name: graphCommit.author.name || 'Unknown',
|
|
331
|
+
email: graphCommit.author.email,
|
|
332
|
+
username: (_e = graphCommit.author.user) === null || _e === void 0 ? void 0 : _e.login,
|
|
333
|
+
}
|
|
334
|
+
: undefined,
|
|
637
335
|
};
|
|
638
336
|
const mergePullRequest = graphCommit.associatedPullRequests.nodes.find(pr => {
|
|
639
337
|
return (
|
|
@@ -654,15 +352,15 @@ class GitHub {
|
|
|
654
352
|
number: pullRequest.number,
|
|
655
353
|
baseBranchName: pullRequest.baseRefName,
|
|
656
354
|
headBranchName: pullRequest.headRefName,
|
|
657
|
-
mergeCommitOid: (
|
|
355
|
+
mergeCommitOid: (_f = pullRequest.mergeCommit) === null || _f === void 0 ? void 0 : _f.oid,
|
|
658
356
|
title: pullRequest.title,
|
|
659
357
|
body: pullRequest.body,
|
|
660
358
|
labels: pullRequest.labels.nodes.map(node => node.name),
|
|
661
|
-
files: (((
|
|
359
|
+
files: (((_g = pullRequest.files) === null || _g === void 0 ? void 0 : _g.nodes) || []).map(node => node.path),
|
|
662
360
|
};
|
|
663
361
|
}
|
|
664
362
|
if (mergePullRequest) {
|
|
665
|
-
if (((
|
|
363
|
+
if (((_j = (_h = mergePullRequest.files) === null || _h === void 0 ? void 0 : _h.pageInfo) === null || _j === void 0 ? void 0 : _j.hasNextPage) &&
|
|
666
364
|
options.backfillFiles) {
|
|
667
365
|
this.logger.info(`PR #${mergePullRequest.number} has many files, backfilling`);
|
|
668
366
|
commit.files = await this.getCommitFiles(graphCommit.sha);
|
|
@@ -670,7 +368,7 @@ class GitHub {
|
|
|
670
368
|
else {
|
|
671
369
|
// We cannot directly fetch files on commits via graphql, only provide file
|
|
672
370
|
// information for commits with associated pull requests
|
|
673
|
-
commit.files = (((
|
|
371
|
+
commit.files = (((_k = mergePullRequest.files) === null || _k === void 0 ? void 0 : _k.nodes) || []).map(node => node.path);
|
|
674
372
|
}
|
|
675
373
|
}
|
|
676
374
|
else if (options.backfillFiles) {
|
|
@@ -700,167 +398,7 @@ class GitHub {
|
|
|
700
398
|
* @throws {GitHubAPIError} on an API error
|
|
701
399
|
*/
|
|
702
400
|
async *pullRequestIterator(targetBranch, status = 'MERGED', maxResults = Number.MAX_SAFE_INTEGER, includeFiles = true) {
|
|
703
|
-
|
|
704
|
-
? this.pullRequestIteratorWithFiles(targetBranch, status, maxResults)
|
|
705
|
-
: this.pullRequestIteratorWithoutFiles(targetBranch, status, maxResults);
|
|
706
|
-
for await (const pullRequest of generator) {
|
|
707
|
-
yield pullRequest;
|
|
708
|
-
}
|
|
709
|
-
}
|
|
710
|
-
/**
|
|
711
|
-
* Helper implementation of pullRequestIterator that includes files via
|
|
712
|
-
* the graphQL API.
|
|
713
|
-
*
|
|
714
|
-
* @param {string} targetBranch The base branch of the pull request
|
|
715
|
-
* @param {string} status The status of the pull request
|
|
716
|
-
* @param {number} maxResults Limit the number of results searched
|
|
717
|
-
*/
|
|
718
|
-
async *pullRequestIteratorWithFiles(targetBranch, status = 'MERGED', maxResults = Number.MAX_SAFE_INTEGER) {
|
|
719
|
-
let cursor = undefined;
|
|
720
|
-
let results = 0;
|
|
721
|
-
while (results < maxResults) {
|
|
722
|
-
const response = await this.pullRequestsGraphQL(targetBranch, status, cursor);
|
|
723
|
-
// no response usually means we ran out of results
|
|
724
|
-
if (!response) {
|
|
725
|
-
break;
|
|
726
|
-
}
|
|
727
|
-
for (let i = 0; i < response.data.length; i++) {
|
|
728
|
-
results += 1;
|
|
729
|
-
yield response.data[i];
|
|
730
|
-
}
|
|
731
|
-
if (!response.pageInfo.hasNextPage) {
|
|
732
|
-
break;
|
|
733
|
-
}
|
|
734
|
-
cursor = response.pageInfo.endCursor;
|
|
735
|
-
}
|
|
736
|
-
}
|
|
737
|
-
/**
|
|
738
|
-
* Helper implementation of pullRequestIterator that excludes files
|
|
739
|
-
* via the REST API.
|
|
740
|
-
*
|
|
741
|
-
* @param {string} targetBranch The base branch of the pull request
|
|
742
|
-
* @param {string} status The status of the pull request
|
|
743
|
-
* @param {number} maxResults Limit the number of results searched
|
|
744
|
-
*/
|
|
745
|
-
async *pullRequestIteratorWithoutFiles(targetBranch, status = 'MERGED', maxResults = Number.MAX_SAFE_INTEGER) {
|
|
746
|
-
const statusMap = {
|
|
747
|
-
OPEN: 'open',
|
|
748
|
-
CLOSED: 'closed',
|
|
749
|
-
MERGED: 'closed',
|
|
750
|
-
};
|
|
751
|
-
let results = 0;
|
|
752
|
-
for await (const { data: pulls } of this.octokit.paginate.iterator('GET /repos/{owner}/{repo}/pulls', {
|
|
753
|
-
state: statusMap[status],
|
|
754
|
-
owner: this.repository.owner,
|
|
755
|
-
repo: this.repository.repo,
|
|
756
|
-
base: targetBranch,
|
|
757
|
-
sort: 'updated',
|
|
758
|
-
direction: 'desc',
|
|
759
|
-
})) {
|
|
760
|
-
for (const pull of pulls) {
|
|
761
|
-
// The REST API does not have an option for "merged"
|
|
762
|
-
// pull requests - they are closed with a `merged_at` timestamp
|
|
763
|
-
if (status !== 'MERGED' || pull.merged_at) {
|
|
764
|
-
results += 1;
|
|
765
|
-
yield {
|
|
766
|
-
headBranchName: pull.head.ref,
|
|
767
|
-
baseBranchName: pull.base.ref,
|
|
768
|
-
number: pull.number,
|
|
769
|
-
title: pull.title,
|
|
770
|
-
body: pull.body || '',
|
|
771
|
-
labels: pull.labels.map(label => label.name),
|
|
772
|
-
files: [],
|
|
773
|
-
sha: pull.merge_commit_sha || undefined,
|
|
774
|
-
};
|
|
775
|
-
if (results >= maxResults) {
|
|
776
|
-
break;
|
|
777
|
-
}
|
|
778
|
-
}
|
|
779
|
-
}
|
|
780
|
-
if (results >= maxResults) {
|
|
781
|
-
break;
|
|
782
|
-
}
|
|
783
|
-
}
|
|
784
|
-
}
|
|
785
|
-
/**
|
|
786
|
-
* Return a list of merged pull requests. The list is not guaranteed to be sorted
|
|
787
|
-
* by merged_at, but is generally most recent first.
|
|
788
|
-
*
|
|
789
|
-
* @param {string} targetBranch - Base branch of the pull request. Defaults to
|
|
790
|
-
* the configured default branch.
|
|
791
|
-
* @param {number} page - Page of results. Defaults to 1.
|
|
792
|
-
* @param {number} perPage - Number of results per page. Defaults to 100.
|
|
793
|
-
* @returns {PullRequestHistory | null} - List of merged pull requests
|
|
794
|
-
* @throws {GitHubAPIError} on an API error
|
|
795
|
-
*/
|
|
796
|
-
async pullRequestsGraphQL(targetBranch, states = 'MERGED', cursor) {
|
|
797
|
-
var _a;
|
|
798
|
-
this.logger.debug(`Fetching ${states} pull requests on branch ${targetBranch} with cursor ${cursor}`);
|
|
799
|
-
const response = await this.graphqlRequest({
|
|
800
|
-
query: `query mergedPullRequests($owner: String!, $repo: String!, $num: Int!, $maxFilesChanged: Int, $targetBranch: String!, $states: [PullRequestState!], $cursor: String) {
|
|
801
|
-
repository(owner: $owner, name: $repo) {
|
|
802
|
-
pullRequests(first: $num, after: $cursor, baseRefName: $targetBranch, states: $states, orderBy: {field: CREATED_AT, direction: DESC}) {
|
|
803
|
-
nodes {
|
|
804
|
-
number
|
|
805
|
-
title
|
|
806
|
-
baseRefName
|
|
807
|
-
headRefName
|
|
808
|
-
labels(first: 10) {
|
|
809
|
-
nodes {
|
|
810
|
-
name
|
|
811
|
-
}
|
|
812
|
-
}
|
|
813
|
-
body
|
|
814
|
-
mergeCommit {
|
|
815
|
-
oid
|
|
816
|
-
}
|
|
817
|
-
files(first: $maxFilesChanged) {
|
|
818
|
-
nodes {
|
|
819
|
-
path
|
|
820
|
-
}
|
|
821
|
-
pageInfo {
|
|
822
|
-
endCursor
|
|
823
|
-
hasNextPage
|
|
824
|
-
}
|
|
825
|
-
}
|
|
826
|
-
}
|
|
827
|
-
pageInfo {
|
|
828
|
-
endCursor
|
|
829
|
-
hasNextPage
|
|
830
|
-
}
|
|
831
|
-
}
|
|
832
|
-
}
|
|
833
|
-
}`,
|
|
834
|
-
cursor,
|
|
835
|
-
owner: this.repository.owner,
|
|
836
|
-
repo: this.repository.repo,
|
|
837
|
-
num: 25,
|
|
838
|
-
targetBranch,
|
|
839
|
-
states,
|
|
840
|
-
maxFilesChanged: 64,
|
|
841
|
-
});
|
|
842
|
-
if (!((_a = response === null || response === void 0 ? void 0 : response.repository) === null || _a === void 0 ? void 0 : _a.pullRequests)) {
|
|
843
|
-
this.logger.warn(`Could not find merged pull requests for branch ${targetBranch} - it likely does not exist.`);
|
|
844
|
-
return null;
|
|
845
|
-
}
|
|
846
|
-
const pullRequests = (response.repository.pullRequests.nodes ||
|
|
847
|
-
[]);
|
|
848
|
-
return {
|
|
849
|
-
pageInfo: response.repository.pullRequests.pageInfo,
|
|
850
|
-
data: pullRequests.map(pullRequest => {
|
|
851
|
-
var _a, _b, _c;
|
|
852
|
-
return {
|
|
853
|
-
sha: (_a = pullRequest.mergeCommit) === null || _a === void 0 ? void 0 : _a.oid,
|
|
854
|
-
number: pullRequest.number,
|
|
855
|
-
baseBranchName: pullRequest.baseRefName,
|
|
856
|
-
headBranchName: pullRequest.headRefName,
|
|
857
|
-
labels: (((_b = pullRequest.labels) === null || _b === void 0 ? void 0 : _b.nodes) || []).map(l => l.name),
|
|
858
|
-
title: pullRequest.title,
|
|
859
|
-
body: pullRequest.body + '',
|
|
860
|
-
files: (((_c = pullRequest.files) === null || _c === void 0 ? void 0 : _c.nodes) || []).map(node => node.path),
|
|
861
|
-
};
|
|
862
|
-
}),
|
|
863
|
-
};
|
|
401
|
+
yield* this.gitHubApi.pullRequestIterator(targetBranch, status, maxResults, includeFiles);
|
|
864
402
|
}
|
|
865
403
|
/**
|
|
866
404
|
* Iterate through releases with a max number of results scanned.
|
|
@@ -872,80 +410,7 @@ class GitHub {
|
|
|
872
410
|
* @throws {GitHubAPIError} on an API error
|
|
873
411
|
*/
|
|
874
412
|
async *releaseIterator(options = {}) {
|
|
875
|
-
|
|
876
|
-
const maxResults = (_a = options.maxResults) !== null && _a !== void 0 ? _a : Number.MAX_SAFE_INTEGER;
|
|
877
|
-
let results = 0;
|
|
878
|
-
let cursor = undefined;
|
|
879
|
-
while (true) {
|
|
880
|
-
const response = await this.releaseGraphQL(cursor);
|
|
881
|
-
if (!response) {
|
|
882
|
-
break;
|
|
883
|
-
}
|
|
884
|
-
for (let i = 0; i < response.data.length; i++) {
|
|
885
|
-
if ((results += 1) > maxResults) {
|
|
886
|
-
break;
|
|
887
|
-
}
|
|
888
|
-
yield response.data[i];
|
|
889
|
-
}
|
|
890
|
-
if (results > maxResults || !response.pageInfo.hasNextPage) {
|
|
891
|
-
break;
|
|
892
|
-
}
|
|
893
|
-
cursor = response.pageInfo.endCursor;
|
|
894
|
-
}
|
|
895
|
-
}
|
|
896
|
-
async releaseGraphQL(cursor) {
|
|
897
|
-
this.logger.debug(`Fetching releases with cursor ${cursor}`);
|
|
898
|
-
const response = await this.graphqlRequest({
|
|
899
|
-
query: `query releases($owner: String!, $repo: String!, $num: Int!, $cursor: String) {
|
|
900
|
-
repository(owner: $owner, name: $repo) {
|
|
901
|
-
releases(first: $num, after: $cursor, orderBy: {field: CREATED_AT, direction: DESC}) {
|
|
902
|
-
nodes {
|
|
903
|
-
name
|
|
904
|
-
tag {
|
|
905
|
-
name
|
|
906
|
-
}
|
|
907
|
-
tagCommit {
|
|
908
|
-
oid
|
|
909
|
-
}
|
|
910
|
-
url
|
|
911
|
-
description
|
|
912
|
-
isDraft
|
|
913
|
-
}
|
|
914
|
-
pageInfo {
|
|
915
|
-
endCursor
|
|
916
|
-
hasNextPage
|
|
917
|
-
}
|
|
918
|
-
}
|
|
919
|
-
}
|
|
920
|
-
}`,
|
|
921
|
-
cursor,
|
|
922
|
-
owner: this.repository.owner,
|
|
923
|
-
repo: this.repository.repo,
|
|
924
|
-
num: 25,
|
|
925
|
-
});
|
|
926
|
-
if (!response.repository.releases.nodes.length) {
|
|
927
|
-
this.logger.warn('Could not find releases.');
|
|
928
|
-
return null;
|
|
929
|
-
}
|
|
930
|
-
const releases = response.repository.releases.nodes;
|
|
931
|
-
return {
|
|
932
|
-
pageInfo: response.repository.releases.pageInfo,
|
|
933
|
-
data: releases
|
|
934
|
-
.filter(release => !!release.tagCommit)
|
|
935
|
-
.map(release => {
|
|
936
|
-
if (!release.tag || !release.tagCommit) {
|
|
937
|
-
this.logger.debug(release);
|
|
938
|
-
}
|
|
939
|
-
return {
|
|
940
|
-
name: release.name || undefined,
|
|
941
|
-
tagName: release.tag ? release.tag.name : 'unknown',
|
|
942
|
-
sha: release.tagCommit.oid,
|
|
943
|
-
notes: release.description,
|
|
944
|
-
url: release.url,
|
|
945
|
-
draft: release.isDraft,
|
|
946
|
-
};
|
|
947
|
-
}),
|
|
948
|
-
};
|
|
413
|
+
yield* this.gitHubApi.releaseIterator(options);
|
|
949
414
|
}
|
|
950
415
|
/**
|
|
951
416
|
* Iterate through tags with a max number of results scanned.
|
|
@@ -1042,33 +507,91 @@ class GitHub {
|
|
|
1042
507
|
/**
|
|
1043
508
|
* Open a pull request
|
|
1044
509
|
*
|
|
1045
|
-
* @
|
|
1046
|
-
* can be more complicated if the release notes are too big
|
|
1047
|
-
* @param {ReleasePullRequest} releasePullRequest Pull request data to update
|
|
510
|
+
* @param {PullRequest} pullRequest Pull request data to update
|
|
1048
511
|
* @param {string} targetBranch The base branch of the pull request
|
|
1049
|
-
* @param {
|
|
512
|
+
* @param {string} message The commit message for the commit
|
|
513
|
+
* @param {Update[]} updates The files to update
|
|
514
|
+
* @param {CreatePullRequestOptions} options The pull request options
|
|
1050
515
|
* @throws {GitHubAPIError} on an API error
|
|
1051
516
|
*/
|
|
1052
|
-
async
|
|
517
|
+
async createPullRequest(pullRequest, targetBranch, message, updates, options) {
|
|
518
|
+
const changes = await this.buildChangeSet(updates, targetBranch);
|
|
519
|
+
const prNumber = await (0, code_suggester_1.createPullRequest)(this.octokit, changes, {
|
|
520
|
+
upstreamOwner: this.repository.owner,
|
|
521
|
+
upstreamRepo: this.repository.repo,
|
|
522
|
+
title: pullRequest.title,
|
|
523
|
+
branch: pullRequest.headBranchName,
|
|
524
|
+
description: pullRequest.body,
|
|
525
|
+
primary: targetBranch,
|
|
526
|
+
force: true,
|
|
527
|
+
fork: !!(options === null || options === void 0 ? void 0 : options.fork),
|
|
528
|
+
message,
|
|
529
|
+
logger: this.logger,
|
|
530
|
+
draft: !!(options === null || options === void 0 ? void 0 : options.draft),
|
|
531
|
+
labels: pullRequest.labels,
|
|
532
|
+
});
|
|
533
|
+
if (prNumber === 0) {
|
|
534
|
+
this.logger.warn('no code changes detected, skipping pull request creation');
|
|
535
|
+
return {
|
|
536
|
+
headBranchName: pullRequest.headBranchName,
|
|
537
|
+
baseBranchName: targetBranch,
|
|
538
|
+
number: 0,
|
|
539
|
+
title: pullRequest.title,
|
|
540
|
+
body: pullRequest.body,
|
|
541
|
+
labels: pullRequest.labels,
|
|
542
|
+
files: [],
|
|
543
|
+
};
|
|
544
|
+
}
|
|
545
|
+
return await this.getPullRequest(prNumber);
|
|
546
|
+
}
|
|
547
|
+
/**
|
|
548
|
+
* Fetch a pull request given the pull number
|
|
549
|
+
* @param {number} number The pull request number
|
|
550
|
+
* @returns {PullRequest}
|
|
551
|
+
*/
|
|
552
|
+
async getPullRequest(number) {
|
|
553
|
+
return await this.gitHubApi.getPullRequest(number);
|
|
554
|
+
}
|
|
555
|
+
/**
|
|
556
|
+
* Update a pull request's title and body.
|
|
557
|
+
* @param {number} number The pull request number
|
|
558
|
+
* @param {ReleasePullRequest} releasePullRequest Pull request data to update
|
|
559
|
+
* @param {string} targetBranch The target branch of the pull request
|
|
560
|
+
* @param {string} options.signoffUser Optional. Commit signoff message
|
|
561
|
+
* @param {boolean} options.fork Optional. Whether to open the pull request from
|
|
562
|
+
* a fork or not. Defaults to `false`
|
|
563
|
+
* @param {PullRequestOverflowHandler} options.pullRequestOverflowHandler Optional.
|
|
564
|
+
* Handles extra large pull request body messages.
|
|
565
|
+
*/
|
|
566
|
+
async updatePullRequest(number, releasePullRequest, targetBranch, options) {
|
|
567
|
+
const changes = await this.buildChangeSet(releasePullRequest.updates, targetBranch);
|
|
1053
568
|
let message = releasePullRequest.title.toString();
|
|
1054
569
|
if (options === null || options === void 0 ? void 0 : options.signoffUser) {
|
|
1055
570
|
message = (0, signoff_commit_message_1.signoffCommitMessage)(message, options.signoffUser);
|
|
1056
571
|
}
|
|
1057
|
-
const
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
|
|
1069
|
-
|
|
572
|
+
const title = releasePullRequest.title.toString();
|
|
573
|
+
const body = ((options === null || options === void 0 ? void 0 : options.pullRequestOverflowHandler)
|
|
574
|
+
? await options.pullRequestOverflowHandler.handleOverflow(releasePullRequest)
|
|
575
|
+
: releasePullRequest.body)
|
|
576
|
+
.toString()
|
|
577
|
+
.slice(0, MAX_ISSUE_BODY_SIZE);
|
|
578
|
+
const prNumber = await (0, code_suggester_1.createPullRequest)(this.octokit, changes, {
|
|
579
|
+
upstreamOwner: this.repository.owner,
|
|
580
|
+
upstreamRepo: this.repository.repo,
|
|
581
|
+
title,
|
|
582
|
+
branch: releasePullRequest.headRefName,
|
|
583
|
+
description: body,
|
|
584
|
+
primary: targetBranch,
|
|
585
|
+
force: true,
|
|
586
|
+
fork: (options === null || options === void 0 ? void 0 : options.fork) === false ? false : true,
|
|
587
|
+
message,
|
|
588
|
+
logger: this.logger,
|
|
1070
589
|
draft: releasePullRequest.draft,
|
|
1071
590
|
});
|
|
591
|
+
if (prNumber !== number) {
|
|
592
|
+
this.logger.warn(`updated code for ${prNumber}, but update requested for ${number}`);
|
|
593
|
+
}
|
|
594
|
+
return this.gitHubApi.updatePullRequest(number, title, body);
|
|
1072
595
|
}
|
|
1073
596
|
/**
|
|
1074
597
|
* Given a set of proposed updates, build a changeset to suggest.
|
|
@@ -1129,6 +652,45 @@ class GitHub {
|
|
|
1129
652
|
async findFilesByExtension(extension, prefix) {
|
|
1130
653
|
return this.findFilesByExtensionAndRef(extension, this.repository.defaultBranch, prefix);
|
|
1131
654
|
}
|
|
655
|
+
/**
|
|
656
|
+
* Create a GitHub release
|
|
657
|
+
*
|
|
658
|
+
* @param {Release} release Release parameters
|
|
659
|
+
* @param {ReleaseOptions} options Release option parameters
|
|
660
|
+
* @throws {DuplicateReleaseError} if the release tag already exists
|
|
661
|
+
* @throws {GitHubAPIError} on other API errors
|
|
662
|
+
*/
|
|
663
|
+
async createRelease(release, options = {}) {
|
|
664
|
+
return await this.gitHubApi.createRelease(release, options);
|
|
665
|
+
}
|
|
666
|
+
/**
|
|
667
|
+
* Makes a comment on a issue/pull request.
|
|
668
|
+
*
|
|
669
|
+
* @param {string} comment - The body of the comment to post.
|
|
670
|
+
* @param {number} number - The issue or pull request number.
|
|
671
|
+
* @throws {GitHubAPIError} on an API error
|
|
672
|
+
*/
|
|
673
|
+
async commentOnIssue(comment, number) {
|
|
674
|
+
return await this.gitHubApi.commentOnIssue(comment, number);
|
|
675
|
+
}
|
|
676
|
+
/**
|
|
677
|
+
* Removes labels from an issue/pull request.
|
|
678
|
+
*
|
|
679
|
+
* @param {string[]} labels The labels to remove.
|
|
680
|
+
* @param {number} number The issue/pull request number.
|
|
681
|
+
*/
|
|
682
|
+
async removeIssueLabels(labels, number) {
|
|
683
|
+
return await this.gitHubApi.removeIssueLabels(labels, number);
|
|
684
|
+
}
|
|
685
|
+
/**
|
|
686
|
+
* Adds label to an issue/pull request.
|
|
687
|
+
*
|
|
688
|
+
* @param {string[]} labels The labels to add.
|
|
689
|
+
* @param {number} number The issue/pull request number.
|
|
690
|
+
*/
|
|
691
|
+
async addIssueLabels(labels, number) {
|
|
692
|
+
return await this.gitHubApi.addIssueLabels(labels, number);
|
|
693
|
+
}
|
|
1132
694
|
/**
|
|
1133
695
|
* Generate release notes from GitHub at tag
|
|
1134
696
|
* @param {string} tagName Name of new release tag
|
|
@@ -1136,14 +698,7 @@ class GitHub {
|
|
|
1136
698
|
* @param {string} previousTag Optional. Name of previous tag to analyze commits since
|
|
1137
699
|
*/
|
|
1138
700
|
async generateReleaseNotes(tagName, targetCommitish, previousTag) {
|
|
1139
|
-
|
|
1140
|
-
owner: this.repository.owner,
|
|
1141
|
-
repo: this.repository.repo,
|
|
1142
|
-
tag_name: tagName,
|
|
1143
|
-
previous_tag_name: previousTag,
|
|
1144
|
-
target_commitish: targetCommitish,
|
|
1145
|
-
});
|
|
1146
|
-
return resp.data.body;
|
|
701
|
+
return await this.gitHubApi.generateReleaseNotes(tagName, targetCommitish, previousTag);
|
|
1147
702
|
}
|
|
1148
703
|
/**
|
|
1149
704
|
* Create a single file on a new branch based on an existing
|
|
@@ -1156,107 +711,7 @@ class GitHub {
|
|
|
1156
711
|
* @returns {string} HTML URL of the new file
|
|
1157
712
|
*/
|
|
1158
713
|
async createFileOnNewBranch(filename, contents, newBranchName, baseBranchName) {
|
|
1159
|
-
|
|
1160
|
-
await this.forkBranch(newBranchName, baseBranchName);
|
|
1161
|
-
// use the single file upload API
|
|
1162
|
-
const { data: { content }, } = await this.octokit.repos.createOrUpdateFileContents({
|
|
1163
|
-
owner: this.repository.owner,
|
|
1164
|
-
repo: this.repository.repo,
|
|
1165
|
-
path: filename,
|
|
1166
|
-
// contents need to be base64 encoded
|
|
1167
|
-
content: Buffer.from(contents, 'binary').toString('base64'),
|
|
1168
|
-
message: 'Saving release notes',
|
|
1169
|
-
branch: newBranchName,
|
|
1170
|
-
});
|
|
1171
|
-
if (!(content === null || content === void 0 ? void 0 : content.html_url)) {
|
|
1172
|
-
throw new Error(`Failed to write to file: ${filename} on branch: ${newBranchName}`);
|
|
1173
|
-
}
|
|
1174
|
-
return content.html_url;
|
|
1175
|
-
}
|
|
1176
|
-
/**
|
|
1177
|
-
* Helper to fetch the SHA of a branch
|
|
1178
|
-
* @param {string} branchName The name of the branch
|
|
1179
|
-
* @return {string | undefined} Returns the SHA of the branch
|
|
1180
|
-
* or undefined if it can't be found.
|
|
1181
|
-
*/
|
|
1182
|
-
async getBranchSha(branchName) {
|
|
1183
|
-
this.logger.debug(`Looking up SHA for branch: ${branchName}`);
|
|
1184
|
-
try {
|
|
1185
|
-
const { data: { object: { sha }, }, } = await this.octokit.git.getRef({
|
|
1186
|
-
owner: this.repository.owner,
|
|
1187
|
-
repo: this.repository.repo,
|
|
1188
|
-
ref: `heads/${branchName}`,
|
|
1189
|
-
});
|
|
1190
|
-
this.logger.debug(`SHA for branch: ${sha}`);
|
|
1191
|
-
return sha;
|
|
1192
|
-
}
|
|
1193
|
-
catch (e) {
|
|
1194
|
-
if (e instanceof request_error_1.RequestError && e.status === 404) {
|
|
1195
|
-
this.logger.debug(`Branch: ${branchName} does not exist`);
|
|
1196
|
-
return undefined;
|
|
1197
|
-
}
|
|
1198
|
-
throw e;
|
|
1199
|
-
}
|
|
1200
|
-
}
|
|
1201
|
-
/**
|
|
1202
|
-
* Helper to fork a branch from an existing branch. Uses `force` so
|
|
1203
|
-
* it will overwrite the contents of `targetBranchName` to match
|
|
1204
|
-
* the current contents of `baseBranchName`.
|
|
1205
|
-
*
|
|
1206
|
-
* @param {string} targetBranchName The name of the new forked branch
|
|
1207
|
-
* @param {string} baseBranchName The base branch from which to fork.
|
|
1208
|
-
* @returns {string} The branch SHA
|
|
1209
|
-
* @throws {ConfigurationError} if the base branch cannot be found.
|
|
1210
|
-
*/
|
|
1211
|
-
async forkBranch(targetBranchName, baseBranchName) {
|
|
1212
|
-
const baseBranchSha = await this.getBranchSha(baseBranchName);
|
|
1213
|
-
if (!baseBranchSha) {
|
|
1214
|
-
// this is highly unlikely to be thrown as we will have
|
|
1215
|
-
// already attempted to read from the branch
|
|
1216
|
-
throw new errors_1.ConfigurationError(`Unable to find base branch: ${baseBranchName}`, 'core', `${this.repository.owner}/${this.repository.repo}`);
|
|
1217
|
-
}
|
|
1218
|
-
// see if newBranchName exists
|
|
1219
|
-
if (await this.getBranchSha(targetBranchName)) {
|
|
1220
|
-
// branch already exists, update it to the match the base branch
|
|
1221
|
-
const branchSha = await this.updateBranchSha(targetBranchName, baseBranchSha);
|
|
1222
|
-
this.logger.debug(`Updated ${targetBranchName} to match ${baseBranchName} at ${branchSha}`);
|
|
1223
|
-
return branchSha;
|
|
1224
|
-
}
|
|
1225
|
-
else {
|
|
1226
|
-
// branch does not exist, create a new branch from the base branch
|
|
1227
|
-
const branchSha = await this.createNewBranch(targetBranchName, baseBranchSha);
|
|
1228
|
-
this.logger.debug(`Forked ${targetBranchName} from ${baseBranchName} at ${branchSha}`);
|
|
1229
|
-
return branchSha;
|
|
1230
|
-
}
|
|
1231
|
-
}
|
|
1232
|
-
/**
|
|
1233
|
-
* Helper to create a new branch from a given SHA.
|
|
1234
|
-
* @param {string} branchName The new branch name
|
|
1235
|
-
* @param {string} branchSha The SHA of the branch
|
|
1236
|
-
* @returns {string} The SHA of the new branch
|
|
1237
|
-
*/
|
|
1238
|
-
async createNewBranch(branchName, branchSha) {
|
|
1239
|
-
this.logger.debug(`Creating new branch: ${branchName} at ${branchSha}`);
|
|
1240
|
-
const { data: { object: { sha }, }, } = await this.octokit.git.createRef({
|
|
1241
|
-
owner: this.repository.owner,
|
|
1242
|
-
repo: this.repository.repo,
|
|
1243
|
-
ref: `refs/heads/${branchName}`,
|
|
1244
|
-
sha: branchSha,
|
|
1245
|
-
});
|
|
1246
|
-
this.logger.debug(`New branch: ${branchName} at ${sha}`);
|
|
1247
|
-
return sha;
|
|
1248
|
-
}
|
|
1249
|
-
async updateBranchSha(branchName, branchSha) {
|
|
1250
|
-
this.logger.debug(`Updating branch ${branchName} to ${branchSha}`);
|
|
1251
|
-
const { data: { object: { sha }, }, } = await this.octokit.git.updateRef({
|
|
1252
|
-
owner: this.repository.owner,
|
|
1253
|
-
repo: this.repository.repo,
|
|
1254
|
-
ref: `heads/${branchName}`,
|
|
1255
|
-
sha: branchSha,
|
|
1256
|
-
force: true,
|
|
1257
|
-
});
|
|
1258
|
-
this.logger.debug(`Updated branch: ${branchName} to ${sha}`);
|
|
1259
|
-
return sha;
|
|
714
|
+
return await this.gitHubApi.createFileOnNewBranch(filename, contents, newBranchName, baseBranchName);
|
|
1260
715
|
}
|
|
1261
716
|
}
|
|
1262
717
|
exports.GitHub = GitHub;
|