pr-shepherd 0.33.0 → 0.35.0
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/.claude-plugin/plugin.json +3 -2
- package/.grok-plugin/marketplace.json +17 -0
- package/README.md +63 -41
- package/bin/api.d.mts +80 -0
- package/bin/api.mjs +236 -0
- package/bin/checks/classify.d.mts +41 -0
- package/bin/checks/startup-failures.d.mts +2 -0
- package/bin/checks/superseded.d.mts +21 -0
- package/bin/checks/triage.d.mts +4 -0
- package/bin/classify/apply.d.mts +18 -0
- package/bin/classify/apply.mjs +4 -0
- package/bin/classify/loader.d.mts +10 -0
- package/bin/classify/types.d.mts +35 -0
- package/bin/cli/args.d.mts +18 -0
- package/bin/cli/clean-formatter.d.mts +2 -0
- package/bin/cli/default-poll.d.mts +2 -0
- package/bin/cli/default-poll.mjs +2 -1
- package/bin/cli/duration-flag.d.mts +2 -0
- package/bin/cli/duration-flag.mjs +5 -4
- package/bin/cli/duration.d.mts +13 -0
- package/bin/cli/{exit-codes.mjs → duration.mjs} +0 -26
- package/bin/cli/fence.d.mts +1 -0
- package/bin/cli/fix-formatter-extra.d.mts +3 -0
- package/bin/cli/fix-formatter.d.mts +2 -0
- package/bin/cli/fix-formatter.mjs +6 -6
- package/bin/cli/formatters.d.mts +7 -0
- package/bin/cli/handlers.d.mts +4 -0
- package/bin/cli/handlers.mjs +20 -18
- package/bin/cli/help-command-pages.d.mts +231 -0
- package/bin/cli/help-command-pages.mjs +116 -72
- package/bin/cli/help-iterate-poll-pages.d.mts +4 -0
- package/bin/cli/help-iterate-poll-pages.mjs +74 -0
- package/bin/cli/help-log-file-page.d.mts +1 -0
- package/bin/cli/help-top-page.d.mts +1 -0
- package/bin/cli/help-top-page.mjs +22 -20
- package/bin/cli/help.d.mts +236 -0
- package/bin/cli/help.mjs +17 -0
- package/bin/cli/iterate-emitter.d.mts +8 -0
- package/bin/cli/iterate-emitter.mjs +2 -2
- package/bin/cli/iterate-flags.d.mts +11 -0
- package/bin/cli/iterate-flags.mjs +1 -1
- package/bin/cli/iterate-formatter.d.mts +19 -0
- package/bin/cli/iterate-instructions.d.mts +6 -0
- package/bin/cli/iterate-lean.d.mts +12 -0
- package/bin/cli/journal-formatter.d.mts +2 -0
- package/bin/cli/journal-formatter.mjs +15 -0
- package/bin/cli/journal-handler.d.mts +1 -0
- package/bin/cli/journal-handler.mjs +13 -25
- package/bin/cli/list-formatters.d.mts +76 -0
- package/bin/cli/list-formatters.mjs +9 -9
- package/bin/cli/mark-files-as-viewed-flags.d.mts +11 -0
- package/bin/cli/mark-files-as-viewed-formatter.d.mts +2 -0
- package/bin/cli/mutate-formatter.d.mts +2 -0
- package/bin/cli/poll-handler.d.mts +1 -0
- package/bin/cli/poll-handler.mjs +3 -3
- package/bin/cli/resolve-validators.d.mts +3 -0
- package/bin/cli/resolve-validators.mjs +6 -5
- package/bin/cli/runner.d.mts +7 -0
- package/bin/cli/suggestion-renderer.d.mts +3 -0
- package/bin/cli/validate-default-args.d.mts +6 -0
- package/bin/cli-parser.d.mts +2 -0
- package/bin/cli-parser.mjs +77 -20
- package/bin/commands/check-annotations.d.mts +5 -0
- package/bin/commands/check-status.d.mts +3 -0
- package/bin/commands/check-terminal-report.d.mts +5 -0
- package/bin/commands/check.d.mts +6 -0
- package/bin/commands/check.mjs +4 -2
- package/bin/commands/clean.d.mts +21 -0
- package/bin/commands/commit-suggestion-instruction.d.mts +8 -0
- package/bin/commands/commit-suggestion-instruction.mjs +3 -3
- package/bin/commands/commit-suggestion.d.mts +8 -0
- package/bin/commands/commit-suggestion.mjs +28 -26
- package/bin/commands/iterate/check-instructions.d.mts +16 -0
- package/bin/commands/iterate/check-instructions.mjs +3 -3
- package/bin/commands/iterate/classify.d.mts +18 -0
- package/bin/commands/iterate/classify.mjs +4 -4
- package/bin/commands/iterate/escalate.d.mts +31 -0
- package/bin/commands/iterate/escalate.mjs +7 -4
- package/bin/commands/iterate/fix-code.d.mts +25 -0
- package/bin/commands/iterate/helpers.d.mts +13 -0
- package/bin/commands/iterate/helpers.mjs +4 -1
- package/bin/commands/iterate/index.d.mts +2 -0
- package/bin/commands/iterate/index.mjs +10 -5
- package/bin/commands/iterate/render.d.mts +5 -0
- package/bin/commands/iterate/render.mjs +8 -6
- package/bin/commands/iterate/reruns.d.mts +20 -0
- package/bin/commands/iterate/stall.d.mts +6 -0
- package/bin/commands/journal/index.d.mts +14 -0
- package/bin/commands/journal/index.mjs +1 -0
- package/bin/commands/journal/transform.d.mts +22 -0
- package/bin/commands/log-file.d.mts +5 -0
- package/bin/commands/mark-files-as-viewed.d.mts +26 -0
- package/bin/commands/mark-files-as-viewed.mjs +8 -5
- package/bin/commands/poll.d.mts +10 -0
- package/bin/commands/poll.mjs +1 -0
- package/bin/commands/ready-delay.d.mts +29 -0
- package/bin/commands/ready-mergeability.d.mts +15 -0
- package/bin/commands/resolve-mutate.d.mts +4 -0
- package/bin/commands/resolve-mutate.mjs +3 -1
- package/bin/commands/resolve.d.mts +4 -0
- package/bin/commands/shepherd-journal.d.mts +7 -0
- package/bin/commands/shepherd-journal.mjs +2 -2
- package/bin/comments/authors.d.mts +14 -0
- package/bin/comments/marker.d.mts +2 -0
- package/bin/comments/minimize-policy.d.mts +4 -0
- package/bin/comments/pending-ops.d.mts +15 -0
- package/bin/comments/rate-limit.d.mts +18 -0
- package/bin/comments/resolve.d.mts +34 -0
- package/bin/comments/resolve.mjs +1 -0
- package/bin/comments/review-thread-markers.d.mts +8 -0
- package/bin/comments/review-visibility.d.mts +28 -0
- package/bin/comments/sha-poll.d.mts +2 -0
- package/bin/comments/thread-visibility.d.mts +11 -0
- package/bin/comments/visible-comments.d.mts +11 -0
- package/bin/config/load.d.mts +60 -0
- package/bin/config/load.mjs +72 -1
- package/bin/config.json +0 -2
- package/bin/execution-context.d.mts +9 -0
- package/bin/execution-context.mjs +19 -0
- package/bin/exit-codes.d.mts +51 -0
- package/bin/exit-codes.mjs +74 -0
- package/bin/github/activity.d.mts +3 -0
- package/bin/github/activity.mjs +7 -0
- package/bin/github/batch-parser-helpers.d.mts +22 -0
- package/bin/github/batch-parsers.d.mts +3 -0
- package/bin/github/batch-parsers.mjs +6 -0
- package/bin/github/batch-raw-types.d.mts +207 -0
- package/bin/github/batch-response.d.mts +4 -0
- package/bin/github/batch-response.mjs +8 -3
- package/bin/github/batch.d.mts +22 -0
- package/bin/github/branch-protection.d.mts +3 -0
- package/bin/github/check-annotations.d.mts +2 -0
- package/bin/github/client.d.mts +46 -0
- package/bin/github/client.mjs +7 -2
- package/bin/github/errors.d.mts +25 -0
- package/bin/github/errors.mjs +26 -2
- package/bin/github/gql/batch-pr.gql +5 -0
- package/bin/github/gql/review-thread-comments.gql +1 -0
- package/bin/github/graphql-http.d.mts +19 -0
- package/bin/github/graphql-response.d.mts +7 -0
- package/bin/github/graphql-response.mjs +5 -0
- package/bin/github/http-auth.d.mts +4 -0
- package/bin/github/http-auth.mjs +2 -1
- package/bin/github/http-request.d.mts +7 -0
- package/bin/github/http-utils.d.mts +11 -0
- package/bin/github/http.d.mts +5 -0
- package/bin/github/pagination.d.mts +45 -0
- package/bin/github/queries.d.mts +24 -0
- package/bin/github/rest-http.d.mts +2 -0
- package/bin/github/rest-http.mjs +19 -5
- package/bin/github/thread-comments.d.mts +2 -0
- package/bin/index.d.mts +10 -0
- package/bin/index.mjs +3 -2
- package/bin/log/log-file.d.mts +28 -0
- package/bin/log/session.d.mts +31 -0
- package/bin/log/setup.d.mts +6 -0
- package/bin/mcp/index.d.mts +5 -0
- package/bin/mcp/index.mjs +8 -0
- package/bin/mcp/server.d.mts +8 -0
- package/bin/mcp/server.mjs +157 -0
- package/bin/mcp-stdio.d.mts +2 -0
- package/bin/mcp-stdio.mjs +7 -0
- package/bin/merge-status/derive.d.mts +19 -0
- package/bin/reporters/agent.d.mts +23 -0
- package/bin/reporters/agent.mjs +3 -0
- package/bin/state/base.d.mts +1 -0
- package/bin/state/bot-cr-seen.d.mts +51 -0
- package/bin/state/bot-cr-seen.mjs +1 -1
- package/bin/state/fix-attempts.d.mts +27 -0
- package/bin/state/iterate-stall.d.mts +27 -0
- package/bin/state/seen-comments.d.mts +62 -0
- package/bin/suggestions/extract.d.mts +8 -0
- package/bin/suggestions/parse.d.mts +48 -0
- package/bin/suggestions/patch.d.mts +14 -0
- package/bin/threads/transcript.d.mts +14 -0
- package/bin/threads/transcript.mjs +4 -0
- package/bin/types/activity.d.mts +30 -0
- package/bin/types/agent-thread.d.mts +9 -0
- package/bin/types/check-annotations.d.mts +14 -0
- package/bin/types/check-classification.d.mts +19 -0
- package/bin/types/github.d.mts +139 -0
- package/bin/types/iterate.d.mts +157 -0
- package/bin/types/protected-run.d.mts +6 -0
- package/bin/types/report.d.mts +176 -0
- package/bin/types/review-thread.d.mts +12 -0
- package/bin/types.d.mts +9 -0
- package/bin/util/markdown.d.mts +1 -0
- package/bin/util/path-segment.d.mts +2 -0
- package/bin/util/sleep.d.mts +1 -0
- package/bin/util/worktree.d.mts +9 -0
- package/bin/util/worktree.mjs +4 -1
- package/package.json +51 -37
- package/plugins/pr-shepherd/.codex-plugin/plugin.json +3 -2
- package/plugins/pr-shepherd/.codex.mcp.json +8 -0
- package/plugins/pr-shepherd/.mcp.json +6 -0
- package/plugins/pr-shepherd/skills/mark-files-as-viewed/SKILL.md +5 -19
- package/plugins/pr-shepherd/skills/pr-shepherd/SKILL.md +6 -15
- package/src/classify/types.mts +12 -0
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Process exit codes for the pr-shepherd CLI.
|
|
3
|
+
*
|
|
4
|
+
* Three bands:
|
|
5
|
+
* 0 done — shepherd finished and the PR is in a good terminal state
|
|
6
|
+
* 10-19 shepherd RAN successfully; the code reports PR state
|
|
7
|
+
* 64-78 shepherd FAILED (BSD `sysexits.h` codes)
|
|
8
|
+
*
|
|
9
|
+
* Caller rule: `$? >= 64` means shepherd itself failed. `0` or `10-19` means it
|
|
10
|
+
* ran to completion and is reporting PR state. See docs/exit-codes.md.
|
|
11
|
+
*/
|
|
12
|
+
import type { IterateResult } from "./types.mts";
|
|
13
|
+
export declare const EXIT: Readonly<{
|
|
14
|
+
/** `cancel` + `merged` or `ready-delay-elapsed` — shepherd finished cleanly. */
|
|
15
|
+
readonly OK: 0;
|
|
16
|
+
/** Nothing to do yet; CI still in progress. */
|
|
17
|
+
readonly WAIT: 10;
|
|
18
|
+
/** Draft PR converted to ready for review. */
|
|
19
|
+
readonly MARK_READY: 11;
|
|
20
|
+
/** Agent work required. */
|
|
21
|
+
readonly FIX_CODE: 12;
|
|
22
|
+
/** Human attention required. */
|
|
23
|
+
readonly ESCALATE: 13;
|
|
24
|
+
/** `cancel` + `closed` — PR closed without merging. */
|
|
25
|
+
readonly CLOSED: 14;
|
|
26
|
+
/** Bad/unknown flag, unknown subcommand, missing required arg, invalid duration. */
|
|
27
|
+
readonly USAGE: 64;
|
|
28
|
+
/** Malformed caller data: bad `--require-sha`, `PRRC_*` IDs, bad repo string. */
|
|
29
|
+
readonly DATAERR: 65;
|
|
30
|
+
/** Input file/stdin could not be read. */
|
|
31
|
+
readonly NOINPUT: 66;
|
|
32
|
+
/** Precondition unmet: no open PR for branch, thread not eligible, unclassified 4xx. */
|
|
33
|
+
readonly UNAVAILABLE: 69;
|
|
34
|
+
/** Unexpected/unclassified internal error — the fallback. */
|
|
35
|
+
readonly SOFTWARE: 70;
|
|
36
|
+
/** Retryable GitHub failure: 429, 5xx, rate limit exhausted, `Retry-After` present. */
|
|
37
|
+
readonly TEMPFAIL: 75;
|
|
38
|
+
/** GitHub 401/403 — missing token or insufficient PAT scopes. */
|
|
39
|
+
readonly NOPERM: 77;
|
|
40
|
+
/** `.pr-shepherdrc.yml` validation failure. */
|
|
41
|
+
readonly CONFIG: 78;
|
|
42
|
+
}>;
|
|
43
|
+
/** An error that carries its own exit code, so the top-level handler doesn't have to guess. */
|
|
44
|
+
export declare class ShepherdError extends Error {
|
|
45
|
+
readonly exitCode: number;
|
|
46
|
+
constructor(message: string, exitCode: number, opts?: {
|
|
47
|
+
cause?: unknown;
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
export declare function iterateResultToExitCode(result: IterateResult): number;
|
|
51
|
+
export declare function errorToExitCode(err: unknown): number;
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Process exit codes for the pr-shepherd CLI.
|
|
3
|
+
*
|
|
4
|
+
* Three bands:
|
|
5
|
+
* 0 done — shepherd finished and the PR is in a good terminal state
|
|
6
|
+
* 10-19 shepherd RAN successfully; the code reports PR state
|
|
7
|
+
* 64-78 shepherd FAILED (BSD `sysexits.h` codes)
|
|
8
|
+
*
|
|
9
|
+
* Caller rule: `$? >= 64` means shepherd itself failed. `0` or `10-19` means it
|
|
10
|
+
* ran to completion and is reporting PR state. See docs/exit-codes.md.
|
|
11
|
+
*/
|
|
12
|
+
export const EXIT = Object.freeze({
|
|
13
|
+
/** `cancel` + `merged` or `ready-delay-elapsed` — shepherd finished cleanly. */
|
|
14
|
+
OK: 0,
|
|
15
|
+
/** Nothing to do yet; CI still in progress. */
|
|
16
|
+
WAIT: 10,
|
|
17
|
+
/** Draft PR converted to ready for review. */
|
|
18
|
+
MARK_READY: 11,
|
|
19
|
+
/** Agent work required. */
|
|
20
|
+
FIX_CODE: 12,
|
|
21
|
+
/** Human attention required. */
|
|
22
|
+
ESCALATE: 13,
|
|
23
|
+
/** `cancel` + `closed` — PR closed without merging. */
|
|
24
|
+
CLOSED: 14,
|
|
25
|
+
/** Bad/unknown flag, unknown subcommand, missing required arg, invalid duration. */
|
|
26
|
+
USAGE: 64,
|
|
27
|
+
/** Malformed caller data: bad `--require-sha`, `PRRC_*` IDs, bad repo string. */
|
|
28
|
+
DATAERR: 65,
|
|
29
|
+
/** Input file/stdin could not be read. */
|
|
30
|
+
NOINPUT: 66,
|
|
31
|
+
/** Precondition unmet: no open PR for branch, thread not eligible, unclassified 4xx. */
|
|
32
|
+
UNAVAILABLE: 69,
|
|
33
|
+
/** Unexpected/unclassified internal error — the fallback. */
|
|
34
|
+
SOFTWARE: 70,
|
|
35
|
+
/** Retryable GitHub failure: 429, 5xx, rate limit exhausted, `Retry-After` present. */
|
|
36
|
+
TEMPFAIL: 75,
|
|
37
|
+
/** GitHub 401/403 — missing token or insufficient PAT scopes. */
|
|
38
|
+
NOPERM: 77,
|
|
39
|
+
/** `.pr-shepherdrc.yml` validation failure. */
|
|
40
|
+
CONFIG: 78,
|
|
41
|
+
});
|
|
42
|
+
/** An error that carries its own exit code, so the top-level handler doesn't have to guess. */
|
|
43
|
+
export class ShepherdError extends Error {
|
|
44
|
+
exitCode;
|
|
45
|
+
constructor(message, exitCode, opts) {
|
|
46
|
+
super(message, opts);
|
|
47
|
+
this.name = "ShepherdError";
|
|
48
|
+
this.exitCode = exitCode;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
const CANCEL_REASON_EXIT_CODE = {
|
|
52
|
+
merged: EXIT.OK,
|
|
53
|
+
"ready-delay-elapsed": EXIT.OK,
|
|
54
|
+
closed: EXIT.CLOSED,
|
|
55
|
+
};
|
|
56
|
+
export function iterateResultToExitCode(result) {
|
|
57
|
+
switch (result.action) {
|
|
58
|
+
case "cancel":
|
|
59
|
+
return CANCEL_REASON_EXIT_CODE[result.reason];
|
|
60
|
+
case "wait":
|
|
61
|
+
return EXIT.WAIT;
|
|
62
|
+
case "mark_ready":
|
|
63
|
+
return EXIT.MARK_READY;
|
|
64
|
+
case "fix_code":
|
|
65
|
+
return EXIT.FIX_CODE;
|
|
66
|
+
case "escalate":
|
|
67
|
+
return EXIT.ESCALATE;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
export function errorToExitCode(err) {
|
|
71
|
+
if (err instanceof ShepherdError)
|
|
72
|
+
return err.exitCode;
|
|
73
|
+
return EXIT.SOFTWARE;
|
|
74
|
+
}
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import type { PrActivitySummary, PrComment, Review, ReviewThread } from "../types.mts";
|
|
2
|
+
import type { RawPr } from "./batch-raw-types.mts";
|
|
3
|
+
export declare function buildPrActivitySummary(raw: RawPr, comments: PrComment[], reviewThreads: ReviewThread[], reviewSummaries: Review[], changesRequestedReviews: Review[], approvedReviews: Review[]): PrActivitySummary;
|
package/bin/github/activity.mjs
CHANGED
|
@@ -8,6 +8,7 @@ function reviewActivityItems(reviews, latestCommitCommittedAtUnix, kind) {
|
|
|
8
8
|
id: r.id,
|
|
9
9
|
author: r.author,
|
|
10
10
|
authorType: r.authorType,
|
|
11
|
+
...(r.authorAssociation !== undefined && { authorAssociation: r.authorAssociation }),
|
|
11
12
|
body: r.body,
|
|
12
13
|
createdAtUnix: r.createdAtUnix ?? 0,
|
|
13
14
|
}));
|
|
@@ -26,6 +27,9 @@ export function buildPrActivitySummary(raw, comments, reviewThreads, reviewSumma
|
|
|
26
27
|
id: c.id,
|
|
27
28
|
author: c.author,
|
|
28
29
|
authorType: c.authorType,
|
|
30
|
+
...(c.authorAssociation !== undefined && {
|
|
31
|
+
authorAssociation: c.authorAssociation,
|
|
32
|
+
}),
|
|
29
33
|
body: c.body,
|
|
30
34
|
url: c.url,
|
|
31
35
|
createdAtUnix: c.createdAtUnix,
|
|
@@ -37,6 +41,9 @@ export function buildPrActivitySummary(raw, comments, reviewThreads, reviewSumma
|
|
|
37
41
|
id: c.id,
|
|
38
42
|
author: c.author,
|
|
39
43
|
authorType: c.authorType,
|
|
44
|
+
...(c.authorAssociation !== undefined && {
|
|
45
|
+
authorAssociation: c.authorAssociation,
|
|
46
|
+
}),
|
|
40
47
|
body: c.body,
|
|
41
48
|
url: c.url,
|
|
42
49
|
createdAtUnix: c.createdAtUnix,
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { AuthorType, CheckConclusion, CheckRun, CheckStatus, Review, ReviewThread } from "../types.mts";
|
|
2
|
+
import type { RawContextNode } from "./batch-raw-types.mts";
|
|
3
|
+
export declare function mapAuthorType(typeName: string | undefined | null, login?: string | undefined | null): AuthorType;
|
|
4
|
+
export declare function parseCreatedAt(iso: string): number;
|
|
5
|
+
/** Map a GraphQL CheckRun context node to a CheckRun. */
|
|
6
|
+
export declare function mapCheckRunNode(node: Extract<RawContextNode, {
|
|
7
|
+
__typename: "CheckRun";
|
|
8
|
+
}>): CheckRun;
|
|
9
|
+
export declare function latestApprovedLogins(latest: Array<{
|
|
10
|
+
login: string;
|
|
11
|
+
state: string;
|
|
12
|
+
}>): Set<string>;
|
|
13
|
+
/**
|
|
14
|
+
* A CR review is stale when its commit.oid differs from the PR head AND every
|
|
15
|
+
* associated review thread is resolved or outdated. Reviews with no associated
|
|
16
|
+
* threads are treated conservatively (not marked stale).
|
|
17
|
+
*/
|
|
18
|
+
export declare function isReviewStale(review: Review, headRefOid: string, reviewThreads: ReviewThread[]): boolean;
|
|
19
|
+
export declare function mapStatusContextState(state: string): {
|
|
20
|
+
status: CheckStatus;
|
|
21
|
+
conclusion: CheckConclusion;
|
|
22
|
+
};
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import type { BatchPrData } from "../types.mts";
|
|
2
|
+
import type { RawPr, RawThread, RawComment, RawReview, RawReviewSummary, RawContextNode } from "./batch-raw-types.mts";
|
|
3
|
+
export declare function parseRawPr(raw: RawPr, rawThreadPages: RawThread[], rawCommentNodes: RawComment[], rawReviewNodes: RawReview[], rawReviewSummaryNodes: RawReviewSummary[], rawApprovedReviewNodes: RawReviewSummary[], rawCheckNodes: RawContextNode[]): BatchPrData;
|
|
@@ -6,6 +6,7 @@ function parseReviewNode(r) {
|
|
|
6
6
|
id: r.id,
|
|
7
7
|
author: r.author?.login ?? "unknown",
|
|
8
8
|
authorType: mapAuthorType(r.author?.__typename, r.author?.login),
|
|
9
|
+
...(r.authorAssociation !== undefined && { authorAssociation: r.authorAssociation }),
|
|
9
10
|
body: r.body,
|
|
10
11
|
createdAtUnix: r.createdAt ? parseCreatedAt(r.createdAt) : 0,
|
|
11
12
|
};
|
|
@@ -32,6 +33,7 @@ export function parseRawPr(raw, rawThreadPages, rawCommentNodes, rawReviewNodes,
|
|
|
32
33
|
...(c.pullRequestReview?.id ? { reviewId: c.pullRequestReview.id } : undefined),
|
|
33
34
|
author: c.author?.login ?? "unknown",
|
|
34
35
|
authorType: mapAuthorType(c.author?.__typename, c.author?.login),
|
|
36
|
+
...(c.authorAssociation !== undefined && { authorAssociation: c.authorAssociation }),
|
|
35
37
|
body: c.body,
|
|
36
38
|
url: c.url,
|
|
37
39
|
createdAtUnix: c.createdAt ? parseCreatedAt(c.createdAt) : 0,
|
|
@@ -47,6 +49,9 @@ export function parseRawPr(raw, rawThreadPages, rawCommentNodes, rawReviewNodes,
|
|
|
47
49
|
...(comment?.pullRequestReview?.id ? { reviewId: comment.pullRequestReview.id } : undefined),
|
|
48
50
|
author: comment?.author?.login ?? "unknown",
|
|
49
51
|
authorType: mapAuthorType(comment?.author?.__typename, comment?.author?.login),
|
|
52
|
+
...(comment?.authorAssociation !== undefined && {
|
|
53
|
+
authorAssociation: comment.authorAssociation,
|
|
54
|
+
}),
|
|
50
55
|
body: comment?.body ?? "",
|
|
51
56
|
url: comment?.url ?? "",
|
|
52
57
|
createdAtUnix: comment?.createdAt ? parseCreatedAt(comment.createdAt) : 0,
|
|
@@ -58,6 +63,7 @@ export function parseRawPr(raw, rawThreadPages, rawCommentNodes, rawReviewNodes,
|
|
|
58
63
|
isMinimized: c.isMinimized,
|
|
59
64
|
author: c.author?.login ?? "unknown",
|
|
60
65
|
authorType: mapAuthorType(c.author?.__typename, c.author?.login),
|
|
66
|
+
...(c.authorAssociation !== undefined && { authorAssociation: c.authorAssociation }),
|
|
61
67
|
body: c.body,
|
|
62
68
|
url: c.url,
|
|
63
69
|
createdAtUnix: c.createdAt ? parseCreatedAt(c.createdAt) : 0,
|
|
@@ -0,0 +1,207 @@
|
|
|
1
|
+
import type { CommentAuthorAssociation } from "../types/github.mts";
|
|
2
|
+
export interface RawBatchResponse {
|
|
3
|
+
repository: {
|
|
4
|
+
pullRequest: RawPr | null;
|
|
5
|
+
} | null;
|
|
6
|
+
}
|
|
7
|
+
export interface RawPr {
|
|
8
|
+
id: string;
|
|
9
|
+
number: number;
|
|
10
|
+
state: string;
|
|
11
|
+
isDraft: boolean;
|
|
12
|
+
mergeable: string;
|
|
13
|
+
mergeStateStatus: string;
|
|
14
|
+
reviewDecision: string | null;
|
|
15
|
+
headRefOid: string;
|
|
16
|
+
headRefName: string;
|
|
17
|
+
headRepository: {
|
|
18
|
+
nameWithOwner: string;
|
|
19
|
+
} | null;
|
|
20
|
+
baseRefName: string;
|
|
21
|
+
baseRef: {
|
|
22
|
+
branchProtectionRule: RawBranchProtectionRule | null;
|
|
23
|
+
} | null;
|
|
24
|
+
reviewRequests: {
|
|
25
|
+
nodes: Array<{
|
|
26
|
+
requestedReviewer: {
|
|
27
|
+
login?: string;
|
|
28
|
+
name?: string;
|
|
29
|
+
} | null;
|
|
30
|
+
}>;
|
|
31
|
+
};
|
|
32
|
+
latestReviews: {
|
|
33
|
+
nodes: Array<{
|
|
34
|
+
author: RawAuthor | null;
|
|
35
|
+
state: string;
|
|
36
|
+
}>;
|
|
37
|
+
};
|
|
38
|
+
reviewThreads: {
|
|
39
|
+
pageInfo: {
|
|
40
|
+
hasPreviousPage: boolean;
|
|
41
|
+
startCursor: string | null;
|
|
42
|
+
};
|
|
43
|
+
nodes: RawThread[];
|
|
44
|
+
};
|
|
45
|
+
comments: {
|
|
46
|
+
pageInfo: {
|
|
47
|
+
hasPreviousPage: boolean;
|
|
48
|
+
startCursor: string | null;
|
|
49
|
+
};
|
|
50
|
+
nodes: RawComment[];
|
|
51
|
+
};
|
|
52
|
+
changesRequestedReviews: {
|
|
53
|
+
pageInfo: {
|
|
54
|
+
hasPreviousPage: boolean;
|
|
55
|
+
startCursor: string | null;
|
|
56
|
+
};
|
|
57
|
+
nodes: RawReview[];
|
|
58
|
+
};
|
|
59
|
+
reviewSummaries: {
|
|
60
|
+
pageInfo: {
|
|
61
|
+
hasPreviousPage: boolean;
|
|
62
|
+
startCursor: string | null;
|
|
63
|
+
};
|
|
64
|
+
nodes: RawReviewSummary[];
|
|
65
|
+
};
|
|
66
|
+
allReviews?: {
|
|
67
|
+
totalCount: number;
|
|
68
|
+
};
|
|
69
|
+
approvedReviews: {
|
|
70
|
+
pageInfo: {
|
|
71
|
+
hasPreviousPage: boolean;
|
|
72
|
+
startCursor: string | null;
|
|
73
|
+
};
|
|
74
|
+
nodes: RawReviewSummary[];
|
|
75
|
+
};
|
|
76
|
+
commits: {
|
|
77
|
+
totalCount?: number;
|
|
78
|
+
nodes: Array<{
|
|
79
|
+
commit: {
|
|
80
|
+
oid: string;
|
|
81
|
+
committedDate?: string;
|
|
82
|
+
statusCheckRollup: {
|
|
83
|
+
contexts: {
|
|
84
|
+
pageInfo: {
|
|
85
|
+
hasNextPage: boolean;
|
|
86
|
+
endCursor: string | null;
|
|
87
|
+
};
|
|
88
|
+
nodes: Array<RawContextNode | null>;
|
|
89
|
+
};
|
|
90
|
+
} | null;
|
|
91
|
+
};
|
|
92
|
+
}>;
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
interface RawAuthor {
|
|
96
|
+
__typename?: string;
|
|
97
|
+
login: string;
|
|
98
|
+
}
|
|
99
|
+
export interface RawThreadComment {
|
|
100
|
+
id: string;
|
|
101
|
+
isMinimized: boolean;
|
|
102
|
+
url: string;
|
|
103
|
+
authorAssociation?: CommentAuthorAssociation;
|
|
104
|
+
author: RawAuthor | null;
|
|
105
|
+
pullRequestReview?: {
|
|
106
|
+
id: string;
|
|
107
|
+
} | null;
|
|
108
|
+
body: string;
|
|
109
|
+
path: string | null;
|
|
110
|
+
line: number | null;
|
|
111
|
+
startLine: number | null;
|
|
112
|
+
createdAt?: string;
|
|
113
|
+
}
|
|
114
|
+
export interface RawThread {
|
|
115
|
+
id: string;
|
|
116
|
+
isResolved: boolean;
|
|
117
|
+
isOutdated: boolean;
|
|
118
|
+
path?: string | null;
|
|
119
|
+
line?: number | null;
|
|
120
|
+
startLine?: number | null;
|
|
121
|
+
comments: {
|
|
122
|
+
pageInfo?: {
|
|
123
|
+
hasNextPage: boolean;
|
|
124
|
+
endCursor: string | null;
|
|
125
|
+
};
|
|
126
|
+
nodes: RawThreadComment[];
|
|
127
|
+
};
|
|
128
|
+
}
|
|
129
|
+
export interface RawReviewThreadCommentsResponse {
|
|
130
|
+
node: {
|
|
131
|
+
__typename?: string;
|
|
132
|
+
comments: {
|
|
133
|
+
pageInfo: {
|
|
134
|
+
hasNextPage: boolean;
|
|
135
|
+
endCursor: string | null;
|
|
136
|
+
};
|
|
137
|
+
nodes: RawThreadComment[];
|
|
138
|
+
} | null;
|
|
139
|
+
} | null;
|
|
140
|
+
}
|
|
141
|
+
export interface RawComment {
|
|
142
|
+
id: string;
|
|
143
|
+
isMinimized: boolean;
|
|
144
|
+
url: string;
|
|
145
|
+
authorAssociation?: CommentAuthorAssociation;
|
|
146
|
+
author: RawAuthor | null;
|
|
147
|
+
body: string;
|
|
148
|
+
createdAt?: string;
|
|
149
|
+
}
|
|
150
|
+
export interface RawReview {
|
|
151
|
+
id: string;
|
|
152
|
+
authorAssociation?: CommentAuthorAssociation;
|
|
153
|
+
author: RawAuthor | null;
|
|
154
|
+
body: string;
|
|
155
|
+
createdAt?: string;
|
|
156
|
+
commit?: {
|
|
157
|
+
oid: string;
|
|
158
|
+
};
|
|
159
|
+
}
|
|
160
|
+
export interface RawReviewSummary {
|
|
161
|
+
id: string;
|
|
162
|
+
isMinimized: boolean;
|
|
163
|
+
authorAssociation?: CommentAuthorAssociation;
|
|
164
|
+
author: RawAuthor | null;
|
|
165
|
+
body: string;
|
|
166
|
+
createdAt?: string;
|
|
167
|
+
}
|
|
168
|
+
interface RawBranchProtectionRule {
|
|
169
|
+
requiresApprovingReviews: boolean;
|
|
170
|
+
requiredApprovingReviewCount: number;
|
|
171
|
+
requiresConversationResolution: boolean;
|
|
172
|
+
requiresStatusChecks: boolean;
|
|
173
|
+
requiredStatusCheckContexts: string[] | null;
|
|
174
|
+
}
|
|
175
|
+
export type RawContextNode = {
|
|
176
|
+
__typename: "CheckRun";
|
|
177
|
+
id: string;
|
|
178
|
+
name: string;
|
|
179
|
+
status: string;
|
|
180
|
+
conclusion: string | null;
|
|
181
|
+
detailsUrl: string | null;
|
|
182
|
+
completedAt?: string | null;
|
|
183
|
+
startedAt?: string | null;
|
|
184
|
+
title: string | null;
|
|
185
|
+
summary: string | null;
|
|
186
|
+
checkSuite: {
|
|
187
|
+
createdAt?: string;
|
|
188
|
+
updatedAt?: string;
|
|
189
|
+
workflowRun: {
|
|
190
|
+
event: string;
|
|
191
|
+
createdAt?: string;
|
|
192
|
+
updatedAt?: string;
|
|
193
|
+
workflow?: {
|
|
194
|
+
name: string;
|
|
195
|
+
databaseId?: number | null;
|
|
196
|
+
} | null;
|
|
197
|
+
} | null;
|
|
198
|
+
} | null;
|
|
199
|
+
} | {
|
|
200
|
+
__typename: "StatusContext";
|
|
201
|
+
context: string;
|
|
202
|
+
state: string;
|
|
203
|
+
createdAt?: string;
|
|
204
|
+
targetUrl: string | null;
|
|
205
|
+
description: string | null;
|
|
206
|
+
};
|
|
207
|
+
export {};
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { RepoInfo } from "./client.mts";
|
|
2
|
+
import type { RawBatchResponse, RawContextNode, RawPr } from "./batch-raw-types.mts";
|
|
3
|
+
export declare function requireRawPr(response: RawBatchResponse | null | undefined, pr: number, repo: RepoInfo): RawPr;
|
|
4
|
+
export declare function requireContextNodes(nodes: Array<RawContextNode | null>): RawContextNode[];
|
|
@@ -1,16 +1,21 @@
|
|
|
1
|
+
import { EXIT, ShepherdError } from "../exit-codes.mjs";
|
|
1
2
|
import { GitHubRequestError } from "./errors.mjs";
|
|
2
3
|
export function requireRawPr(response, pr, repo) {
|
|
3
4
|
if (!response?.repository) {
|
|
4
5
|
throw new GitHubRequestError(`GitHub GraphQL response did not include repository ${repo.owner}/${repo.name} (not found or access denied)`, { status: 200 });
|
|
5
6
|
}
|
|
6
|
-
if (!response.repository.pullRequest)
|
|
7
|
-
throw new
|
|
7
|
+
if (!response.repository.pullRequest) {
|
|
8
|
+
throw new ShepherdError(`PR #${pr} not found`, EXIT.UNAVAILABLE);
|
|
9
|
+
}
|
|
8
10
|
return response.repository.pullRequest;
|
|
9
11
|
}
|
|
10
12
|
export function requireContextNodes(nodes) {
|
|
11
13
|
const nullIndex = nodes.findIndex((node) => node === null);
|
|
12
14
|
if (nullIndex !== -1) {
|
|
13
|
-
|
|
15
|
+
// A null context node is an unexpected/malformed shape, not a precondition or
|
|
16
|
+
// permission problem — force EX_SOFTWARE rather than falling through to the
|
|
17
|
+
// (200-status-derived) EX_UNAVAILABLE default.
|
|
18
|
+
throw new GitHubRequestError(`Malformed GitHub GraphQL response: null check context at repository.pullRequest.commits.nodes.0.commit.statusCheckRollup.contexts.nodes.${nullIndex}`, { status: 200, exitCodeOverride: EXIT.SOFTWARE });
|
|
14
19
|
}
|
|
15
20
|
return nodes;
|
|
16
21
|
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { type RateLimitInfo, type RepoInfo } from "./client.mts";
|
|
2
|
+
import type { BatchPrData } from "../types.mts";
|
|
3
|
+
interface BatchResult {
|
|
4
|
+
data: BatchPrData;
|
|
5
|
+
rateLimit?: RateLimitInfo;
|
|
6
|
+
}
|
|
7
|
+
interface FetchPrBatchOptions {
|
|
8
|
+
/**
|
|
9
|
+
* When false (default), the first-page approvedReviews are returned but
|
|
10
|
+
* backward pagination is skipped. Iterate's approvals-minimize flow sets this
|
|
11
|
+
* to true only when the user opts in, so long-lived PRs with > 50 approvals
|
|
12
|
+
* don't pay extra GraphQL round-trips per iterate call for data no consumer
|
|
13
|
+
* currently uses. The first page is free — already inside the one batch
|
|
14
|
+
* request — so there's no need to conditionally omit the field itself.
|
|
15
|
+
*/
|
|
16
|
+
paginateApprovedReviews?: boolean;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Fetch all PR data needed for a `shepherd check` in one (or a few, if paginating) GraphQL requests.
|
|
20
|
+
*/
|
|
21
|
+
export declare function fetchPrBatch(pr: number, repo: RepoInfo, opts?: FetchPrBatchOptions): Promise<BatchResult>;
|
|
22
|
+
export {};
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* High-level GitHub client — wraps http.mts for application-level concerns.
|
|
3
|
+
*
|
|
4
|
+
* All GitHub I/O goes through native fetch (via http.mts); the `gh` CLI is no
|
|
5
|
+
* longer used for GitHub API calls, but may be invoked as an auth-token
|
|
6
|
+
* fallback via `gh auth token` when neither GH_TOKEN nor GITHUB_TOKEN is set.
|
|
7
|
+
*/
|
|
8
|
+
import type { MergeableState, MergeStateStatus } from "../types.mts";
|
|
9
|
+
export type { RateLimitInfo } from "./http.mts";
|
|
10
|
+
export { graphql, graphqlWithRateLimit } from "./http.mts";
|
|
11
|
+
export interface RepoInfo {
|
|
12
|
+
owner: string;
|
|
13
|
+
name: string;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Returns the current repo's owner and name by parsing `git remote get-url origin`.
|
|
17
|
+
* Handles https://, git@, and ssh:// remote URL formats.
|
|
18
|
+
*/
|
|
19
|
+
export declare function getRepoInfo(): Promise<RepoInfo>;
|
|
20
|
+
/**
|
|
21
|
+
* Derives the PR number for the current HEAD branch.
|
|
22
|
+
* Returns null if no open PR is found.
|
|
23
|
+
*/
|
|
24
|
+
export declare function getCurrentPrNumber(): Promise<number | null>;
|
|
25
|
+
/** Returns the PR number for a given branch, or null if no open PR is found. */
|
|
26
|
+
export declare function getPrNumberForBranch(branch: string, owner: string, repo: string): Promise<number | null>;
|
|
27
|
+
/** Returns the `headRefOid` (commit SHA) of the given PR as reported by GitHub. */
|
|
28
|
+
export declare function getPrHeadSha(pr: number, owner: string, name: string): Promise<string>;
|
|
29
|
+
/** Fetches the node ID and body text for a PR. GitHub returns null body for empty bodies — coerced to "". */
|
|
30
|
+
export declare function getPullRequestBody(pr: number, owner: string, name: string): Promise<{
|
|
31
|
+
nodeId: string;
|
|
32
|
+
body: string;
|
|
33
|
+
}>;
|
|
34
|
+
/** Overwrites the PR body. */
|
|
35
|
+
export declare function updatePullRequestBody(pullRequestId: string, body: string): Promise<void>;
|
|
36
|
+
/**
|
|
37
|
+
* Fetches `mergeable` and `mergeStateStatus` via the REST API.
|
|
38
|
+
*
|
|
39
|
+
* Used as a fallback when the GraphQL API returns `UNKNOWN` for these fields —
|
|
40
|
+
* a known GitHub quirk where GraphQL lags behind the REST layer.
|
|
41
|
+
*/
|
|
42
|
+
export declare function getMergeableState(pr: number, owner: string, repo: string): Promise<{
|
|
43
|
+
mergeable: MergeableState;
|
|
44
|
+
mergeStateStatus: MergeStateStatus;
|
|
45
|
+
}>;
|
|
46
|
+
export declare function getCurrentBranch(): Promise<string>;
|
package/bin/github/client.mjs
CHANGED
|
@@ -9,6 +9,7 @@ import { execFile as execFileCb } from "node:child_process";
|
|
|
9
9
|
import { promisify } from "node:util";
|
|
10
10
|
import { graphql as httpGraphql, rest } from "./http.mjs";
|
|
11
11
|
import { PR_NUMBER_BY_BRANCH_QUERY, GET_PR_HEAD_SHA_QUERY, GET_PR_BODY_QUERY, UPDATE_PR_BODY_MUTATION, } from "./queries.mjs";
|
|
12
|
+
import { getExecutionCwd } from "../execution-context.mjs";
|
|
12
13
|
const execFile = promisify(execFileCb);
|
|
13
14
|
// ---------------------------------------------------------------------------
|
|
14
15
|
// GraphQL — thin re-exports so callers don't need to import http.mts directly
|
|
@@ -19,7 +20,9 @@ export { graphql, graphqlWithRateLimit } from "./http.mjs";
|
|
|
19
20
|
* Handles https://, git@, and ssh:// remote URL formats.
|
|
20
21
|
*/
|
|
21
22
|
export async function getRepoInfo() {
|
|
22
|
-
const { stdout } = await execFile("git", ["remote", "get-url", "origin"]
|
|
23
|
+
const { stdout } = await execFile("git", ["remote", "get-url", "origin"], {
|
|
24
|
+
cwd: getExecutionCwd(),
|
|
25
|
+
});
|
|
23
26
|
const url = stdout.trim();
|
|
24
27
|
return parseRemoteUrl(url);
|
|
25
28
|
}
|
|
@@ -95,7 +98,9 @@ export async function getMergeableState(pr, owner, repo) {
|
|
|
95
98
|
// Internal helpers
|
|
96
99
|
// ---------------------------------------------------------------------------
|
|
97
100
|
export async function getCurrentBranch() {
|
|
98
|
-
const { stdout } = await execFile("git", ["rev-parse", "--abbrev-ref", "HEAD"]
|
|
101
|
+
const { stdout } = await execFile("git", ["rev-parse", "--abbrev-ref", "HEAD"], {
|
|
102
|
+
cwd: getExecutionCwd(),
|
|
103
|
+
});
|
|
99
104
|
return stdout.trim();
|
|
100
105
|
}
|
|
101
106
|
function parseRemoteUrl(url) {
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { ShepherdError } from "../exit-codes.mts";
|
|
2
|
+
import type { RateLimitInfo } from "./http.mts";
|
|
3
|
+
export interface GitHubGraphQlError {
|
|
4
|
+
message: string;
|
|
5
|
+
path?: unknown;
|
|
6
|
+
}
|
|
7
|
+
export declare class GitHubRequestError extends ShepherdError {
|
|
8
|
+
readonly status: number;
|
|
9
|
+
readonly rateLimit?: RateLimitInfo;
|
|
10
|
+
readonly retryAfterSeconds?: number;
|
|
11
|
+
readonly graphqlErrors?: GitHubGraphQlError[];
|
|
12
|
+
constructor(message: string, opts: {
|
|
13
|
+
status: number;
|
|
14
|
+
rateLimit?: RateLimitInfo;
|
|
15
|
+
retryAfterSeconds?: number;
|
|
16
|
+
graphqlErrors?: GitHubGraphQlError[];
|
|
17
|
+
/**
|
|
18
|
+
* Bypasses status-based classification entirely — for callers that already
|
|
19
|
+
* know the failure kind better than the HTTP status can express (e.g. a
|
|
20
|
+
* response that failed to parse at all, which is an internal failure, not
|
|
21
|
+
* an availability or permission problem).
|
|
22
|
+
*/
|
|
23
|
+
exitCodeOverride?: number;
|
|
24
|
+
});
|
|
25
|
+
}
|
package/bin/github/errors.mjs
CHANGED
|
@@ -1,10 +1,34 @@
|
|
|
1
|
-
|
|
1
|
+
import { EXIT, ShepherdError } from "../exit-codes.mjs";
|
|
2
|
+
// GitHub's GraphQL API reports field-level permission failures (e.g. a fine-grained
|
|
3
|
+
// PAT missing a scope) as an `errors[].message` entry at HTTP 200, not as an HTTP
|
|
4
|
+
// 401/403 — the transport-level request succeeded even though one field could not
|
|
5
|
+
// be resolved. Status alone can't see this, so classification must also inspect the
|
|
6
|
+
// GraphQL error messages themselves.
|
|
7
|
+
const GRAPHQL_PERMISSION_ERROR = /resource not accessible/i;
|
|
8
|
+
function hasPermissionError(graphqlErrors) {
|
|
9
|
+
return graphqlErrors?.some((e) => GRAPHQL_PERMISSION_ERROR.test(e.message)) ?? false;
|
|
10
|
+
}
|
|
11
|
+
function classifyStatus(status, rateLimit, retryAfterSeconds, graphqlErrors) {
|
|
12
|
+
// Retry signals take priority over everything else: GitHub's secondary rate limit
|
|
13
|
+
// returns 403 with a Retry-After header, which is a transient throttle — not the
|
|
14
|
+
// permission-denied 403 a bad/missing token produces. Treat any retry signal as
|
|
15
|
+
// TEMPFAIL first so it isn't shadowed by the checks below.
|
|
16
|
+
const rateLimitExhausted = rateLimit !== undefined && rateLimit.remaining <= 0;
|
|
17
|
+
if (status === 429 || status >= 500 || retryAfterSeconds !== undefined || rateLimitExhausted) {
|
|
18
|
+
return EXIT.TEMPFAIL;
|
|
19
|
+
}
|
|
20
|
+
if (status === 401 || status === 403 || hasPermissionError(graphqlErrors))
|
|
21
|
+
return EXIT.NOPERM;
|
|
22
|
+
return EXIT.UNAVAILABLE;
|
|
23
|
+
}
|
|
24
|
+
export class GitHubRequestError extends ShepherdError {
|
|
2
25
|
status;
|
|
3
26
|
rateLimit;
|
|
4
27
|
retryAfterSeconds;
|
|
5
28
|
graphqlErrors;
|
|
6
29
|
constructor(message, opts) {
|
|
7
|
-
super(message
|
|
30
|
+
super(message, opts.exitCodeOverride ??
|
|
31
|
+
classifyStatus(opts.status, opts.rateLimit, opts.retryAfterSeconds, opts.graphqlErrors));
|
|
8
32
|
this.name = "GitHubRequestError";
|
|
9
33
|
this.status = opts.status;
|
|
10
34
|
this.rateLimit = opts.rateLimit;
|
|
@@ -82,6 +82,7 @@ query BatchPr(
|
|
|
82
82
|
id
|
|
83
83
|
isMinimized
|
|
84
84
|
url
|
|
85
|
+
authorAssociation
|
|
85
86
|
author {
|
|
86
87
|
__typename
|
|
87
88
|
login
|
|
@@ -107,6 +108,7 @@ query BatchPr(
|
|
|
107
108
|
id
|
|
108
109
|
isMinimized
|
|
109
110
|
url
|
|
111
|
+
authorAssociation
|
|
110
112
|
author {
|
|
111
113
|
__typename
|
|
112
114
|
login
|
|
@@ -126,6 +128,7 @@ query BatchPr(
|
|
|
126
128
|
}
|
|
127
129
|
nodes {
|
|
128
130
|
id
|
|
131
|
+
authorAssociation
|
|
129
132
|
author {
|
|
130
133
|
__typename
|
|
131
134
|
login
|
|
@@ -145,6 +148,7 @@ query BatchPr(
|
|
|
145
148
|
nodes {
|
|
146
149
|
id
|
|
147
150
|
isMinimized
|
|
151
|
+
authorAssociation
|
|
148
152
|
author {
|
|
149
153
|
__typename
|
|
150
154
|
login
|
|
@@ -164,6 +168,7 @@ query BatchPr(
|
|
|
164
168
|
nodes {
|
|
165
169
|
id
|
|
166
170
|
isMinimized
|
|
171
|
+
authorAssociation
|
|
167
172
|
author {
|
|
168
173
|
__typename
|
|
169
174
|
login
|