1 | "use strict";
|
2 | Object.defineProperty(exports, "__esModule", { value: true });
|
3 | exports.automatedCommentIdentifier = void 0;
|
4 | const tslib_1 = require("tslib");
|
5 | const graphql_1 = require("@octokit/graphql");
|
6 | const plugin_enterprise_compatibility_1 = require("@octokit/plugin-enterprise-compatibility");
|
7 | const path_1 = tslib_1.__importDefault(require("path"));
|
8 | const plugin_retry_1 = require("@octokit/plugin-retry");
|
9 | const plugin_throttling_1 = require("@octokit/plugin-throttling");
|
10 | const rest_1 = require("@octokit/rest");
|
11 | const gitlog_1 = require("gitlog");
|
12 | const tinycolor2_1 = tslib_1.__importDefault(require("tinycolor2"));
|
13 | const endent_1 = tslib_1.__importDefault(require("endent"));
|
14 | const await_to_js_1 = tslib_1.__importDefault(require("await-to-js"));
|
15 | const url_join_1 = tslib_1.__importDefault(require("url-join"));
|
16 | const typescript_memoize_1 = require("typescript-memoize");
|
17 | const verify_auth_1 = tslib_1.__importDefault(require("./utils/verify-auth"));
|
18 | const exec_promise_1 = tslib_1.__importDefault(require("./utils/exec-promise"));
|
19 | const logger_1 = require("./utils/logger");
|
20 | const semver_1 = require("semver");
|
21 | const match_sha_to_pr_1 = require("./match-sha-to-pr");
|
22 |
|
23 | class GitAPIError extends Error {
|
24 |
|
25 | constructor(api, args, origError) {
|
26 | super(`Error calling github: ${api}\n\twith: ${JSON.stringify(args)}.\n\t${origError.message}`);
|
27 | }
|
28 | }
|
29 | const taggedPackageRegex = /(\S+)@(\S+)/;
|
30 |
|
31 |
|
32 |
|
33 |
|
34 |
|
35 |
|
36 |
|
37 |
|
38 |
|
39 |
|
40 | function getVersionFromTag(tag) {
|
41 | if (taggedPackageRegex.test(tag)) {
|
42 | const [, , version] = tag.match(taggedPackageRegex);
|
43 | return version;
|
44 | }
|
45 | return tag;
|
46 | }
|
47 | exports.automatedCommentIdentifier = "<!-- GITHUB_RELEASE";
|
48 |
|
49 | const makeIdentifier = (type, context) => `${exports.automatedCommentIdentifier} ${type}: ${context} -->`;
|
50 |
|
51 | const makeCommentIdentifier = (context) => makeIdentifier("COMMENT", context);
|
52 |
|
53 | const makePrBodyIdentifier = (context) => makeIdentifier("PR BODY", context);
|
54 |
|
55 |
|
56 |
|
57 |
|
58 | class Git {
|
59 |
|
60 | constructor(options, logger = logger_1.dummyLog()) {
|
61 | this.logger = logger;
|
62 | this.options = options;
|
63 | this.baseUrl = this.options.baseUrl || "https://api.github.com";
|
64 | this.graphqlBaseUrl = this.options.baseUrl
|
65 | ? this.options.graphqlBaseUrl || url_join_1.default(new URL(this.baseUrl).origin, "api")
|
66 | : this.baseUrl;
|
67 | this.logger.veryVerbose.info(`Initializing GitHub with: ${this.baseUrl}`);
|
68 | const GitHub = rest_1.Octokit.plugin(plugin_enterprise_compatibility_1.enterpriseCompatibility)
|
69 | .plugin(plugin_retry_1.retry)
|
70 | .plugin(plugin_throttling_1.throttling);
|
71 | this.github = new GitHub({
|
72 | baseUrl: this.baseUrl,
|
73 | auth: this.options.token,
|
74 | previews: ["symmetra-preview"],
|
75 | request: { agent: this.options.agent },
|
76 | throttle: {
|
77 | onRateLimit: (retryAfter, opts) => {
|
78 | this.logger.log.warn(`Request quota exhausted for request ${opts.method} ${opts.url}`);
|
79 | if (opts.request.retryCount < 5) {
|
80 | this.logger.verbose.log(`Retrying after ${retryAfter} seconds!`);
|
81 | return true;
|
82 | }
|
83 | },
|
84 | onAbuseLimit: (_, opts) => {
|
85 |
|
86 | this.logger.log.error(`Went over abuse rate limit ${opts.method} ${opts.url}`);
|
87 | },
|
88 | },
|
89 | });
|
90 | this.github.hook.error("request", (error) => {
|
91 | var _a;
|
92 | if ((_a = error === null || error === void 0 ? void 0 : error.headers) === null || _a === void 0 ? void 0 : _a.authorization) {
|
93 | delete error.headers.authorization;
|
94 | }
|
95 | throw error;
|
96 | });
|
97 | }
|
98 |
|
99 | async verifyAuth(url) {
|
100 | return verify_auth_1.default(url, this.options.baseBranch);
|
101 | }
|
102 |
|
103 | async getLatestReleaseInfo() {
|
104 | const latestRelease = await this.github.repos.getLatestRelease({
|
105 | owner: this.options.owner,
|
106 | repo: this.options.repo,
|
107 | });
|
108 | return latestRelease.data;
|
109 | }
|
110 |
|
111 | async getLatestRelease() {
|
112 | try {
|
113 | const latestRelease = await this.getLatestReleaseInfo();
|
114 | this.logger.veryVerbose.info('Got response for "getLatestRelease":\n', latestRelease);
|
115 | this.logger.verbose.info("Got latest release:\n", latestRelease);
|
116 | return latestRelease.tag_name;
|
117 | }
|
118 | catch (e) {
|
119 | if (e.status === 404) {
|
120 | this.logger.verbose.info("Couldn't find latest release on GitHub, using first commit.");
|
121 | return this.getFirstCommit();
|
122 | }
|
123 | throw e;
|
124 | }
|
125 | }
|
126 |
|
127 | async getCommitDate(sha) {
|
128 | const date = await exec_promise_1.default("git", ["show", "-s", "--format=%ci", sha]);
|
129 | const [day, time, timezone] = date.split(" ");
|
130 | return `${day}T${time}${timezone}`;
|
131 | }
|
132 |
|
133 | async getFirstCommit() {
|
134 | const list = await exec_promise_1.default("git", ["rev-list", "HEAD"]);
|
135 | return list.split("\n").pop();
|
136 | }
|
137 |
|
138 | async getSha(short) {
|
139 | const result = await exec_promise_1.default("git", [
|
140 | "rev-parse",
|
141 | short && "--short",
|
142 | "HEAD",
|
143 | ]);
|
144 | this.logger.verbose.info(`Got commit SHA from HEAD: ${result}`);
|
145 | return result;
|
146 | }
|
147 |
|
148 | async shaExists(sha) {
|
149 | try {
|
150 | await exec_promise_1.default("git", ["rev-parse", "--verify", sha]);
|
151 | return true;
|
152 | }
|
153 | catch (error) {
|
154 | return false;
|
155 | }
|
156 | }
|
157 |
|
158 | async getLabels(prNumber) {
|
159 | this.logger.verbose.info(`Getting labels for PR: ${prNumber}`);
|
160 | const args = {
|
161 | owner: this.options.owner,
|
162 | repo: this.options.repo,
|
163 | issue_number: prNumber,
|
164 | };
|
165 | this.logger.verbose.info("Getting issue labels using:", args);
|
166 | try {
|
167 | const labels = await this.github.issues.listLabelsOnIssue(args);
|
168 | this.logger.veryVerbose.info('Got response for "listLabelsOnIssue":\n', labels);
|
169 | this.logger.verbose.info("Found labels on PR:\n", labels.data);
|
170 | return labels.data.map((l) => l.name);
|
171 | }
|
172 | catch (e) {
|
173 | throw new GitAPIError("listLabelsOnIssue", args, e);
|
174 | }
|
175 | }
|
176 |
|
177 | async getPr(prNumber) {
|
178 | this.logger.verbose.info(`Getting info for PR: ${prNumber}`);
|
179 | const args = {
|
180 | owner: this.options.owner,
|
181 | repo: this.options.repo,
|
182 | issue_number: prNumber,
|
183 | };
|
184 | this.logger.verbose.info("Getting issue info using:", args);
|
185 | try {
|
186 | const info = await this.github.issues.get(args);
|
187 | this.logger.veryVerbose.info('Got response for "issues.get":\n', info);
|
188 | return info;
|
189 | }
|
190 | catch (e) {
|
191 | throw new GitAPIError("getPr", args, e);
|
192 | }
|
193 | }
|
194 |
|
195 | async getCommit(sha) {
|
196 | this.logger.verbose.info(`Getting info for commit: ${sha}`);
|
197 | try {
|
198 | const info = await this.github.repos.getCommit({
|
199 | owner: this.options.owner,
|
200 | repo: this.options.repo,
|
201 | ref: sha,
|
202 | });
|
203 | this.logger.veryVerbose.info('Got response for "repos.getCommit":\n', info);
|
204 | return info;
|
205 | }
|
206 | catch (e) {
|
207 | throw new GitAPIError("getCommit", [], e);
|
208 | }
|
209 | }
|
210 |
|
211 | async getProjectLabels() {
|
212 | this.logger.verbose.info(`Getting labels for project: ${this.options.repo}`);
|
213 | const args = {
|
214 | owner: this.options.owner,
|
215 | repo: this.options.repo,
|
216 | };
|
217 | try {
|
218 | const labels = await this.github.paginate(this.github.issues.listLabelsForRepo, args);
|
219 | this.logger.veryVerbose.info('Got response for "getProjectLabels":\n', labels);
|
220 | this.logger.verbose.info("Found labels on project:\n", labels);
|
221 | return labels.map((l) => l.name);
|
222 | }
|
223 | catch (e) {
|
224 | throw new GitAPIError("getProjectLabels", args, e);
|
225 | }
|
226 | }
|
227 |
|
228 | async getGitLog(start, end = "HEAD") {
|
229 | try {
|
230 | const first = await this.getFirstCommit();
|
231 |
|
232 |
|
233 |
|
234 | const startSha = (await this.shaExists(start))
|
235 | ? await exec_promise_1.default("git", ["rev-parse", start])
|
236 | : "";
|
237 | const log = await gitlog_1.gitlogPromise({
|
238 | repo: process.cwd(),
|
239 | number: Number.MAX_SAFE_INTEGER,
|
240 | fields: ["hash", "authorName", "authorEmail", "rawBody"],
|
241 |
|
242 |
|
243 | branch: first === startSha ? end : `${start.trim()}..${end.trim()}`,
|
244 | execOptions: { maxBuffer: Infinity },
|
245 | includeMergeCommitFiles: true,
|
246 | });
|
247 | return log
|
248 | .map((commit) => ({
|
249 | hash: commit.hash,
|
250 | authorName: commit.authorName,
|
251 | authorEmail: commit.authorEmail,
|
252 | subject: commit.rawBody,
|
253 | files: (commit.files || []).map((file) => path_1.default.resolve(file)),
|
254 | }))
|
255 | .reduce((all, commit) => {
|
256 |
|
257 |
|
258 |
|
259 |
|
260 | const current = all.find((c) => c.hash === commit.hash);
|
261 | if (current) {
|
262 | current.files = [...current.files, ...commit.files];
|
263 | }
|
264 | else {
|
265 | all.push(commit);
|
266 | }
|
267 | return all;
|
268 | }, []);
|
269 | }
|
270 | catch (error) {
|
271 | console.log(error);
|
272 | const tag = error.match(/ambiguous argument '(\S+)\.\.\S+'/);
|
273 | if (tag) {
|
274 | this.logger.log.error(endent_1.default `
|
275 | Missing tag "${tag[1]}" so the command could not run.
|
276 |
|
277 | To fix this run the following command:
|
278 |
|
279 | git fetch --tags\n
|
280 | `);
|
281 | process.exit(1);
|
282 | }
|
283 | throw new Error(error);
|
284 | }
|
285 | }
|
286 |
|
287 | async getUserByEmail(email) {
|
288 | try {
|
289 | const search = (await this.github.search.users({
|
290 | q: `in:email ${email}`,
|
291 | })).data;
|
292 | return (search === null || search === void 0 ? void 0 : search.items.length) > 0 ? search.items[0] : {};
|
293 | }
|
294 | catch (error) {
|
295 | this.logger.verbose.warn(`Could not find user by email: ${email}`);
|
296 | }
|
297 | }
|
298 |
|
299 | async getTokenPermissionLevel() {
|
300 | const [, user] = await await_to_js_1.default(this.github.users.getAuthenticated());
|
301 | if (!user) {
|
302 | return {
|
303 | permission: "none",
|
304 | };
|
305 | }
|
306 | try {
|
307 | const { permission } = (await this.github.repos.getCollaboratorPermissionLevel({
|
308 | owner: this.options.owner,
|
309 | repo: this.options.repo,
|
310 | username: user.data.login,
|
311 | })).data;
|
312 | return { permission, user: user.data };
|
313 | }
|
314 | catch (error) {
|
315 | this.logger.verbose.error(`Could not get permissions for token`);
|
316 | return { permission: "read", user: user.data };
|
317 | }
|
318 | }
|
319 |
|
320 | async getUserByUsername(username) {
|
321 | try {
|
322 | const user = await this.github.users.getByUsername({
|
323 | username,
|
324 | });
|
325 | return user.data;
|
326 | }
|
327 | catch (error) {
|
328 | this.logger.verbose.warn(`Could not find user by username: ${username}`);
|
329 | }
|
330 | }
|
331 |
|
332 | async getPullRequest(pr) {
|
333 | this.logger.verbose.info(`Getting Pull Request: ${pr}`);
|
334 | const args = {
|
335 | owner: this.options.owner,
|
336 | repo: this.options.repo,
|
337 | pull_number: pr,
|
338 | };
|
339 | this.logger.verbose.info("Getting pull request info using:", args);
|
340 | const result = await this.github.pulls.get(args);
|
341 | this.logger.veryVerbose.info("Got pull request data\n", result);
|
342 | this.logger.verbose.info("Got pull request info");
|
343 | return result;
|
344 | }
|
345 |
|
346 | async searchRepo(options) {
|
347 | const repo = `repo:${this.options.owner}/${this.options.repo}`;
|
348 | options.q = `${repo} ${options.q}`;
|
349 | this.logger.verbose.info("Searching repo using:\n", options);
|
350 | const result = await this.github.search.issuesAndPullRequests(options);
|
351 | this.logger.veryVerbose.info("Got response from search\n", result);
|
352 | this.logger.verbose.info("Searched repo on GitHub.");
|
353 | return result.data;
|
354 | }
|
355 |
|
356 | async graphql(query) {
|
357 | this.logger.verbose.info("Querying Github using GraphQL:\n", query);
|
358 | const data = await graphql_1.graphql(query, {
|
359 | baseUrl: this.graphqlBaseUrl,
|
360 | request: { agent: this.options.agent },
|
361 | headers: {
|
362 | authorization: `token ${this.options.token}`,
|
363 | },
|
364 | });
|
365 | this.logger.veryVerbose.info("Got response from query\n", data);
|
366 | return data;
|
367 | }
|
368 |
|
369 | async createStatus(prInfo) {
|
370 | const args = Object.assign(Object.assign({}, prInfo), { owner: this.options.owner, repo: this.options.repo });
|
371 | this.logger.verbose.info("Creating status using:\n", args);
|
372 | const result = await this.github.repos.createCommitStatus(args);
|
373 | this.logger.veryVerbose.info("Got response from createStatues\n", result);
|
374 | this.logger.verbose.info("Created status on GitHub.");
|
375 | return result;
|
376 | }
|
377 |
|
378 | async createLabel(label) {
|
379 | this.logger.verbose.info(`Creating "${label.releaseType || "general"}" label :\n${label.name}`);
|
380 | const color = label.color
|
381 | ? tinycolor2_1.default(label.color).toString("hex6")
|
382 | : tinycolor2_1.default.random().toString("hex6");
|
383 | const result = await this.github.issues.createLabel({
|
384 | name: label.name,
|
385 | owner: this.options.owner,
|
386 | repo: this.options.repo,
|
387 | color: color.replace("#", ""),
|
388 | description: label.description,
|
389 | });
|
390 | this.logger.veryVerbose.info("Got response from createLabel\n", result);
|
391 | this.logger.verbose.info("Created label on GitHub.");
|
392 | return result;
|
393 | }
|
394 |
|
395 | async updateLabel(label) {
|
396 | this.logger.verbose.info(`Updating "${label.releaseType || "generic"}" label :\n${label.name}`);
|
397 | const color = label.color
|
398 | ? tinycolor2_1.default(label.color).toString("hex6")
|
399 | : tinycolor2_1.default.random().toString("hex6");
|
400 | const result = await this.github.issues.updateLabel({
|
401 | current_name: label.name,
|
402 | name: label.name,
|
403 | owner: this.options.owner,
|
404 | repo: this.options.repo,
|
405 | color: color.replace("#", ""),
|
406 | description: label.description,
|
407 | });
|
408 | this.logger.veryVerbose.info("Got response from updateLabel\n", result);
|
409 | this.logger.verbose.info("Updated label on GitHub.");
|
410 | return result;
|
411 | }
|
412 |
|
413 | async addLabelToPr(pr, label) {
|
414 | this.logger.verbose.info(`Creating "${label}" label to PR ${pr}`);
|
415 | const result = await this.github.issues.addLabels({
|
416 | issue_number: pr,
|
417 | owner: this.options.owner,
|
418 | repo: this.options.repo,
|
419 | labels: [label],
|
420 | });
|
421 | this.logger.veryVerbose.info("Got response from addLabels\n", result);
|
422 | this.logger.verbose.info("Added labels on Pull Request.");
|
423 | return result;
|
424 | }
|
425 |
|
426 | async removeLabel(pr, label) {
|
427 | this.logger.verbose.info(`Removing "${label}" from #${pr}`);
|
428 | const result = await this.github.issues.removeLabel({
|
429 | issue_number: pr,
|
430 | owner: this.options.owner,
|
431 | repo: this.options.repo,
|
432 | name: label,
|
433 | });
|
434 | this.logger.veryVerbose.info("Got response from removeLabel\n", result);
|
435 | this.logger.verbose.info("Removed label on Pull Request.");
|
436 | return result;
|
437 | }
|
438 |
|
439 | async lockIssue(issue) {
|
440 | this.logger.verbose.info(`Locking #${issue} issue...`);
|
441 | const result = await this.github.issues.lock({
|
442 | issue_number: issue,
|
443 | owner: this.options.owner,
|
444 | repo: this.options.repo,
|
445 | });
|
446 | this.logger.veryVerbose.info("Got response from lock\n", result);
|
447 | this.logger.verbose.info("Locked issue.");
|
448 | return result;
|
449 | }
|
450 |
|
451 | async getProject() {
|
452 | this.logger.verbose.info("Getting project from GitHub");
|
453 | const result = (await this.github.repos.get({
|
454 | owner: this.options.owner,
|
455 | repo: this.options.repo,
|
456 | })).data;
|
457 | this.logger.veryVerbose.info("Got response from repos\n", result);
|
458 | this.logger.verbose.info("Got project information.");
|
459 | return result;
|
460 | }
|
461 |
|
462 | async getPullRequests(options) {
|
463 | this.logger.verbose.info("Getting pull requests...");
|
464 | const result = (await this.github.pulls.list(Object.assign({ owner: this.options.owner.toLowerCase(), repo: this.options.repo.toLowerCase() }, options))).data;
|
465 | this.logger.veryVerbose.info("Got response from pull requests", result);
|
466 | this.logger.verbose.info("Got pull request");
|
467 | return result;
|
468 | }
|
469 |
|
470 | async getCommitsForPR(pr) {
|
471 | this.logger.verbose.info(`Getting commits for PR #${pr}`);
|
472 | const result = await this.github.paginate(this.github.pulls.listCommits, {
|
473 | owner: this.options.owner.toLowerCase(),
|
474 | repo: this.options.repo.toLowerCase(),
|
475 | pull_number: pr,
|
476 | });
|
477 | this.logger.veryVerbose.info(`Got response from PR #${pr}\n`, result);
|
478 | this.logger.verbose.info(`Got commits for PR #${pr}.`);
|
479 | return result;
|
480 | }
|
481 |
|
482 | async getCommentId(pr, context = "default") {
|
483 | const commentIdentifier = makeCommentIdentifier(context);
|
484 | this.logger.verbose.info("Getting previous comments on:", pr);
|
485 | const comments = await this.github.issues.listComments({
|
486 | owner: this.options.owner,
|
487 | repo: this.options.repo,
|
488 | issue_number: pr,
|
489 | });
|
490 | this.logger.veryVerbose.info("Got PR comments\n", comments);
|
491 | const oldMessage = comments.data.find((comment) => comment.body.includes(commentIdentifier));
|
492 | if (!oldMessage) {
|
493 | return -1;
|
494 | }
|
495 | this.logger.verbose.info("Found previous message from same scope.");
|
496 | return oldMessage.id;
|
497 | }
|
498 |
|
499 | async deleteComment(pr, context = "default") {
|
500 | const commentId = await this.getCommentId(pr, context);
|
501 | if (commentId === -1) {
|
502 | return;
|
503 | }
|
504 | this.logger.verbose.info(`Deleting comment: ${commentId}`);
|
505 | await this.github.issues.deleteComment({
|
506 | owner: this.options.owner,
|
507 | repo: this.options.repo,
|
508 | comment_id: commentId,
|
509 | });
|
510 | this.logger.verbose.info(`Successfully deleted comment: ${commentId}`);
|
511 | }
|
512 |
|
513 | async createComment(message, pr, context = "default") {
|
514 | const commentIdentifier = makeCommentIdentifier(context);
|
515 | this.logger.verbose.info("Using comment identifier:", commentIdentifier);
|
516 | await this.deleteComment(pr, context);
|
517 | this.logger.verbose.info("Creating new comment");
|
518 | const result = await this.github.issues.createComment({
|
519 | owner: this.options.owner,
|
520 | repo: this.options.repo,
|
521 | issue_number: pr,
|
522 | body: `${commentIdentifier}\n${message}`,
|
523 | });
|
524 | this.logger.veryVerbose.info("Got response from creating comment\n", result);
|
525 | this.logger.verbose.info("Successfully posted comment to PR");
|
526 | return result;
|
527 | }
|
528 |
|
529 | async editComment(message, pr, context = "default") {
|
530 | const commentIdentifier = makeCommentIdentifier(context);
|
531 | this.logger.verbose.info("Using comment identifier:", commentIdentifier);
|
532 | const commentId = await this.getCommentId(pr, context);
|
533 | if (commentId === -1) {
|
534 | return this.createComment(message, pr, context);
|
535 | }
|
536 | this.logger.verbose.info("Editing comment");
|
537 | const result = await this.github.issues.updateComment({
|
538 | owner: this.options.owner,
|
539 | repo: this.options.repo,
|
540 | comment_id: commentId,
|
541 | body: `${commentIdentifier}\n${message}`,
|
542 | });
|
543 | this.logger.veryVerbose.info("Got response from editing comment\n", result);
|
544 | this.logger.verbose.info("Successfully edited comment on PR");
|
545 | return result;
|
546 | }
|
547 |
|
548 | async addToPrBody(message, pr, context = "default") {
|
549 | const id = makePrBodyIdentifier(context);
|
550 | this.logger.verbose.info("Using PR body identifier:", id);
|
551 | this.logger.verbose.info("Getting previous pr body on:", pr);
|
552 | const issue = await this.github.issues.get({
|
553 | owner: this.options.owner,
|
554 | repo: this.options.repo,
|
555 | issue_number: pr,
|
556 | });
|
557 | this.logger.veryVerbose.info("Got PR description\n", issue.data.body);
|
558 | const regex = new RegExp(`(${id})\\s*([\\S\\s]*)\\s*(${id})`);
|
559 | let body = issue.data.body;
|
560 | if (!body) {
|
561 | body = message ? `\n${id}\n${message}\n${id}\n` : "";
|
562 | }
|
563 | else if (body.match(regex)) {
|
564 | this.logger.verbose.info("Found previous message from same scope.");
|
565 | this.logger.verbose.info("Replacing pr body comment");
|
566 | body = body.replace(regex, message ? `$1\n${message}\n$3` : "");
|
567 | }
|
568 | else {
|
569 | body += message ? `\n${id}\n${message}\n${id}\n` : "";
|
570 | }
|
571 | this.logger.verbose.info("Creating new pr body");
|
572 | const result = await this.github.issues.update({
|
573 | owner: this.options.owner,
|
574 | repo: this.options.repo,
|
575 | issue_number: pr,
|
576 | body,
|
577 | });
|
578 | this.logger.veryVerbose.info("Got response from updating body\n", result);
|
579 | this.logger.verbose.info(`Successfully updated body of PR #${pr}`);
|
580 | return result;
|
581 | }
|
582 |
|
583 | async publish(releaseNotes, tag, prerelease = false) {
|
584 | this.logger.verbose.info("Creating release on GitHub for tag:", tag);
|
585 | const result = await this.github.repos.createRelease({
|
586 | owner: this.options.owner,
|
587 | repo: this.options.repo,
|
588 | tag_name: tag,
|
589 | name: tag,
|
590 | body: releaseNotes,
|
591 | prerelease,
|
592 | });
|
593 | this.logger.veryVerbose.info("Got response from createRelease\n", result);
|
594 | this.logger.verbose.info("Created GitHub release.");
|
595 | return result;
|
596 | }
|
597 |
|
598 | async getLatestTagInBranch(since) {
|
599 | return exec_promise_1.default("git", ["describe", "--tags", "--abbrev=0", since]);
|
600 | }
|
601 |
|
602 | async getPreviousTagInBranch() {
|
603 | const latest = await this.getLatestTagInBranch();
|
604 | return this.getLatestTagInBranch(`${latest}^1`);
|
605 | }
|
606 |
|
607 | async getTags(branch) {
|
608 | const tags = await exec_promise_1.default("git", [
|
609 | "tag",
|
610 | "--sort='creatordate'",
|
611 | "--merged",
|
612 | branch,
|
613 | ]);
|
614 | return tags
|
615 | .split("\n")
|
616 | .map((tag) => tag.trim())
|
617 | .filter(Boolean);
|
618 | }
|
619 |
|
620 | async getTagNotInBaseBranch(branch, options = {}) {
|
621 | const baseTags = (await this.getTags(`origin/${this.options.baseBranch}`)).reverse();
|
622 | const branchTags = (await this.getTags(`heads/${branch}`)).reverse();
|
623 | const comparator = options.first ? semver_1.lt : semver_1.gt;
|
624 | let firstGreatestUnique;
|
625 | branchTags.forEach((tag) => {
|
626 | const tagVersion = getVersionFromTag(tag);
|
627 | const greatestVersion = firstGreatestUnique
|
628 | ? getVersionFromTag(firstGreatestUnique)
|
629 | : undefined;
|
630 | if (!baseTags.includes(tag) &&
|
631 | (!greatestVersion || comparator(tagVersion, greatestVersion))) {
|
632 | firstGreatestUnique = tag;
|
633 | }
|
634 | });
|
635 | this.logger.verbose.info("Tags found in base branch:", baseTags);
|
636 | this.logger.verbose.info("Tags found in branch:", branchTags);
|
637 | this.logger.verbose.info(`${options.first ? "First" : "Latest"} tag in branch:`, firstGreatestUnique || "Not Found");
|
638 | return firstGreatestUnique;
|
639 | }
|
640 |
|
641 | async getLastTagNotInBaseBranch(branch) {
|
642 | return this.getTagNotInBaseBranch(branch);
|
643 | }
|
644 |
|
645 | async matchCommitToPr(sha) {
|
646 | const query = match_sha_to_pr_1.buildSearchQuery(this.options.owner, this.options.repo, [
|
647 | sha,
|
648 | ]);
|
649 | if (!query) {
|
650 | return;
|
651 | }
|
652 | const key = `hash_${sha}`;
|
653 | const result = await this.graphql(query);
|
654 | if (!result || !result[key] || !result[key].edges[0]) {
|
655 | return;
|
656 | }
|
657 | const pr = result[key].edges[0].node;
|
658 | return Object.assign(Object.assign({}, pr), { labels: pr.labels ? pr.labels.edges.map((edge) => edge.node.name) : [] });
|
659 | }
|
660 | }
|
661 | tslib_1.__decorate([
|
662 | typescript_memoize_1.Memoize()
|
663 | ], Git.prototype, "getLatestReleaseInfo", null);
|
664 | tslib_1.__decorate([
|
665 | typescript_memoize_1.Memoize()
|
666 | ], Git.prototype, "getLatestRelease", null);
|
667 | tslib_1.__decorate([
|
668 | typescript_memoize_1.Memoize()
|
669 | ], Git.prototype, "getLabels", null);
|
670 | tslib_1.__decorate([
|
671 | typescript_memoize_1.Memoize()
|
672 | ], Git.prototype, "getPr", null);
|
673 | tslib_1.__decorate([
|
674 | typescript_memoize_1.Memoize()
|
675 | ], Git.prototype, "getCommit", null);
|
676 | tslib_1.__decorate([
|
677 | typescript_memoize_1.Memoize()
|
678 | ], Git.prototype, "getGitLog", null);
|
679 | tslib_1.__decorate([
|
680 | typescript_memoize_1.Memoize()
|
681 | ], Git.prototype, "getUserByEmail", null);
|
682 | tslib_1.__decorate([
|
683 | typescript_memoize_1.Memoize()
|
684 | ], Git.prototype, "getTokenPermissionLevel", null);
|
685 | tslib_1.__decorate([
|
686 | typescript_memoize_1.Memoize()
|
687 | ], Git.prototype, "getUserByUsername", null);
|
688 | tslib_1.__decorate([
|
689 | typescript_memoize_1.Memoize()
|
690 | ], Git.prototype, "getPullRequest", null);
|
691 | tslib_1.__decorate([
|
692 | typescript_memoize_1.Memoize()
|
693 | ], Git.prototype, "getProject", null);
|
694 | tslib_1.__decorate([
|
695 | typescript_memoize_1.Memoize()
|
696 | ], Git.prototype, "getCommitsForPR", null);
|
697 | exports.default = Git;
|
698 |
|
\ | No newline at end of file |