@blogic-cz/agent-tools 1.16.1 → 1.16.2
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 +19 -0
- package/dist/gh-tool/issue/triage.d.ts +1 -1
- package/dist/gh-tool/issue/triage.d.ts.map +1 -1
- package/dist/gh-tool/main.d.ts.map +1 -1
- package/dist/gh-tool/pr/commands.d.ts +7 -7
- package/dist/gh-tool/pr/commands.d.ts.map +1 -1
- package/dist/gh-tool/pr/core.d.ts +9 -9
- package/dist/gh-tool/pr/review.d.ts +3 -3
- package/dist/gh-tool/pr/review.d.ts.map +1 -1
- package/dist/gh-tool/read/graphql-fallback.d.ts +21 -0
- package/dist/gh-tool/read/graphql-fallback.d.ts.map +1 -0
- package/dist/gh-tool/read/pulls.d.ts +13 -12
- package/dist/gh-tool/read/pulls.d.ts.map +1 -1
- package/dist/gh-tool/read/reads.d.ts +6 -5
- package/dist/gh-tool/read/reads.d.ts.map +1 -1
- package/dist/gh-tool/read/rest-porcelain.d.ts +131 -0
- package/dist/gh-tool/read/rest-porcelain.d.ts.map +1 -0
- package/dist/gh-tool/read/review-guards.d.ts +1 -1
- package/dist/gh-tool/read/review-guards.d.ts.map +1 -1
- package/dist/gh-tool/read/review-model.d.ts +1 -1
- package/dist/gh-tool/read/review-model.d.ts.map +1 -1
- package/dist/gh-tool/read/reviews.d.ts.map +1 -1
- package/dist/gh-tool/read/telemetry.d.ts +1 -1
- package/dist/gh-tool/read/telemetry.d.ts.map +1 -1
- package/dist/gh-tool/read/transport.d.ts.map +1 -1
- package/dist/gh-tool/types.d.ts +2 -2
- package/dist/gh-tool/types.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/gh-tool/issue/triage.ts +1 -1
- package/src/gh-tool/main.ts +2 -1
- package/src/gh-tool/pr/commands.ts +15 -6
- package/src/gh-tool/pr/review.ts +27 -7
- package/src/gh-tool/read/graphql-fallback.ts +366 -0
- package/src/gh-tool/read/pulls.ts +60 -10
- package/src/gh-tool/read/reads.ts +2 -0
- package/src/gh-tool/read/rest-porcelain.ts +571 -0
- package/src/gh-tool/read/review-guards.ts +8 -2
- package/src/gh-tool/read/review-model.ts +1 -1
- package/src/gh-tool/read/reviews.ts +19 -3
- package/src/gh-tool/read/telemetry.ts +6 -3
- package/src/gh-tool/read/transport.ts +314 -7
- package/src/gh-tool/types.ts +2 -2
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"reviews.d.ts","sourceRoot":"","sources":["../../../src/gh-tool/read/reviews.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAU,MAAM,QAAQ,CAAC;AACxC,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;
|
|
1
|
+
{"version":3,"file":"reviews.d.ts","sourceRoot":"","sources":["../../../src/gh-tool/read/reviews.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAU,MAAM,QAAQ,CAAC;AACxC,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAQnD,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,QAAQ,CAAC;AAMtC,OAAO,KAAK,EACV,UAAU,EAGV,4BAA4B,EAC5B,gBAAgB,EAChB,oBAAoB,EACrB,MAAM,gBAAgB,CAAC;AAoGxB,eAAO,MAAM,UAAU,uHAGrB,CAAC;AACH,eAAO,MAAM,SAAS,2HAGpB,CAAC;AACH,eAAO,MAAM,aAAa,gKAwBxB,CAAC;AACH,eAAO,MAAM,iBAAiB,iIAoB5B,CAAC"}
|
|
@@ -4,7 +4,7 @@ export type RequestEvent = {
|
|
|
4
4
|
method: string;
|
|
5
5
|
endpoint: string;
|
|
6
6
|
status: number | null;
|
|
7
|
-
outcome: "cache" | "304" | "200" | "bypass" | "error" | "subprocess";
|
|
7
|
+
outcome: "cache" | "304" | "200" | "bypass" | "error" | "subprocess" | "fallback";
|
|
8
8
|
resource: string | null;
|
|
9
9
|
used: number | null;
|
|
10
10
|
remaining: number | null;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"telemetry.d.ts","sourceRoot":"","sources":["../../../src/gh-tool/read/telemetry.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAGzC,MAAM,MAAM,YAAY,GAAG;IACzB,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,OAAO,EAAE,OAAO,GAAG,KAAK,GAAG,KAAK,GAAG,QAAQ,GAAG,OAAO,GAAG,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"telemetry.d.ts","sourceRoot":"","sources":["../../../src/gh-tool/read/telemetry.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAGzC,MAAM,MAAM,YAAY,GAAG;IACzB,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,OAAO,EAAE,OAAO,GAAG,KAAK,GAAG,KAAK,GAAG,QAAQ,GAAG,OAAO,GAAG,YAAY,GAAG,UAAU,CAAC;IAClF,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;CACtB,CAAC;AACF,MAAM,MAAM,UAAU,GAAG,YAAY,GAAG;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC;AAC5F,MAAM,MAAM,cAAc,GAAG;IAC3B,MAAM,EAAE,CAAC,KAAK,EAAE,YAAY,KAAK,IAAI,CAAC;IACtC,IAAI,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,SAAS,UAAU,EAAE,CAAC;IAC/C,KAAK,EAAE,MAAM,IAAI,CAAC;CACnB,CAAC;AAEF,eAAO,MAAM,SAAS,0CAEpB,CAAC;AACH,eAAO,MAAM,YAAY,4BAEvB,CAAC;AAEH,eAAO,MAAM,gBAAgB,SAAU,MAAM,KAAG,MAO/C,CAAC;AAEF,eAAO,MAAM,aAAa,UAAW,YAAY,KAAG,MAAM,CAAC,MAAM,CAAC,IAAI,CAYlE,CAAC;AAEL,eAAO,MAAM,UAAU,cAAe,MAAM,KAAG,YAU7C,CAAC;AAsBH,eAAO,MAAM,iBAAiB,SAAU,SAAS,MAAM,EAAE,YAAY,MAAM,KAAG,YAiC7E,CAAC;AAiBF,eAAO,MAAM,iBAAiB,SAAU,SAAS,UAAU,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA4D5D,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"transport.d.ts","sourceRoot":"","sources":["../../../src/gh-tool/read/transport.ts"],"names":[],"mappings":"AACA,OAAO,EAAgB,mBAAmB,EAAE,MAAM,gBAAgB,CAAC;AACnE,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,EAAkB,MAAM,QAAQ,CAAC;
|
|
1
|
+
{"version":3,"file":"transport.d.ts","sourceRoot":"","sources":["../../../src/gh-tool/read/transport.ts"],"names":[],"mappings":"AACA,OAAO,EAAgB,mBAAmB,EAAE,MAAM,gBAAgB,CAAC;AACnE,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,EAAkB,MAAM,QAAQ,CAAC;AAmBhE,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAC;AAChD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,QAAQ,CAAC;AAStC,OAAO,EAAE,eAAe,EAAE,kBAAkB,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAC;AAGtF,OAAO,KAAK,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,MAAM,OAAO,CAAC;AACjE,OAAO,EAAE,aAAa,EAA4C,MAAM,SAAS,CAAC;AA6DlF,MAAM,MAAM,QAAQ,GAAG;IACrB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;CAClB,CAAC;AAEF,MAAM,MAAM,OAAO,GAAG,kBAAkB,GAAG,eAAe,GAAG,mBAAmB,CAAC;AACjF,MAAM,MAAM,eAAe,GAAG;IAC5B,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC;IACvB,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,WAAW,EAAE,GAAG,GAAG,GAAG,CAAC;IAChC,QAAQ,CAAC,aAAa,EAAE,SAAS,MAAM,EAAE,CAAC;CAC3C,CAAC;;oBAKkB,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,MAAM,CAAC,MAAM,CAAC,QAAQ,EAAE,OAAO,CAAC;+BACzC,CAAC,IAAI,EAAE,eAAe,KAAK,MAAM,CAAC,MAAM,CAAC,QAAQ,EAAE,OAAO,CAAC;wBAClE,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,MAAM,CAAC,MAAM,CAAC,CAAC,EAAE,OAAO,CAAC;yBAC/C,CACnB,KAAK,EAAE,MAAM,EACb,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAAC,KAC9C,MAAM,CAAC,MAAM,CAAC,OAAO,EAAE,OAAO,CAAC;yBACf,CAAC,CAAC,EACrB,IAAI,EAAE,gBAAgB,KACnB,MAAM,CAAC,MAAM,CAAC,iBAAiB,CAAC,CAAC,CAAC,EAAE,OAAO,CAAC;4BACzB,MAAM,MAAM,CAAC,MAAM,CAAC,gBAAgB,GAAG,SAAS,EAAE,KAAK,CAAC;0BAC1D,MAAM,MAAM,CAAC,MAAM,CAAC,QAAQ,EAAE,OAAO,CAAC;yBACvC,MAAM,MAAM,CAAC,MAAM,CAAC,OAAO,EAAE,OAAO,CAAC;6BACjC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAC/B,MAAM,EAAE,MAAM,GAAG,IAAI,EACrB,MAAM,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,KAC3B,MAAM,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,GAAG,kBAAkB,EAAE,CAAC,CAAC;;AAnBpD,qBAAa,aAAc,SAAQ,kBAqBF;IAC/B,MAAM,CAAC,QAAQ,CAAC,KAAK,6FAorBnB;CACH"}
|
package/dist/gh-tool/types.d.ts
CHANGED
|
@@ -26,7 +26,7 @@ export type PRViewInfo = PRInfo & {
|
|
|
26
26
|
login: string;
|
|
27
27
|
is_bot: boolean;
|
|
28
28
|
};
|
|
29
|
-
reviewDecision: "APPROVED" | "CHANGES_REQUESTED" | "REVIEW_REQUIRED" | "";
|
|
29
|
+
reviewDecision: "APPROVED" | "CHANGES_REQUESTED" | "REVIEW_REQUIRED" | "UNKNOWN" | "";
|
|
30
30
|
reviewRequests: ReviewRequest[];
|
|
31
31
|
};
|
|
32
32
|
export declare const FeedbackOrigin: Schema.Literals<readonly ["current_head", "pre_existing", "unknown"]>;
|
|
@@ -42,7 +42,7 @@ export type ReviewThread = {
|
|
|
42
42
|
originalCommitSha: string | null;
|
|
43
43
|
diffHunk: string | null;
|
|
44
44
|
body: string;
|
|
45
|
-
isResolved: boolean;
|
|
45
|
+
isResolved: boolean | null;
|
|
46
46
|
hasReply: boolean;
|
|
47
47
|
replyCount: number;
|
|
48
48
|
needsHumanReply: boolean;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/gh-tool/types.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAEhC,MAAM,MAAM,aAAa,GAAG,QAAQ,GAAG,OAAO,GAAG,QAAQ,CAAC;AAE1D,MAAM,MAAM,MAAM,GAAG;IACnB,MAAM,EAAE,MAAM,CAAC;IACf,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,OAAO,CAAC;IACjB,SAAS,EAAE,WAAW,GAAG,aAAa,GAAG,SAAS,CAAC;CACpD,CAAC;AAEF,MAAM,MAAM,aAAa,GACrB;IAAE,UAAU,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,GACrC;IAAE,UAAU,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC;AAEvD,MAAM,MAAM,UAAU,GAAG,MAAM,GAAG;IAChC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,OAAO,CAAA;KAAE,CAAC;IAC3C,cAAc,EAAE,UAAU,GAAG,mBAAmB,GAAG,iBAAiB,GAAG,EAAE,CAAC;
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/gh-tool/types.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -61,7 +61,7 @@ type ReviewTriageSnapshot = {
|
|
|
61
61
|
readonly summary: {
|
|
62
62
|
readonly visibleOpenReviewThreadsCount: number;
|
|
63
63
|
readonly unrepliedReviewThreadsCount: number;
|
|
64
|
-
readonly unresolvedReviewThreadsCount: number;
|
|
64
|
+
readonly unresolvedReviewThreadsCount: number | null;
|
|
65
65
|
readonly latestIssueComment: IssueComment | null;
|
|
66
66
|
};
|
|
67
67
|
readonly checks: readonly CheckResult[];
|
package/src/gh-tool/main.ts
CHANGED
|
@@ -7,6 +7,7 @@ import { makeSchemaCommand, renderCauseToStderr, VERSION } from "#shared";
|
|
|
7
7
|
import { AuditService, AuditServiceLayer, withAudit } from "#shared/audit";
|
|
8
8
|
import { openRequestTelemetry } from "#gh/read/telemetry-store";
|
|
9
9
|
import { withRedactedOutput } from "#shared/output-boundary";
|
|
10
|
+
import { withFallbackOutput } from "#gh/read/graphql-fallback";
|
|
10
11
|
import { ConfigServiceLayer } from "#config";
|
|
11
12
|
import {
|
|
12
13
|
issueCloseCommand,
|
|
@@ -292,7 +293,7 @@ const observed = Effect.gen(function* () {
|
|
|
292
293
|
} catch {
|
|
293
294
|
/* Telemetry is optional. */
|
|
294
295
|
}
|
|
295
|
-
return yield* withReadCache(withRedactedOutput(withAudit("gh", cli))).pipe(
|
|
296
|
+
return yield* withReadCache(withRedactedOutput(withFallbackOutput(withAudit("gh", cli)))).pipe(
|
|
296
297
|
Effect.provideService(Telemetry, store),
|
|
297
298
|
Effect.ensuring(
|
|
298
299
|
Effect.sync(() => {
|
|
@@ -182,7 +182,7 @@ export const requestReview = (pr: number, reviewers: string) =>
|
|
|
182
182
|
type ReviewTriageSummary = {
|
|
183
183
|
readonly visibleOpenReviewThreadsCount: number;
|
|
184
184
|
readonly unrepliedReviewThreadsCount: number;
|
|
185
|
-
readonly unresolvedReviewThreadsCount: number;
|
|
185
|
+
readonly unresolvedReviewThreadsCount: number | null;
|
|
186
186
|
};
|
|
187
187
|
|
|
188
188
|
type ReviewTriageClassification = {
|
|
@@ -206,7 +206,11 @@ export const classifyReviewTriage = (
|
|
|
206
206
|
: []),
|
|
207
207
|
...(summary.visibleOpenReviewThreadsCount > 0 ? ["visible_open_review_threads"] : []),
|
|
208
208
|
...(summary.unrepliedReviewThreadsCount > 0 ? ["unreplied_review_threads"] : []),
|
|
209
|
-
...(summary.unresolvedReviewThreadsCount
|
|
209
|
+
...(summary.unresolvedReviewThreadsCount === null
|
|
210
|
+
? ["unknown_review_thread_resolution"]
|
|
211
|
+
: summary.unresolvedReviewThreadsCount > 0
|
|
212
|
+
? ["unresolved_review_threads"]
|
|
213
|
+
: []),
|
|
210
214
|
];
|
|
211
215
|
return { status: reasons.length > 0 ? "needs_investigation" : "clear", reasons };
|
|
212
216
|
};
|
|
@@ -402,7 +406,7 @@ const countFeedbackOrigins = (items: ReadonlyArray<{ feedbackOrigin: string }>)
|
|
|
402
406
|
export const fetchReviewTriage = Effect.fn("pr.fetchReviewTriage")(function* (
|
|
403
407
|
prNumber: number | null,
|
|
404
408
|
) {
|
|
405
|
-
const { info, value } = yield* withStableHead(
|
|
409
|
+
const { info: baseInfo, value } = yield* withStableHead(
|
|
406
410
|
prNumber,
|
|
407
411
|
(number, headSha) =>
|
|
408
412
|
Effect.gen(function* () {
|
|
@@ -413,10 +417,13 @@ export const fetchReviewTriage = Effect.fn("pr.fetchReviewTriage")(function* (
|
|
|
413
417
|
fetchReviews(number, null, null, null, headSha),
|
|
414
418
|
fetchComments(number, null, headSha),
|
|
415
419
|
]);
|
|
416
|
-
|
|
420
|
+
const repo = yield* resolveRepo(null);
|
|
421
|
+
const reviewDecision = yield* reads.prReviewDecision(repo, number);
|
|
422
|
+
return { allThreads, summary, checkReport, reviews, inlineComments, reviewDecision };
|
|
417
423
|
}),
|
|
418
424
|
{ operation: "review triage", command: "gh-tool pr review-triage" },
|
|
419
425
|
);
|
|
426
|
+
const info = { ...baseInfo, reviewDecision: value.reviewDecision };
|
|
420
427
|
const { allThreads, summary, checkReport, reviews, inlineComments } = value;
|
|
421
428
|
const checks = checkReport.checks ?? [];
|
|
422
429
|
const unresolvedThreads = allThreads.filter((thread) => !thread.isResolved);
|
|
@@ -438,7 +445,9 @@ export const fetchReviewTriage = Effect.fn("pr.fetchReviewTriage")(function* (
|
|
|
438
445
|
) {
|
|
439
446
|
blocking.push("unknown_checks");
|
|
440
447
|
}
|
|
441
|
-
if (summary.unresolvedReviewThreadsCount
|
|
448
|
+
if (summary.unresolvedReviewThreadsCount === null)
|
|
449
|
+
blocking.push("unknown_review_thread_resolution");
|
|
450
|
+
else if (summary.unresolvedReviewThreadsCount > 0) blocking.push("unresolved_threads");
|
|
442
451
|
if (info.reviewDecision !== "" && info.reviewDecision !== "APPROVED") {
|
|
443
452
|
blocking.push(`review=${info.reviewDecision}`);
|
|
444
453
|
}
|
|
@@ -491,7 +500,7 @@ type CompactReviewTriage = {
|
|
|
491
500
|
readonly classification: ReviewTriageClassification;
|
|
492
501
|
readonly visibleOpenReviewThreadsCount: number;
|
|
493
502
|
readonly unrepliedReviewThreadsCount: number;
|
|
494
|
-
readonly unresolvedReviewThreadsCount: number;
|
|
503
|
+
readonly unresolvedReviewThreadsCount: number | null;
|
|
495
504
|
readonly visibleOpenThreadIds: readonly string[];
|
|
496
505
|
};
|
|
497
506
|
|
package/src/gh-tool/pr/review.ts
CHANGED
|
@@ -465,13 +465,19 @@ export const fetchDiscussionSummary = Effect.fn("pr.fetchDiscussionSummary")(fun
|
|
|
465
465
|
visibleOpenReviewThreadsCount: threads.filter((thread) => thread.isVisibleOpen).length,
|
|
466
466
|
repliedReviewThreadsCount: threads.length - unrepliedReviewThreadsCount,
|
|
467
467
|
unrepliedReviewThreadsCount,
|
|
468
|
-
resolvedUnrepliedReviewThreadsCount: threads.
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
468
|
+
resolvedUnrepliedReviewThreadsCount: threads.some((thread) => thread.isResolved === null)
|
|
469
|
+
? null
|
|
470
|
+
: threads.filter(
|
|
471
|
+
(thread) => thread.isResolved && !repliedThreadCommentIds.has(thread.commentId),
|
|
472
|
+
).length,
|
|
473
|
+
unresolvedReviewThreadsCount: threads.some((thread) => thread.isResolved === null)
|
|
474
|
+
? null
|
|
475
|
+
: threads.filter((thread) => thread.isResolved === false).length,
|
|
476
|
+
unresolvedUnrepliedReviewThreadsCount: threads.some((thread) => thread.isResolved === null)
|
|
477
|
+
? null
|
|
478
|
+
: threads.filter(
|
|
479
|
+
(thread) => !thread.isResolved && !repliedThreadCommentIds.has(thread.commentId),
|
|
480
|
+
).length,
|
|
475
481
|
};
|
|
476
482
|
});
|
|
477
483
|
|
|
@@ -750,6 +756,15 @@ export const replyAndResolveComment = Effect.fn("pr.replyAndResolveComment")(fun
|
|
|
750
756
|
}
|
|
751
757
|
const inferredThreadId = matches[0]?.id;
|
|
752
758
|
if (inferredThreadId === undefined) return yield* Effect.die("matched thread missing");
|
|
759
|
+
if (inferredThreadId.startsWith("rest-thread:"))
|
|
760
|
+
return yield* new GitHubCommandError({
|
|
761
|
+
command: "gh-tool pr reply-and-resolve",
|
|
762
|
+
exitCode: 1,
|
|
763
|
+
message:
|
|
764
|
+
"GitHub GraphQL is blocked; REST cannot resolve a review thread. No reply was posted.",
|
|
765
|
+
stderr: "REST cannot resolve a review thread",
|
|
766
|
+
hint: "Retry after GitHub lifts the GraphQL limit, or post a reply separately.",
|
|
767
|
+
});
|
|
753
768
|
if (threadId !== null && threadId !== inferredThreadId) {
|
|
754
769
|
return yield* Effect.fail(
|
|
755
770
|
new GitHubCommandError({
|
|
@@ -996,6 +1011,8 @@ export const submitPendingReview = Effect.fn("pr.submitPendingReview")(function*
|
|
|
996
1011
|
const pendingReview = (yield* reads.reviewGuards.pendingReviewContent(
|
|
997
1012
|
targetReviewId,
|
|
998
1013
|
afterComment,
|
|
1014
|
+
repoInfo,
|
|
1015
|
+
resolvedPr,
|
|
999
1016
|
)) as PendingReviewContentQueryResult;
|
|
1000
1017
|
|
|
1001
1018
|
const review = pendingReview?.node;
|
|
@@ -1073,6 +1090,9 @@ export const submitPendingReview = Effect.fn("pr.submitPendingReview")(function*
|
|
|
1073
1090
|
reviewId: targetReviewId,
|
|
1074
1091
|
event: REVIEW_EVENT_API[event],
|
|
1075
1092
|
body: body ?? "",
|
|
1093
|
+
owner: repoInfo.owner,
|
|
1094
|
+
name: repoInfo.name,
|
|
1095
|
+
pr: resolvedPr,
|
|
1076
1096
|
},
|
|
1077
1097
|
reviewTags(repoInfo, resolvedPr, "reviews"),
|
|
1078
1098
|
)) as SubmitReviewResult;
|
|
@@ -0,0 +1,366 @@
|
|
|
1
|
+
import { Console, Context, Effect, Schema } from "effect";
|
|
2
|
+
import type { JsonRead } from "./rest-porcelain";
|
|
3
|
+
import type { GhError } from "./transport";
|
|
4
|
+
import { parseRest, restGet, restPages, restPull, restReviewDecision } from "./rest-porcelain";
|
|
5
|
+
import { GitHubCommandError } from "#gh/errors";
|
|
6
|
+
import { ghSubprocessEvent, recordRequest } from "./telemetry";
|
|
7
|
+
|
|
8
|
+
export type Fallback = { source: "REST"; reason: string; unknown: string[] };
|
|
9
|
+
const fallbackResults = new WeakSet<object>();
|
|
10
|
+
export const markFallbackResult = <A extends object>(value: A): A => {
|
|
11
|
+
fallbackResults.add(value);
|
|
12
|
+
return value;
|
|
13
|
+
};
|
|
14
|
+
export const isFallbackResult = (value: unknown): boolean =>
|
|
15
|
+
typeof value === "object" && value !== null && fallbackResults.has(value);
|
|
16
|
+
|
|
17
|
+
export const FallbackState = Context.Reference<{ notices: Fallback[] } | null>("gh/FallbackState", {
|
|
18
|
+
defaultValue: () => null,
|
|
19
|
+
});
|
|
20
|
+
const fallbackMessage = (unknown: string[]) =>
|
|
21
|
+
unknown.length === 0
|
|
22
|
+
? "GitHub GraphQL is blocked (rate limit); answered from REST. All fields were provided."
|
|
23
|
+
: `GitHub GraphQL is blocked (rate limit); answered from REST. Not provided: ${unknown.join(", ")}. A null or UNKNOWN value there means "not provided", never false, unresolved or not approved. If your next step depends on it, retry in a few minutes; if it is still not provided, tell the user. Do not guess.`;
|
|
24
|
+
export const reportFallback = (unknown: string[]) =>
|
|
25
|
+
Effect.gen(function* () {
|
|
26
|
+
const notice: Fallback = { source: "REST", reason: "GitHub GraphQL rate limit", unknown };
|
|
27
|
+
const state = yield* FallbackState;
|
|
28
|
+
state?.notices.push(notice);
|
|
29
|
+
if (state === null) yield* Console.warn(fallbackMessage(unknown));
|
|
30
|
+
yield* recordRequest({
|
|
31
|
+
...ghSubprocessEvent(["api", "graphql"], 0),
|
|
32
|
+
method: "FALLBACK",
|
|
33
|
+
endpoint: "graphql-to-rest",
|
|
34
|
+
outcome: "fallback",
|
|
35
|
+
});
|
|
36
|
+
return notice;
|
|
37
|
+
});
|
|
38
|
+
export const withFallbackOutput = <A, E, R>(program: Effect.Effect<A, E, R>) =>
|
|
39
|
+
Effect.gen(function* () {
|
|
40
|
+
const current = yield* Console.Console;
|
|
41
|
+
const state = { notices: [] as Fallback[] };
|
|
42
|
+
let warned = false;
|
|
43
|
+
const flushWarning = () => {
|
|
44
|
+
if (warned || state.notices.length === 0) return;
|
|
45
|
+
warned = true;
|
|
46
|
+
current.warn(
|
|
47
|
+
fallbackMessage([...new Set(state.notices.flatMap((notice) => notice.unknown))]),
|
|
48
|
+
);
|
|
49
|
+
};
|
|
50
|
+
const console = {
|
|
51
|
+
...current,
|
|
52
|
+
log: (...args: readonly unknown[]) => {
|
|
53
|
+
flushWarning();
|
|
54
|
+
current.log(
|
|
55
|
+
...args.map((arg) => {
|
|
56
|
+
if (state.notices.length === 0 || typeof arg !== "string") return arg;
|
|
57
|
+
try {
|
|
58
|
+
const value: unknown = JSON.parse(arg);
|
|
59
|
+
if (value === null || typeof value !== "object") return arg;
|
|
60
|
+
const fallback = {
|
|
61
|
+
source: "REST",
|
|
62
|
+
reason: "GitHub GraphQL rate limit",
|
|
63
|
+
unknown: [...new Set(state.notices.flatMap((notice) => notice.unknown))],
|
|
64
|
+
};
|
|
65
|
+
return JSON.stringify(
|
|
66
|
+
Array.isArray(value) ? { items: value, fallback } : { ...value, fallback },
|
|
67
|
+
null,
|
|
68
|
+
arg.includes("\n") ? 2 : undefined,
|
|
69
|
+
);
|
|
70
|
+
} catch {
|
|
71
|
+
return arg;
|
|
72
|
+
}
|
|
73
|
+
}),
|
|
74
|
+
);
|
|
75
|
+
},
|
|
76
|
+
};
|
|
77
|
+
return yield* program.pipe(
|
|
78
|
+
Effect.provideService(FallbackState, state),
|
|
79
|
+
Effect.provideService(Console.Console, console),
|
|
80
|
+
Effect.ensuring(Effect.sync(flushWarning)),
|
|
81
|
+
);
|
|
82
|
+
});
|
|
83
|
+
const Comment = Schema.Struct({
|
|
84
|
+
id: Schema.Number,
|
|
85
|
+
node_id: Schema.String,
|
|
86
|
+
in_reply_to_id: Schema.optional(Schema.NullOr(Schema.Number)),
|
|
87
|
+
path: Schema.String,
|
|
88
|
+
line: Schema.NullOr(Schema.Number),
|
|
89
|
+
body: Schema.String,
|
|
90
|
+
user: Schema.Struct({ login: Schema.String }),
|
|
91
|
+
commit_id: Schema.String,
|
|
92
|
+
});
|
|
93
|
+
const Reviewer = Schema.Struct({ login: Schema.String, type: Schema.optional(Schema.String) });
|
|
94
|
+
export const restGraphql = (
|
|
95
|
+
query: string,
|
|
96
|
+
variables: Record<string, string | number | null>,
|
|
97
|
+
read: JsonRead,
|
|
98
|
+
): Effect.Effect<unknown, GhError> | null => {
|
|
99
|
+
if (
|
|
100
|
+
(query.includes("mutation") && !query.includes("submitPullRequestReview")) ||
|
|
101
|
+
typeof variables.owner !== "string" ||
|
|
102
|
+
typeof variables.name !== "string" ||
|
|
103
|
+
typeof variables.pr !== "number"
|
|
104
|
+
)
|
|
105
|
+
return null;
|
|
106
|
+
const repo = `${variables.owner}/${variables.name}`;
|
|
107
|
+
const pr = variables.pr;
|
|
108
|
+
const root = `repos/${repo}/pulls/${pr}`;
|
|
109
|
+
if (
|
|
110
|
+
query.includes("states: [PENDING]") ||
|
|
111
|
+
query.includes("... on PullRequestReview {") ||
|
|
112
|
+
query.includes("submitPullRequestReview")
|
|
113
|
+
)
|
|
114
|
+
return pendingRest(query, variables, read, root, repo, variables.pr);
|
|
115
|
+
if (query.includes("reviewThreads"))
|
|
116
|
+
return Effect.gen(function* () {
|
|
117
|
+
const comments = (yield* parseRest(
|
|
118
|
+
Schema.Array(Schema.Array(Comment)),
|
|
119
|
+
yield* restPages(read, `${root}/comments`),
|
|
120
|
+
)).flat();
|
|
121
|
+
const groups = new Map<number, Array<typeof Comment.Type>>();
|
|
122
|
+
for (const comment of comments) {
|
|
123
|
+
const rootId = comment.in_reply_to_id ?? comment.id;
|
|
124
|
+
const group = groups.get(rootId) ?? [];
|
|
125
|
+
group.push(comment);
|
|
126
|
+
groups.set(rootId, group);
|
|
127
|
+
}
|
|
128
|
+
const nodes = [...groups.entries()].map(([rootId, group]) => ({
|
|
129
|
+
id: `rest-thread:${rootId}`,
|
|
130
|
+
isResolved: null,
|
|
131
|
+
comments: {
|
|
132
|
+
nodes: group
|
|
133
|
+
.toSorted((a, b) => Number(b.id === rootId) - Number(a.id === rootId))
|
|
134
|
+
.map((item) => ({
|
|
135
|
+
id: item.node_id,
|
|
136
|
+
databaseId: item.id,
|
|
137
|
+
path: item.path,
|
|
138
|
+
line: item.line,
|
|
139
|
+
body: item.body,
|
|
140
|
+
author: { login: item.user.login },
|
|
141
|
+
commit: { oid: item.commit_id },
|
|
142
|
+
replyTo:
|
|
143
|
+
item.in_reply_to_id === undefined || item.in_reply_to_id === null
|
|
144
|
+
? null
|
|
145
|
+
: { id: String(item.in_reply_to_id) },
|
|
146
|
+
})),
|
|
147
|
+
pageInfo: { hasNextPage: false, endCursor: null },
|
|
148
|
+
},
|
|
149
|
+
}));
|
|
150
|
+
const pull = yield* restPull(read, repo, String(pr));
|
|
151
|
+
const reviewDecision = query.includes("reviewDecision")
|
|
152
|
+
? yield* restReviewDecision(read, {
|
|
153
|
+
repo,
|
|
154
|
+
number: pr,
|
|
155
|
+
baseRefName: pull.baseRefName,
|
|
156
|
+
headSha: pull.headSha,
|
|
157
|
+
})
|
|
158
|
+
: pull.reviewDecision;
|
|
159
|
+
const fallback = yield* reportFallback([
|
|
160
|
+
"review thread resolution",
|
|
161
|
+
...(query.includes("reviewDecision") && reviewDecision === "UNKNOWN"
|
|
162
|
+
? ["reviewDecision"]
|
|
163
|
+
: []),
|
|
164
|
+
]);
|
|
165
|
+
return {
|
|
166
|
+
fallback,
|
|
167
|
+
repository: {
|
|
168
|
+
pullRequest: {
|
|
169
|
+
...pull,
|
|
170
|
+
reviewDecision,
|
|
171
|
+
reviewRequests: {
|
|
172
|
+
nodes: pull.reviewRequests.map((reviewer) => ({ requestedReviewer: reviewer })),
|
|
173
|
+
},
|
|
174
|
+
reviewThreads: { nodes, pageInfo: { hasNextPage: false, endCursor: null } },
|
|
175
|
+
},
|
|
176
|
+
},
|
|
177
|
+
};
|
|
178
|
+
});
|
|
179
|
+
if (query.includes("reviews(last:") && query.includes("reviewRequests"))
|
|
180
|
+
return Effect.gen(function* () {
|
|
181
|
+
const reviews = (yield* parseRest(
|
|
182
|
+
Schema.Array(
|
|
183
|
+
Schema.Array(
|
|
184
|
+
Schema.Struct({
|
|
185
|
+
user: Schema.NullOr(Reviewer),
|
|
186
|
+
state: Schema.String,
|
|
187
|
+
submitted_at: Schema.NullOr(Schema.String),
|
|
188
|
+
}),
|
|
189
|
+
),
|
|
190
|
+
),
|
|
191
|
+
yield* restPages(read, `${root}/reviews`),
|
|
192
|
+
)).flat();
|
|
193
|
+
const requested = yield* parseRest(
|
|
194
|
+
Schema.Struct({
|
|
195
|
+
users: Schema.Array(Reviewer),
|
|
196
|
+
teams: Schema.Array(Schema.Struct({ name: Schema.String })),
|
|
197
|
+
}),
|
|
198
|
+
yield* restGet(read, `${root}/requested_reviewers`),
|
|
199
|
+
);
|
|
200
|
+
const fallback = yield* reportFallback([]);
|
|
201
|
+
return {
|
|
202
|
+
fallback,
|
|
203
|
+
repository: {
|
|
204
|
+
pullRequest: {
|
|
205
|
+
reviewRequests: {
|
|
206
|
+
nodes: [
|
|
207
|
+
...requested.users.map((user) => ({
|
|
208
|
+
requestedReviewer: {
|
|
209
|
+
__typename: user.type === "Bot" ? "Bot" : "User",
|
|
210
|
+
login: user.login,
|
|
211
|
+
},
|
|
212
|
+
})),
|
|
213
|
+
...requested.teams.map((team) => ({
|
|
214
|
+
requestedReviewer: { __typename: "Team", name: team.name },
|
|
215
|
+
})),
|
|
216
|
+
],
|
|
217
|
+
},
|
|
218
|
+
reviews: {
|
|
219
|
+
nodes: reviews.map((review) => ({
|
|
220
|
+
author: review.user === null ? null : { login: review.user.login },
|
|
221
|
+
state: review.state,
|
|
222
|
+
submittedAt: review.submitted_at,
|
|
223
|
+
})),
|
|
224
|
+
},
|
|
225
|
+
},
|
|
226
|
+
},
|
|
227
|
+
};
|
|
228
|
+
});
|
|
229
|
+
return null;
|
|
230
|
+
};
|
|
231
|
+
export const isGraphqlLimit = (error: unknown) =>
|
|
232
|
+
error instanceof GitHubCommandError &&
|
|
233
|
+
/rate.?limit|already exceeded|secondary limit|abuse detection|HTTP 429/i.test(error.stderr);
|
|
234
|
+
export const rateLimitResponse = (stdout: string): string | null => {
|
|
235
|
+
try {
|
|
236
|
+
const value = Schema.decodeUnknownSync(
|
|
237
|
+
Schema.Struct({
|
|
238
|
+
errors: Schema.optional(Schema.Array(Schema.Unknown)),
|
|
239
|
+
type: Schema.optional(Schema.String),
|
|
240
|
+
code: Schema.optional(Schema.String),
|
|
241
|
+
message: Schema.optional(Schema.String),
|
|
242
|
+
}),
|
|
243
|
+
)(JSON.parse(stdout));
|
|
244
|
+
const detail = JSON.stringify(value.errors ?? value);
|
|
245
|
+
return /RATE_LIMIT|graphql_rate_limit|rate limit|secondary limit/i.test(detail) ? detail : null;
|
|
246
|
+
} catch {
|
|
247
|
+
return null;
|
|
248
|
+
}
|
|
249
|
+
};
|
|
250
|
+
export const graphqlLimitError = () =>
|
|
251
|
+
new GitHubCommandError({
|
|
252
|
+
command: "gh api graphql",
|
|
253
|
+
exitCode: 1,
|
|
254
|
+
message: "GraphQL rate limit already exceeded",
|
|
255
|
+
stderr: "GraphQL rate limit already exceeded",
|
|
256
|
+
});
|
|
257
|
+
|
|
258
|
+
const PendingReview = Schema.Struct({
|
|
259
|
+
id: Schema.Number,
|
|
260
|
+
node_id: Schema.String,
|
|
261
|
+
state: Schema.String,
|
|
262
|
+
body: Schema.NullOr(Schema.String),
|
|
263
|
+
user: Schema.NullOr(Schema.Struct({ login: Schema.String })),
|
|
264
|
+
pull_request_url: Schema.String,
|
|
265
|
+
});
|
|
266
|
+
const pendingRest = (
|
|
267
|
+
query: string,
|
|
268
|
+
variables: Record<string, string | number | null>,
|
|
269
|
+
read: JsonRead,
|
|
270
|
+
root: string,
|
|
271
|
+
repo: string,
|
|
272
|
+
pr: number,
|
|
273
|
+
): Effect.Effect<unknown, GhError> =>
|
|
274
|
+
Effect.gen(function* () {
|
|
275
|
+
const reviews = (yield* parseRest(
|
|
276
|
+
Schema.Array(Schema.Array(PendingReview)),
|
|
277
|
+
yield* restPages(read, `${root}/reviews`),
|
|
278
|
+
)).flat();
|
|
279
|
+
const viewer = yield* parseRest(
|
|
280
|
+
Schema.Struct({ login: Schema.String }),
|
|
281
|
+
yield* restGet(read, "user"),
|
|
282
|
+
);
|
|
283
|
+
const pageInfo = { hasNextPage: false, endCursor: null };
|
|
284
|
+
if (query.includes("states: [PENDING]")) {
|
|
285
|
+
const fallback = yield* reportFallback([]);
|
|
286
|
+
return {
|
|
287
|
+
fallback,
|
|
288
|
+
viewer,
|
|
289
|
+
repository: {
|
|
290
|
+
pullRequest: {
|
|
291
|
+
reviews: {
|
|
292
|
+
nodes: reviews
|
|
293
|
+
.filter((review) => review.state === "PENDING")
|
|
294
|
+
.map((review) => ({
|
|
295
|
+
id: review.node_id,
|
|
296
|
+
state: review.state,
|
|
297
|
+
author: review.user,
|
|
298
|
+
})),
|
|
299
|
+
pageInfo,
|
|
300
|
+
},
|
|
301
|
+
},
|
|
302
|
+
},
|
|
303
|
+
};
|
|
304
|
+
}
|
|
305
|
+
const review = reviews.find((item) => item.node_id === variables.reviewId);
|
|
306
|
+
if (
|
|
307
|
+
review === undefined ||
|
|
308
|
+
review.state !== "PENDING" ||
|
|
309
|
+
review.user?.login !== viewer.login ||
|
|
310
|
+
review.pull_request_url !== `https://api.github.com/${root}`
|
|
311
|
+
)
|
|
312
|
+
return yield* new GitHubCommandError({
|
|
313
|
+
command: "gh-tool pr submit-review",
|
|
314
|
+
exitCode: 1,
|
|
315
|
+
message: "REST could not verify an owned pending review on this PR",
|
|
316
|
+
stderr: "REST could not verify an owned pending review on this PR",
|
|
317
|
+
});
|
|
318
|
+
if (query.includes("submitPullRequestReview")) {
|
|
319
|
+
if (
|
|
320
|
+
typeof variables.event !== "string" ||
|
|
321
|
+
!["COMMENT", "APPROVE", "REQUEST_CHANGES"].includes(variables.event) ||
|
|
322
|
+
typeof variables.body !== "string"
|
|
323
|
+
)
|
|
324
|
+
return yield* new GitHubCommandError({
|
|
325
|
+
command: "gh-tool pr submit-review",
|
|
326
|
+
exitCode: 1,
|
|
327
|
+
message: "Invalid review event or body",
|
|
328
|
+
stderr: "Invalid review event or body",
|
|
329
|
+
});
|
|
330
|
+
const result = yield* parseRest(
|
|
331
|
+
Schema.Struct({ node_id: Schema.String, state: Schema.String }),
|
|
332
|
+
yield* read([
|
|
333
|
+
"api",
|
|
334
|
+
"--method",
|
|
335
|
+
"POST",
|
|
336
|
+
`${root}/reviews/${review.id}/events`,
|
|
337
|
+
"-f",
|
|
338
|
+
`event=${variables.event}`,
|
|
339
|
+
"-f",
|
|
340
|
+
`body=${variables.body}`,
|
|
341
|
+
]),
|
|
342
|
+
);
|
|
343
|
+
const fallback = yield* reportFallback([]);
|
|
344
|
+
return {
|
|
345
|
+
fallback,
|
|
346
|
+
submitPullRequestReview: { pullRequestReview: { id: result.node_id, state: result.state } },
|
|
347
|
+
};
|
|
348
|
+
}
|
|
349
|
+
const comments = (yield* parseRest(
|
|
350
|
+
Schema.Array(Schema.Array(Schema.Struct({ body: Schema.String }))),
|
|
351
|
+
yield* restPages(read, `${root}/reviews/${review.id}/comments`),
|
|
352
|
+
)).flat();
|
|
353
|
+
const fallback = yield* reportFallback([]);
|
|
354
|
+
return {
|
|
355
|
+
fallback,
|
|
356
|
+
viewer,
|
|
357
|
+
node: {
|
|
358
|
+
id: review.node_id,
|
|
359
|
+
state: review.state,
|
|
360
|
+
body: review.body,
|
|
361
|
+
author: review.user,
|
|
362
|
+
pullRequest: { number: pr, repository: { nameWithOwner: repo } },
|
|
363
|
+
comments: { nodes: comments, pageInfo },
|
|
364
|
+
},
|
|
365
|
+
};
|
|
366
|
+
});
|