@henryqw/pi-pr 0.3.1 → 0.3.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/extensions/pr.ts +16 -22
- package/package.json +1 -1
package/extensions/pr.ts
CHANGED
|
@@ -15,15 +15,15 @@ const CREATE_PR_SKILL_COMMAND = "skill:pi-pr-create";
|
|
|
15
15
|
const FAILED_CHECK_STATES = new Set(["ACTION_REQUIRED", "CANCELLED", "ERROR", "FAILURE", "STALE", "STARTUP_FAILURE", "TIMED_OUT"]);
|
|
16
16
|
const SUCCESSFUL_CHECK_STATES = new Set(["NEUTRAL", "SKIPPED", "SUCCESS"]);
|
|
17
17
|
|
|
18
|
-
type Lifecycle = "D" | "O" | "M" | "C";
|
|
19
18
|
type CiStatus = "success" | "running" | "failure" | "none";
|
|
20
19
|
type PullRequest = {
|
|
21
20
|
id: string;
|
|
22
21
|
number: number;
|
|
23
|
-
url:
|
|
22
|
+
url: URL;
|
|
24
23
|
headRefOid: string;
|
|
25
24
|
updatedAt: string;
|
|
26
|
-
|
|
25
|
+
state: "OPEN" | "MERGED" | "CLOSED";
|
|
26
|
+
isDraft: boolean;
|
|
27
27
|
mergeable: string;
|
|
28
28
|
reviewDecision: string | null;
|
|
29
29
|
statusCheckRollup: unknown[];
|
|
@@ -33,14 +33,10 @@ function isRecord(value: unknown): value is Record<string, unknown> {
|
|
|
33
33
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
34
34
|
}
|
|
35
35
|
|
|
36
|
-
function pullRequestUrl(value: unknown):
|
|
37
|
-
if (typeof value !== "string") return undefined;
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
return url.protocol === "http:" || url.protocol === "https:" ? url.href : undefined;
|
|
41
|
-
} catch {
|
|
42
|
-
return undefined;
|
|
43
|
-
}
|
|
36
|
+
function pullRequestUrl(value: unknown): URL | undefined {
|
|
37
|
+
if (typeof value !== "string" || !URL.canParse(value)) return undefined;
|
|
38
|
+
const url = new URL(value);
|
|
39
|
+
return url.protocol === "http:" || url.protocol === "https:" ? url : undefined;
|
|
44
40
|
}
|
|
45
41
|
|
|
46
42
|
export function parsePullRequest(value: unknown): PullRequest | undefined {
|
|
@@ -60,16 +56,14 @@ export function parsePullRequest(value: unknown): PullRequest | undefined {
|
|
|
60
56
|
typeof id !== "string" || !id ||
|
|
61
57
|
typeof number !== "number" || !Number.isSafeInteger(number) || number <= 0 || !url ||
|
|
62
58
|
typeof headRefOid !== "string" || !headRefOid ||
|
|
63
|
-
typeof updatedAt !== "string" || Number.isNaN(Date.parse(updatedAt)) ||
|
|
59
|
+
typeof updatedAt !== "string" || Number.isNaN(Date.parse(updatedAt)) ||
|
|
60
|
+
(state !== "MERGED" && state !== "CLOSED" && state !== "OPEN") ||
|
|
64
61
|
typeof isDraft !== "boolean" || typeof mergeable !== "string" ||
|
|
65
62
|
(reviewDecision !== null && typeof reviewDecision !== "string") ||
|
|
66
63
|
(statusCheckRollup !== null && !Array.isArray(statusCheckRollup))
|
|
67
64
|
) return undefined;
|
|
68
65
|
|
|
69
|
-
|
|
70
|
-
if (!lifecycle) return undefined;
|
|
71
|
-
|
|
72
|
-
return { id, number, url, headRefOid, updatedAt, lifecycle, mergeable, reviewDecision, statusCheckRollup: statusCheckRollup ?? [] };
|
|
66
|
+
return { id, number, url, headRefOid, updatedAt, state, isDraft, mergeable, reviewDecision, statusCheckRollup: statusCheckRollup ?? [] };
|
|
73
67
|
}
|
|
74
68
|
|
|
75
69
|
function parseUnresolvedReviewCount(value: string): number {
|
|
@@ -136,19 +130,19 @@ type Status = {
|
|
|
136
130
|
};
|
|
137
131
|
|
|
138
132
|
function statusFor(pullRequest: PullRequest, ci: CiStatus): Status {
|
|
139
|
-
if (pullRequest.
|
|
140
|
-
if (pullRequest.
|
|
133
|
+
if (pullRequest.state === "MERGED") return { text: "merged", color: "success" };
|
|
134
|
+
if (pullRequest.state === "CLOSED") return { text: "closed", color: "dim" };
|
|
141
135
|
if (pullRequest.mergeable === "CONFLICTING") return { text: "merge conflict", color: "error" };
|
|
142
136
|
if (pullRequest.reviewDecision === "CHANGES_REQUESTED") return { text: "changes requested", color: "error" };
|
|
143
137
|
if (ci === "failure") return { text: "CI failed", color: "error" };
|
|
144
138
|
if (ci === "running") return { text: "CI running", color: "warning" };
|
|
145
|
-
if (pullRequest.
|
|
139
|
+
if (pullRequest.isDraft) return { text: "draft", color: "warning" };
|
|
146
140
|
if (pullRequest.reviewDecision === "APPROVED") return { text: "approved", color: "success" };
|
|
147
141
|
return { text: "open", color: "accent" };
|
|
148
142
|
}
|
|
149
143
|
|
|
150
144
|
export function formatPullRequest(pullRequest: PullRequest, theme: ExtensionContext["ui"]["theme"], unresolved = 0): string {
|
|
151
|
-
const link = hyperlink(theme.fg("text", `PR #${pullRequest.number}`), pullRequest.url);
|
|
145
|
+
const link = hyperlink(theme.fg("text", `PR #${pullRequest.number}`), pullRequest.url.href);
|
|
152
146
|
const status = unresolved > 0
|
|
153
147
|
? { text: `${unresolved} unresolved`, color: "warning" as const }
|
|
154
148
|
: statusFor(pullRequest, ciStatus(pullRequest.statusCheckRollup));
|
|
@@ -203,7 +197,7 @@ export default function pullRequestExtension(pi: ExtensionAPI): void {
|
|
|
203
197
|
ctx.ui.setStatus("pi-pr", undefined);
|
|
204
198
|
return;
|
|
205
199
|
}
|
|
206
|
-
if (pullRequest.
|
|
200
|
+
if (pullRequest.state === "MERGED" || pullRequest.state === "CLOSED") {
|
|
207
201
|
reviewState = undefined;
|
|
208
202
|
reviewWindow = undefined;
|
|
209
203
|
ctx.ui.setStatus("pi-pr", formatPullRequest(pullRequest, ctx.ui.theme));
|
|
@@ -234,7 +228,7 @@ export default function pullRequestExtension(pi: ExtensionAPI): void {
|
|
|
234
228
|
const reviews = await pi.exec(
|
|
235
229
|
"gh",
|
|
236
230
|
[
|
|
237
|
-
"api", "graphql", "--hostname",
|
|
231
|
+
"api", "graphql", "--hostname", pullRequest.url.hostname, "--paginate",
|
|
238
232
|
"-f", `query=${REVIEW_THREADS_QUERY}`, "-F", `id=${pullRequest.id}`,
|
|
239
233
|
"--jq", "[.data.node.reviewThreads.nodes[] | select(.isResolved == false)] | length",
|
|
240
234
|
],
|