@osdlc/typed-gh 0.9.0 → 0.9.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +14 -0
- package/CONTRIBUTING.md +1 -1
- package/README.md +98 -96
- package/SECURITY.md +4 -4
- package/dist/async.d.ts +28 -27
- package/dist/async.js +29 -28
- package/dist/doors.d.ts +25 -23
- package/dist/doors.js +29 -27
- package/dist/failure.d.ts +8 -8
- package/dist/failure.js +6 -6
- package/dist/index.d.ts +13 -14
- package/dist/index.js +14 -15
- package/dist/parse.d.ts +21 -21
- package/dist/parse.js +34 -36
- package/dist/repo.d.ts +13 -13
- package/dist/repo.js +13 -13
- package/dist/run.d.ts +12 -13
- package/dist/run.js +11 -12
- package/dist/sync.d.ts +66 -64
- package/dist/sync.js +67 -65
- package/dist/types.d.ts +31 -32
- package/dist/types.js +8 -8
- package/dist/verbs.d.ts +120 -122
- package/dist/verbs.js +119 -110
- package/package.json +3 -3
package/dist/sync.js
CHANGED
|
@@ -1,25 +1,26 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* `Gh
|
|
2
|
+
* `Gh`: the synchronous GitHub client, the companion of `@osdlc/typed-git`'s
|
|
3
3
|
* `Git`, bound to one working directory and one {@link CommandRunner}.
|
|
4
4
|
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
5
|
+
* `gh` handles authentication. No token is read, stored, or passed. That is
|
|
6
|
+
* why this runs the CLI instead of calling the REST API. The credential is
|
|
7
|
+
* already in the user's keychain. A library that reads `GITHUB_TOKEN` can
|
|
8
|
+
* leak it.
|
|
9
9
|
*
|
|
10
|
-
*
|
|
11
|
-
* or throws
|
|
12
|
-
* `GhFailure
|
|
13
|
-
* `
|
|
14
|
-
* `
|
|
15
|
-
* `
|
|
10
|
+
* It has the same three call styles as the git client. The plain method
|
|
11
|
+
* returns a value or throws. A failed `gh` throws a `FailureError` carrying
|
|
12
|
+
* the classified `GhFailure`. Output that cannot be read throws one of kind
|
|
13
|
+
* `unreadable`. A query for one thing (`prView`, `issueView`, `repoView`)
|
|
14
|
+
* returns `null` when GitHub says there is no such thing. `gh.try.*` returns
|
|
15
|
+
* the failure as a `Result<T, GhFailure>`. `gh.soft.*` returns `null` for it.
|
|
16
|
+
* `raw` and `rawChecked` run any `gh` call.
|
|
16
17
|
*/
|
|
17
18
|
import { resolveRunner, spawnRunner, } from '@osdlc/command-seam';
|
|
18
19
|
import { runCheckedGh, softSync, triedSync } from "./doors.js";
|
|
19
20
|
import { runVerb } from "./run.js";
|
|
20
21
|
import * as v from "./verbs.js";
|
|
21
22
|
import { ownerRepoSlug, parseOwnerRepo, parsePrRef } from "./repo.js";
|
|
22
|
-
/**
|
|
23
|
+
/** The default factory: real runners that use `spawnSync`. */
|
|
23
24
|
export const defaultRunnerFactory = spawnRunner;
|
|
24
25
|
/** How long to wait between merge-state retries, in milliseconds. */
|
|
25
26
|
const MERGE_STATE_RETRY_DELAY_MS = 1_500;
|
|
@@ -63,59 +64,61 @@ export class Gh {
|
|
|
63
64
|
}
|
|
64
65
|
/**
|
|
65
66
|
* The whole surface again, returning a `Result<T, GhFailure>` instead of
|
|
66
|
-
* throwing
|
|
67
|
+
* throwing. `gh.try.prList()` is `{ ok: true, value } | { ok: false, error }`.
|
|
67
68
|
* A query for one thing that finds nothing is `ok: true` with `null`. See
|
|
68
69
|
* `./doors.ts`.
|
|
69
70
|
*
|
|
70
|
-
* The type leaves out
|
|
71
|
-
* the proxy wraps `raw` and `rawChecked` too. Call those on the
|
|
71
|
+
* The type leaves out `raw`, `rawChecked` and the helpers that run nothing.
|
|
72
|
+
* At runtime the proxy wraps `raw` and `rawChecked` too. Call those on the
|
|
73
|
+
* client itself.
|
|
72
74
|
*/
|
|
73
75
|
get try() {
|
|
74
76
|
return (this.tried ??= triedSync(this));
|
|
75
77
|
}
|
|
76
78
|
/**
|
|
77
79
|
* Each query again, returning `null` instead of throwing when `gh` fails. A
|
|
78
|
-
* mutation has no soft form. Do not
|
|
79
|
-
*
|
|
80
|
+
* mutation has no soft form. Do not decide a write on a `null` from `soft`.
|
|
81
|
+
* It is the answer for "could not ask" as well as for "nothing there". Use
|
|
80
82
|
* `try` where the difference matters.
|
|
81
83
|
*/
|
|
82
84
|
get soft() {
|
|
83
85
|
return (this.softened ??= softSync(this));
|
|
84
86
|
}
|
|
85
|
-
// ──
|
|
86
|
-
/**
|
|
87
|
+
// ── raw calls ─────────────────────────────────────────────────────────────
|
|
88
|
+
/** Run any `gh` call and return the result, whatever the exit code. */
|
|
87
89
|
raw(argv, opts = {}) {
|
|
88
90
|
return this.runner.run(argv, { cwd: this.cwd, ...opts });
|
|
89
91
|
}
|
|
90
|
-
/**
|
|
92
|
+
/** Run any `gh` call. Throws the classified failure on a non-zero exit. */
|
|
91
93
|
rawChecked(argv, opts = {}) {
|
|
92
94
|
return runCheckedGh(this.runner, argv, { cwd: this.cwd, ...opts });
|
|
93
95
|
}
|
|
94
|
-
/** Run one verb from the table,
|
|
96
|
+
/** Run one verb from the table, checked or unchecked as the verb says. */
|
|
95
97
|
exec(verb, timeoutMs) {
|
|
96
98
|
return runVerb(verb, this.runner, { cwd: this.cwd, timeoutMs });
|
|
97
99
|
}
|
|
98
|
-
/** {@link exec} for a verb that never
|
|
100
|
+
/** {@link exec} for a verb that never returns `null` as a value. A failed or unreadable run throws. */
|
|
99
101
|
read(verb, timeoutMs) {
|
|
100
102
|
return this.exec(verb, timeoutMs);
|
|
101
103
|
}
|
|
102
104
|
// ── queries ───────────────────────────────────────────────────────────────
|
|
103
|
-
/** Pull requests matching `opts`. Throws when gh fails
|
|
105
|
+
/** Pull requests matching `opts`. Throws when gh fails. `soft.prList` gives null instead. */
|
|
104
106
|
prList(opts = {}) {
|
|
105
107
|
return this.read(v.prList(opts, this.target), opts.timeoutMs);
|
|
106
108
|
}
|
|
107
109
|
/**
|
|
108
|
-
* One PR by number, branch or URL, with the
|
|
109
|
-
* no such PR. Throws when gh fails otherwise.
|
|
110
|
+
* One PR by number, branch or URL, with the full field set. Null when there
|
|
111
|
+
* is no such PR. Throws when gh fails otherwise.
|
|
110
112
|
*/
|
|
111
113
|
prView(ref, opts = {}) {
|
|
112
114
|
return this.exec(v.prView(ref, opts.fields ?? v.PR_VIEW_FIELDS, this.target), opts.timeoutMs);
|
|
113
115
|
}
|
|
114
116
|
/**
|
|
115
|
-
* The one PR that `input` names, or null
|
|
116
|
-
* `#42`, `owner/name#42`, a URL or a branch (read by
|
|
117
|
+
* The one PR that `input` names, or null. `input` is what a person typed,
|
|
118
|
+
* such as `42`, `#42`, `owner/name#42`, a URL or a branch (read by
|
|
119
|
+
* `parsePrRef`).
|
|
117
120
|
*
|
|
118
|
-
* Digits are a PR number first
|
|
121
|
+
* Digits are a PR number first. When no such PR comes back, they are tried
|
|
119
122
|
* as a branch. A branch gives its open PR, or else its newest closed or
|
|
120
123
|
* merged one, so a tool run after the merge still finds it. Fields default
|
|
121
124
|
* to {@link PR_LIST_FIELDS}.
|
|
@@ -137,12 +140,10 @@ export class Gh {
|
|
|
137
140
|
/**
|
|
138
141
|
* The open PR whose head exactly equals `branch`, or null.
|
|
139
142
|
*
|
|
140
|
-
* Defaults to {@link PR_REF_FIELDS}
|
|
141
|
-
* merge
|
|
142
|
-
* `isDraft`) in the
|
|
143
|
-
*
|
|
144
|
-
* separately would cost a second round trip for the common case where the
|
|
145
|
-
* caller already knows it wants that field up front.
|
|
143
|
+
* Defaults to {@link PR_REF_FIELDS}, so finding a PR does not make GitHub
|
|
144
|
+
* compute the merge state. Pass `opts.fields` to ask for more (such as
|
|
145
|
+
* `isDraft`) in the same call. That saves a second `prList` or `prView`
|
|
146
|
+
* call when the caller already knows it needs the field.
|
|
146
147
|
*/
|
|
147
148
|
openPrFor(branch, opts = {}) {
|
|
148
149
|
const rows = this.prList({
|
|
@@ -153,16 +154,16 @@ export class Gh {
|
|
|
153
154
|
return v.pickPrForBranch(rows.rows, branch);
|
|
154
155
|
}
|
|
155
156
|
/**
|
|
156
|
-
* {@link prView},
|
|
157
|
+
* {@link prView}, asked again until GitHub has computed the merge state.
|
|
157
158
|
*
|
|
158
|
-
* GitHub computes mergeability
|
|
159
|
-
* answers `UNKNOWN` while it runs. A caller that
|
|
160
|
-
*
|
|
161
|
-
* `attempts` times
|
|
162
|
-
* returned
|
|
163
|
-
*
|
|
159
|
+
* GitHub computes mergeability only when asked. The first query starts it
|
|
160
|
+
* and answers `UNKNOWN` while it runs. A caller that trusts that first
|
|
161
|
+
* answer misjudges every PR whose computation is slow. So this asks up to
|
|
162
|
+
* `attempts` times while the answer is `UNKNOWN`. The last answer is
|
|
163
|
+
* returned either way. `UNKNOWN` can be the final answer, and callers must
|
|
164
|
+
* still handle it.
|
|
164
165
|
*
|
|
165
|
-
* `sleep` is
|
|
166
|
+
* `sleep` is an option so a test does not spend real seconds waiting.
|
|
166
167
|
*/
|
|
167
168
|
prViewSettled(number, opts = {}) {
|
|
168
169
|
const attempts = Math.max(1, opts.attempts ?? 3);
|
|
@@ -182,15 +183,15 @@ export class Gh {
|
|
|
182
183
|
return this.read(v.prBody(number, this.target), opts.timeoutMs);
|
|
183
184
|
}
|
|
184
185
|
/**
|
|
185
|
-
* A REST GET through `gh api`. Never throws for a failed call, in any
|
|
186
|
-
*
|
|
186
|
+
* A REST GET through `gh api`. Never throws for a failed call, in any call
|
|
187
|
+
* style. Failure is `ok: false` on the returned {@link ApiResponse}.
|
|
187
188
|
*/
|
|
188
189
|
api(endpoint, opts = {}) {
|
|
189
190
|
return this.exec(v.api(endpoint, opts, this.target), opts.timeoutMs);
|
|
190
191
|
}
|
|
191
192
|
/**
|
|
192
|
-
* A GraphQL query
|
|
193
|
-
* `soft.graphql` gives null. See the `graphql` verb.
|
|
193
|
+
* A GraphQL query. Returns each page's `data`. Throws on a failed or partial
|
|
194
|
+
* result. `soft.graphql` gives null. See the `graphql` verb.
|
|
194
195
|
*
|
|
195
196
|
* @experimental
|
|
196
197
|
*/
|
|
@@ -205,7 +206,7 @@ export class Gh {
|
|
|
205
206
|
issueList(opts = {}) {
|
|
206
207
|
return this.read(v.issueList(opts, this.target), opts.timeoutMs);
|
|
207
208
|
}
|
|
208
|
-
/** One issue with its labels
|
|
209
|
+
/** One issue with its labels, or null when there is no such issue. Throws when gh fails otherwise. */
|
|
209
210
|
issueView(number, opts = {}) {
|
|
210
211
|
return this.exec(v.issueView(number, this.target), opts.timeoutMs);
|
|
211
212
|
}
|
|
@@ -226,22 +227,23 @@ export class Gh {
|
|
|
226
227
|
return this.exec(v.installed());
|
|
227
228
|
}
|
|
228
229
|
/**
|
|
229
|
-
* True iff `gh` holds credentials.
|
|
230
|
-
*
|
|
231
|
-
*
|
|
232
|
-
*
|
|
230
|
+
* True iff `gh` holds credentials. Call it on its own to report the two
|
|
231
|
+
* checks separately. "gh is missing" and "gh is not logged in" need
|
|
232
|
+
* different fixes. A report that merges them sends someone to install
|
|
233
|
+
* software they already have.
|
|
233
234
|
*/
|
|
234
235
|
authenticated() {
|
|
235
236
|
return this.authStatus().ok;
|
|
236
237
|
}
|
|
237
|
-
/** Login state and what `gh auth status` printed
|
|
238
|
+
/** Login state and what `gh auth status` printed. `authenticated()` is its `ok`. */
|
|
238
239
|
authStatus() {
|
|
239
240
|
return this.exec(v.authStatus(this.target));
|
|
240
241
|
}
|
|
241
242
|
/**
|
|
242
|
-
* True iff `gh` is installed
|
|
243
|
+
* True iff `gh` is installed and authenticated.
|
|
243
244
|
*
|
|
244
|
-
*
|
|
245
|
+
* Skips the auth check when `gh` is not installed, since there is nothing to
|
|
246
|
+
* ask.
|
|
245
247
|
*/
|
|
246
248
|
ready() {
|
|
247
249
|
return this.installed() && this.authenticated();
|
|
@@ -250,7 +252,7 @@ export class Gh {
|
|
|
250
252
|
* `{owner, repo}` parsed from the remote URL you pass, or null when it is
|
|
251
253
|
* null or names no project.
|
|
252
254
|
*
|
|
253
|
-
*
|
|
255
|
+
* It reads no git config, starts no process and does not ask GitHub.
|
|
254
256
|
*/
|
|
255
257
|
ownerRepo(remoteUrl) {
|
|
256
258
|
return remoteUrl === null ? null : parseOwnerRepo(remoteUrl);
|
|
@@ -264,16 +266,16 @@ export class Gh {
|
|
|
264
266
|
editPr(number, opts) {
|
|
265
267
|
this.exec(v.editPr(number, opts, this.target));
|
|
266
268
|
}
|
|
267
|
-
/** The PR's unified diff
|
|
269
|
+
/** The PR's unified diff. Throws the classified failure when gh cannot produce it. */
|
|
268
270
|
prDiff(number) {
|
|
269
271
|
return this.exec(v.prDiff(number, this.target));
|
|
270
272
|
}
|
|
271
|
-
/** Post one conversation comment on a PR
|
|
273
|
+
/** Post one conversation comment on a PR. Returns its URL ('' if gh printed none). */
|
|
272
274
|
prComment(number, body) {
|
|
273
275
|
return this.exec(v.prComment(number, body, this.target));
|
|
274
276
|
}
|
|
275
277
|
/**
|
|
276
|
-
* Create a `COMMENT` review with inline comments
|
|
278
|
+
* Create a `COMMENT` review with inline comments. Returns the review's URL ('' if none came back).
|
|
277
279
|
*
|
|
278
280
|
* @experimental
|
|
279
281
|
*/
|
|
@@ -293,14 +295,14 @@ export class Gh {
|
|
|
293
295
|
this.exec(v.prSetDraft(number, draft, this.target));
|
|
294
296
|
}
|
|
295
297
|
/**
|
|
296
|
-
* Rewrite one PR conversation comment's body. `commentId` is the numeric REST id
|
|
298
|
+
* Rewrite one PR conversation comment's body. `commentId` is the numeric REST id. Anything else throws `RangeError`.
|
|
297
299
|
*
|
|
298
300
|
* @experimental
|
|
299
301
|
*/
|
|
300
302
|
issueCommentEdit(commentId, body) {
|
|
301
303
|
this.exec(v.issueCommentEdit(commentId, body, this.target));
|
|
302
304
|
}
|
|
303
|
-
/** Merge a PR
|
|
305
|
+
/** Merge a PR. GitHub refuses when its head is no longer `opts.headSha`. */
|
|
304
306
|
prMerge(number, opts) {
|
|
305
307
|
this.exec(v.prMerge(number, opts, this.target));
|
|
306
308
|
}
|
|
@@ -318,8 +320,8 @@ export class Gh {
|
|
|
318
320
|
}
|
|
319
321
|
/**
|
|
320
322
|
* Swap an issue's label: remove `currentLabel` (when given) and add
|
|
321
|
-
* `newLabel`, in a single `gh issue edit` call
|
|
322
|
-
* or
|
|
323
|
+
* `newLabel`, in a single `gh issue edit` call. The issue is never left
|
|
324
|
+
* with neither label or both labels in between.
|
|
323
325
|
*/
|
|
324
326
|
setIssueLabel(number, currentLabel, newLabel) {
|
|
325
327
|
this.exec(v.setIssueLabel(number, currentLabel, newLabel, this.target));
|
|
@@ -337,9 +339,9 @@ function prForBranchOn(gh, branch, call) {
|
|
|
337
339
|
return v.branchPr(rows);
|
|
338
340
|
}
|
|
339
341
|
/**
|
|
340
|
-
* Block the calling thread.
|
|
341
|
-
*
|
|
342
|
-
*
|
|
342
|
+
* Block the calling thread. The synchronous client has no event loop to
|
|
343
|
+
* await on. The alternative is to make every caller async for one retry
|
|
344
|
+
* delay.
|
|
343
345
|
*/
|
|
344
346
|
function sleepSync(ms) {
|
|
345
347
|
Atomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, ms);
|
package/dist/types.d.ts
CHANGED
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* The GitHub model, typed.
|
|
3
3
|
*
|
|
4
|
-
* `gh` returns GraphQL-shaped JSON whose fields depend on what you asked for
|
|
5
|
-
*
|
|
6
|
-
* known". Absent and unknowable are the same answer to a caller
|
|
7
|
-
* them one
|
|
8
|
-
*
|
|
4
|
+
* `gh` returns GraphQL-shaped JSON whose fields depend on what you asked for.
|
|
5
|
+
* So every field here always has a value: a real one, or the value that means
|
|
6
|
+
* "not known". Absent and unknowable are the same answer to a caller. Giving
|
|
7
|
+
* them one value keeps a caller from reading a field it never requested as a
|
|
8
|
+
* fact.
|
|
9
9
|
*
|
|
10
10
|
* Most enums are open on purpose. GitHub adds members, and a client that
|
|
11
|
-
* crashes on an
|
|
12
|
-
*
|
|
13
|
-
*
|
|
11
|
+
* crashes on an unknown one is worse than a client that passes it on. Unions
|
|
12
|
+
* end in `(string & {})`, so a new value still types as the enum and the known
|
|
13
|
+
* members keep their autocomplete.
|
|
14
14
|
*
|
|
15
15
|
* Two are closed: {@link MergeableState} and {@link ReviewDecision}. Callers
|
|
16
16
|
* compare them member by member to decide whether to merge, so the parser
|
|
@@ -25,10 +25,10 @@ export type MergeableState = 'MERGEABLE' | 'CONFLICTING' | 'UNKNOWN';
|
|
|
25
25
|
/**
|
|
26
26
|
* The merge-button state.
|
|
27
27
|
*
|
|
28
|
-
* `BEHIND` only
|
|
29
|
-
*
|
|
30
|
-
* `
|
|
31
|
-
*
|
|
28
|
+
* `BEHIND` appears only when branch protection requires an up-to-date branch.
|
|
29
|
+
* Without that rule, a branch a hundred commits behind still reports `CLEAN`.
|
|
30
|
+
* So `BEHIND` is a hint that a branch is out of date, not a measure of it.
|
|
31
|
+
* Compute that from the commit graph.
|
|
32
32
|
*/
|
|
33
33
|
export type MergeStateStatus = 'BEHIND' | 'BLOCKED' | 'CLEAN' | 'DIRTY' | 'DRAFT' | 'HAS_HOOKS' | 'UNKNOWN' | 'UNSTABLE' | (string & {});
|
|
34
34
|
/** Where a pull request is in its life: open, closed without a merge, or merged. */
|
|
@@ -41,23 +41,22 @@ export type PullRequestState = 'OPEN' | 'CLOSED' | 'MERGED' | (string & {});
|
|
|
41
41
|
export type ReviewDecision = 'APPROVED' | 'CHANGES_REQUESTED' | 'REVIEW_REQUIRED' | null;
|
|
42
42
|
/** The state of one review. `PENDING` is a review its author has not submitted yet. */
|
|
43
43
|
export type ReviewState = 'APPROVED' | 'CHANGES_REQUESTED' | 'COMMENTED' | 'DISMISSED' | 'PENDING' | (string & {});
|
|
44
|
-
/** Who wrote something. `login` is normalized
|
|
44
|
+
/** Who wrote something. `login` is normalized: a `[bot]` suffix is stripped. */
|
|
45
45
|
export interface Actor {
|
|
46
46
|
login: string;
|
|
47
47
|
/** True when GitHub marks the account as a bot, or the login carried `[bot]`. */
|
|
48
48
|
isBot: boolean;
|
|
49
49
|
}
|
|
50
|
-
/** A repository label. `color` is hex digits such as `d73a4a
|
|
50
|
+
/** A repository label. `color` is hex digits such as `d73a4a`. A field the payload lacks is `''`. */
|
|
51
51
|
export interface Label {
|
|
52
52
|
name: string;
|
|
53
53
|
color: string;
|
|
54
54
|
description: string;
|
|
55
55
|
}
|
|
56
56
|
/**
|
|
57
|
-
* A GitHub issue,
|
|
58
|
-
* number,title,body,labels,state`.
|
|
59
|
-
*
|
|
60
|
-
* off an issue.
|
|
57
|
+
* A GitHub issue, from `gh issue list`/`gh issue view --json
|
|
58
|
+
* number,title,body,labels,state`. It has a small field set on purpose,
|
|
59
|
+
* because nothing here reads reviews, checks or comments on an issue.
|
|
61
60
|
*/
|
|
62
61
|
export interface IssueRow {
|
|
63
62
|
number: number;
|
|
@@ -69,22 +68,22 @@ export interface IssueRow {
|
|
|
69
68
|
/**
|
|
70
69
|
* How a finished check ended, as GitHub reports it. Null while the check is
|
|
71
70
|
* still running, and always null for a legacy status context. Read
|
|
72
|
-
* {@link CheckRun.verdict} for
|
|
71
|
+
* {@link CheckRun.verdict} for one answer that covers both node types.
|
|
73
72
|
*/
|
|
74
73
|
export type CheckConclusion = 'SUCCESS' | 'FAILURE' | 'NEUTRAL' | 'CANCELLED' | 'TIMED_OUT' | 'ACTION_REQUIRED' | 'SKIPPED' | 'STALE' | 'STARTUP_FAILURE' | (string & {}) | null;
|
|
75
|
-
/** One
|
|
74
|
+
/** One check from the status rollup, with GitHub's two node types mapped to one shape. */
|
|
76
75
|
export interface CheckRun {
|
|
77
76
|
/** A CheckRun's `name`, or a legacy StatusContext's `context`. */
|
|
78
77
|
name: string;
|
|
79
|
-
/** `QUEUED` / `IN_PROGRESS` / `COMPLETED
|
|
78
|
+
/** `QUEUED` / `IN_PROGRESS` / `COMPLETED`. Null for a status context. */
|
|
80
79
|
status: string | null;
|
|
81
80
|
conclusion: CheckConclusion;
|
|
82
81
|
/**
|
|
83
|
-
* The normalized verdict. A check still running is `pending`, not a pass
|
|
84
|
-
*
|
|
82
|
+
* The normalized verdict. A check still running is `pending`, not a pass.
|
|
83
|
+
* If "no failure yet" counted as green, a red build could merge.
|
|
85
84
|
*/
|
|
86
85
|
verdict: 'pending' | 'success' | 'failure' | 'neutral';
|
|
87
|
-
/** A CheckRun's `detailsUrl`, or a legacy StatusContext's `targetUrl
|
|
86
|
+
/** A CheckRun's `detailsUrl`, or a legacy StatusContext's `targetUrl`: where to read the log. Null when GitHub gives none. */
|
|
88
87
|
url: string | null;
|
|
89
88
|
}
|
|
90
89
|
/** One conversation comment on a pull request. */
|
|
@@ -114,7 +113,7 @@ export interface Review {
|
|
|
114
113
|
*
|
|
115
114
|
* Fields `gh` was not asked for come back at their "not known" value, so this
|
|
116
115
|
* type is safe to build from any field subset. `number` is the only field
|
|
117
|
-
* without one
|
|
116
|
+
* without one. A payload with no number is not a PR, and parsing returns null.
|
|
118
117
|
*/
|
|
119
118
|
export interface PullRequest {
|
|
120
119
|
number: number;
|
|
@@ -125,11 +124,11 @@ export interface PullRequest {
|
|
|
125
124
|
isDraft: boolean;
|
|
126
125
|
baseRefName: string;
|
|
127
126
|
headRefName: string;
|
|
128
|
-
/** Head commit sha, when requested
|
|
127
|
+
/** Head commit sha, when requested. Use it as the expected value for `--force-with-lease`. */
|
|
129
128
|
headRefOid: string | null;
|
|
130
129
|
/**
|
|
131
|
-
* True when the head branch
|
|
132
|
-
* base repository's `origin
|
|
130
|
+
* True when the head branch is in a fork. Its ref is then not on the
|
|
131
|
+
* base repository's `origin`. Fetch `refs/pull/<n>/head` instead.
|
|
133
132
|
*/
|
|
134
133
|
isCrossRepository: boolean;
|
|
135
134
|
mergeable: MergeableState;
|
|
@@ -152,7 +151,7 @@ export interface OwnerRepo {
|
|
|
152
151
|
/** Who can see a repository. */
|
|
153
152
|
export type RepositoryVisibility = 'PUBLIC' | 'PRIVATE' | 'INTERNAL' | (string & {});
|
|
154
153
|
/**
|
|
155
|
-
* A repository,
|
|
154
|
+
* A repository, from `gh repo list`/`gh repo view --json`. A field not asked
|
|
156
155
|
* for comes back at its "not known" value. `nameWithOwner` is the only field
|
|
157
156
|
* without one: a row without it is dropped.
|
|
158
157
|
*/
|
|
@@ -162,15 +161,15 @@ export interface Repository {
|
|
|
162
161
|
owner: string;
|
|
163
162
|
name: string;
|
|
164
163
|
description: string;
|
|
165
|
-
/** The default branch
|
|
164
|
+
/** The default branch. Null when not asked for, or when the repository is empty. */
|
|
166
165
|
defaultBranch: string | null;
|
|
167
166
|
visibility: RepositoryVisibility | null;
|
|
168
167
|
isArchived: boolean;
|
|
169
168
|
url: string;
|
|
170
169
|
}
|
|
171
170
|
/**
|
|
172
|
-
* One pull request found by `gh search prs`. Search has its own field set
|
|
173
|
-
*
|
|
171
|
+
* One pull request found by `gh search prs`. Search has its own field set.
|
|
172
|
+
* It names the repository but carries no head or base branch, so this is not
|
|
174
173
|
* a {@link PullRequest}. `state` is upper-cased to match `PullRequest`.
|
|
175
174
|
*/
|
|
176
175
|
export interface PrSearchHit {
|
package/dist/types.js
CHANGED
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* The GitHub model, typed.
|
|
3
3
|
*
|
|
4
|
-
* `gh` returns GraphQL-shaped JSON whose fields depend on what you asked for
|
|
5
|
-
*
|
|
6
|
-
* known". Absent and unknowable are the same answer to a caller
|
|
7
|
-
* them one
|
|
8
|
-
*
|
|
4
|
+
* `gh` returns GraphQL-shaped JSON whose fields depend on what you asked for.
|
|
5
|
+
* So every field here always has a value: a real one, or the value that means
|
|
6
|
+
* "not known". Absent and unknowable are the same answer to a caller. Giving
|
|
7
|
+
* them one value keeps a caller from reading a field it never requested as a
|
|
8
|
+
* fact.
|
|
9
9
|
*
|
|
10
10
|
* Most enums are open on purpose. GitHub adds members, and a client that
|
|
11
|
-
* crashes on an
|
|
12
|
-
*
|
|
13
|
-
*
|
|
11
|
+
* crashes on an unknown one is worse than a client that passes it on. Unions
|
|
12
|
+
* end in `(string & {})`, so a new value still types as the enum and the known
|
|
13
|
+
* members keep their autocomplete.
|
|
14
14
|
*
|
|
15
15
|
* Two are closed: {@link MergeableState} and {@link ReviewDecision}. Callers
|
|
16
16
|
* compare them member by member to decide whether to merge, so the parser
|