pr-shepherd 0.35.0 → 0.37.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 +1 -1
- package/README.md +32 -12
- package/bin/checks/conclusions.d.mts +6 -0
- package/bin/checks/conclusions.mjs +9 -0
- package/bin/checks/triage.mjs +11 -3
- package/bin/cli/args.mjs +1 -0
- package/bin/cli/default-poll.mjs +1 -0
- package/bin/cli/fix-formatter.mjs +4 -2
- package/bin/cli/help-command-pages.d.mts +1 -1
- package/bin/cli/help-iterate-poll-pages.d.mts +1 -1
- package/bin/cli/help-iterate-poll-pages.mjs +10 -5
- package/bin/cli/help-top-page.d.mts +1 -1
- package/bin/cli/help-top-page.mjs +2 -1
- package/bin/cli/help.d.mts +2 -2
- package/bin/cli/iterate-formatter.mjs +11 -2
- package/bin/cli/iterate-lean.mjs +1 -0
- package/bin/cli/poll-handler.mjs +7 -0
- package/bin/commands/check-annotations.d.mts +16 -3
- package/bin/commands/check-annotations.mjs +37 -1
- package/bin/commands/check.d.mts +1 -0
- package/bin/commands/check.mjs +35 -28
- package/bin/commands/commit-suggestion.mjs +11 -5
- package/bin/commands/iterate/fix-code.mjs +13 -6
- package/bin/commands/iterate/helpers.d.mts +1 -0
- package/bin/commands/iterate/helpers.mjs +15 -6
- package/bin/commands/iterate/index.mjs +5 -10
- package/bin/commands/iterate/render.mjs +9 -5
- package/bin/commands/iterate/stall.mjs +5 -0
- package/bin/commands/poll.d.mts +2 -0
- package/bin/commands/poll.mjs +51 -17
- package/bin/commands/ready-delay.mjs +3 -13
- package/bin/config/load.mjs +67 -25
- package/bin/github/batch-page-helpers.d.mts +45 -0
- package/bin/github/batch-page-helpers.mjs +63 -0
- package/bin/github/batch-page.d.mts +14 -0
- package/bin/github/batch-page.mjs +62 -0
- package/bin/github/batch-parse-suites.d.mts +4 -0
- package/bin/github/batch-parse-suites.mjs +25 -0
- package/bin/github/batch-parser-helpers.mjs +1 -0
- package/bin/github/batch-parsers-rules.d.mts +6 -0
- package/bin/github/batch-parsers-rules.mjs +122 -0
- package/bin/github/batch-parsers.mjs +6 -0
- package/bin/github/batch-raw-rules.d.mts +59 -0
- package/bin/github/batch-raw-rules.mjs +1 -0
- package/bin/github/batch-raw-types.d.mts +25 -11
- package/bin/github/batch.d.mts +2 -0
- package/bin/github/batch.mjs +14 -120
- package/bin/github/gql/batch-pr-page.gql +194 -0
- package/bin/github/gql/batch-pr.gql +79 -21
- package/bin/github/gql/commit-suggestion-thread.gql +40 -0
- package/bin/github/http.d.mts +2 -1
- package/bin/github/http.mjs +2 -1
- package/bin/github/pagination.d.mts +3 -2
- package/bin/github/pagination.mjs +3 -2
- package/bin/github/queries.d.mts +4 -0
- package/bin/github/queries.mjs +4 -0
- package/bin/github/rest-http.d.mts +6 -1
- package/bin/github/rest-http.mjs +25 -86
- package/bin/github/rest-text.d.mts +1 -0
- package/bin/github/rest-text.mjs +88 -0
- package/bin/github/suggestion-thread.d.mts +9 -0
- package/bin/github/suggestion-thread.mjs +45 -0
- package/bin/github/thread-comments.mjs +12 -8
- package/bin/merge-status/derive.mjs +2 -0
- package/bin/merge-status/requirements-format.d.mts +3 -0
- package/bin/merge-status/requirements-format.mjs +88 -0
- package/bin/merge-status/requirements.d.mts +2 -0
- package/bin/merge-status/requirements.mjs +51 -0
- package/bin/reporters/agent.mjs +0 -3
- package/bin/state/base.d.mts +9 -0
- package/bin/state/base.mjs +23 -0
- package/bin/state/bot-cr-seen.mjs +3 -13
- package/bin/state/fix-attempts.mjs +3 -13
- package/bin/state/iterate-stall.mjs +3 -13
- package/bin/state/seen-comments.mjs +6 -13
- package/bin/types/check-classification.d.mts +2 -2
- package/bin/types/github.d.mts +6 -7
- package/bin/types/iterate.d.mts +6 -7
- package/bin/types/merge-requirements.d.mts +82 -0
- package/bin/types/merge-requirements.mjs +2 -0
- package/bin/types/report.d.mts +5 -5
- package/bin/types.d.mts +1 -0
- package/bin/types.mjs +1 -0
- package/bin/util/path-segment.d.mts +2 -0
- package/bin/util/path-segment.mjs +2 -0
- package/bin/util/pool.d.mts +2 -0
- package/bin/util/pool.mjs +18 -0
- package/package.json +1 -1
- package/plugins/pr-shepherd/.codex-plugin/plugin.json +1 -1
- package/plugins/pr-shepherd/.codex.mcp.json +1 -1
- package/plugins/pr-shepherd/.mcp.json +1 -1
package/bin/github/batch.mjs
CHANGED
|
@@ -1,134 +1,28 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { paginateForward, paginateBackward } from "./pagination.mjs";
|
|
1
|
+
import { graphqlWithRateLimit } from "./client.mjs";
|
|
3
2
|
import { hydrateThreadCommentPages } from "./thread-comments.mjs";
|
|
4
3
|
import { BATCH_PR_QUERY } from "./queries.mjs";
|
|
5
4
|
import { parseRawPr } from "./batch-parsers.mjs";
|
|
6
|
-
import {
|
|
5
|
+
import { parseCheckSuitesComplete, parseSuiteStartupFailures } from "./batch-parse-suites.mjs";
|
|
6
|
+
import { mergeStartupFailureChecks } from "../checks/startup-failures.mjs";
|
|
7
|
+
import { paginateBatchConnections } from "./batch-page.mjs";
|
|
8
|
+
import { requireRawPr } from "./batch-response.mjs";
|
|
7
9
|
/**
|
|
8
10
|
* Fetch all PR data needed for a `shepherd check` in one (or a few, if paginating) GraphQL requests.
|
|
9
11
|
*/
|
|
10
12
|
export async function fetchPrBatch(pr, repo, opts = {}) {
|
|
11
|
-
// First page: no cursor variables.
|
|
12
13
|
const result = await graphqlWithRateLimit(BATCH_PR_QUERY, {
|
|
13
14
|
owner: repo.owner,
|
|
14
15
|
repo: repo.name,
|
|
15
16
|
pr,
|
|
16
17
|
});
|
|
17
18
|
const raw = requireRawPr(result.data, pr, repo);
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
pr,
|
|
28
|
-
...(cursor ? { threadsCursor: cursor } : {}),
|
|
29
|
-
});
|
|
30
|
-
const pr2 = requireRawPr(res.data, pr, repo);
|
|
31
|
-
return pr2.reviewThreads;
|
|
32
|
-
}, raw.reviewThreads.pageInfo.startCursor);
|
|
33
|
-
// extra contains pages before the first page.
|
|
34
|
-
rawThreadPages = [...extra, ...rawThreadPages];
|
|
35
|
-
}
|
|
36
|
-
rawThreadPages = await hydrateThreadCommentPages(rawThreadPages);
|
|
37
|
-
// Paginate comments backward if the first page is incomplete.
|
|
38
|
-
let rawCommentNodes = raw.comments.nodes;
|
|
39
|
-
if (raw.comments.pageInfo.hasPreviousPage && raw.comments.pageInfo.startCursor) {
|
|
40
|
-
const extra = await paginateBackward(async (cursor) => {
|
|
41
|
-
const res = await graphql(BATCH_PR_QUERY, {
|
|
42
|
-
owner: repo.owner,
|
|
43
|
-
repo: repo.name,
|
|
44
|
-
pr,
|
|
45
|
-
...(cursor ? { commentsCursor: cursor } : {}),
|
|
46
|
-
});
|
|
47
|
-
const pr2 = requireRawPr(res.data, pr, repo);
|
|
48
|
-
return pr2.comments;
|
|
49
|
-
}, raw.comments.pageInfo.startCursor);
|
|
50
|
-
rawCommentNodes = [...extra, ...rawCommentNodes];
|
|
51
|
-
}
|
|
52
|
-
// Paginate CHANGES_REQUESTED reviews backward if the first page is incomplete.
|
|
53
|
-
let rawReviewNodes = raw.changesRequestedReviews.nodes;
|
|
54
|
-
if (raw.changesRequestedReviews.pageInfo.hasPreviousPage &&
|
|
55
|
-
raw.changesRequestedReviews.pageInfo.startCursor) {
|
|
56
|
-
const extra = await paginateBackward(async (cursor) => {
|
|
57
|
-
const res = await graphql(BATCH_PR_QUERY, {
|
|
58
|
-
owner: repo.owner,
|
|
59
|
-
repo: repo.name,
|
|
60
|
-
pr,
|
|
61
|
-
...(cursor ? { changesRequestedCursor: cursor } : {}),
|
|
62
|
-
});
|
|
63
|
-
const pr2 = requireRawPr(res.data, pr, repo);
|
|
64
|
-
return pr2.changesRequestedReviews;
|
|
65
|
-
}, raw.changesRequestedReviews.pageInfo.startCursor);
|
|
66
|
-
rawReviewNodes = [...extra, ...rawReviewNodes];
|
|
67
|
-
}
|
|
68
|
-
// Paginate COMMENTED review summaries backward if the first page is incomplete.
|
|
69
|
-
let rawReviewSummaryNodes = raw.reviewSummaries.nodes;
|
|
70
|
-
if (raw.reviewSummaries.pageInfo.hasPreviousPage && raw.reviewSummaries.pageInfo.startCursor) {
|
|
71
|
-
const extra = await paginateBackward(async (cursor) => {
|
|
72
|
-
const res = await graphql(BATCH_PR_QUERY, {
|
|
73
|
-
owner: repo.owner,
|
|
74
|
-
repo: repo.name,
|
|
75
|
-
pr,
|
|
76
|
-
...(cursor ? { reviewSummariesCursor: cursor } : {}),
|
|
77
|
-
});
|
|
78
|
-
const pr2 = requireRawPr(res.data, pr, repo);
|
|
79
|
-
return pr2.reviewSummaries;
|
|
80
|
-
}, raw.reviewSummaries.pageInfo.startCursor);
|
|
81
|
-
rawReviewSummaryNodes = [...extra, ...rawReviewSummaryNodes];
|
|
82
|
-
}
|
|
83
|
-
// Paginate APPROVED reviews backward if the first page is incomplete — gated behind
|
|
84
|
-
// `paginateApprovedReviews` because approvals minimization is opt-in. See FetchPrBatchOptions.
|
|
85
|
-
let rawApprovedReviewNodes = raw.approvedReviews.nodes;
|
|
86
|
-
if (opts.paginateApprovedReviews &&
|
|
87
|
-
raw.approvedReviews.pageInfo.hasPreviousPage &&
|
|
88
|
-
raw.approvedReviews.pageInfo.startCursor) {
|
|
89
|
-
const extra = await paginateBackward(async (cursor) => {
|
|
90
|
-
const res = await graphql(BATCH_PR_QUERY, {
|
|
91
|
-
owner: repo.owner,
|
|
92
|
-
repo: repo.name,
|
|
93
|
-
pr,
|
|
94
|
-
...(cursor ? { approvedReviewsCursor: cursor } : {}),
|
|
95
|
-
});
|
|
96
|
-
const pr2 = requireRawPr(res.data, pr, repo);
|
|
97
|
-
return pr2.approvedReviews;
|
|
98
|
-
}, raw.approvedReviews.pageInfo.startCursor);
|
|
99
|
-
rawApprovedReviewNodes = [...extra, ...rawApprovedReviewNodes];
|
|
100
|
-
}
|
|
101
|
-
// Paginate check contexts forward if the first page is incomplete.
|
|
102
|
-
let rawCheckNodes = requireContextNodes(raw.commits.nodes[0]?.commit.statusCheckRollup?.contexts.nodes ?? []);
|
|
103
|
-
const checksPageInfo = raw.commits.nodes[0]?.commit.statusCheckRollup?.contexts.pageInfo;
|
|
104
|
-
const firstOid = raw.commits.nodes[0]?.commit.oid;
|
|
105
|
-
if (checksPageInfo?.hasNextPage && checksPageInfo.endCursor) {
|
|
106
|
-
// Pass endCursor so paginateForward fetches pages *after* the already-
|
|
107
|
-
// fetched first page instead of re-fetching it from the start.
|
|
108
|
-
let pageCount = 0;
|
|
109
|
-
const extra = await paginateForward(async (cursor) => {
|
|
110
|
-
const res = await graphql(BATCH_PR_QUERY, {
|
|
111
|
-
owner: repo.owner,
|
|
112
|
-
repo: repo.name,
|
|
113
|
-
pr,
|
|
114
|
-
...(cursor ? { checksCursor: cursor } : {}),
|
|
115
|
-
});
|
|
116
|
-
const pr2 = requireRawPr(res.data, pr, repo);
|
|
117
|
-
if (!pr2?.commits.nodes[0]?.commit.statusCheckRollup) {
|
|
118
|
-
throw new Error(`Check-context pagination interrupted: statusCheckRollup disappeared on page ${pageCount + 2} (possible force-push race). Retry after the push stabilizes.`);
|
|
119
|
-
}
|
|
120
|
-
const currentOid = pr2.commits.nodes[0]?.commit.oid;
|
|
121
|
-
if (firstOid !== undefined && currentOid !== undefined && currentOid !== firstOid) {
|
|
122
|
-
throw new Error(`Check-context pagination interrupted: head commit changed from ${firstOid} to ${currentOid} between pages (force-push race). Retry.`);
|
|
123
|
-
}
|
|
124
|
-
pageCount++;
|
|
125
|
-
const ctxs = pr2.commits.nodes[0]?.commit.statusCheckRollup?.contexts;
|
|
126
|
-
if (!ctxs)
|
|
127
|
-
return { pageInfo: { hasNextPage: false, endCursor: null }, nodes: [] };
|
|
128
|
-
return { ...ctxs, nodes: requireContextNodes(ctxs.nodes) };
|
|
129
|
-
}, checksPageInfo.endCursor);
|
|
130
|
-
rawCheckNodes = [...rawCheckNodes, ...extra];
|
|
131
|
-
}
|
|
132
|
-
const data = parseRawPr(raw, rawThreadPages, rawCommentNodes, rawReviewNodes, rawReviewSummaryNodes, rawApprovedReviewNodes, rawCheckNodes);
|
|
133
|
-
return { data, rateLimit: result.rateLimit };
|
|
19
|
+
const paged = await paginateBatchConnections(pr, repo, raw, opts, result.rateLimit);
|
|
20
|
+
const rawThreadPages = await hydrateThreadCommentPages(paged.threads);
|
|
21
|
+
const data = parseRawPr(raw, rawThreadPages, paged.comments, paged.changesRequested, paged.reviewSummaries, paged.approvedReviews, paged.checks);
|
|
22
|
+
data.checks = mergeStartupFailureChecks(data.checks, parseSuiteStartupFailures(raw));
|
|
23
|
+
return {
|
|
24
|
+
data,
|
|
25
|
+
rateLimit: paged.rateLimit ?? result.rateLimit,
|
|
26
|
+
...(parseCheckSuitesComplete(raw) && { checkSuitesComplete: true }),
|
|
27
|
+
};
|
|
134
28
|
}
|
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
# Follow-up pages only — skipped connections are omitted via @include so extra
|
|
2
|
+
# pages do not re-pay the full batch-pr.gql node cost. Outstanding cursors are
|
|
3
|
+
# sent together in one request.
|
|
4
|
+
query BatchPrPage(
|
|
5
|
+
$owner: String!
|
|
6
|
+
$repo: String!
|
|
7
|
+
$pr: Int!
|
|
8
|
+
$includeThreads: Boolean!
|
|
9
|
+
$threadsCursor: String
|
|
10
|
+
$includeComments: Boolean!
|
|
11
|
+
$commentsCursor: String
|
|
12
|
+
$includeChangesRequested: Boolean!
|
|
13
|
+
$changesRequestedCursor: String
|
|
14
|
+
$includeReviewSummaries: Boolean!
|
|
15
|
+
$reviewSummariesCursor: String
|
|
16
|
+
$includeApprovedReviews: Boolean!
|
|
17
|
+
$approvedReviewsCursor: String
|
|
18
|
+
$includeChecks: Boolean!
|
|
19
|
+
$checksCursor: String
|
|
20
|
+
) {
|
|
21
|
+
repository(owner: $owner, name: $repo) {
|
|
22
|
+
pullRequest(number: $pr) {
|
|
23
|
+
reviewThreads(last: 100, before: $threadsCursor) @include(if: $includeThreads) {
|
|
24
|
+
pageInfo {
|
|
25
|
+
hasPreviousPage
|
|
26
|
+
startCursor
|
|
27
|
+
}
|
|
28
|
+
nodes {
|
|
29
|
+
id
|
|
30
|
+
isResolved
|
|
31
|
+
isOutdated
|
|
32
|
+
path
|
|
33
|
+
line
|
|
34
|
+
startLine
|
|
35
|
+
comments(first: 100) {
|
|
36
|
+
pageInfo {
|
|
37
|
+
hasNextPage
|
|
38
|
+
endCursor
|
|
39
|
+
}
|
|
40
|
+
nodes {
|
|
41
|
+
id
|
|
42
|
+
isMinimized
|
|
43
|
+
url
|
|
44
|
+
authorAssociation
|
|
45
|
+
author {
|
|
46
|
+
__typename
|
|
47
|
+
login
|
|
48
|
+
}
|
|
49
|
+
pullRequestReview {
|
|
50
|
+
id
|
|
51
|
+
}
|
|
52
|
+
body
|
|
53
|
+
path
|
|
54
|
+
line
|
|
55
|
+
startLine
|
|
56
|
+
createdAt
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
comments(last: 100, before: $commentsCursor) @include(if: $includeComments) {
|
|
62
|
+
pageInfo {
|
|
63
|
+
hasPreviousPage
|
|
64
|
+
startCursor
|
|
65
|
+
}
|
|
66
|
+
nodes {
|
|
67
|
+
id
|
|
68
|
+
isMinimized
|
|
69
|
+
url
|
|
70
|
+
authorAssociation
|
|
71
|
+
author {
|
|
72
|
+
__typename
|
|
73
|
+
login
|
|
74
|
+
}
|
|
75
|
+
body
|
|
76
|
+
createdAt
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
changesRequestedReviews: reviews(
|
|
80
|
+
states: CHANGES_REQUESTED
|
|
81
|
+
last: 50
|
|
82
|
+
before: $changesRequestedCursor
|
|
83
|
+
) @include(if: $includeChangesRequested) {
|
|
84
|
+
pageInfo {
|
|
85
|
+
hasPreviousPage
|
|
86
|
+
startCursor
|
|
87
|
+
}
|
|
88
|
+
nodes {
|
|
89
|
+
id
|
|
90
|
+
authorAssociation
|
|
91
|
+
author {
|
|
92
|
+
__typename
|
|
93
|
+
login
|
|
94
|
+
}
|
|
95
|
+
body
|
|
96
|
+
createdAt
|
|
97
|
+
commit {
|
|
98
|
+
oid
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
reviewSummaries: reviews(states: COMMENTED, last: 50, before: $reviewSummariesCursor)
|
|
103
|
+
@include(if: $includeReviewSummaries) {
|
|
104
|
+
pageInfo {
|
|
105
|
+
hasPreviousPage
|
|
106
|
+
startCursor
|
|
107
|
+
}
|
|
108
|
+
nodes {
|
|
109
|
+
id
|
|
110
|
+
isMinimized
|
|
111
|
+
authorAssociation
|
|
112
|
+
author {
|
|
113
|
+
__typename
|
|
114
|
+
login
|
|
115
|
+
}
|
|
116
|
+
body
|
|
117
|
+
createdAt
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
approvedReviews: reviews(states: APPROVED, last: 50, before: $approvedReviewsCursor)
|
|
121
|
+
@include(if: $includeApprovedReviews) {
|
|
122
|
+
pageInfo {
|
|
123
|
+
hasPreviousPage
|
|
124
|
+
startCursor
|
|
125
|
+
}
|
|
126
|
+
nodes {
|
|
127
|
+
id
|
|
128
|
+
isMinimized
|
|
129
|
+
authorAssociation
|
|
130
|
+
author {
|
|
131
|
+
__typename
|
|
132
|
+
login
|
|
133
|
+
}
|
|
134
|
+
body
|
|
135
|
+
createdAt
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
commits(last: 1) @include(if: $includeChecks) {
|
|
139
|
+
nodes {
|
|
140
|
+
commit {
|
|
141
|
+
oid
|
|
142
|
+
statusCheckRollup {
|
|
143
|
+
contexts(first: 100, after: $checksCursor) {
|
|
144
|
+
pageInfo {
|
|
145
|
+
hasNextPage
|
|
146
|
+
endCursor
|
|
147
|
+
}
|
|
148
|
+
nodes {
|
|
149
|
+
__typename
|
|
150
|
+
... on CheckRun {
|
|
151
|
+
id
|
|
152
|
+
name
|
|
153
|
+
status
|
|
154
|
+
conclusion
|
|
155
|
+
detailsUrl
|
|
156
|
+
completedAt
|
|
157
|
+
startedAt
|
|
158
|
+
title
|
|
159
|
+
summary
|
|
160
|
+
annotations(first: 1) {
|
|
161
|
+
nodes {
|
|
162
|
+
message
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
checkSuite {
|
|
166
|
+
createdAt
|
|
167
|
+
updatedAt
|
|
168
|
+
workflowRun {
|
|
169
|
+
event
|
|
170
|
+
createdAt
|
|
171
|
+
updatedAt
|
|
172
|
+
workflow {
|
|
173
|
+
name
|
|
174
|
+
databaseId
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
... on StatusContext {
|
|
180
|
+
context
|
|
181
|
+
state
|
|
182
|
+
createdAt
|
|
183
|
+
targetUrl
|
|
184
|
+
description
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
}
|
|
@@ -1,14 +1,6 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
$pr: Int!
|
|
5
|
-
$threadsCursor: String
|
|
6
|
-
$checksCursor: String
|
|
7
|
-
$commentsCursor: String
|
|
8
|
-
$changesRequestedCursor: String
|
|
9
|
-
$reviewSummariesCursor: String
|
|
10
|
-
$approvedReviewsCursor: String
|
|
11
|
-
) {
|
|
1
|
+
# First page only. Extra pages use batch-pr-page.gql so follow-ups do not
|
|
2
|
+
# re-select every connection (GraphQL points scale with possible nodes).
|
|
3
|
+
query BatchPr($owner: String!, $repo: String!, $pr: Int!) {
|
|
12
4
|
repository(owner: $owner, name: $repo) {
|
|
13
5
|
pullRequest(number: $pr) {
|
|
14
6
|
id
|
|
@@ -24,13 +16,62 @@ query BatchPr(
|
|
|
24
16
|
nameWithOwner
|
|
25
17
|
}
|
|
26
18
|
baseRefName
|
|
19
|
+
isInMergeQueue
|
|
20
|
+
isMergeQueueEnabled
|
|
21
|
+
mergeQueueEntry {
|
|
22
|
+
position
|
|
23
|
+
state
|
|
24
|
+
estimatedTimeToMerge
|
|
25
|
+
}
|
|
26
|
+
stack {
|
|
27
|
+
number
|
|
28
|
+
size
|
|
29
|
+
baseRefName
|
|
30
|
+
}
|
|
31
|
+
stackEntry {
|
|
32
|
+
position
|
|
33
|
+
}
|
|
27
34
|
baseRef {
|
|
28
35
|
branchProtectionRule {
|
|
29
36
|
requiresApprovingReviews
|
|
30
37
|
requiredApprovingReviewCount
|
|
31
38
|
requiresConversationResolution
|
|
39
|
+
requiresCodeOwnerReviews
|
|
40
|
+
requireLastPushApproval
|
|
41
|
+
requiresCommitSignatures
|
|
42
|
+
requiresLinearHistory
|
|
32
43
|
requiresStatusChecks
|
|
33
44
|
requiredStatusCheckContexts
|
|
45
|
+
requiresStrictStatusChecks
|
|
46
|
+
requiresDeployments
|
|
47
|
+
requiredDeploymentEnvironments
|
|
48
|
+
}
|
|
49
|
+
rules(first: 100) {
|
|
50
|
+
nodes {
|
|
51
|
+
type
|
|
52
|
+
parameters {
|
|
53
|
+
... on PullRequestParameters {
|
|
54
|
+
requiredApprovingReviewCount
|
|
55
|
+
requiredReviewThreadResolution
|
|
56
|
+
requireCodeOwnerReview
|
|
57
|
+
requireLastPushApproval
|
|
58
|
+
}
|
|
59
|
+
... on RequiredStatusChecksParameters {
|
|
60
|
+
strictRequiredStatusChecksPolicy
|
|
61
|
+
requiredStatusChecks {
|
|
62
|
+
context
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
... on RequiredDeploymentsParameters {
|
|
66
|
+
requiredDeploymentEnvironments
|
|
67
|
+
}
|
|
68
|
+
... on CodeScanningParameters {
|
|
69
|
+
codeScanningTools {
|
|
70
|
+
tool
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
}
|
|
34
75
|
}
|
|
35
76
|
}
|
|
36
77
|
# Not paginated — capped at 50; PRs with more pending reviewers truncate silently.
|
|
@@ -61,7 +102,7 @@ query BatchPr(
|
|
|
61
102
|
state
|
|
62
103
|
}
|
|
63
104
|
}
|
|
64
|
-
reviewThreads(last: 100
|
|
105
|
+
reviewThreads(last: 100) {
|
|
65
106
|
pageInfo {
|
|
66
107
|
hasPreviousPage
|
|
67
108
|
startCursor
|
|
@@ -99,7 +140,7 @@ query BatchPr(
|
|
|
99
140
|
}
|
|
100
141
|
}
|
|
101
142
|
}
|
|
102
|
-
comments(last: 100
|
|
143
|
+
comments(last: 100) {
|
|
103
144
|
pageInfo {
|
|
104
145
|
hasPreviousPage
|
|
105
146
|
startCursor
|
|
@@ -117,11 +158,7 @@ query BatchPr(
|
|
|
117
158
|
createdAt
|
|
118
159
|
}
|
|
119
160
|
}
|
|
120
|
-
changesRequestedReviews: reviews(
|
|
121
|
-
states: CHANGES_REQUESTED
|
|
122
|
-
last: 50
|
|
123
|
-
before: $changesRequestedCursor
|
|
124
|
-
) {
|
|
161
|
+
changesRequestedReviews: reviews(states: CHANGES_REQUESTED, last: 50) {
|
|
125
162
|
pageInfo {
|
|
126
163
|
hasPreviousPage
|
|
127
164
|
startCursor
|
|
@@ -140,7 +177,7 @@ query BatchPr(
|
|
|
140
177
|
}
|
|
141
178
|
}
|
|
142
179
|
}
|
|
143
|
-
reviewSummaries: reviews(states: COMMENTED, last: 50
|
|
180
|
+
reviewSummaries: reviews(states: COMMENTED, last: 50) {
|
|
144
181
|
pageInfo {
|
|
145
182
|
hasPreviousPage
|
|
146
183
|
startCursor
|
|
@@ -160,7 +197,7 @@ query BatchPr(
|
|
|
160
197
|
allReviews: reviews(last: 1) {
|
|
161
198
|
totalCount
|
|
162
199
|
}
|
|
163
|
-
approvedReviews: reviews(states: APPROVED, last: 50
|
|
200
|
+
approvedReviews: reviews(states: APPROVED, last: 50) {
|
|
164
201
|
pageInfo {
|
|
165
202
|
hasPreviousPage
|
|
166
203
|
startCursor
|
|
@@ -183,8 +220,24 @@ query BatchPr(
|
|
|
183
220
|
commit {
|
|
184
221
|
oid
|
|
185
222
|
committedDate
|
|
223
|
+
checkSuites(first: 50) {
|
|
224
|
+
pageInfo {
|
|
225
|
+
hasNextPage
|
|
226
|
+
}
|
|
227
|
+
nodes {
|
|
228
|
+
conclusion
|
|
229
|
+
workflowRun {
|
|
230
|
+
databaseId
|
|
231
|
+
event
|
|
232
|
+
url
|
|
233
|
+
workflow {
|
|
234
|
+
name
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
}
|
|
186
239
|
statusCheckRollup {
|
|
187
|
-
contexts(first: 100
|
|
240
|
+
contexts(first: 100) {
|
|
188
241
|
pageInfo {
|
|
189
242
|
hasNextPage
|
|
190
243
|
endCursor
|
|
@@ -201,6 +254,11 @@ query BatchPr(
|
|
|
201
254
|
startedAt
|
|
202
255
|
title
|
|
203
256
|
summary
|
|
257
|
+
annotations(first: 1) {
|
|
258
|
+
nodes {
|
|
259
|
+
message
|
|
260
|
+
}
|
|
261
|
+
}
|
|
204
262
|
checkSuite {
|
|
205
263
|
createdAt
|
|
206
264
|
updatedAt
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
query CommitSuggestionThread($owner: String!, $repo: String!, $pr: Int!, $threadId: ID!) {
|
|
2
|
+
repository(owner: $owner, name: $repo) {
|
|
3
|
+
pullRequest(number: $pr) {
|
|
4
|
+
headRefOid
|
|
5
|
+
headRefName
|
|
6
|
+
headRepository {
|
|
7
|
+
nameWithOwner
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
node(id: $threadId) {
|
|
12
|
+
... on PullRequestReviewThread {
|
|
13
|
+
id
|
|
14
|
+
isResolved
|
|
15
|
+
isOutdated
|
|
16
|
+
path
|
|
17
|
+
line
|
|
18
|
+
startLine
|
|
19
|
+
pullRequest {
|
|
20
|
+
number
|
|
21
|
+
}
|
|
22
|
+
comments(first: 1) {
|
|
23
|
+
nodes {
|
|
24
|
+
isMinimized
|
|
25
|
+
url
|
|
26
|
+
authorAssociation
|
|
27
|
+
author {
|
|
28
|
+
__typename
|
|
29
|
+
login
|
|
30
|
+
}
|
|
31
|
+
body
|
|
32
|
+
path
|
|
33
|
+
line
|
|
34
|
+
startLine
|
|
35
|
+
createdAt
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
}
|
package/bin/github/http.d.mts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
export { GitHubRequestError } from "./errors.mts";
|
|
2
2
|
export { _resetTokenCache } from "./http-auth.mts";
|
|
3
3
|
export { graphql, graphqlWithRateLimit } from "./graphql-http.mts";
|
|
4
|
-
export { rest,
|
|
4
|
+
export { rest, restWithRateLimit } from "./rest-http.mts";
|
|
5
|
+
export { restText } from "./rest-text.mts";
|
|
5
6
|
export type { RateLimitInfo } from "./http-utils.mts";
|
package/bin/github/http.mjs
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
export { GitHubRequestError } from "./errors.mjs";
|
|
2
2
|
export { _resetTokenCache } from "./http-auth.mjs";
|
|
3
3
|
export { graphql, graphqlWithRateLimit } from "./graphql-http.mjs";
|
|
4
|
-
export { rest,
|
|
4
|
+
export { rest, restWithRateLimit } from "./rest-http.mjs";
|
|
5
|
+
export { restText } from "./rest-text.mjs";
|
|
@@ -6,8 +6,9 @@
|
|
|
6
6
|
* that returns pages of fake data.
|
|
7
7
|
*
|
|
8
8
|
* GitHub's GraphQL connections support two cursor directions:
|
|
9
|
-
* - Forward (`after` + `first`) — used by check contexts.
|
|
10
|
-
* - Backward (`before` + `last`) — used by reviewThreads
|
|
9
|
+
* - Forward (`after` + `first`) — used by check contexts and nested thread comments.
|
|
10
|
+
* - Backward (`before` + `last`) — used by reviewThreads/comments/reviews extra pages
|
|
11
|
+
* (combined in `batch-page.mts`; `paginateBackward` remains the generic primitive).
|
|
11
12
|
*/
|
|
12
13
|
interface PageInfo {
|
|
13
14
|
hasNextPage?: boolean;
|
|
@@ -6,8 +6,9 @@
|
|
|
6
6
|
* that returns pages of fake data.
|
|
7
7
|
*
|
|
8
8
|
* GitHub's GraphQL connections support two cursor directions:
|
|
9
|
-
* - Forward (`after` + `first`) — used by check contexts.
|
|
10
|
-
* - Backward (`before` + `last`) — used by reviewThreads
|
|
9
|
+
* - Forward (`after` + `first`) — used by check contexts and nested thread comments.
|
|
10
|
+
* - Backward (`before` + `last`) — used by reviewThreads/comments/reviews extra pages
|
|
11
|
+
* (combined in `batch-page.mts`; `paginateBackward` remains the generic primitive).
|
|
11
12
|
*/
|
|
12
13
|
/**
|
|
13
14
|
* Paginate forward through a GraphQL connection (`first` / `after` cursors).
|
package/bin/github/queries.d.mts
CHANGED
|
@@ -8,6 +8,10 @@
|
|
|
8
8
|
*/
|
|
9
9
|
/** The primary batch query that fetches CI + comments + merge status in one round-trip. */
|
|
10
10
|
export declare const BATCH_PR_QUERY: string;
|
|
11
|
+
/** Slim @include follow-up for outstanding batch-query connections. */
|
|
12
|
+
export declare const BATCH_PR_PAGE_QUERY: string;
|
|
13
|
+
/** PR head fields plus a single review thread for `commit-suggestion`. */
|
|
14
|
+
export declare const COMMIT_SUGGESTION_THREAD_QUERY: string;
|
|
11
15
|
/** Fetches additional comments for a single review thread when its nested connection paginates. */
|
|
12
16
|
export declare const REVIEW_THREAD_COMMENTS_QUERY: string;
|
|
13
17
|
/** Fetch inline annotations for a single CheckRun by node ID. */
|
package/bin/github/queries.mjs
CHANGED
|
@@ -11,6 +11,10 @@ import { join } from "node:path";
|
|
|
11
11
|
const gql = (name) => readFileSync(join(import.meta.dirname, "gql", name), "utf8");
|
|
12
12
|
/** The primary batch query that fetches CI + comments + merge status in one round-trip. */
|
|
13
13
|
export const BATCH_PR_QUERY = gql("batch-pr.gql");
|
|
14
|
+
/** Slim @include follow-up for outstanding batch-query connections. */
|
|
15
|
+
export const BATCH_PR_PAGE_QUERY = gql("batch-pr-page.gql");
|
|
16
|
+
/** PR head fields plus a single review thread for `commit-suggestion`. */
|
|
17
|
+
export const COMMIT_SUGGESTION_THREAD_QUERY = gql("commit-suggestion-thread.gql");
|
|
14
18
|
/** Fetches additional comments for a single review thread when its nested connection paginates. */
|
|
15
19
|
export const REVIEW_THREAD_COMMENTS_QUERY = gql("review-thread-comments.gql");
|
|
16
20
|
/** Fetch inline annotations for a single CheckRun by node ID. */
|
|
@@ -1,2 +1,7 @@
|
|
|
1
|
+
import { type RateLimitInfo } from "./http-utils.mts";
|
|
2
|
+
export interface RestResult<T = unknown> {
|
|
3
|
+
data: T;
|
|
4
|
+
rateLimit?: RateLimitInfo;
|
|
5
|
+
}
|
|
1
6
|
export declare function rest<T = unknown>(method: string, path: string, body?: unknown): Promise<T>;
|
|
2
|
-
export declare function
|
|
7
|
+
export declare function restWithRateLimit<T = unknown>(method: string, path: string, body?: unknown): Promise<RestResult<T>>;
|