@blogic-cz/agent-tools 1.7.5 → 1.8.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/README.md +2 -1
- package/dist/db-tool/service.d.ts.map +1 -1
- package/dist/gh-tool/branch.d.ts +2 -3
- package/dist/gh-tool/branch.d.ts.map +1 -1
- package/dist/gh-tool/environment.d.ts +1 -1
- package/dist/gh-tool/environment.d.ts.map +1 -1
- package/dist/gh-tool/gist.d.ts +8 -28
- package/dist/gh-tool/gist.d.ts.map +1 -1
- package/dist/gh-tool/issue/commands.d.ts +9 -9
- package/dist/gh-tool/issue/commands.d.ts.map +1 -1
- package/dist/gh-tool/issue/core.d.ts +103 -9
- package/dist/gh-tool/issue/core.d.ts.map +1 -1
- package/dist/gh-tool/issue/triage.d.ts +6 -6
- package/dist/gh-tool/issue/triage.d.ts.map +1 -1
- package/dist/gh-tool/pr/commands.d.ts +53 -46
- package/dist/gh-tool/pr/commands.d.ts.map +1 -1
- package/dist/gh-tool/pr/core.d.ts +156 -86
- package/dist/gh-tool/pr/core.d.ts.map +1 -1
- package/dist/gh-tool/pr/review.d.ts +16 -16
- package/dist/gh-tool/pr/review.d.ts.map +1 -1
- package/dist/gh-tool/pr/snapshot.d.ts +9 -0
- package/dist/gh-tool/pr/snapshot.d.ts.map +1 -0
- package/dist/gh-tool/pr/stack-read.d.ts +1 -6
- package/dist/gh-tool/pr/stack-read.d.ts.map +1 -1
- package/dist/gh-tool/pr/stack.d.ts +3 -3
- package/dist/gh-tool/pr/stack.d.ts.map +1 -1
- package/dist/gh-tool/{api.d.ts → read/api.d.ts} +9 -3
- package/dist/gh-tool/read/api.d.ts.map +1 -0
- package/dist/gh-tool/read/cache.d.ts +44 -0
- package/dist/gh-tool/read/cache.d.ts.map +1 -0
- package/dist/gh-tool/read/catalog.d.ts +170 -0
- package/dist/gh-tool/read/catalog.d.ts.map +1 -0
- package/dist/gh-tool/read/classes.d.ts +94 -0
- package/dist/gh-tool/read/classes.d.ts.map +1 -0
- package/dist/gh-tool/read/commands.d.ts +3 -0
- package/dist/gh-tool/read/commands.d.ts.map +1 -0
- package/dist/gh-tool/read/gated.d.ts +14 -0
- package/dist/gh-tool/read/gated.d.ts.map +1 -0
- package/dist/gh-tool/read/index.d.ts +5 -0
- package/dist/gh-tool/read/index.d.ts.map +1 -0
- package/dist/gh-tool/read/issues.d.ts +68 -0
- package/dist/gh-tool/read/issues.d.ts.map +1 -0
- package/dist/gh-tool/read/keys.d.ts +61 -0
- package/dist/gh-tool/read/keys.d.ts.map +1 -0
- package/dist/gh-tool/read/porcelain.d.ts +68 -0
- package/dist/gh-tool/read/porcelain.d.ts.map +1 -0
- package/dist/gh-tool/read/pulls.d.ts +137 -0
- package/dist/gh-tool/read/pulls.d.ts.map +1 -0
- package/dist/gh-tool/read/reads.d.ts +209 -0
- package/dist/gh-tool/read/reads.d.ts.map +1 -0
- package/dist/gh-tool/read/rest.d.ts +49 -0
- package/dist/gh-tool/read/rest.d.ts.map +1 -0
- package/dist/gh-tool/read/review-guards.d.ts +20 -0
- package/dist/gh-tool/read/review-guards.d.ts.map +1 -0
- package/dist/gh-tool/read/review-model.d.ts +190 -0
- package/dist/gh-tool/read/review-model.d.ts.map +1 -0
- package/dist/gh-tool/read/reviews.d.ts +9 -0
- package/dist/gh-tool/read/reviews.d.ts.map +1 -0
- package/dist/gh-tool/read/stacks.d.ts +7 -0
- package/dist/gh-tool/read/stacks.d.ts.map +1 -0
- package/dist/gh-tool/read/store.d.ts +70 -0
- package/dist/gh-tool/read/store.d.ts.map +1 -0
- package/dist/gh-tool/{service.d.ts → read/transport.d.ts} +5 -3
- package/dist/gh-tool/read/transport.d.ts.map +1 -0
- package/dist/gh-tool/read/waits.d.ts +22 -0
- package/dist/gh-tool/read/waits.d.ts.map +1 -0
- package/dist/gh-tool/read/writes.d.ts +16 -0
- package/dist/gh-tool/read/writes.d.ts.map +1 -0
- package/dist/gh-tool/release.d.ts +10 -26
- package/dist/gh-tool/release.d.ts.map +1 -1
- package/dist/gh-tool/repo.d.ts +4 -4
- package/dist/gh-tool/repo.d.ts.map +1 -1
- package/dist/gh-tool/types.d.ts +1 -1
- package/dist/gh-tool/types.d.ts.map +1 -1
- package/dist/gh-tool/workflow.d.ts +43 -21
- package/dist/gh-tool/workflow.d.ts.map +1 -1
- package/dist/observability-tool/shared.d.ts.map +1 -1
- package/dist/shared/content-security.d.ts +2 -0
- package/dist/shared/content-security.d.ts.map +1 -1
- package/package.json +6 -6
- package/src/api-tool/proxy-entry.ts +3 -1
- package/src/db-tool/service.ts +4 -1
- package/src/gh-tool/branch.ts +5 -8
- package/src/gh-tool/environment.ts +2 -1
- package/src/gh-tool/gist.ts +8 -35
- package/src/gh-tool/issue/commands.ts +1 -1
- package/src/gh-tool/issue/core.ts +55 -122
- package/src/gh-tool/issue/triage.ts +4 -26
- package/src/gh-tool/main.ts +5 -2
- package/src/gh-tool/pr/commands.ts +17 -15
- package/src/gh-tool/pr/core.ts +486 -582
- package/src/gh-tool/pr/review.ts +106 -454
- package/src/gh-tool/pr/snapshot.ts +23 -0
- package/src/gh-tool/pr/stack-read.ts +1 -73
- package/src/gh-tool/pr/stack.ts +37 -36
- package/src/gh-tool/{api.ts → read/api.ts} +40 -7
- package/src/gh-tool/read/cache.ts +192 -0
- package/src/gh-tool/read/catalog.ts +310 -0
- package/src/gh-tool/read/classes.ts +30 -0
- package/src/gh-tool/read/commands.ts +25 -0
- package/src/gh-tool/read/gated.ts +56 -0
- package/src/gh-tool/read/index.ts +4 -0
- package/src/gh-tool/read/issues.ts +107 -0
- package/src/gh-tool/read/keys.ts +102 -0
- package/src/gh-tool/read/porcelain.ts +58 -0
- package/src/gh-tool/read/pulls.ts +266 -0
- package/src/gh-tool/read/reads.ts +306 -0
- package/src/gh-tool/read/rest.ts +111 -0
- package/src/gh-tool/read/review-guards.ts +61 -0
- package/src/gh-tool/read/review-model.ts +286 -0
- package/src/gh-tool/read/reviews.ts +114 -0
- package/src/gh-tool/read/stacks.ts +73 -0
- package/src/gh-tool/read/store.ts +504 -0
- package/src/gh-tool/{service.ts → read/transport.ts} +26 -6
- package/src/gh-tool/read/waits.ts +52 -0
- package/src/gh-tool/read/writes.ts +37 -0
- package/src/gh-tool/release.ts +15 -168
- package/src/gh-tool/repo.ts +5 -78
- package/src/gh-tool/types.ts +1 -1
- package/src/gh-tool/workflow.ts +123 -214
- package/src/observability-tool/shared.ts +2 -1
- package/src/shared/content-security.ts +10 -1
- package/src/shared/credential-patterns.ts +1 -1
- package/dist/gh-tool/api.d.ts.map +0 -1
- package/dist/gh-tool/pr/check-status-cache.d.ts +0 -6
- package/dist/gh-tool/pr/check-status-cache.d.ts.map +0 -1
- package/dist/gh-tool/service.d.ts.map +0 -1
- package/src/gh-tool/pr/check-status-cache.ts +0 -142
package/src/gh-tool/pr/review.ts
CHANGED
|
@@ -14,302 +14,52 @@ import type {
|
|
|
14
14
|
import type { REVIEW_EVENTS } from "#gh/config";
|
|
15
15
|
|
|
16
16
|
import { GitHubCommandError } from "#gh/errors";
|
|
17
|
-
import { GitHubService } from "#gh/
|
|
17
|
+
import { GitHubService } from "#gh/read/transport";
|
|
18
|
+
import { repoSlug } from "#gh/read/keys";
|
|
19
|
+
import type { RepoRef, Tag } from "#gh/read/keys";
|
|
18
20
|
import { validateOutboundText } from "#gh/text-input";
|
|
19
21
|
|
|
20
22
|
import { viewPR } from "./core";
|
|
23
|
+
import { reads, resolveRepo, writes } from "#gh/read/index";
|
|
24
|
+
import { RESOLVE_THREAD_MUTATION, SUBMIT_REVIEW_MUTATION } from "#gh/read/review-model";
|
|
25
|
+
import type {
|
|
26
|
+
ThreadNode,
|
|
27
|
+
RawIssueComment,
|
|
28
|
+
EditableComment,
|
|
29
|
+
RequestedReviewerNode,
|
|
30
|
+
ResolveThreadResult,
|
|
31
|
+
PendingReviewsQueryResult,
|
|
32
|
+
PendingReviewContentQueryResult,
|
|
33
|
+
SubmitReviewResult,
|
|
34
|
+
} from "#gh/read/review-model";
|
|
35
|
+
const reviewTags = (
|
|
36
|
+
repo: RepoRef,
|
|
37
|
+
pr: number | null,
|
|
38
|
+
facet: "issue-comments" | "review-comments" | "reviews",
|
|
39
|
+
): readonly Tag[] =>
|
|
40
|
+
pr === null
|
|
41
|
+
? [`repo:${repoSlug(repo)}`]
|
|
42
|
+
: facet === "issue-comments"
|
|
43
|
+
? [`issue-comments:${repoSlug(repo)}#${pr}`]
|
|
44
|
+
: facet === "reviews"
|
|
45
|
+
? [
|
|
46
|
+
`pulls:${repoSlug(repo)}`,
|
|
47
|
+
`reviews:${repoSlug(repo)}#${pr}`,
|
|
48
|
+
`review-comments:${repoSlug(repo)}#${pr}`,
|
|
49
|
+
`pr:${repoSlug(repo)}#${pr}`,
|
|
50
|
+
`threads:${repoSlug(repo)}#${pr}`,
|
|
51
|
+
]
|
|
52
|
+
: [`review-comments:${repoSlug(repo)}#${pr}`, `threads:${repoSlug(repo)}#${pr}`];
|
|
53
|
+
|
|
54
|
+
const fetchAllThreadNodes = (pr: number) =>
|
|
55
|
+
Effect.gen(function* () {
|
|
56
|
+
return yield* reads.reviewThreads(yield* resolveRepo(null), pr);
|
|
57
|
+
});
|
|
21
58
|
|
|
22
59
|
// ---------------------------------------------------------------------------
|
|
23
60
|
// GraphQL queries & mutations
|
|
24
61
|
// ---------------------------------------------------------------------------
|
|
25
62
|
|
|
26
|
-
const REVIEW_THREADS_QUERY = `
|
|
27
|
-
query($owner: String!, $name: String!, $pr: Int!, $after: String) {
|
|
28
|
-
repository(owner: $owner, name: $name) {
|
|
29
|
-
pullRequest(number: $pr) {
|
|
30
|
-
reviewThreads(first: 100, after: $after) {
|
|
31
|
-
nodes {
|
|
32
|
-
id
|
|
33
|
-
isResolved
|
|
34
|
-
comments(first: 100) {
|
|
35
|
-
nodes {
|
|
36
|
-
id
|
|
37
|
-
databaseId
|
|
38
|
-
path
|
|
39
|
-
line
|
|
40
|
-
body
|
|
41
|
-
author { login }
|
|
42
|
-
commit { oid }
|
|
43
|
-
}
|
|
44
|
-
pageInfo { hasNextPage endCursor }
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
-
pageInfo {
|
|
48
|
-
hasNextPage
|
|
49
|
-
endCursor
|
|
50
|
-
}
|
|
51
|
-
}
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
}
|
|
55
|
-
`;
|
|
56
|
-
|
|
57
|
-
const REVIEW_THREAD_COMMENTS_QUERY = `
|
|
58
|
-
query($threadId: ID!, $after: String) {
|
|
59
|
-
node(id: $threadId) {
|
|
60
|
-
... on PullRequestReviewThread {
|
|
61
|
-
comments(first: 100, after: $after) {
|
|
62
|
-
nodes {
|
|
63
|
-
id
|
|
64
|
-
databaseId
|
|
65
|
-
path
|
|
66
|
-
line
|
|
67
|
-
body
|
|
68
|
-
author { login }
|
|
69
|
-
commit { oid }
|
|
70
|
-
}
|
|
71
|
-
pageInfo { hasNextPage endCursor }
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
}
|
|
76
|
-
`;
|
|
77
|
-
|
|
78
|
-
const RESOLVE_THREAD_MUTATION = `
|
|
79
|
-
mutation($threadId: ID!) {
|
|
80
|
-
resolveReviewThread(input: {threadId: $threadId}) {
|
|
81
|
-
thread { id isResolved }
|
|
82
|
-
}
|
|
83
|
-
}
|
|
84
|
-
`;
|
|
85
|
-
|
|
86
|
-
const PENDING_REVIEWS_QUERY = `
|
|
87
|
-
query($owner: String!, $name: String!, $pr: Int!, $after: String) {
|
|
88
|
-
viewer { login }
|
|
89
|
-
repository(owner: $owner, name: $name) {
|
|
90
|
-
pullRequest(number: $pr) {
|
|
91
|
-
reviews(first: 100, after: $after, states: [PENDING]) {
|
|
92
|
-
nodes {
|
|
93
|
-
id
|
|
94
|
-
state
|
|
95
|
-
author { login }
|
|
96
|
-
}
|
|
97
|
-
pageInfo { hasNextPage endCursor }
|
|
98
|
-
}
|
|
99
|
-
}
|
|
100
|
-
}
|
|
101
|
-
}
|
|
102
|
-
`;
|
|
103
|
-
|
|
104
|
-
const PENDING_REVIEW_CONTENT_QUERY = `
|
|
105
|
-
query($reviewId: ID!, $after: String) {
|
|
106
|
-
viewer { login }
|
|
107
|
-
node(id: $reviewId) {
|
|
108
|
-
... on PullRequestReview {
|
|
109
|
-
id
|
|
110
|
-
state
|
|
111
|
-
body
|
|
112
|
-
author { login }
|
|
113
|
-
pullRequest {
|
|
114
|
-
number
|
|
115
|
-
repository { nameWithOwner }
|
|
116
|
-
}
|
|
117
|
-
comments(first: 100, after: $after) {
|
|
118
|
-
nodes { body }
|
|
119
|
-
pageInfo { hasNextPage endCursor }
|
|
120
|
-
}
|
|
121
|
-
}
|
|
122
|
-
}
|
|
123
|
-
}
|
|
124
|
-
`;
|
|
125
|
-
|
|
126
|
-
const SUBMIT_REVIEW_MUTATION = `
|
|
127
|
-
mutation($reviewId: ID!, $event: PullRequestReviewEvent!, $body: String) {
|
|
128
|
-
submitPullRequestReview(input: { pullRequestReviewId: $reviewId, event: $event, body: $body }) {
|
|
129
|
-
pullRequestReview { id state }
|
|
130
|
-
}
|
|
131
|
-
}
|
|
132
|
-
`;
|
|
133
|
-
|
|
134
|
-
const LAST_HUMAN_REVIEWER_QUERY = `
|
|
135
|
-
query($owner: String!, $name: String!, $pr: Int!) {
|
|
136
|
-
repository(owner: $owner, name: $name) {
|
|
137
|
-
pullRequest(number: $pr) {
|
|
138
|
-
reviewRequests(first: 100) {
|
|
139
|
-
nodes {
|
|
140
|
-
requestedReviewer {
|
|
141
|
-
__typename
|
|
142
|
-
... on User { login }
|
|
143
|
-
... on Team { name }
|
|
144
|
-
... on Bot { login }
|
|
145
|
-
}
|
|
146
|
-
}
|
|
147
|
-
}
|
|
148
|
-
reviews(last: 100) {
|
|
149
|
-
nodes {
|
|
150
|
-
author { login }
|
|
151
|
-
state
|
|
152
|
-
submittedAt
|
|
153
|
-
}
|
|
154
|
-
}
|
|
155
|
-
}
|
|
156
|
-
}
|
|
157
|
-
}
|
|
158
|
-
`;
|
|
159
|
-
|
|
160
|
-
// ---------------------------------------------------------------------------
|
|
161
|
-
// Internal types
|
|
162
|
-
// ---------------------------------------------------------------------------
|
|
163
|
-
|
|
164
|
-
type ThreadNode = {
|
|
165
|
-
id: string;
|
|
166
|
-
isResolved: boolean;
|
|
167
|
-
comments: {
|
|
168
|
-
nodes: Array<{
|
|
169
|
-
id: string;
|
|
170
|
-
databaseId: number;
|
|
171
|
-
path: string;
|
|
172
|
-
line: number;
|
|
173
|
-
body: string;
|
|
174
|
-
author: { login: string };
|
|
175
|
-
commit: { oid: string } | null;
|
|
176
|
-
}>;
|
|
177
|
-
pageInfo?: { hasNextPage: boolean; endCursor: string | null };
|
|
178
|
-
};
|
|
179
|
-
};
|
|
180
|
-
|
|
181
|
-
type ThreadCommentsQueryResult = {
|
|
182
|
-
node: { comments: ThreadNode["comments"] } | null;
|
|
183
|
-
};
|
|
184
|
-
|
|
185
|
-
type ThreadsQueryResult = {
|
|
186
|
-
repository: {
|
|
187
|
-
pullRequest: {
|
|
188
|
-
reviewThreads: {
|
|
189
|
-
nodes: ThreadNode[];
|
|
190
|
-
pageInfo: {
|
|
191
|
-
hasNextPage: boolean;
|
|
192
|
-
endCursor: string | null;
|
|
193
|
-
};
|
|
194
|
-
};
|
|
195
|
-
};
|
|
196
|
-
};
|
|
197
|
-
};
|
|
198
|
-
|
|
199
|
-
type ResolveThreadResult = {
|
|
200
|
-
resolveReviewThread: {
|
|
201
|
-
thread: { id: string; isResolved: boolean };
|
|
202
|
-
};
|
|
203
|
-
};
|
|
204
|
-
|
|
205
|
-
type PendingReviewsQueryResult = {
|
|
206
|
-
viewer: { login: string };
|
|
207
|
-
repository: {
|
|
208
|
-
pullRequest: {
|
|
209
|
-
reviews: {
|
|
210
|
-
nodes: Array<{
|
|
211
|
-
id: string;
|
|
212
|
-
state: string;
|
|
213
|
-
author: { login: string };
|
|
214
|
-
}>;
|
|
215
|
-
pageInfo: { hasNextPage: boolean; endCursor: string | null };
|
|
216
|
-
};
|
|
217
|
-
};
|
|
218
|
-
};
|
|
219
|
-
};
|
|
220
|
-
|
|
221
|
-
type PendingReviewContentQueryResult = {
|
|
222
|
-
viewer: { login: string };
|
|
223
|
-
node: {
|
|
224
|
-
id: string;
|
|
225
|
-
state: string;
|
|
226
|
-
body: string | null;
|
|
227
|
-
author: { login: string };
|
|
228
|
-
pullRequest: { number: number; repository: { nameWithOwner: string } };
|
|
229
|
-
comments: {
|
|
230
|
-
nodes: Array<{ body: string }>;
|
|
231
|
-
pageInfo: { hasNextPage: boolean; endCursor: string | null };
|
|
232
|
-
};
|
|
233
|
-
} | null;
|
|
234
|
-
};
|
|
235
|
-
|
|
236
|
-
type SubmitReviewResult = {
|
|
237
|
-
submitPullRequestReview: {
|
|
238
|
-
pullRequestReview: { id: string; state: string };
|
|
239
|
-
};
|
|
240
|
-
};
|
|
241
|
-
|
|
242
|
-
type RequestedReviewerNode = {
|
|
243
|
-
__typename: string;
|
|
244
|
-
login?: string;
|
|
245
|
-
name?: string;
|
|
246
|
-
} | null;
|
|
247
|
-
|
|
248
|
-
type LastHumanReviewerQueryResult = {
|
|
249
|
-
repository: {
|
|
250
|
-
pullRequest: {
|
|
251
|
-
reviewRequests: {
|
|
252
|
-
nodes: Array<{ requestedReviewer: RequestedReviewerNode }>;
|
|
253
|
-
};
|
|
254
|
-
reviews: {
|
|
255
|
-
nodes: Array<{
|
|
256
|
-
author: { login: string } | null;
|
|
257
|
-
state: string;
|
|
258
|
-
submittedAt: string | null;
|
|
259
|
-
}>;
|
|
260
|
-
};
|
|
261
|
-
};
|
|
262
|
-
};
|
|
263
|
-
};
|
|
264
|
-
|
|
265
|
-
type RawReviewComment = {
|
|
266
|
-
id: number;
|
|
267
|
-
in_reply_to_id: number | null;
|
|
268
|
-
user: { login: string };
|
|
269
|
-
body: string;
|
|
270
|
-
path: string;
|
|
271
|
-
line: number;
|
|
272
|
-
created_at: string;
|
|
273
|
-
updated_at: string;
|
|
274
|
-
pull_request_review_id?: number | null;
|
|
275
|
-
commit_id?: string | null;
|
|
276
|
-
};
|
|
277
|
-
|
|
278
|
-
type RawIssueComment = {
|
|
279
|
-
id: number;
|
|
280
|
-
user: { login: string };
|
|
281
|
-
body: string;
|
|
282
|
-
created_at: string;
|
|
283
|
-
html_url: string;
|
|
284
|
-
};
|
|
285
|
-
|
|
286
|
-
type RawPullRequestReview = {
|
|
287
|
-
id: number;
|
|
288
|
-
user: { login: string } | null;
|
|
289
|
-
state: string;
|
|
290
|
-
body: string | null;
|
|
291
|
-
submitted_at: string | null;
|
|
292
|
-
html_url: string;
|
|
293
|
-
commit_id?: string | null;
|
|
294
|
-
};
|
|
295
|
-
|
|
296
|
-
type ReviewCommentById = {
|
|
297
|
-
id: number;
|
|
298
|
-
in_reply_to_id: number | null;
|
|
299
|
-
pull_request_url: string;
|
|
300
|
-
};
|
|
301
|
-
|
|
302
|
-
type EditableComment = {
|
|
303
|
-
id: number;
|
|
304
|
-
user: { login: string };
|
|
305
|
-
html_url: string;
|
|
306
|
-
updated_at: string;
|
|
307
|
-
pull_request_url?: string;
|
|
308
|
-
issue_url?: string;
|
|
309
|
-
};
|
|
310
|
-
|
|
311
|
-
const REST_PAGE_SIZE = 100;
|
|
312
|
-
|
|
313
63
|
const feedbackOrigin = (commitSha: string | null, currentHeadSha: string | null): FeedbackOrigin =>
|
|
314
64
|
commitSha === null || currentHeadSha === null
|
|
315
65
|
? "unknown"
|
|
@@ -317,89 +67,6 @@ const feedbackOrigin = (commitSha: string | null, currentHeadSha: string | null)
|
|
|
317
67
|
? "current_head"
|
|
318
68
|
: "pre_existing";
|
|
319
69
|
|
|
320
|
-
const parseJson = <T>(
|
|
321
|
-
stdout: string,
|
|
322
|
-
command: string,
|
|
323
|
-
parseFailurePrefix: string,
|
|
324
|
-
): Effect.Effect<T, GitHubCommandError> =>
|
|
325
|
-
Effect.try({
|
|
326
|
-
try: () => JSON.parse(stdout) as T,
|
|
327
|
-
catch: (error) =>
|
|
328
|
-
new GitHubCommandError({
|
|
329
|
-
command,
|
|
330
|
-
exitCode: 0,
|
|
331
|
-
stderr: `${parseFailurePrefix}: ${error instanceof Error ? error.message : String(error)}`,
|
|
332
|
-
message: `${parseFailurePrefix}: ${error instanceof Error ? error.message : String(error)}`,
|
|
333
|
-
}),
|
|
334
|
-
});
|
|
335
|
-
|
|
336
|
-
const fetchAllRestPages = Effect.fn("pr.fetchAllRestPages")(function* <T>(
|
|
337
|
-
endpoint: string,
|
|
338
|
-
command: string,
|
|
339
|
-
parseFailurePrefix: string,
|
|
340
|
-
) {
|
|
341
|
-
const service = yield* GitHubService;
|
|
342
|
-
|
|
343
|
-
const results: T[] = [];
|
|
344
|
-
let page = 1;
|
|
345
|
-
|
|
346
|
-
while (true) {
|
|
347
|
-
const separator = endpoint.includes("?") ? "&" : "?";
|
|
348
|
-
const result = yield* service.runGh([
|
|
349
|
-
"api",
|
|
350
|
-
`${endpoint}${separator}per_page=${REST_PAGE_SIZE}&page=${page}`,
|
|
351
|
-
]);
|
|
352
|
-
|
|
353
|
-
const rawPage = yield* parseJson<T[]>(result.stdout, command, parseFailurePrefix);
|
|
354
|
-
results.push(...rawPage);
|
|
355
|
-
|
|
356
|
-
if (rawPage.length < REST_PAGE_SIZE) {
|
|
357
|
-
return results;
|
|
358
|
-
}
|
|
359
|
-
|
|
360
|
-
page += 1;
|
|
361
|
-
}
|
|
362
|
-
});
|
|
363
|
-
|
|
364
|
-
const fetchAllThreadNodes = Effect.fn("pr.fetchAllThreadNodes")(function* (pr: number) {
|
|
365
|
-
const service = yield* GitHubService;
|
|
366
|
-
const repoInfo = yield* service.getRepoInfo();
|
|
367
|
-
|
|
368
|
-
const nodes: ThreadNode[] = [];
|
|
369
|
-
let after: string | null = null;
|
|
370
|
-
|
|
371
|
-
while (true) {
|
|
372
|
-
const response = (yield* service.runGraphQL(REVIEW_THREADS_QUERY, {
|
|
373
|
-
owner: repoInfo.owner,
|
|
374
|
-
name: repoInfo.name,
|
|
375
|
-
pr,
|
|
376
|
-
after,
|
|
377
|
-
})) as ThreadsQueryResult;
|
|
378
|
-
|
|
379
|
-
const page = response.repository.pullRequest.reviewThreads;
|
|
380
|
-
for (const node of page.nodes) {
|
|
381
|
-
let commentsAfter = node.comments.pageInfo?.endCursor ?? null;
|
|
382
|
-
while (node.comments.pageInfo?.hasNextPage && commentsAfter !== null) {
|
|
383
|
-
const commentsResponse = (yield* service.runGraphQL(REVIEW_THREAD_COMMENTS_QUERY, {
|
|
384
|
-
threadId: node.id,
|
|
385
|
-
after: commentsAfter,
|
|
386
|
-
})) as ThreadCommentsQueryResult;
|
|
387
|
-
if (commentsResponse.node === null) break;
|
|
388
|
-
node.comments.nodes.push(...commentsResponse.node.comments.nodes);
|
|
389
|
-
node.comments.pageInfo = commentsResponse.node.comments.pageInfo;
|
|
390
|
-
commentsAfter = commentsResponse.node.comments.pageInfo?.endCursor ?? null;
|
|
391
|
-
}
|
|
392
|
-
nodes.push(node);
|
|
393
|
-
}
|
|
394
|
-
|
|
395
|
-
if (!page.pageInfo.hasNextPage || page.pageInfo.endCursor === null) {
|
|
396
|
-
return nodes;
|
|
397
|
-
}
|
|
398
|
-
|
|
399
|
-
after = page.pageInfo.endCursor;
|
|
400
|
-
}
|
|
401
|
-
});
|
|
402
|
-
|
|
403
70
|
const enrichThreads = (
|
|
404
71
|
threads: ThreadNode[],
|
|
405
72
|
reviewComments: ReviewComment[],
|
|
@@ -464,7 +131,7 @@ const enrichThreads = (
|
|
|
464
131
|
const dedupedByKey = new Map<string, number>();
|
|
465
132
|
const deduped: ReviewThread[] = [];
|
|
466
133
|
for (const thread of mapped) {
|
|
467
|
-
const key = `${thread.path}
|
|
134
|
+
const key = `${thread.path}\u0000${thread.line}\u0000${thread.body.trim()}`;
|
|
468
135
|
const existingIndex = dedupedByKey.get(key);
|
|
469
136
|
if (existingIndex === undefined) {
|
|
470
137
|
dedupedByKey.set(key, deduped.length);
|
|
@@ -546,11 +213,7 @@ export const fetchComments = Effect.fn("pr.fetchComments")(function* (
|
|
|
546
213
|
|
|
547
214
|
const resolvedPr = pr ?? (yield* viewPR(null)).number;
|
|
548
215
|
|
|
549
|
-
const raw = yield*
|
|
550
|
-
`repos/${repoInfo.owner}/${repoInfo.name}/pulls/${resolvedPr}/comments`,
|
|
551
|
-
"gh-tool pr comments",
|
|
552
|
-
"Failed to parse response",
|
|
553
|
-
);
|
|
216
|
+
const raw = yield* reads.prComments({ owner: repoInfo.owner, name: repoInfo.name }, resolvedPr);
|
|
554
217
|
|
|
555
218
|
const comments: ReviewComment[] = raw.map((c) => ({
|
|
556
219
|
id: c.id,
|
|
@@ -589,10 +252,9 @@ export const fetchIssueComments = Effect.fn("pr.fetchIssueComments")(function* (
|
|
|
589
252
|
|
|
590
253
|
const resolvedPr = pr ?? (yield* viewPR(null)).number;
|
|
591
254
|
|
|
592
|
-
const raw = yield*
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
"Failed to parse response",
|
|
255
|
+
const raw = yield* reads.issueComments(
|
|
256
|
+
{ owner: repoInfo.owner, name: repoInfo.name },
|
|
257
|
+
resolvedPr,
|
|
596
258
|
);
|
|
597
259
|
|
|
598
260
|
let comments = raw.map(mapRawIssueComment);
|
|
@@ -632,11 +294,7 @@ export const fetchReviews = Effect.fn("pr.fetchReviews")(function* (
|
|
|
632
294
|
|
|
633
295
|
const resolvedPr = pr ?? (yield* viewPR(null)).number;
|
|
634
296
|
|
|
635
|
-
const raw = yield*
|
|
636
|
-
`repos/${repoInfo.owner}/${repoInfo.name}/pulls/${resolvedPr}/reviews`,
|
|
637
|
-
"gh-tool pr reviews",
|
|
638
|
-
"Failed to parse response",
|
|
639
|
-
);
|
|
297
|
+
const raw = yield* reads.prReviews({ owner: repoInfo.owner, name: repoInfo.name }, resolvedPr);
|
|
640
298
|
|
|
641
299
|
let reviews: PullRequestReview[] = raw
|
|
642
300
|
.map((review) => ({
|
|
@@ -727,14 +385,17 @@ export const postIssueComment = Effect.fn("pr.postIssueComment")(function* (
|
|
|
727
385
|
);
|
|
728
386
|
}
|
|
729
387
|
|
|
730
|
-
const result = yield*
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
388
|
+
const result = yield* writes.run(
|
|
389
|
+
[
|
|
390
|
+
"api",
|
|
391
|
+
"-X",
|
|
392
|
+
"POST",
|
|
393
|
+
`repos/${repoInfo.owner}/${repoInfo.name}/issues/${resolvedPr}/comments`,
|
|
394
|
+
"-f",
|
|
395
|
+
`body=${body}`,
|
|
396
|
+
],
|
|
397
|
+
reviewTags(repoInfo, resolvedPr, "issue-comments"),
|
|
398
|
+
);
|
|
738
399
|
|
|
739
400
|
const rawComment = yield* Effect.try({
|
|
740
401
|
try: () => JSON.parse(result.stdout) as RawIssueComment,
|
|
@@ -796,18 +457,7 @@ export const fetchDiscussionSummary = Effect.fn("pr.fetchDiscussionSummary")(fun
|
|
|
796
457
|
};
|
|
797
458
|
});
|
|
798
459
|
|
|
799
|
-
const fetchReviewCommentById =
|
|
800
|
-
commentId: number,
|
|
801
|
-
) {
|
|
802
|
-
const service = yield* GitHubService;
|
|
803
|
-
|
|
804
|
-
const comment = yield* service.runGhJson<ReviewCommentById>([
|
|
805
|
-
"api",
|
|
806
|
-
`repos/{owner}/{repo}/pulls/comments/${commentId}`,
|
|
807
|
-
]);
|
|
808
|
-
|
|
809
|
-
return comment;
|
|
810
|
-
});
|
|
460
|
+
const fetchReviewCommentById = reads.reviewGuards.commentById;
|
|
811
461
|
|
|
812
462
|
export const editComment = Effect.fn("pr.editComment")(function* (
|
|
813
463
|
commentId: number,
|
|
@@ -846,8 +496,8 @@ export const editComment = Effect.fn("pr.editComment")(function* (
|
|
|
846
496
|
}
|
|
847
497
|
|
|
848
498
|
const endpoint = `repos/${repoInfo.owner}/${repoInfo.name}/${kind === "review" ? "pulls" : "issues"}/comments/${commentId}`;
|
|
849
|
-
const target = yield*
|
|
850
|
-
const viewer = yield*
|
|
499
|
+
const target = yield* reads.reviewGuards.editableComment(repoInfo, kind, commentId);
|
|
500
|
+
const viewer = yield* reads.reviewGuards.viewer();
|
|
851
501
|
if (target.user.login.toLowerCase() !== viewer.login.toLowerCase()) {
|
|
852
502
|
return yield* Effect.fail(
|
|
853
503
|
new GitHubCommandError({
|
|
@@ -873,10 +523,7 @@ export const editComment = Effect.fn("pr.editComment")(function* (
|
|
|
873
523
|
);
|
|
874
524
|
}
|
|
875
525
|
if (kind === "issue" && pr !== null) {
|
|
876
|
-
const pullRequest = yield*
|
|
877
|
-
"api",
|
|
878
|
-
`repos/${repoInfo.owner}/${repoInfo.name}/pulls/${pr}`,
|
|
879
|
-
]);
|
|
526
|
+
const pullRequest = yield* reads.reviewGuards.pullNumber(repoInfo, pr);
|
|
880
527
|
if (pullRequest.number !== pr) {
|
|
881
528
|
return yield* Effect.fail(
|
|
882
529
|
new GitHubCommandError({
|
|
@@ -890,14 +537,10 @@ export const editComment = Effect.fn("pr.editComment")(function* (
|
|
|
890
537
|
}
|
|
891
538
|
}
|
|
892
539
|
|
|
893
|
-
const updated = yield*
|
|
894
|
-
"api",
|
|
895
|
-
"-
|
|
896
|
-
|
|
897
|
-
endpoint,
|
|
898
|
-
"-f",
|
|
899
|
-
`body=${body}`,
|
|
900
|
-
]);
|
|
540
|
+
const updated = yield* writes.json<EditableComment>(
|
|
541
|
+
["api", "-X", "PATCH", endpoint, "-f", `body=${body}`],
|
|
542
|
+
reviewTags(repoInfo, pr, kind === "review" ? "review-comments" : "issue-comments"),
|
|
543
|
+
);
|
|
901
544
|
return {
|
|
902
545
|
commentId: updated.id,
|
|
903
546
|
url: updated.html_url,
|
|
@@ -948,15 +591,18 @@ export const replyToComment = Effect.fn("pr.replyToComment")(function* (
|
|
|
948
591
|
);
|
|
949
592
|
}
|
|
950
593
|
|
|
951
|
-
const result = yield*
|
|
952
|
-
.
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
594
|
+
const result = yield* writes
|
|
595
|
+
.run(
|
|
596
|
+
[
|
|
597
|
+
"api",
|
|
598
|
+
"-X",
|
|
599
|
+
"POST",
|
|
600
|
+
`repos/${repoInfo.owner}/${repoInfo.name}/pulls/${resolvedPr}/comments/${rootCommentId}/replies`,
|
|
601
|
+
"-f",
|
|
602
|
+
`body=${body}`,
|
|
603
|
+
],
|
|
604
|
+
reviewTags(repoInfo, resolvedPr, "review-comments"),
|
|
605
|
+
)
|
|
960
606
|
.pipe(
|
|
961
607
|
Effect.catchTag("GitHubCommandError", (error) => {
|
|
962
608
|
if (error.stderr.includes("can only have one pending review per pull request")) {
|
|
@@ -1105,11 +751,15 @@ export const replyAndResolveComment = Effect.fn("pr.replyAndResolveComment")(fun
|
|
|
1105
751
|
* Resolve a review thread via GraphQL mutation.
|
|
1106
752
|
*/
|
|
1107
753
|
export const resolveThread = Effect.fn("pr.resolveThread")(function* (threadId: string) {
|
|
1108
|
-
const
|
|
754
|
+
const repo = yield* resolveRepo(null);
|
|
1109
755
|
|
|
1110
|
-
const response = (yield*
|
|
1111
|
-
|
|
1112
|
-
|
|
756
|
+
const response = (yield* writes.graphql(
|
|
757
|
+
RESOLVE_THREAD_MUTATION,
|
|
758
|
+
{
|
|
759
|
+
threadId,
|
|
760
|
+
},
|
|
761
|
+
[`repo:${repoSlug(repo)}`],
|
|
762
|
+
)) as ResolveThreadResult;
|
|
1113
763
|
|
|
1114
764
|
return {
|
|
1115
765
|
resolved: response.resolveReviewThread.thread.isResolved,
|
|
@@ -1195,11 +845,11 @@ export const createReview = Effect.fn("pr.createReview")(function* (opts: {
|
|
|
1195
845
|
args.push("-f", `body=${opts.body}`);
|
|
1196
846
|
}
|
|
1197
847
|
|
|
1198
|
-
const result = yield*
|
|
848
|
+
const result = yield* writes.json<{
|
|
1199
849
|
id: number;
|
|
1200
850
|
state: string;
|
|
1201
851
|
html_url: string;
|
|
1202
|
-
}>(args);
|
|
852
|
+
}>(args, reviewTags(repoInfo, resolvedPr, "reviews"));
|
|
1203
853
|
|
|
1204
854
|
return {
|
|
1205
855
|
submitted: true as const,
|
|
@@ -1235,12 +885,11 @@ export const submitPendingReview = Effect.fn("pr.submitPendingReview")(function*
|
|
|
1235
885
|
const seenPendingCursors = new Set<string>();
|
|
1236
886
|
|
|
1237
887
|
while (hasNextPage) {
|
|
1238
|
-
const pending = (yield*
|
|
1239
|
-
|
|
1240
|
-
|
|
1241
|
-
pr: resolvedPr,
|
|
888
|
+
const pending = (yield* reads.reviewGuards.pendingReviews(
|
|
889
|
+
repoInfo,
|
|
890
|
+
resolvedPr,
|
|
1242
891
|
after,
|
|
1243
|
-
|
|
892
|
+
)) as PendingReviewsQueryResult;
|
|
1244
893
|
|
|
1245
894
|
if (
|
|
1246
895
|
typeof pending.viewer?.login !== "string" ||
|
|
@@ -1326,10 +975,10 @@ export const submitPendingReview = Effect.fn("pr.submitPendingReview")(function*
|
|
|
1326
975
|
let commentsHaveNextPage = true;
|
|
1327
976
|
const seenCommentCursors = new Set<string>();
|
|
1328
977
|
while (commentsHaveNextPage) {
|
|
1329
|
-
const pendingReview = (yield*
|
|
1330
|
-
|
|
1331
|
-
|
|
1332
|
-
|
|
978
|
+
const pendingReview = (yield* reads.reviewGuards.pendingReviewContent(
|
|
979
|
+
targetReviewId,
|
|
980
|
+
afterComment,
|
|
981
|
+
)) as PendingReviewContentQueryResult;
|
|
1333
982
|
|
|
1334
983
|
const review = pendingReview?.node;
|
|
1335
984
|
if (
|
|
@@ -1400,11 +1049,15 @@ export const submitPendingReview = Effect.fn("pr.submitPendingReview")(function*
|
|
|
1400
1049
|
if (commentsHaveNextPage && afterComment !== null) seenCommentCursors.add(afterComment);
|
|
1401
1050
|
}
|
|
1402
1051
|
|
|
1403
|
-
const result = (yield*
|
|
1404
|
-
|
|
1405
|
-
|
|
1406
|
-
|
|
1407
|
-
|
|
1052
|
+
const result = (yield* writes.graphql(
|
|
1053
|
+
SUBMIT_REVIEW_MUTATION,
|
|
1054
|
+
{
|
|
1055
|
+
reviewId: targetReviewId,
|
|
1056
|
+
event: REVIEW_EVENT_API[event],
|
|
1057
|
+
body: body ?? "",
|
|
1058
|
+
},
|
|
1059
|
+
reviewTags(repoInfo, resolvedPr, "reviews"),
|
|
1060
|
+
)) as SubmitReviewResult;
|
|
1408
1061
|
|
|
1409
1062
|
return {
|
|
1410
1063
|
submitted: true as const,
|
|
@@ -1434,11 +1087,10 @@ export const fetchLastHumanReviewer = Effect.fn("pr.fetchLastHumanReviewer")(fun
|
|
|
1434
1087
|
|
|
1435
1088
|
const resolvedPr = pr ?? (yield* viewPR(null)).number;
|
|
1436
1089
|
|
|
1437
|
-
const response =
|
|
1438
|
-
owner: repoInfo.owner,
|
|
1439
|
-
|
|
1440
|
-
|
|
1441
|
-
})) as LastHumanReviewerQueryResult;
|
|
1090
|
+
const response = yield* reads.lastHumanReviewer(
|
|
1091
|
+
{ owner: repoInfo.owner, name: repoInfo.name },
|
|
1092
|
+
resolvedPr,
|
|
1093
|
+
);
|
|
1442
1094
|
|
|
1443
1095
|
const prNode = response.repository.pullRequest;
|
|
1444
1096
|
|