@osdlc/typed-gh 0.7.0 → 0.9.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/CHANGELOG.md +25 -0
- package/CONTRIBUTING.md +1 -1
- package/README.md +116 -92
- package/SECURITY.md +4 -4
- package/dist/async.d.ts +28 -27
- package/dist/async.js +37 -43
- 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 +14 -14
- package/dist/index.js +15 -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 +36 -0
- package/dist/run.js +48 -0
- package/dist/sync.d.ts +66 -64
- package/dist/sync.js +71 -78
- package/dist/types.d.ts +31 -32
- package/dist/types.js +8 -8
- package/dist/verbs.d.ts +122 -122
- package/dist/verbs.js +128 -112
- package/package.json +5 -5
package/dist/sync.js
CHANGED
|
@@ -1,24 +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
|
-
import { runCheckedGh,
|
|
19
|
+
import { runCheckedGh, softSync, triedSync } from "./doors.js";
|
|
20
|
+
import { runVerb } from "./run.js";
|
|
19
21
|
import * as v from "./verbs.js";
|
|
20
22
|
import { ownerRepoSlug, parseOwnerRepo, parsePrRef } from "./repo.js";
|
|
21
|
-
/**
|
|
23
|
+
/** The default factory: real runners that use `spawnSync`. */
|
|
22
24
|
export const defaultRunnerFactory = spawnRunner;
|
|
23
25
|
/** How long to wait between merge-state retries, in milliseconds. */
|
|
24
26
|
const MERGE_STATE_RETRY_DELAY_MS = 1_500;
|
|
@@ -62,69 +64,61 @@ export class Gh {
|
|
|
62
64
|
}
|
|
63
65
|
/**
|
|
64
66
|
* The whole surface again, returning a `Result<T, GhFailure>` instead of
|
|
65
|
-
* throwing
|
|
67
|
+
* throwing. `gh.try.prList()` is `{ ok: true, value } | { ok: false, error }`.
|
|
66
68
|
* A query for one thing that finds nothing is `ok: true` with `null`. See
|
|
67
69
|
* `./doors.ts`.
|
|
68
70
|
*
|
|
69
|
-
* The type leaves out
|
|
70
|
-
* 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.
|
|
71
74
|
*/
|
|
72
75
|
get try() {
|
|
73
76
|
return (this.tried ??= triedSync(this));
|
|
74
77
|
}
|
|
75
78
|
/**
|
|
76
79
|
* Each query again, returning `null` instead of throwing when `gh` fails. A
|
|
77
|
-
* mutation has no soft form. Do not
|
|
78
|
-
*
|
|
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
|
|
79
82
|
* `try` where the difference matters.
|
|
80
83
|
*/
|
|
81
84
|
get soft() {
|
|
82
85
|
return (this.softened ??= softSync(this));
|
|
83
86
|
}
|
|
84
|
-
// ──
|
|
85
|
-
/**
|
|
87
|
+
// ── raw calls ─────────────────────────────────────────────────────────────
|
|
88
|
+
/** Run any `gh` call and return the result, whatever the exit code. */
|
|
86
89
|
raw(argv, opts = {}) {
|
|
87
90
|
return this.runner.run(argv, { cwd: this.cwd, ...opts });
|
|
88
91
|
}
|
|
89
|
-
/**
|
|
92
|
+
/** Run any `gh` call. Throws the classified failure on a non-zero exit. */
|
|
90
93
|
rawChecked(argv, opts = {}) {
|
|
91
94
|
return runCheckedGh(this.runner, argv, { cwd: this.cwd, ...opts });
|
|
92
95
|
}
|
|
93
|
-
/** Run one verb from the table,
|
|
96
|
+
/** Run one verb from the table, checked or unchecked as the verb says. */
|
|
94
97
|
exec(verb, timeoutMs) {
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
if (verb.env !== undefined)
|
|
99
|
-
opts.env = verb.env;
|
|
100
|
-
if (timeoutMs !== undefined)
|
|
101
|
-
opts.timeoutMs = timeoutMs;
|
|
102
|
-
const result = verb.checked
|
|
103
|
-
? runCheckedGh(this.runner, verb.argv, opts)
|
|
104
|
-
: this.runner.run(verb.argv, opts);
|
|
105
|
-
return settle(verb, result, this.runner.binary);
|
|
106
|
-
}
|
|
107
|
-
/** {@link exec} for a verb that never answers `null` as a value: a failed or unreadable run throws. */
|
|
98
|
+
return runVerb(verb, this.runner, { cwd: this.cwd, timeoutMs });
|
|
99
|
+
}
|
|
100
|
+
/** {@link exec} for a verb that never returns `null` as a value. A failed or unreadable run throws. */
|
|
108
101
|
read(verb, timeoutMs) {
|
|
109
102
|
return this.exec(verb, timeoutMs);
|
|
110
103
|
}
|
|
111
104
|
// ── queries ───────────────────────────────────────────────────────────────
|
|
112
|
-
/** Pull requests matching `opts`. Throws when gh fails
|
|
105
|
+
/** Pull requests matching `opts`. Throws when gh fails. `soft.prList` gives null instead. */
|
|
113
106
|
prList(opts = {}) {
|
|
114
107
|
return this.read(v.prList(opts, this.target), opts.timeoutMs);
|
|
115
108
|
}
|
|
116
109
|
/**
|
|
117
|
-
* One PR by number, branch or URL, with the
|
|
118
|
-
* 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.
|
|
119
112
|
*/
|
|
120
113
|
prView(ref, opts = {}) {
|
|
121
114
|
return this.exec(v.prView(ref, opts.fields ?? v.PR_VIEW_FIELDS, this.target), opts.timeoutMs);
|
|
122
115
|
}
|
|
123
116
|
/**
|
|
124
|
-
* The one PR that `input` names, or null
|
|
125
|
-
* `#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`).
|
|
126
120
|
*
|
|
127
|
-
* Digits are a PR number first
|
|
121
|
+
* Digits are a PR number first. When no such PR comes back, they are tried
|
|
128
122
|
* as a branch. A branch gives its open PR, or else its newest closed or
|
|
129
123
|
* merged one, so a tool run after the merge still finds it. Fields default
|
|
130
124
|
* to {@link PR_LIST_FIELDS}.
|
|
@@ -146,12 +140,10 @@ export class Gh {
|
|
|
146
140
|
/**
|
|
147
141
|
* The open PR whose head exactly equals `branch`, or null.
|
|
148
142
|
*
|
|
149
|
-
* Defaults to {@link PR_REF_FIELDS}
|
|
150
|
-
* merge
|
|
151
|
-
* `isDraft`) in the
|
|
152
|
-
*
|
|
153
|
-
* separately would cost a second round trip for the common case where the
|
|
154
|
-
* 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.
|
|
155
147
|
*/
|
|
156
148
|
openPrFor(branch, opts = {}) {
|
|
157
149
|
const rows = this.prList({
|
|
@@ -162,16 +154,16 @@ export class Gh {
|
|
|
162
154
|
return v.pickPrForBranch(rows.rows, branch);
|
|
163
155
|
}
|
|
164
156
|
/**
|
|
165
|
-
* {@link prView},
|
|
157
|
+
* {@link prView}, asked again until GitHub has computed the merge state.
|
|
166
158
|
*
|
|
167
|
-
* GitHub computes mergeability
|
|
168
|
-
* answers `UNKNOWN` while it runs. A caller that
|
|
169
|
-
*
|
|
170
|
-
* `attempts` times
|
|
171
|
-
* returned
|
|
172
|
-
*
|
|
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.
|
|
173
165
|
*
|
|
174
|
-
* `sleep` is
|
|
166
|
+
* `sleep` is an option so a test does not spend real seconds waiting.
|
|
175
167
|
*/
|
|
176
168
|
prViewSettled(number, opts = {}) {
|
|
177
169
|
const attempts = Math.max(1, opts.attempts ?? 3);
|
|
@@ -191,15 +183,15 @@ export class Gh {
|
|
|
191
183
|
return this.read(v.prBody(number, this.target), opts.timeoutMs);
|
|
192
184
|
}
|
|
193
185
|
/**
|
|
194
|
-
* A REST GET through `gh api`. Never throws for a failed call, in any
|
|
195
|
-
*
|
|
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}.
|
|
196
188
|
*/
|
|
197
189
|
api(endpoint, opts = {}) {
|
|
198
190
|
return this.exec(v.api(endpoint, opts, this.target), opts.timeoutMs);
|
|
199
191
|
}
|
|
200
192
|
/**
|
|
201
|
-
* A GraphQL query
|
|
202
|
-
* `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.
|
|
203
195
|
*
|
|
204
196
|
* @experimental
|
|
205
197
|
*/
|
|
@@ -214,7 +206,7 @@ export class Gh {
|
|
|
214
206
|
issueList(opts = {}) {
|
|
215
207
|
return this.read(v.issueList(opts, this.target), opts.timeoutMs);
|
|
216
208
|
}
|
|
217
|
-
/** One issue with its labels
|
|
209
|
+
/** One issue with its labels, or null when there is no such issue. Throws when gh fails otherwise. */
|
|
218
210
|
issueView(number, opts = {}) {
|
|
219
211
|
return this.exec(v.issueView(number, this.target), opts.timeoutMs);
|
|
220
212
|
}
|
|
@@ -235,22 +227,23 @@ export class Gh {
|
|
|
235
227
|
return this.exec(v.installed());
|
|
236
228
|
}
|
|
237
229
|
/**
|
|
238
|
-
* True iff `gh` holds credentials.
|
|
239
|
-
*
|
|
240
|
-
*
|
|
241
|
-
*
|
|
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.
|
|
242
234
|
*/
|
|
243
235
|
authenticated() {
|
|
244
236
|
return this.authStatus().ok;
|
|
245
237
|
}
|
|
246
|
-
/** Login state and what `gh auth status` printed
|
|
238
|
+
/** Login state and what `gh auth status` printed. `authenticated()` is its `ok`. */
|
|
247
239
|
authStatus() {
|
|
248
240
|
return this.exec(v.authStatus(this.target));
|
|
249
241
|
}
|
|
250
242
|
/**
|
|
251
|
-
* True iff `gh` is installed
|
|
243
|
+
* True iff `gh` is installed and authenticated.
|
|
252
244
|
*
|
|
253
|
-
*
|
|
245
|
+
* Skips the auth check when `gh` is not installed, since there is nothing to
|
|
246
|
+
* ask.
|
|
254
247
|
*/
|
|
255
248
|
ready() {
|
|
256
249
|
return this.installed() && this.authenticated();
|
|
@@ -259,7 +252,7 @@ export class Gh {
|
|
|
259
252
|
* `{owner, repo}` parsed from the remote URL you pass, or null when it is
|
|
260
253
|
* null or names no project.
|
|
261
254
|
*
|
|
262
|
-
*
|
|
255
|
+
* It reads no git config, starts no process and does not ask GitHub.
|
|
263
256
|
*/
|
|
264
257
|
ownerRepo(remoteUrl) {
|
|
265
258
|
return remoteUrl === null ? null : parseOwnerRepo(remoteUrl);
|
|
@@ -273,16 +266,16 @@ export class Gh {
|
|
|
273
266
|
editPr(number, opts) {
|
|
274
267
|
this.exec(v.editPr(number, opts, this.target));
|
|
275
268
|
}
|
|
276
|
-
/** The PR's unified diff
|
|
269
|
+
/** The PR's unified diff. Throws the classified failure when gh cannot produce it. */
|
|
277
270
|
prDiff(number) {
|
|
278
271
|
return this.exec(v.prDiff(number, this.target));
|
|
279
272
|
}
|
|
280
|
-
/** Post one conversation comment on a PR
|
|
273
|
+
/** Post one conversation comment on a PR. Returns its URL ('' if gh printed none). */
|
|
281
274
|
prComment(number, body) {
|
|
282
275
|
return this.exec(v.prComment(number, body, this.target));
|
|
283
276
|
}
|
|
284
277
|
/**
|
|
285
|
-
* Create a `COMMENT` review with inline comments
|
|
278
|
+
* Create a `COMMENT` review with inline comments. Returns the review's URL ('' if none came back).
|
|
286
279
|
*
|
|
287
280
|
* @experimental
|
|
288
281
|
*/
|
|
@@ -302,14 +295,14 @@ export class Gh {
|
|
|
302
295
|
this.exec(v.prSetDraft(number, draft, this.target));
|
|
303
296
|
}
|
|
304
297
|
/**
|
|
305
|
-
* 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`.
|
|
306
299
|
*
|
|
307
300
|
* @experimental
|
|
308
301
|
*/
|
|
309
302
|
issueCommentEdit(commentId, body) {
|
|
310
303
|
this.exec(v.issueCommentEdit(commentId, body, this.target));
|
|
311
304
|
}
|
|
312
|
-
/** Merge a PR
|
|
305
|
+
/** Merge a PR. GitHub refuses when its head is no longer `opts.headSha`. */
|
|
313
306
|
prMerge(number, opts) {
|
|
314
307
|
this.exec(v.prMerge(number, opts, this.target));
|
|
315
308
|
}
|
|
@@ -327,8 +320,8 @@ export class Gh {
|
|
|
327
320
|
}
|
|
328
321
|
/**
|
|
329
322
|
* Swap an issue's label: remove `currentLabel` (when given) and add
|
|
330
|
-
* `newLabel`, in a single `gh issue edit` call
|
|
331
|
-
* or
|
|
323
|
+
* `newLabel`, in a single `gh issue edit` call. The issue is never left
|
|
324
|
+
* with neither label or both labels in between.
|
|
332
325
|
*/
|
|
333
326
|
setIssueLabel(number, currentLabel, newLabel) {
|
|
334
327
|
this.exec(v.setIssueLabel(number, currentLabel, newLabel, this.target));
|
|
@@ -346,9 +339,9 @@ function prForBranchOn(gh, branch, call) {
|
|
|
346
339
|
return v.branchPr(rows);
|
|
347
340
|
}
|
|
348
341
|
/**
|
|
349
|
-
* Block the calling thread.
|
|
350
|
-
*
|
|
351
|
-
*
|
|
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.
|
|
352
345
|
*/
|
|
353
346
|
function sleepSync(ms) {
|
|
354
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
|