| 74 | * - basic rate-limit backoff (single retry with bounded sleep) |
| 75 | */ |
| 76 | export class GitHubFetch { |
| 77 | /** |
| 78 | * @param {object} opts |
| 79 | * @param {string} opts.repo - "owner/name" |
| 80 | * @param {string} [opts.cacheDir] - defaults to ".cache/pr-sheriff/github" |
| 81 | * @param {number} [opts.cacheTtlSeconds] - defaults to 300 seconds |
| 82 | * @param {(args: string[], runnerOpts?: any) => Promise<{exitCode:number, stdout:string, stderr:string, timedOut?:boolean}>} [opts.ghRunner] |
| 83 | * @param {(ms:number) => Promise<void>} [opts.sleepFn] |
| 84 | * @param {number} [opts.maxBackoffSeconds] - max sleep for rate-limit backoff |
| 85 | */ |
| 86 | constructor({ |
| 87 | repo, |
| 88 | cacheDir = path.join('.cache', 'pr-sheriff', 'github'), |
| 89 | cacheTtlSeconds = 300, |
| 90 | ghRunner = defaultGhRunner, |
| 91 | sleepFn = (ms) => new Promise((r) => setTimeout(r, ms)), |
| 92 | maxBackoffSeconds = 10, |
| 93 | }) { |
| 94 | const { owner, name } = parseOwnerRepo(repo); |
| 95 | this.repo = repo; |
| 96 | this.owner = owner; |
| 97 | this.name = name; |
| 98 | |
| 99 | this.cacheDir = cacheDir; |
| 100 | this.cacheTtlSeconds = cacheTtlSeconds; |
| 101 | this.ghRunner = ghRunner; |
| 102 | this.sleepFn = sleepFn; |
| 103 | this.maxBackoffSeconds = maxBackoffSeconds; |
| 104 | } |
| 105 | |
| 106 | /** |
| 107 | * Fetch pull request details. |
| 108 | */ |
| 109 | async getPR(number, { useCache = true } = {}) { |
| 110 | return await this.#restRequest({ |
| 111 | method: 'GET', |
| 112 | endpoint: `/repos/${this.owner}/${this.name}/pulls/${number}`, |
| 113 | useCache, |
| 114 | }); |
| 115 | } |
| 116 | |
| 117 | /** |
| 118 | * Fetch issue details. |
| 119 | */ |
| 120 | async getIssue(number, { useCache = true } = {}) { |
| 121 | return await this.#restRequest({ |
| 122 | method: 'GET', |
| 123 | endpoint: `/repos/${this.owner}/${this.name}/issues/${number}`, |
| 124 | useCache, |
| 125 | }); |
| 126 | } |
| 127 | |
| 128 | /** |
| 129 | * List all comments on a PR: issue comments + PR review (inline) comments. |
| 130 | * |
| 131 | * @returns {Promise<{issueComments:any[], reviewComments:any[], all:any[]}>} |
| 132 | */ |
| 133 | async listPRComments(number, { useCache = true } = {}) { |
nothing calls this directly
no outgoing calls
no test coverage detected