pr-shepherd 0.35.0 → 0.36.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/triage.mjs +11 -3
- package/bin/cli/args.mjs +1 -0
- package/bin/cli/default-poll.mjs +1 -0
- 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.d.mts +1 -0
- package/bin/commands/check.mjs +26 -22
- package/bin/commands/commit-suggestion.mjs +11 -5
- package/bin/commands/iterate/fix-code.mjs +1 -1
- package/bin/commands/iterate/helpers.d.mts +1 -0
- package/bin/commands/iterate/helpers.mjs +15 -6
- package/bin/commands/iterate/index.mjs +3 -10
- 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-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 +20 -11
- package/bin/github/batch.d.mts +2 -0
- package/bin/github/batch.mjs +14 -120
- package/bin/github/gql/batch-pr-page.gql +189 -0
- package/bin/github/gql/batch-pr.gql +74 -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/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/github.d.mts +4 -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.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
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { mapAuthorType, parseCreatedAt, mapStatusContextState, latestApprovedLogins, isReviewStale, mapCheckRunNode, } from "./batch-parser-helpers.mjs";
|
|
2
2
|
import { buildPrActivitySummary } from "./activity.mjs";
|
|
3
3
|
import { parseBranchProtection } from "./branch-protection.mjs";
|
|
4
|
+
import { parseBranchRules, parseMergeQueueEntry, parseStack } from "./batch-parsers-rules.mjs";
|
|
4
5
|
function parseReviewNode(r) {
|
|
5
6
|
const base = {
|
|
6
7
|
id: r.id,
|
|
@@ -130,6 +131,11 @@ export function parseRawPr(raw, rawThreadPages, rawCommentNodes, rawReviewNodes,
|
|
|
130
131
|
approvedReviews,
|
|
131
132
|
checks,
|
|
132
133
|
branchProtection: parseBranchProtection(raw),
|
|
134
|
+
branchRules: parseBranchRules(raw.baseRef),
|
|
135
|
+
isInMergeQueue: raw.isInMergeQueue ?? false,
|
|
136
|
+
isMergeQueueEnabled: raw.isMergeQueueEnabled ?? false,
|
|
137
|
+
mergeQueueEntry: parseMergeQueueEntry(raw.mergeQueueEntry),
|
|
138
|
+
stack: parseStack(raw),
|
|
133
139
|
activity: buildPrActivitySummary(raw, comments, reviewThreads, reviewSummaries, allChangesRequestedReviews, approvedReviews),
|
|
134
140
|
};
|
|
135
141
|
}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
export interface RawBranchProtectionRule {
|
|
2
|
+
requiresApprovingReviews: boolean;
|
|
3
|
+
requiredApprovingReviewCount: number;
|
|
4
|
+
requiresConversationResolution: boolean;
|
|
5
|
+
requiresStatusChecks: boolean;
|
|
6
|
+
requiredStatusCheckContexts: string[] | null;
|
|
7
|
+
requiresCodeOwnerReviews?: boolean;
|
|
8
|
+
requireLastPushApproval?: boolean;
|
|
9
|
+
requiresCommitSignatures?: boolean;
|
|
10
|
+
requiresLinearHistory?: boolean;
|
|
11
|
+
requiresStrictStatusChecks?: boolean;
|
|
12
|
+
requiresDeployments?: boolean;
|
|
13
|
+
requiredDeploymentEnvironments?: string[] | null;
|
|
14
|
+
}
|
|
15
|
+
interface RawMergeQueueEntry {
|
|
16
|
+
position: number;
|
|
17
|
+
state: string;
|
|
18
|
+
estimatedTimeToMerge: number | null;
|
|
19
|
+
}
|
|
20
|
+
interface RawStack {
|
|
21
|
+
number: number;
|
|
22
|
+
size: number;
|
|
23
|
+
baseRefName: string;
|
|
24
|
+
}
|
|
25
|
+
export interface RawRepositoryRule {
|
|
26
|
+
type: string;
|
|
27
|
+
parameters: RawRuleParameters | null;
|
|
28
|
+
}
|
|
29
|
+
interface RawRuleParameters {
|
|
30
|
+
requiredApprovingReviewCount?: number;
|
|
31
|
+
requiredReviewThreadResolution?: boolean;
|
|
32
|
+
requireCodeOwnerReview?: boolean;
|
|
33
|
+
requireLastPushApproval?: boolean;
|
|
34
|
+
strictRequiredStatusChecksPolicy?: boolean;
|
|
35
|
+
requiredStatusChecks?: Array<{
|
|
36
|
+
context: string;
|
|
37
|
+
}>;
|
|
38
|
+
requiredDeploymentEnvironments?: string[];
|
|
39
|
+
codeScanningTools?: Array<{
|
|
40
|
+
tool: string;
|
|
41
|
+
}>;
|
|
42
|
+
}
|
|
43
|
+
export interface RawBaseRef {
|
|
44
|
+
branchProtectionRule: RawBranchProtectionRule | null;
|
|
45
|
+
rules: {
|
|
46
|
+
nodes: RawRepositoryRule[];
|
|
47
|
+
} | null;
|
|
48
|
+
}
|
|
49
|
+
export interface RawPrMergeFields {
|
|
50
|
+
isInMergeQueue?: boolean;
|
|
51
|
+
isMergeQueueEnabled?: boolean;
|
|
52
|
+
mergeQueueEntry?: RawMergeQueueEntry | null;
|
|
53
|
+
stack?: RawStack | null;
|
|
54
|
+
stackEntry?: {
|
|
55
|
+
position: number;
|
|
56
|
+
} | null;
|
|
57
|
+
baseRef?: RawBaseRef | null;
|
|
58
|
+
}
|
|
59
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import type { CommentAuthorAssociation } from "../types/github.mts";
|
|
2
|
+
import type { RawPrMergeFields } from "./batch-raw-rules.mts";
|
|
2
3
|
export interface RawBatchResponse {
|
|
3
4
|
repository: {
|
|
4
5
|
pullRequest: RawPr | null;
|
|
5
6
|
} | null;
|
|
6
7
|
}
|
|
7
|
-
export interface RawPr {
|
|
8
|
+
export interface RawPr extends RawPrMergeFields {
|
|
8
9
|
id: string;
|
|
9
10
|
number: number;
|
|
10
11
|
state: string;
|
|
@@ -18,9 +19,7 @@ export interface RawPr {
|
|
|
18
19
|
nameWithOwner: string;
|
|
19
20
|
} | null;
|
|
20
21
|
baseRefName: string;
|
|
21
|
-
baseRef:
|
|
22
|
-
branchProtectionRule: RawBranchProtectionRule | null;
|
|
23
|
-
} | null;
|
|
22
|
+
baseRef: import("./batch-raw-rules.mts").RawBaseRef | null;
|
|
24
23
|
reviewRequests: {
|
|
25
24
|
nodes: Array<{
|
|
26
25
|
requestedReviewer: {
|
|
@@ -79,6 +78,7 @@ export interface RawPr {
|
|
|
79
78
|
commit: {
|
|
80
79
|
oid: string;
|
|
81
80
|
committedDate?: string;
|
|
81
|
+
checkSuites?: RawCheckSuites;
|
|
82
82
|
statusCheckRollup: {
|
|
83
83
|
contexts: {
|
|
84
84
|
pageInfo: {
|
|
@@ -92,6 +92,22 @@ export interface RawPr {
|
|
|
92
92
|
}>;
|
|
93
93
|
};
|
|
94
94
|
}
|
|
95
|
+
interface RawCheckSuites {
|
|
96
|
+
pageInfo: {
|
|
97
|
+
hasNextPage: boolean;
|
|
98
|
+
};
|
|
99
|
+
nodes: Array<{
|
|
100
|
+
conclusion: string | null;
|
|
101
|
+
workflowRun: {
|
|
102
|
+
databaseId: number | null;
|
|
103
|
+
event: string | null;
|
|
104
|
+
url: string | null;
|
|
105
|
+
workflow: {
|
|
106
|
+
name: string | null;
|
|
107
|
+
} | null;
|
|
108
|
+
} | null;
|
|
109
|
+
}>;
|
|
110
|
+
}
|
|
95
111
|
interface RawAuthor {
|
|
96
112
|
__typename?: string;
|
|
97
113
|
login: string;
|
|
@@ -165,13 +181,6 @@ export interface RawReviewSummary {
|
|
|
165
181
|
body: string;
|
|
166
182
|
createdAt?: string;
|
|
167
183
|
}
|
|
168
|
-
interface RawBranchProtectionRule {
|
|
169
|
-
requiresApprovingReviews: boolean;
|
|
170
|
-
requiredApprovingReviewCount: number;
|
|
171
|
-
requiresConversationResolution: boolean;
|
|
172
|
-
requiresStatusChecks: boolean;
|
|
173
|
-
requiredStatusCheckContexts: string[] | null;
|
|
174
|
-
}
|
|
175
184
|
export type RawContextNode = {
|
|
176
185
|
__typename: "CheckRun";
|
|
177
186
|
id: string;
|
package/bin/github/batch.d.mts
CHANGED
|
@@ -3,6 +3,8 @@ import type { BatchPrData } from "../types.mts";
|
|
|
3
3
|
interface BatchResult {
|
|
4
4
|
data: BatchPrData;
|
|
5
5
|
rateLimit?: RateLimitInfo;
|
|
6
|
+
/** True when GraphQL returned a complete CheckSuite page; skip REST startup-failure fetch. */
|
|
7
|
+
checkSuitesComplete?: boolean;
|
|
6
8
|
}
|
|
7
9
|
interface FetchPrBatchOptions {
|
|
8
10
|
/**
|
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,189 @@
|
|
|
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
|
+
checkSuite {
|
|
161
|
+
createdAt
|
|
162
|
+
updatedAt
|
|
163
|
+
workflowRun {
|
|
164
|
+
event
|
|
165
|
+
createdAt
|
|
166
|
+
updatedAt
|
|
167
|
+
workflow {
|
|
168
|
+
name
|
|
169
|
+
databaseId
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
... on StatusContext {
|
|
175
|
+
context
|
|
176
|
+
state
|
|
177
|
+
createdAt
|
|
178
|
+
targetUrl
|
|
179
|
+
description
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
}
|
|
@@ -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
|
|
@@ -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
|
+
}
|