UNPKG

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