opencode-forgekeeper 2.1.1 → 2.2.1
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 +34 -14
- package/dist/index.js +376 -44
- package/dist/tui.js +429 -200
- package/package.json +1 -1
package/dist/tui.js
CHANGED
|
@@ -73,14 +73,182 @@ class ForgeError extends Error {
|
|
|
73
73
|
var query = (text) => text;
|
|
74
74
|
var typed = (transport) => async (host, query2, variables) => await transport(host, query2, variables);
|
|
75
75
|
|
|
76
|
-
// packages/forgekeeper/src/
|
|
76
|
+
// packages/forgekeeper/src/github-feedback.ts
|
|
77
77
|
var PAGE_SIZE = 100;
|
|
78
78
|
var MAX_COMMENT_PAGES = 20;
|
|
79
|
+
var MAX_FETCH_REQUESTS = 200;
|
|
80
|
+
var author = "author { __typename login ... on User { id } ... on Bot { id } ... on Mannequin { id } }";
|
|
81
|
+
var page = "pageInfo { hasPreviousPage startCursor }";
|
|
82
|
+
var INLINE_FIELDS = `id url state createdAt publishedAt lastEditedAt isMinimized ${author}`;
|
|
83
|
+
var listQuery = (field, connection) => query(`query($owner: String!, $repo: String!, $number: Int!, $before: String) {
|
|
84
|
+
viewer { id }
|
|
85
|
+
repository(owner: $owner, name: $repo) {
|
|
86
|
+
pullRequest(number: $number) {
|
|
87
|
+
${field}(last: ${PAGE_SIZE}, before: $before) { ${page} nodes { ${connection} } }
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
}`);
|
|
91
|
+
var ISSUE_COMMENTS_QUERY = listQuery("comments", `id url createdAt publishedAt lastEditedAt isMinimized ${author}`);
|
|
92
|
+
var REVIEWS_QUERY = listQuery("reviews", `id url state body submittedAt lastEditedAt isMinimized ${author}`);
|
|
93
|
+
var THREADS_QUERY = listQuery("reviewThreads", `id isResolved comments(last: ${PAGE_SIZE}) { ${page} nodes { ${INLINE_FIELDS} } }`);
|
|
94
|
+
var THREAD_COMMENTS_QUERY = query(`query($id: ID!, $before: String) {
|
|
95
|
+
node(id: $id) {
|
|
96
|
+
... on PullRequestReviewThread {
|
|
97
|
+
comments(last: ${PAGE_SIZE}, before: $before) { ${page} nodes { ${INLINE_FIELDS} } }
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
}`);
|
|
101
|
+
var REVIEW_STATES = new Set(["COMMENTED", "CHANGES_REQUESTED", "APPROVED"]);
|
|
102
|
+
var time = (...values) => {
|
|
103
|
+
const value = values.find((candidate) => candidate);
|
|
104
|
+
return value ? Date.parse(value) : NaN;
|
|
105
|
+
};
|
|
106
|
+
var activity = (lastEditedAt, postedAt) => {
|
|
107
|
+
const edited = lastEditedAt ? Date.parse(lastEditedAt) : NaN;
|
|
108
|
+
return Number.isFinite(edited) ? Math.max(edited, postedAt) : postedAt;
|
|
109
|
+
};
|
|
110
|
+
function build({ node, postedAt, editedAt, resolved }) {
|
|
111
|
+
if (node.isMinimized || !node.author?.id || !Number.isFinite(postedAt) || !Number.isFinite(editedAt))
|
|
112
|
+
return;
|
|
113
|
+
const { __typename, login } = node.author;
|
|
114
|
+
return {
|
|
115
|
+
id: node.id,
|
|
116
|
+
order: postedAt,
|
|
117
|
+
url: node.url ?? "",
|
|
118
|
+
editedAt,
|
|
119
|
+
resolved,
|
|
120
|
+
bot: __typename === "Bot" || login.endsWith("[bot]"),
|
|
121
|
+
authorID: node.author.id,
|
|
122
|
+
username: login
|
|
123
|
+
};
|
|
124
|
+
}
|
|
125
|
+
function toIssueComment(node) {
|
|
126
|
+
const postedAt = time(node.publishedAt, node.createdAt);
|
|
127
|
+
return build({
|
|
128
|
+
node,
|
|
129
|
+
postedAt,
|
|
130
|
+
editedAt: activity(node.lastEditedAt, postedAt),
|
|
131
|
+
resolved: false
|
|
132
|
+
});
|
|
133
|
+
}
|
|
134
|
+
function toReview(node) {
|
|
135
|
+
if (!REVIEW_STATES.has(node.state) || !node.body.trim())
|
|
136
|
+
return;
|
|
137
|
+
const postedAt = time(node.submittedAt);
|
|
138
|
+
return build({
|
|
139
|
+
node,
|
|
140
|
+
postedAt,
|
|
141
|
+
editedAt: activity(node.lastEditedAt, postedAt),
|
|
142
|
+
resolved: false
|
|
143
|
+
});
|
|
144
|
+
}
|
|
145
|
+
function toInlineComment(node, resolved) {
|
|
146
|
+
if (node.state === "PENDING")
|
|
147
|
+
return;
|
|
148
|
+
const postedAt = time(node.publishedAt, node.createdAt);
|
|
149
|
+
return build({
|
|
150
|
+
node,
|
|
151
|
+
postedAt,
|
|
152
|
+
editedAt: activity(node.lastEditedAt, postedAt),
|
|
153
|
+
resolved
|
|
154
|
+
});
|
|
155
|
+
}
|
|
156
|
+
var commentWindow = { pages: MAX_COMMENT_PAGES, completeAtLimit: true };
|
|
157
|
+
var allThreads = { pages: MAX_FETCH_REQUESTS, completeAtLimit: false };
|
|
158
|
+
async function readList(graphql, host, base, text, field, limit = commentWindow) {
|
|
159
|
+
const pages = [];
|
|
160
|
+
let viewer;
|
|
161
|
+
let before;
|
|
162
|
+
const result = (complete) => ({
|
|
163
|
+
items: pages.toReversed().flat(),
|
|
164
|
+
viewer,
|
|
165
|
+
complete
|
|
166
|
+
});
|
|
167
|
+
for (let count = 0;count < limit.pages; count++) {
|
|
168
|
+
const variables = before ? { ...base, before } : base;
|
|
169
|
+
const data = await graphql(host, text, variables);
|
|
170
|
+
viewer ??= data.viewer?.id ?? undefined;
|
|
171
|
+
const connection = data.repository?.pullRequest?.[field];
|
|
172
|
+
if (!connection)
|
|
173
|
+
return count === 0 ? { viewer, complete: false } : result(false);
|
|
174
|
+
pages.push(connection.nodes);
|
|
175
|
+
if (!connection.pageInfo.hasPreviousPage)
|
|
176
|
+
return result(true);
|
|
177
|
+
before = connection.pageInfo.startCursor ?? undefined;
|
|
178
|
+
if (!before)
|
|
179
|
+
return result(false);
|
|
180
|
+
}
|
|
181
|
+
return result(limit.completeAtLimit);
|
|
182
|
+
}
|
|
183
|
+
async function readOlderComments(graphql, host, thread) {
|
|
184
|
+
if (!thread.comments)
|
|
185
|
+
return { comments: [], complete: false };
|
|
186
|
+
const pages = [];
|
|
187
|
+
let before = thread.comments?.pageInfo.hasPreviousPage ? thread.comments.pageInfo.startCursor ?? undefined : undefined;
|
|
188
|
+
if (thread.comments?.pageInfo.hasPreviousPage && !before)
|
|
189
|
+
return { comments: [], complete: false };
|
|
190
|
+
for (let count = 1;before && count < MAX_COMMENT_PAGES; count++) {
|
|
191
|
+
const data = await graphql(host, THREAD_COMMENTS_QUERY, { id: thread.id, before });
|
|
192
|
+
const connection = data.node?.comments;
|
|
193
|
+
if (!connection)
|
|
194
|
+
return { comments: pages.toReversed().flat(), complete: false };
|
|
195
|
+
pages.push(connection.nodes);
|
|
196
|
+
before = connection.pageInfo.hasPreviousPage ? connection.pageInfo.startCursor ?? undefined : undefined;
|
|
197
|
+
if (connection.pageInfo.hasPreviousPage && !before)
|
|
198
|
+
return { comments: pages.toReversed().flat(), complete: false };
|
|
199
|
+
}
|
|
200
|
+
return { comments: pages.toReversed().flat(), complete: true };
|
|
201
|
+
}
|
|
202
|
+
async function fetchComments(transport, host, project, number) {
|
|
203
|
+
let requests = 0;
|
|
204
|
+
const graphql = typed(async (...args) => {
|
|
205
|
+
if (requests++ >= MAX_FETCH_REQUESTS)
|
|
206
|
+
return {};
|
|
207
|
+
return transport(...args);
|
|
208
|
+
});
|
|
209
|
+
const [owner, repo] = project.split("/");
|
|
210
|
+
const base = { owner, repo, number: Number(number) };
|
|
211
|
+
const [conversation, reviews, threads] = await Promise.all([
|
|
212
|
+
readList(graphql, host, base, ISSUE_COMMENTS_QUERY, "comments"),
|
|
213
|
+
readList(graphql, host, base, REVIEWS_QUERY, "reviews"),
|
|
214
|
+
readList(graphql, host, base, THREADS_QUERY, "reviewThreads", allThreads)
|
|
215
|
+
]);
|
|
216
|
+
if (!conversation.items || !reviews.items || !threads.items)
|
|
217
|
+
return;
|
|
218
|
+
const viewerID = conversation.viewer ?? reviews.viewer ?? threads.viewer;
|
|
219
|
+
let threadsComplete = threads.complete;
|
|
220
|
+
const inline = [];
|
|
221
|
+
for (const thread of threads.items) {
|
|
222
|
+
const older = await readOlderComments(graphql, host, thread);
|
|
223
|
+
threadsComplete &&= older.complete;
|
|
224
|
+
for (const node of [...older.comments, ...thread.comments?.nodes ?? []]) {
|
|
225
|
+
const comment = toInlineComment(node, thread.isResolved);
|
|
226
|
+
if (comment)
|
|
227
|
+
inline.push(comment);
|
|
228
|
+
}
|
|
229
|
+
inline.sort((a, b) => b.order - a.order);
|
|
230
|
+
inline.splice(PAGE_SIZE * MAX_COMMENT_PAGES);
|
|
231
|
+
}
|
|
232
|
+
const comments = [
|
|
233
|
+
...conversation.items.map(toIssueComment),
|
|
234
|
+
...reviews.items.map(toReview),
|
|
235
|
+
...inline.sort((a, b) => a.order - b.order).slice(-PAGE_SIZE * MAX_COMMENT_PAGES)
|
|
236
|
+
].flatMap((comment) => comment ?? []);
|
|
237
|
+
return {
|
|
238
|
+
complete: conversation.complete && reviews.complete && threadsComplete && viewerID !== undefined,
|
|
239
|
+
viewerID,
|
|
240
|
+
comments: comments.sort((a, b) => a.order - b.order)
|
|
241
|
+
};
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
// packages/forgekeeper/src/gitlab-feedback.ts
|
|
245
|
+
var PAGE_SIZE2 = 100;
|
|
246
|
+
var MAX_COMMENT_PAGES2 = 20;
|
|
79
247
|
var COMMENTS_QUERY = query(`query($project: ID!, $iid: String!, $before: String) {
|
|
80
248
|
currentUser { id }
|
|
81
249
|
project(fullPath: $project) {
|
|
82
250
|
mergeRequest(iid: $iid) {
|
|
83
|
-
notes(last: ${
|
|
251
|
+
notes(last: ${PAGE_SIZE2}, before: $before, filter: ONLY_COMMENTS) {
|
|
84
252
|
pageInfo { hasPreviousPage startCursor }
|
|
85
253
|
nodes {
|
|
86
254
|
id url createdAt updatedAt lastEditedAt system
|
|
@@ -109,7 +277,7 @@ function toComment(node) {
|
|
|
109
277
|
username: node.author.username
|
|
110
278
|
};
|
|
111
279
|
}
|
|
112
|
-
async function
|
|
280
|
+
async function fetchComments2(transport, host, project, iid) {
|
|
113
281
|
const graphql = typed(transport);
|
|
114
282
|
const pages = [];
|
|
115
283
|
let viewerID;
|
|
@@ -119,7 +287,7 @@ async function fetchComments(transport, host, project, iid) {
|
|
|
119
287
|
viewerID,
|
|
120
288
|
comments: pages.toReversed().flat()
|
|
121
289
|
});
|
|
122
|
-
for (let
|
|
290
|
+
for (let page2 = 0;page2 < MAX_COMMENT_PAGES2; page2++) {
|
|
123
291
|
const variables = { project, iid };
|
|
124
292
|
if (before)
|
|
125
293
|
variables.before = before;
|
|
@@ -127,7 +295,7 @@ async function fetchComments(transport, host, project, iid) {
|
|
|
127
295
|
viewerID ??= data.currentUser?.id ?? undefined;
|
|
128
296
|
const connection = data.project?.mergeRequest?.notes;
|
|
129
297
|
if (!connection)
|
|
130
|
-
return
|
|
298
|
+
return page2 === 0 ? undefined : snapshot(false);
|
|
131
299
|
pages.push(connection.nodes.flatMap((node) => toComment(node) ?? []));
|
|
132
300
|
if (!connection.pageInfo.hasPreviousPage)
|
|
133
301
|
return snapshot(true);
|
|
@@ -140,7 +308,7 @@ async function fetchComments(transport, host, project, iid) {
|
|
|
140
308
|
|
|
141
309
|
// packages/forgekeeper/src/gitlab.ts
|
|
142
310
|
var DISCUSSIONS = "pageInfo { hasNextPage endCursor } nodes { resolvable resolved }";
|
|
143
|
-
var
|
|
311
|
+
var PAGE_SIZE3 = 100;
|
|
144
312
|
var MAX_DISCUSSION_PAGES = 50;
|
|
145
313
|
var MERGE_REQUEST_FIELDS = `
|
|
146
314
|
iid title webUrl state draft conflicts approved detailedMergeStatus diffHeadSha updatedAt targetBranch
|
|
@@ -149,7 +317,7 @@ var MERGE_REQUEST_FIELDS = `
|
|
|
149
317
|
targetProject { fullPath }
|
|
150
318
|
headPipeline { status path detailedStatus { label } }
|
|
151
319
|
reviewers(first: 100) { nodes { type username bot mergeRequestInteraction { reviewState approved } } }
|
|
152
|
-
discussions(first: ${
|
|
320
|
+
discussions(first: ${PAGE_SIZE3}) { ${DISCUSSIONS} }
|
|
153
321
|
`;
|
|
154
322
|
function mergeRequestsQuery(projectCount) {
|
|
155
323
|
const variables = Array.from({ length: projectCount }, (_, index) => `$p${index}: ID!`).join(", ");
|
|
@@ -184,7 +352,7 @@ var SOURCE_BRANCH_QUERY = query(`query($project: ID!, $iid: String!) {
|
|
|
184
352
|
}`);
|
|
185
353
|
var DISCUSSIONS_QUERY = query(`query($project: ID!, $iid: String!, $after: String) {
|
|
186
354
|
project(fullPath: $project) {
|
|
187
|
-
mergeRequest(iid: $iid) { discussions(first: ${
|
|
355
|
+
mergeRequest(iid: $iid) { discussions(first: ${PAGE_SIZE3}, after: $after) { ${DISCUSSIONS} } }
|
|
188
356
|
}
|
|
189
357
|
}`);
|
|
190
358
|
function classifyError(message, code) {
|
|
@@ -223,7 +391,7 @@ function glabGraphQL(run, cwd) {
|
|
|
223
391
|
return body.data;
|
|
224
392
|
};
|
|
225
393
|
}
|
|
226
|
-
var countUnresolved = (
|
|
394
|
+
var countUnresolved = (page2) => page2.nodes.filter((discussion) => discussion.resolvable && !discussion.resolved).length;
|
|
227
395
|
var gitlabTraits = {
|
|
228
396
|
kind: "gitlab",
|
|
229
397
|
noun: "MR",
|
|
@@ -258,7 +426,7 @@ var gitlabTraits = {
|
|
|
258
426
|
feedback: {
|
|
259
427
|
async fetch(run, directory, request) {
|
|
260
428
|
const ref = gitlabTraits.parseUrl(request.url);
|
|
261
|
-
return ref ?
|
|
429
|
+
return ref ? fetchComments2(glabGraphQL(run, directory), ref.host, ref.project, ref.iid) : undefined;
|
|
262
430
|
}
|
|
263
431
|
}
|
|
264
432
|
};
|
|
@@ -330,22 +498,22 @@ class GitLabForge {
|
|
|
330
498
|
}
|
|
331
499
|
async unresolvedThreads(host, node) {
|
|
332
500
|
let count = countUnresolved(node.discussions);
|
|
333
|
-
let
|
|
501
|
+
let page2 = node.discussions.pageInfo;
|
|
334
502
|
let pages = 1;
|
|
335
|
-
while (
|
|
503
|
+
while (page2.hasNextPage && page2.endCursor && pages < MAX_DISCUSSION_PAGES) {
|
|
336
504
|
const data = await this.graphql(host, DISCUSSIONS_QUERY, {
|
|
337
505
|
project: node.targetProject.fullPath,
|
|
338
506
|
iid: node.iid,
|
|
339
|
-
after:
|
|
507
|
+
after: page2.endCursor
|
|
340
508
|
});
|
|
341
509
|
const next = data.project?.mergeRequest?.discussions;
|
|
342
510
|
if (!next)
|
|
343
511
|
break;
|
|
344
512
|
count += countUnresolved(next);
|
|
345
|
-
|
|
513
|
+
page2 = next.pageInfo;
|
|
346
514
|
pages++;
|
|
347
515
|
}
|
|
348
|
-
return { count, complete: !
|
|
516
|
+
return { count, complete: !page2.hasNextPage };
|
|
349
517
|
}
|
|
350
518
|
async normalize(host, node) {
|
|
351
519
|
const threads = await this.unresolvedThreads(host, node);
|
|
@@ -384,10 +552,12 @@ class GitLabForge {
|
|
|
384
552
|
}
|
|
385
553
|
|
|
386
554
|
// packages/forgekeeper/src/github.ts
|
|
555
|
+
var COPILOT_AUTHOR = "copilot-pull-request-reviewer[bot]";
|
|
387
556
|
var fields = `number title url state isDraft mergeable reviewDecision headRefOid headRefName
|
|
388
557
|
headRepository { nameWithOwner } baseRepository { nameWithOwner } baseRefName updatedAt
|
|
389
558
|
reviewThreads(first:100) { nodes { isResolved } pageInfo { hasNextPage endCursor } }
|
|
390
|
-
reviewRequests(first:100) { nodes { requestedReviewer { ... on User { login } ... on Team { name } } } pageInfo { hasNextPage } }
|
|
559
|
+
reviewRequests(first:100) { nodes { requestedReviewer { __typename ... on User { login } ... on Bot { login } ... on Team { name } } } pageInfo { hasNextPage endCursor } }
|
|
560
|
+
copilotReviews: reviews(last:1, author:"${COPILOT_AUTHOR}", states:[COMMENTED,CHANGES_REQUESTED,APPROVED,DISMISSED]) { nodes { id state comments { totalCount } } }
|
|
391
561
|
commits(last:1) { nodes { commit { statusCheckRollup { contexts(first:100) {
|
|
392
562
|
nodes { __typename ... on CheckRun { status conclusion detailsUrl } ... on StatusContext { state targetUrl } }
|
|
393
563
|
pageInfo { hasNextPage endCursor }
|
|
@@ -445,22 +615,31 @@ var CONCLUSIONS = [
|
|
|
445
615
|
];
|
|
446
616
|
var STATES = ["SUCCESS", "FAILURE", "ERROR", "PENDING", "EXPECTED"];
|
|
447
617
|
function checks(nodes, complete, url) {
|
|
618
|
+
const count = (value) => `${value} check${value === 1 ? "" : "s"}`;
|
|
448
619
|
const failed = nodes.filter((node) => FAILED.includes(node.conclusion ?? node.state ?? "")).length;
|
|
449
620
|
const pending = nodes.filter((node) => node.status ? node.status !== "COMPLETED" : ["PENDING", "EXPECTED"].includes(node.state ?? "")).length;
|
|
450
621
|
const unknown = nodes.some((node) => node.status === "COMPLETED" ? !CONCLUSIONS.includes(node.conclusion ?? "") : !node.status && !STATES.includes(node.state ?? ""));
|
|
451
622
|
if (failed)
|
|
452
623
|
return {
|
|
453
624
|
status: "FAILED",
|
|
454
|
-
label: `${failed} failed${pending ? `, ${pending} pending` : ""}${complete ? "" : " (partial)"}`,
|
|
625
|
+
label: `${count(failed)} failed${pending ? `, ${count(pending)} pending` : ""}${complete ? "" : " (partial)"}`,
|
|
455
626
|
url
|
|
456
627
|
};
|
|
457
628
|
if (pending || !complete || unknown)
|
|
458
629
|
return {
|
|
459
630
|
status: "PENDING",
|
|
460
|
-
label: `${pending ? `${pending} pending` : "unknown"}${complete ? "" : " (partial)"}`,
|
|
631
|
+
label: `${pending ? `${count(pending)} pending` : "unknown"}${complete ? "" : " (partial)"}`,
|
|
461
632
|
url
|
|
462
633
|
};
|
|
463
|
-
|
|
634
|
+
const label = [
|
|
635
|
+
["SUCCESS", "passed"],
|
|
636
|
+
["SKIPPED", "skipped"],
|
|
637
|
+
["NEUTRAL", "neutral"]
|
|
638
|
+
].flatMap(([result, text]) => {
|
|
639
|
+
const total = nodes.filter((node) => (node.conclusion ?? node.state) === result).length;
|
|
640
|
+
return total ? [`${count(total)} ${text}`] : [];
|
|
641
|
+
}).join(", ");
|
|
642
|
+
return { status: "SUCCESS", label: label || "0 checks", url };
|
|
464
643
|
}
|
|
465
644
|
function parseGitHubUrl(url, pattern) {
|
|
466
645
|
const ref = parseWebUrl("github", url, pattern);
|
|
@@ -481,8 +660,43 @@ var githubTraits = {
|
|
|
481
660
|
indicators: (request) => request.reviewDecision === "CHANGES_REQUESTED" ? [{ text: "changes requested", tone: "warning", essential: true }] : [],
|
|
482
661
|
details: (request) => [
|
|
483
662
|
`Review decision: ${request.reviewDecision ? humanize(request.reviewDecision) : "not reported"}`
|
|
484
|
-
]
|
|
663
|
+
],
|
|
664
|
+
automatedReview: {
|
|
665
|
+
name: "GitHub Copilot",
|
|
666
|
+
status: (request) => copilotStatus(request.copilotReview)
|
|
667
|
+
},
|
|
668
|
+
feedback: {
|
|
669
|
+
async fetch(run, directory, request) {
|
|
670
|
+
const ref = githubTraits.parseUrl(request.url);
|
|
671
|
+
return ref ? fetchComments(ghGraphQL(run, directory), ref.host, ref.project, ref.iid) : undefined;
|
|
672
|
+
}
|
|
673
|
+
}
|
|
485
674
|
};
|
|
675
|
+
function copilotStatus(review) {
|
|
676
|
+
if (!review)
|
|
677
|
+
return;
|
|
678
|
+
const feedback = review.comments > 0 && !review.dismissed;
|
|
679
|
+
const label = review.dismissed ? "dismissed" : feedback ? "commented" : "no comments";
|
|
680
|
+
const completed = review.reviewID ? { id: review.reviewID, feedback, label } : undefined;
|
|
681
|
+
if (review.requested)
|
|
682
|
+
return { state: "running", label: "reviewing", completed };
|
|
683
|
+
if (!completed)
|
|
684
|
+
return;
|
|
685
|
+
return { state: feedback ? "feedback" : "settled", label, completed };
|
|
686
|
+
}
|
|
687
|
+
var isCopilotReviewer = (login) => /^copilot-pull-request-reviewer(\[bot\])?$/i.test(login ?? "");
|
|
688
|
+
function copilotReview(node) {
|
|
689
|
+
const requested = node.reviewRequests.nodes.some((request) => isCopilotReviewer(request.requestedReviewer?.login));
|
|
690
|
+
const latest = node.copilotReviews?.nodes?.find((review) => review);
|
|
691
|
+
if (!requested && !latest)
|
|
692
|
+
return;
|
|
693
|
+
return {
|
|
694
|
+
requested,
|
|
695
|
+
reviewID: latest?.id,
|
|
696
|
+
comments: latest?.comments.totalCount ?? 0,
|
|
697
|
+
...latest?.state === "DISMISSED" ? { dismissed: true } : {}
|
|
698
|
+
};
|
|
699
|
+
}
|
|
486
700
|
|
|
487
701
|
class GitHubForge {
|
|
488
702
|
traits = githubTraits;
|
|
@@ -533,7 +747,7 @@ class GitHubForge {
|
|
|
533
747
|
const [owner, repo] = target.path.split("/");
|
|
534
748
|
let after;
|
|
535
749
|
let complete = false;
|
|
536
|
-
for (let
|
|
750
|
+
for (let page2 = 0;page2 < MAX_PAGES; page2++) {
|
|
537
751
|
const data = await this.graphql(target.host, query(`query($owner:String!,$repo:String!,$branch:String!${after ? ",$after:String!" : ""}) {
|
|
538
752
|
repository(owner:$owner,name:$repo) { pullRequests(first:100,states:OPEN,headRefName:$branch${after ? ",after:$after" : ""}) {
|
|
539
753
|
nodes { ${fields} } pageInfo { hasNextPage endCursor }
|
|
@@ -563,21 +777,21 @@ class GitHubForge {
|
|
|
563
777
|
async threads(host, node) {
|
|
564
778
|
const [owner, repo] = node.baseRepository.nameWithOwner.split("/");
|
|
565
779
|
const threads = [...node.reviewThreads.nodes];
|
|
566
|
-
let
|
|
567
|
-
for (let count = 1;
|
|
780
|
+
let page2 = node.reviewThreads.pageInfo;
|
|
781
|
+
for (let count = 1;page2?.hasNextPage && page2.endCursor && count < MAX_PAGES; count++) {
|
|
568
782
|
const data = await this.graphql(host, query(`query($owner:String!,$repo:String!,$number:Int!,$after:String!) {
|
|
569
783
|
repository(owner:$owner,name:$repo) { pullRequest(number:$number) {
|
|
570
784
|
reviewThreads(first:100,after:$after) { nodes { isResolved } pageInfo { hasNextPage endCursor } }
|
|
571
|
-
} } }`), { owner, repo, number: node.number, after:
|
|
785
|
+
} } }`), { owner, repo, number: node.number, after: page2.endCursor });
|
|
572
786
|
const next = data.repository?.pullRequest?.reviewThreads;
|
|
573
787
|
if (!next)
|
|
574
788
|
break;
|
|
575
789
|
threads.push(...next.nodes);
|
|
576
|
-
|
|
790
|
+
page2 = next.pageInfo;
|
|
577
791
|
}
|
|
578
792
|
return {
|
|
579
793
|
unresolved: threads.filter((thread) => !thread.isResolved).length,
|
|
580
|
-
complete: !
|
|
794
|
+
complete: !page2?.hasNextPage
|
|
581
795
|
};
|
|
582
796
|
}
|
|
583
797
|
async contexts(host, node) {
|
|
@@ -598,7 +812,33 @@ class GitHubForge {
|
|
|
598
812
|
}
|
|
599
813
|
return { nodes: contexts, complete: !cursor?.hasNextPage };
|
|
600
814
|
}
|
|
815
|
+
async reviewers(host, node) {
|
|
816
|
+
const nodes = [...node.reviewRequests.nodes];
|
|
817
|
+
let reviewerPage = node.reviewRequests.pageInfo;
|
|
818
|
+
for (let count = 1;reviewerPage?.hasNextPage && count < MAX_PAGES; count++) {
|
|
819
|
+
if (!reviewerPage.endCursor)
|
|
820
|
+
throw new ForgeError("request", "GitHub reviewer pagination cursor missing");
|
|
821
|
+
const [owner, repo] = node.baseRepository.nameWithOwner.split("/");
|
|
822
|
+
const data = await this.graphql(host, query(`query($owner:String!,$repo:String!,$number:Int!,$after:String!) {
|
|
823
|
+
repository(owner:$owner,name:$repo) { pullRequest(number:$number) {
|
|
824
|
+
reviewRequests(first:100,after:$after) {
|
|
825
|
+
nodes { requestedReviewer { __typename ... on User { login } ... on Bot { login } ... on Team { name } } }
|
|
826
|
+
pageInfo { hasNextPage endCursor }
|
|
827
|
+
}
|
|
828
|
+
} }
|
|
829
|
+
}`), { owner, repo, number: node.number, after: reviewerPage.endCursor });
|
|
830
|
+
const next = data.repository?.pullRequest?.reviewRequests;
|
|
831
|
+
if (!next)
|
|
832
|
+
throw new ForgeError("request", "GitHub reviewers unavailable");
|
|
833
|
+
nodes.push(...next.nodes);
|
|
834
|
+
reviewerPage = next.pageInfo;
|
|
835
|
+
}
|
|
836
|
+
if (reviewerPage?.hasNextPage)
|
|
837
|
+
throw new ForgeError("request", "GitHub reviewers exceeded the pagination limit");
|
|
838
|
+
return { nodes, pageInfo: reviewerPage };
|
|
839
|
+
}
|
|
601
840
|
async normalize(host, node) {
|
|
841
|
+
const reviewers = await this.reviewers(host, node);
|
|
602
842
|
const [threads, contexts] = [await this.threads(host, node), await this.contexts(host, node)];
|
|
603
843
|
return {
|
|
604
844
|
forge: "github",
|
|
@@ -611,11 +851,14 @@ class GitHubForge {
|
|
|
611
851
|
conflictsKnown: node.mergeable !== "UNKNOWN",
|
|
612
852
|
approved: node.reviewDecision === "APPROVED",
|
|
613
853
|
reviewDecision: node.reviewDecision ?? undefined,
|
|
614
|
-
|
|
854
|
+
copilotReview: copilotReview({ ...node, reviewRequests: reviewers }),
|
|
855
|
+
awaitingReviewers: reviewers.nodes.flatMap((request) => {
|
|
615
856
|
const reviewer = request.requestedReviewer;
|
|
857
|
+
if (reviewer?.__typename === "Bot")
|
|
858
|
+
return [];
|
|
616
859
|
return reviewer?.login ? [reviewer.login] : reviewer?.name ? [reviewer.name] : [];
|
|
617
860
|
}),
|
|
618
|
-
reviewersComplete: !
|
|
861
|
+
reviewersComplete: !reviewers.pageInfo?.hasNextPage,
|
|
619
862
|
targetProject: node.baseRepository.nameWithOwner,
|
|
620
863
|
targetBranch: node.baseRefName,
|
|
621
864
|
headSha: node.headRefOid,
|
|
@@ -808,7 +1051,7 @@ function responsiveFooterSegments(snapshot, width) {
|
|
|
808
1051
|
}
|
|
809
1052
|
return fitted;
|
|
810
1053
|
}
|
|
811
|
-
var
|
|
1054
|
+
var time2 = (value) => new Date(value).toLocaleTimeString();
|
|
812
1055
|
function describe(request, head) {
|
|
813
1056
|
const traits = traitsOf(request);
|
|
814
1057
|
const lines = [
|
|
@@ -856,9 +1099,9 @@ function detailsMessage(snapshot) {
|
|
|
856
1099
|
lines.push("", ...describe(request, repository?.head ?? ""));
|
|
857
1100
|
}
|
|
858
1101
|
if (error)
|
|
859
|
-
lines.push("", `Last refresh failed at ${
|
|
1102
|
+
lines.push("", `Last refresh failed at ${time2(error.at)}: ${error.message}`);
|
|
860
1103
|
if (fetchedAt !== undefined)
|
|
861
|
-
lines.push("", `Last fetched: ${
|
|
1104
|
+
lines.push("", `Last fetched: ${time2(fetchedAt)}`);
|
|
862
1105
|
return lines.join(`
|
|
863
1106
|
`);
|
|
864
1107
|
}
|
|
@@ -1235,22 +1478,13 @@ var tui_default = {
|
|
|
1235
1478
|
})();
|
|
1236
1479
|
},
|
|
1237
1480
|
children: (url) => (() => {
|
|
1238
|
-
var _el$5 = _$createElement("text"), _el$6 = _$createElement("
|
|
1481
|
+
var _el$5 = _$createElement("text"), _el$6 = _$createElement("u");
|
|
1239
1482
|
_$insertNode(_el$5, _el$6);
|
|
1240
1483
|
_$setProp(_el$5, "wrapMode", "none");
|
|
1241
1484
|
_$setProp(_el$5, "flexShrink", 0);
|
|
1242
1485
|
_$setProp(_el$5, "onMouseUp", () => openUrl(url()));
|
|
1243
|
-
_$
|
|
1244
|
-
_$
|
|
1245
|
-
_$effect((_p$) => {
|
|
1246
|
-
var _v$ = color(segment.tone), _v$2 = url();
|
|
1247
|
-
_v$ !== _p$.e && (_p$.e = _$setProp(_el$5, "fg", _v$, _p$.e));
|
|
1248
|
-
_v$2 !== _p$.t && (_p$.t = _$setProp(_el$6, "href", _v$2, _p$.t));
|
|
1249
|
-
return _p$;
|
|
1250
|
-
}, {
|
|
1251
|
-
e: undefined,
|
|
1252
|
-
t: undefined
|
|
1253
|
-
});
|
|
1486
|
+
_$insert(_el$6, () => segment.text);
|
|
1487
|
+
_$effect((_$p) => _$setProp(_el$5, "fg", color(segment.tone), _$p));
|
|
1254
1488
|
return _el$5;
|
|
1255
1489
|
})()
|
|
1256
1490
|
})]
|
|
@@ -1286,43 +1520,41 @@ var tui_default = {
|
|
|
1286
1520
|
function DetailField(props) {
|
|
1287
1521
|
const foreground = () => props.tone ? color(props.tone) : context.theme.text.base;
|
|
1288
1522
|
return (() => {
|
|
1289
|
-
var _el$
|
|
1290
|
-
_$insertNode(_el$
|
|
1291
|
-
_$insertNode(_el$
|
|
1292
|
-
_$setProp(_el$
|
|
1293
|
-
_$insert(_el$
|
|
1294
|
-
_$insert(_el$
|
|
1523
|
+
var _el$7 = _$createElement("text"), _el$8 = _$createTextNode(`: `), _el$9 = _$createElement("span");
|
|
1524
|
+
_$insertNode(_el$7, _el$8);
|
|
1525
|
+
_$insertNode(_el$7, _el$9);
|
|
1526
|
+
_$setProp(_el$7, "onMouseUp", () => props.url && openUrl(props.url));
|
|
1527
|
+
_$insert(_el$7, () => props.label, _el$8);
|
|
1528
|
+
_$insert(_el$9, _$createComponent(Show, {
|
|
1295
1529
|
get when() {
|
|
1296
1530
|
return props.url;
|
|
1297
1531
|
},
|
|
1298
1532
|
get fallback() {
|
|
1299
1533
|
return (() => {
|
|
1300
|
-
var _el$
|
|
1301
|
-
_$insert(_el$
|
|
1302
|
-
return _el$
|
|
1534
|
+
var _el$10 = _$createElement("b");
|
|
1535
|
+
_$insert(_el$10, () => props.value);
|
|
1536
|
+
return _el$10;
|
|
1303
1537
|
})();
|
|
1304
1538
|
},
|
|
1305
|
-
children
|
|
1306
|
-
var _el$
|
|
1307
|
-
_$insertNode(_el$
|
|
1308
|
-
_$
|
|
1309
|
-
|
|
1310
|
-
|
|
1311
|
-
return _el$10;
|
|
1312
|
-
})()
|
|
1539
|
+
get children() {
|
|
1540
|
+
var _el$0 = _$createElement("u"), _el$1 = _$createElement("b");
|
|
1541
|
+
_$insertNode(_el$0, _el$1);
|
|
1542
|
+
_$insert(_el$1, () => props.value);
|
|
1543
|
+
return _el$0;
|
|
1544
|
+
}
|
|
1313
1545
|
}));
|
|
1314
1546
|
_$effect((_p$) => {
|
|
1315
|
-
var _v$
|
|
1547
|
+
var _v$ = context.theme.text.muted, _v$2 = {
|
|
1316
1548
|
fg: foreground()
|
|
1317
1549
|
};
|
|
1318
|
-
_v$
|
|
1319
|
-
_v$
|
|
1550
|
+
_v$ !== _p$.e && (_p$.e = _$setProp(_el$7, "fg", _v$, _p$.e));
|
|
1551
|
+
_v$2 !== _p$.t && (_p$.t = _$setProp(_el$9, "style", _v$2, _p$.t));
|
|
1320
1552
|
return _p$;
|
|
1321
1553
|
}, {
|
|
1322
1554
|
e: undefined,
|
|
1323
1555
|
t: undefined
|
|
1324
1556
|
});
|
|
1325
|
-
return _el$
|
|
1557
|
+
return _el$7;
|
|
1326
1558
|
})();
|
|
1327
1559
|
}
|
|
1328
1560
|
function RequestDetails(props) {
|
|
@@ -1330,21 +1562,20 @@ var tui_default = {
|
|
|
1330
1562
|
const traits = () => traitsOf(request());
|
|
1331
1563
|
const review = () => automatedReview(request());
|
|
1332
1564
|
return (() => {
|
|
1333
|
-
var _el$
|
|
1565
|
+
var _el$11 = _$createElement("box"), _el$12 = _$createElement("text"), _el$13 = _$createElement("u"), _el$14 = _$createElement("b"), _el$15 = _$createTextNode(` `), _el$16 = _$createElement("box"), _el$17 = _$createElement("box"), _el$18 = _$createElement("text"), _el$19 = _$createElement("b");
|
|
1566
|
+
_$insertNode(_el$11, _el$12);
|
|
1567
|
+
_$insertNode(_el$11, _el$16);
|
|
1568
|
+
_$insertNode(_el$11, _el$17);
|
|
1569
|
+
_$setProp(_el$11, "gap", 1);
|
|
1570
|
+
_$setProp(_el$11, "flexShrink", 0);
|
|
1571
|
+
_$insertNode(_el$12, _el$13);
|
|
1572
|
+
_$setProp(_el$12, "onMouseUp", () => openUrl(request().url));
|
|
1334
1573
|
_$insertNode(_el$13, _el$14);
|
|
1335
|
-
_$insertNode(_el$13, _el$19);
|
|
1336
|
-
_$insertNode(_el$13, _el$20);
|
|
1337
|
-
_$setProp(_el$13, "gap", 1);
|
|
1338
|
-
_$setProp(_el$13, "flexShrink", 0);
|
|
1339
1574
|
_$insertNode(_el$14, _el$15);
|
|
1340
|
-
_$
|
|
1341
|
-
_$
|
|
1342
|
-
_$
|
|
1343
|
-
_$
|
|
1344
|
-
_$insert(_el$17, () => reference(request()), _el$18);
|
|
1345
|
-
_$insert(_el$17, () => request().title, null);
|
|
1346
|
-
_$setProp(_el$19, "flexShrink", 0);
|
|
1347
|
-
_$insert(_el$19, _$createComponent(DetailField, {
|
|
1575
|
+
_$insert(_el$14, () => reference(request()), _el$15);
|
|
1576
|
+
_$insert(_el$14, () => request().title, null);
|
|
1577
|
+
_$setProp(_el$16, "flexShrink", 0);
|
|
1578
|
+
_$insert(_el$16, _$createComponent(DetailField, {
|
|
1348
1579
|
label: "State",
|
|
1349
1580
|
get value() {
|
|
1350
1581
|
return request().state;
|
|
@@ -1353,13 +1584,13 @@ var tui_default = {
|
|
|
1353
1584
|
return request().state === "merged" ? "success" : undefined;
|
|
1354
1585
|
}
|
|
1355
1586
|
}), null);
|
|
1356
|
-
_$insert(_el$
|
|
1587
|
+
_$insert(_el$16, _$createComponent(DetailField, {
|
|
1357
1588
|
label: "Target",
|
|
1358
1589
|
get value() {
|
|
1359
1590
|
return `${request().targetProject} \u2192 ${request().targetBranch}`;
|
|
1360
1591
|
}
|
|
1361
1592
|
}), null);
|
|
1362
|
-
_$insert(_el$
|
|
1593
|
+
_$insert(_el$16, _$createComponent(DetailField, {
|
|
1363
1594
|
get label() {
|
|
1364
1595
|
return traits().ci.charAt(0).toUpperCase() + traits().ci.slice(1);
|
|
1365
1596
|
},
|
|
@@ -1373,7 +1604,7 @@ var tui_default = {
|
|
|
1373
1604
|
return request().pipeline?.url;
|
|
1374
1605
|
}
|
|
1375
1606
|
}), null);
|
|
1376
|
-
_$insert(_el$
|
|
1607
|
+
_$insert(_el$16, _$createComponent(DetailField, {
|
|
1377
1608
|
label: "Unresolved threads",
|
|
1378
1609
|
get value() {
|
|
1379
1610
|
return `${request().unresolvedThreads}${request().threadsComplete ? "" : "+"}`;
|
|
@@ -1382,7 +1613,7 @@ var tui_default = {
|
|
|
1382
1613
|
return request().unresolvedThreads || !request().threadsComplete ? "warning" : undefined;
|
|
1383
1614
|
}
|
|
1384
1615
|
}), null);
|
|
1385
|
-
_$insert(_el$
|
|
1616
|
+
_$insert(_el$16, _$createComponent(DetailField, {
|
|
1386
1617
|
label: "Draft",
|
|
1387
1618
|
get value() {
|
|
1388
1619
|
return yesNo(request().draft);
|
|
@@ -1391,7 +1622,7 @@ var tui_default = {
|
|
|
1391
1622
|
return request().draft ? "warning" : undefined;
|
|
1392
1623
|
}
|
|
1393
1624
|
}), null);
|
|
1394
|
-
_$insert(_el$
|
|
1625
|
+
_$insert(_el$16, _$createComponent(DetailField, {
|
|
1395
1626
|
label: "Conflicts",
|
|
1396
1627
|
get value() {
|
|
1397
1628
|
return _$memo(() => !!request().conflictsKnown)() ? yesNo(request().conflicts) : "unknown";
|
|
@@ -1400,21 +1631,21 @@ var tui_default = {
|
|
|
1400
1631
|
return request().conflicts ? "error" : undefined;
|
|
1401
1632
|
}
|
|
1402
1633
|
}), null);
|
|
1403
|
-
_$insertNode(_el$
|
|
1404
|
-
_$setProp(_el$
|
|
1405
|
-
_$insertNode(_el$
|
|
1406
|
-
_$insertNode(_el$
|
|
1407
|
-
_$insert(_el$
|
|
1634
|
+
_$insertNode(_el$17, _el$18);
|
|
1635
|
+
_$setProp(_el$17, "flexShrink", 0);
|
|
1636
|
+
_$insertNode(_el$18, _el$19);
|
|
1637
|
+
_$insertNode(_el$19, _$createTextNode(`Review and approval`));
|
|
1638
|
+
_$insert(_el$17, _$createComponent(For, {
|
|
1408
1639
|
get each() {
|
|
1409
1640
|
return traits().details(request());
|
|
1410
1641
|
},
|
|
1411
1642
|
children: (line) => {
|
|
1412
1643
|
const separator = line.indexOf(": ");
|
|
1413
1644
|
return separator < 0 ? (() => {
|
|
1414
|
-
var _el$
|
|
1415
|
-
_$insert(_el$
|
|
1416
|
-
_$effect((_$p) => _$setProp(_el$
|
|
1417
|
-
return _el$
|
|
1645
|
+
var _el$26 = _$createElement("text");
|
|
1646
|
+
_$insert(_el$26, line);
|
|
1647
|
+
_$effect((_$p) => _$setProp(_el$26, "fg", context.theme.text.base, _$p));
|
|
1648
|
+
return _el$26;
|
|
1418
1649
|
})() : _$createComponent(DetailField, {
|
|
1419
1650
|
get label() {
|
|
1420
1651
|
return line.slice(0, separator);
|
|
@@ -1425,7 +1656,7 @@ var tui_default = {
|
|
|
1425
1656
|
});
|
|
1426
1657
|
}
|
|
1427
1658
|
}), null);
|
|
1428
|
-
_$insert(_el$
|
|
1659
|
+
_$insert(_el$17, _$createComponent(Show, {
|
|
1429
1660
|
get when() {
|
|
1430
1661
|
return review();
|
|
1431
1662
|
},
|
|
@@ -1441,7 +1672,7 @@ var tui_default = {
|
|
|
1441
1672
|
}
|
|
1442
1673
|
})
|
|
1443
1674
|
}), null);
|
|
1444
|
-
_$insert(_el$
|
|
1675
|
+
_$insert(_el$17, _$createComponent(Show, {
|
|
1445
1676
|
get when() {
|
|
1446
1677
|
return request().awaitingReviewers.length;
|
|
1447
1678
|
},
|
|
@@ -1454,42 +1685,40 @@ var tui_default = {
|
|
|
1454
1685
|
});
|
|
1455
1686
|
}
|
|
1456
1687
|
}), null);
|
|
1457
|
-
_$insert(_el$
|
|
1688
|
+
_$insert(_el$11, _$createComponent(Show, {
|
|
1458
1689
|
get when() {
|
|
1459
1690
|
return !request().reviewersComplete;
|
|
1460
1691
|
},
|
|
1461
1692
|
get children() {
|
|
1462
|
-
var _el$
|
|
1463
|
-
_$insertNode(_el$
|
|
1464
|
-
_$effect((_$p) => _$setProp(_el$
|
|
1465
|
-
return _el$
|
|
1693
|
+
var _el$21 = _$createElement("text");
|
|
1694
|
+
_$insertNode(_el$21, _$createTextNode(`Reviewer list is partial`));
|
|
1695
|
+
_$effect((_$p) => _$setProp(_el$21, "fg", color("warning"), _$p));
|
|
1696
|
+
return _el$21;
|
|
1466
1697
|
}
|
|
1467
1698
|
}), null);
|
|
1468
|
-
_$insert(_el$
|
|
1699
|
+
_$insert(_el$11, _$createComponent(Show, {
|
|
1469
1700
|
get when() {
|
|
1470
1701
|
return _$memo(() => !!(props.head && request().headSha))() && props.head !== request().headSha;
|
|
1471
1702
|
},
|
|
1472
1703
|
get children() {
|
|
1473
|
-
var _el$
|
|
1474
|
-
_$insertNode(_el$
|
|
1475
|
-
_$insertNode(_el$
|
|
1476
|
-
_$insert(_el$
|
|
1477
|
-
_$effect((_$p) => _$setProp(_el$
|
|
1478
|
-
return _el$
|
|
1704
|
+
var _el$23 = _$createElement("text"), _el$24 = _$createTextNode(`Local HEAD differs from the `), _el$25 = _$createTextNode(` head commit (unpushed or not fetched)`);
|
|
1705
|
+
_$insertNode(_el$23, _el$24);
|
|
1706
|
+
_$insertNode(_el$23, _el$25);
|
|
1707
|
+
_$insert(_el$23, () => traits().noun, _el$25);
|
|
1708
|
+
_$effect((_$p) => _$setProp(_el$23, "fg", color("warning"), _$p));
|
|
1709
|
+
return _el$23;
|
|
1479
1710
|
}
|
|
1480
1711
|
}), null);
|
|
1481
1712
|
_$effect((_p$) => {
|
|
1482
|
-
var _v$
|
|
1483
|
-
_v$
|
|
1484
|
-
_v$
|
|
1485
|
-
_v$7 !== _p$.a && (_p$.a = _$setProp(_el$21, "fg", _v$7, _p$.a));
|
|
1713
|
+
var _v$3 = context.theme.text.base, _v$4 = context.theme.text.base;
|
|
1714
|
+
_v$3 !== _p$.e && (_p$.e = _$setProp(_el$12, "fg", _v$3, _p$.e));
|
|
1715
|
+
_v$4 !== _p$.t && (_p$.t = _$setProp(_el$18, "fg", _v$4, _p$.t));
|
|
1486
1716
|
return _p$;
|
|
1487
1717
|
}, {
|
|
1488
1718
|
e: undefined,
|
|
1489
|
-
t: undefined
|
|
1490
|
-
a: undefined
|
|
1719
|
+
t: undefined
|
|
1491
1720
|
});
|
|
1492
|
-
return _el$
|
|
1721
|
+
return _el$11;
|
|
1493
1722
|
})();
|
|
1494
1723
|
}
|
|
1495
1724
|
function StatusDetails(props) {
|
|
@@ -1498,19 +1727,19 @@ var tui_default = {
|
|
|
1498
1727
|
return value?.kind === "found" ? value : undefined;
|
|
1499
1728
|
};
|
|
1500
1729
|
return (() => {
|
|
1501
|
-
var _el$
|
|
1502
|
-
_$setProp(_el$
|
|
1503
|
-
_$setProp(_el$
|
|
1504
|
-
_$insert(_el$
|
|
1730
|
+
var _el$27 = _$createElement("box");
|
|
1731
|
+
_$setProp(_el$27, "gap", 1);
|
|
1732
|
+
_$setProp(_el$27, "flexShrink", 0);
|
|
1733
|
+
_$insert(_el$27, _$createComponent(Show, {
|
|
1505
1734
|
get when() {
|
|
1506
1735
|
return lookup();
|
|
1507
1736
|
},
|
|
1508
1737
|
get fallback() {
|
|
1509
1738
|
return (() => {
|
|
1510
|
-
var _el$
|
|
1511
|
-
_$insert(_el$
|
|
1512
|
-
_$effect((_$p) => _$setProp(_el$
|
|
1513
|
-
return _el$
|
|
1739
|
+
var _el$28 = _$createElement("text");
|
|
1740
|
+
_$insert(_el$28, () => detailsMessage(props.snapshot));
|
|
1741
|
+
_$effect((_$p) => _$setProp(_el$28, "fg", props.snapshot.error ? color("error") : context.theme.text.muted, _$p));
|
|
1742
|
+
return _el$28;
|
|
1514
1743
|
})();
|
|
1515
1744
|
},
|
|
1516
1745
|
children: (found) => [_$createComponent(Show, {
|
|
@@ -1518,21 +1747,21 @@ var tui_default = {
|
|
|
1518
1747
|
return found().repository;
|
|
1519
1748
|
},
|
|
1520
1749
|
children: (repository) => (() => {
|
|
1521
|
-
var _el$
|
|
1522
|
-
_$setProp(_el$
|
|
1523
|
-
_$insert(_el$
|
|
1750
|
+
var _el$33 = _$createElement("box");
|
|
1751
|
+
_$setProp(_el$33, "flexShrink", 0);
|
|
1752
|
+
_$insert(_el$33, _$createComponent(DetailField, {
|
|
1524
1753
|
label: "Repository",
|
|
1525
1754
|
get value() {
|
|
1526
1755
|
return repository().source.path;
|
|
1527
1756
|
}
|
|
1528
1757
|
}), null);
|
|
1529
|
-
_$insert(_el$
|
|
1758
|
+
_$insert(_el$33, _$createComponent(DetailField, {
|
|
1530
1759
|
label: "Branch",
|
|
1531
1760
|
get value() {
|
|
1532
1761
|
return _$memo(() => repository().branch === repository().sourceBranch)() ? repository().branch : `${repository().branch} (pushes to ${repository().sourceBranch})`;
|
|
1533
1762
|
}
|
|
1534
1763
|
}), null);
|
|
1535
|
-
return _el$
|
|
1764
|
+
return _el$33;
|
|
1536
1765
|
})()
|
|
1537
1766
|
}), _$createComponent(Show, {
|
|
1538
1767
|
get when() {
|
|
@@ -1551,27 +1780,27 @@ var tui_default = {
|
|
|
1551
1780
|
return found().failed ?? [];
|
|
1552
1781
|
},
|
|
1553
1782
|
children: (failure) => (() => {
|
|
1554
|
-
var _el$
|
|
1555
|
-
`), _el$
|
|
1783
|
+
var _el$34 = _$createElement("text"), _el$35 = _$createElement("b"), _el$37 = _$createTextNode(`
|
|
1784
|
+
`), _el$38 = _$createTextNode(`
|
|
1556
1785
|
`);
|
|
1557
|
-
_$insertNode(_el$
|
|
1558
|
-
_$insertNode(_el$
|
|
1559
|
-
_$insertNode(_el$
|
|
1560
|
-
_$insertNode(_el$
|
|
1561
|
-
_$insert(_el$
|
|
1562
|
-
_$insert(_el$
|
|
1563
|
-
_$effect((_$p) => _$setProp(_el$
|
|
1564
|
-
return _el$
|
|
1786
|
+
_$insertNode(_el$34, _el$35);
|
|
1787
|
+
_$insertNode(_el$34, _el$37);
|
|
1788
|
+
_$insertNode(_el$34, _el$38);
|
|
1789
|
+
_$insertNode(_el$35, _$createTextNode(`Unavailable`));
|
|
1790
|
+
_$insert(_el$34, () => failure.url, _el$38);
|
|
1791
|
+
_$insert(_el$34, () => failure.reason, null);
|
|
1792
|
+
_$effect((_$p) => _$setProp(_el$34, "fg", color("warning"), _$p));
|
|
1793
|
+
return _el$34;
|
|
1565
1794
|
})()
|
|
1566
1795
|
}), _$createComponent(Show, {
|
|
1567
1796
|
get when() {
|
|
1568
1797
|
return found().requests.length === 0;
|
|
1569
1798
|
},
|
|
1570
1799
|
get children() {
|
|
1571
|
-
var _el$
|
|
1572
|
-
_$insertNode(_el$
|
|
1573
|
-
_$effect((_$p) => _$setProp(_el$
|
|
1574
|
-
return _el$
|
|
1800
|
+
var _el$29 = _$createElement("text");
|
|
1801
|
+
_$insertNode(_el$29, _$createTextNode(`No PR/MR status available.`));
|
|
1802
|
+
_$effect((_$p) => _$setProp(_el$29, "fg", context.theme.text.muted, _$p));
|
|
1803
|
+
return _el$29;
|
|
1575
1804
|
}
|
|
1576
1805
|
}), _$createComponent(For, {
|
|
1577
1806
|
get each() {
|
|
@@ -1588,30 +1817,30 @@ var tui_default = {
|
|
|
1588
1817
|
return props.snapshot.error;
|
|
1589
1818
|
},
|
|
1590
1819
|
children: (error) => (() => {
|
|
1591
|
-
var _el$
|
|
1820
|
+
var _el$39 = _$createElement("text"), _el$40 = _$createElement("b"), _el$41 = _$createTextNode(`Last refresh failed at `), _el$42 = _$createTextNode(`
|
|
1592
1821
|
`);
|
|
1593
|
-
_$insertNode(_el$
|
|
1594
|
-
_$insertNode(_el$
|
|
1595
|
-
_$insertNode(_el$
|
|
1596
|
-
_$insert(_el$
|
|
1597
|
-
_$insert(_el$
|
|
1598
|
-
_$effect((_$p) => _$setProp(_el$
|
|
1599
|
-
return _el$
|
|
1822
|
+
_$insertNode(_el$39, _el$40);
|
|
1823
|
+
_$insertNode(_el$39, _el$42);
|
|
1824
|
+
_$insertNode(_el$40, _el$41);
|
|
1825
|
+
_$insert(_el$40, () => new Date(error().at).toLocaleTimeString(), null);
|
|
1826
|
+
_$insert(_el$39, () => error().message, null);
|
|
1827
|
+
_$effect((_$p) => _$setProp(_el$39, "fg", color("error"), _$p));
|
|
1828
|
+
return _el$39;
|
|
1600
1829
|
})()
|
|
1601
1830
|
}), _$createComponent(Show, {
|
|
1602
1831
|
get when() {
|
|
1603
1832
|
return props.snapshot.fetchedAt !== undefined;
|
|
1604
1833
|
},
|
|
1605
1834
|
get children() {
|
|
1606
|
-
var _el$
|
|
1607
|
-
_$insertNode(_el$
|
|
1608
|
-
_$insert(_el$
|
|
1609
|
-
_$effect((_$p) => _$setProp(_el$
|
|
1610
|
-
return _el$
|
|
1835
|
+
var _el$31 = _$createElement("text"), _el$32 = _$createTextNode(`Last fetched: `);
|
|
1836
|
+
_$insertNode(_el$31, _el$32);
|
|
1837
|
+
_$insert(_el$31, () => new Date(props.snapshot.fetchedAt).toLocaleTimeString(), null);
|
|
1838
|
+
_$effect((_$p) => _$setProp(_el$31, "fg", context.theme.text.muted, _$p));
|
|
1839
|
+
return _el$31;
|
|
1611
1840
|
}
|
|
1612
1841
|
})]
|
|
1613
1842
|
}));
|
|
1614
|
-
return _el$
|
|
1843
|
+
return _el$27;
|
|
1615
1844
|
})();
|
|
1616
1845
|
}
|
|
1617
1846
|
function StatusDialog(props) {
|
|
@@ -1663,55 +1892,55 @@ var tui_default = {
|
|
|
1663
1892
|
}]
|
|
1664
1893
|
}));
|
|
1665
1894
|
return (() => {
|
|
1666
|
-
var _el$
|
|
1667
|
-
_$insertNode(_el$
|
|
1668
|
-
_$insertNode(_el$
|
|
1669
|
-
_$insertNode(_el$
|
|
1670
|
-
_$setProp(_el$
|
|
1671
|
-
_$setProp(_el$
|
|
1672
|
-
_$setProp(_el$
|
|
1673
|
-
_$setProp(_el$
|
|
1674
|
-
_$insertNode(_el$
|
|
1675
|
-
_$insertNode(_el$
|
|
1676
|
-
_$setProp(_el$
|
|
1677
|
-
_$setProp(_el$
|
|
1678
|
-
_$setProp(_el$
|
|
1679
|
-
_$setProp(_el$
|
|
1680
|
-
_$insertNode(_el$
|
|
1681
|
-
_$insertNode(_el$
|
|
1682
|
-
_$insertNode(_el$
|
|
1683
|
-
_$setProp(_el$
|
|
1684
|
-
_$setProp(_el$
|
|
1685
|
-
_$setProp(_el$
|
|
1686
|
-
_$setProp(_el$
|
|
1687
|
-
_$setProp(_el$
|
|
1895
|
+
var _el$43 = _$createElement("box"), _el$44 = _$createElement("box"), _el$45 = _$createElement("text"), _el$46 = _$createElement("b"), _el$48 = _$createElement("text"), _el$50 = _$createElement("scrollbox"), _el$51 = _$createElement("box");
|
|
1896
|
+
_$insertNode(_el$43, _el$44);
|
|
1897
|
+
_$insertNode(_el$43, _el$50);
|
|
1898
|
+
_$insertNode(_el$43, _el$51);
|
|
1899
|
+
_$setProp(_el$43, "paddingLeft", 2);
|
|
1900
|
+
_$setProp(_el$43, "paddingRight", 2);
|
|
1901
|
+
_$setProp(_el$43, "paddingBottom", 1);
|
|
1902
|
+
_$setProp(_el$43, "gap", 1);
|
|
1903
|
+
_$insertNode(_el$44, _el$45);
|
|
1904
|
+
_$insertNode(_el$44, _el$48);
|
|
1905
|
+
_$setProp(_el$44, "height", 1);
|
|
1906
|
+
_$setProp(_el$44, "flexShrink", 0);
|
|
1907
|
+
_$setProp(_el$44, "flexDirection", "row");
|
|
1908
|
+
_$setProp(_el$44, "justifyContent", "space-between");
|
|
1909
|
+
_$insertNode(_el$45, _el$46);
|
|
1910
|
+
_$insertNode(_el$46, _$createTextNode(`PR/MR status`));
|
|
1911
|
+
_$insertNode(_el$48, _$createTextNode(`esc`));
|
|
1912
|
+
_$setProp(_el$48, "onMouseUp", close);
|
|
1913
|
+
_$setProp(_el$50, "minHeight", 1);
|
|
1914
|
+
_$setProp(_el$50, "flexShrink", 0);
|
|
1915
|
+
_$setProp(_el$50, "scrollX", false);
|
|
1916
|
+
_$setProp(_el$50, "contentOptions", {
|
|
1688
1917
|
flexShrink: 0
|
|
1689
1918
|
});
|
|
1690
|
-
_$insert(_el$
|
|
1919
|
+
_$insert(_el$50, _$createComponent(StatusDetails, {
|
|
1691
1920
|
get snapshot() {
|
|
1692
1921
|
return snapshot2();
|
|
1693
1922
|
}
|
|
1694
1923
|
}));
|
|
1695
|
-
_$setProp(_el$
|
|
1696
|
-
_$setProp(_el$
|
|
1697
|
-
_$setProp(_el$
|
|
1698
|
-
_$setProp(_el$
|
|
1699
|
-
_$insert(_el$
|
|
1924
|
+
_$setProp(_el$51, "height", 1);
|
|
1925
|
+
_$setProp(_el$51, "flexShrink", 0);
|
|
1926
|
+
_$setProp(_el$51, "flexDirection", "row");
|
|
1927
|
+
_$setProp(_el$51, "justifyContent", "flex-end");
|
|
1928
|
+
_$insert(_el$51, _$createComponent(For, {
|
|
1700
1929
|
each: ["close", "refresh"],
|
|
1701
1930
|
children: (action) => {
|
|
1702
1931
|
const disabled = () => action === "refresh" && snapshot2().loading;
|
|
1703
1932
|
const active = () => activeAction() === action && !disabled();
|
|
1704
1933
|
return (() => {
|
|
1705
|
-
var _el$
|
|
1706
|
-
_$insertNode(_el$
|
|
1707
|
-
_$setProp(_el$
|
|
1708
|
-
_$setProp(_el$
|
|
1709
|
-
_$setProp(_el$
|
|
1710
|
-
_$setProp(_el$
|
|
1934
|
+
var _el$52 = _$createElement("box"), _el$53 = _$createElement("text");
|
|
1935
|
+
_$insertNode(_el$52, _el$53);
|
|
1936
|
+
_$setProp(_el$52, "paddingLeft", 1);
|
|
1937
|
+
_$setProp(_el$52, "paddingRight", 1);
|
|
1938
|
+
_$setProp(_el$52, "flexShrink", 0);
|
|
1939
|
+
_$setProp(_el$52, "onMouseMove", () => {
|
|
1711
1940
|
if (!disabled())
|
|
1712
1941
|
setActiveAction(action);
|
|
1713
1942
|
});
|
|
1714
|
-
_$setProp(_el$
|
|
1943
|
+
_$setProp(_el$52, "onMouseUp", () => {
|
|
1715
1944
|
if (disabled())
|
|
1716
1945
|
return;
|
|
1717
1946
|
setActiveAction(action);
|
|
@@ -1720,27 +1949,27 @@ var tui_default = {
|
|
|
1720
1949
|
else
|
|
1721
1950
|
close();
|
|
1722
1951
|
});
|
|
1723
|
-
_$setProp(_el$
|
|
1724
|
-
_$insert(_el$
|
|
1952
|
+
_$setProp(_el$53, "wrapMode", "none");
|
|
1953
|
+
_$insert(_el$53, () => action === "close" ? "Close" : snapshot2().loading ? "Refreshing\u2026" : "Refresh");
|
|
1725
1954
|
_$effect((_p$) => {
|
|
1726
|
-
var _v$
|
|
1727
|
-
_v$
|
|
1728
|
-
_v$
|
|
1955
|
+
var _v$9 = active() ? context.theme.background.action.primary.focused : undefined, _v$0 = disabled() ? context.theme.text.action.primary.disabled : active() ? context.theme.text.action.primary.focused : context.theme.text.muted;
|
|
1956
|
+
_v$9 !== _p$.e && (_p$.e = _$setProp(_el$52, "backgroundColor", _v$9, _p$.e));
|
|
1957
|
+
_v$0 !== _p$.t && (_p$.t = _$setProp(_el$53, "fg", _v$0, _p$.t));
|
|
1729
1958
|
return _p$;
|
|
1730
1959
|
}, {
|
|
1731
1960
|
e: undefined,
|
|
1732
1961
|
t: undefined
|
|
1733
1962
|
});
|
|
1734
|
-
return _el$
|
|
1963
|
+
return _el$52;
|
|
1735
1964
|
})();
|
|
1736
1965
|
}
|
|
1737
1966
|
}));
|
|
1738
1967
|
_$effect((_p$) => {
|
|
1739
|
-
var _v$
|
|
1740
|
-
_v$
|
|
1741
|
-
_v$
|
|
1742
|
-
_v$
|
|
1743
|
-
_v$
|
|
1968
|
+
var _v$5 = contentHeight() + 5, _v$6 = context.theme.text.base, _v$7 = context.theme.text.muted, _v$8 = contentHeight();
|
|
1969
|
+
_v$5 !== _p$.e && (_p$.e = _$setProp(_el$43, "height", _v$5, _p$.e));
|
|
1970
|
+
_v$6 !== _p$.t && (_p$.t = _$setProp(_el$45, "fg", _v$6, _p$.t));
|
|
1971
|
+
_v$7 !== _p$.a && (_p$.a = _$setProp(_el$48, "fg", _v$7, _p$.a));
|
|
1972
|
+
_v$8 !== _p$.o && (_p$.o = _$setProp(_el$50, "height", _v$8, _p$.o));
|
|
1744
1973
|
return _p$;
|
|
1745
1974
|
}, {
|
|
1746
1975
|
e: undefined,
|
|
@@ -1748,7 +1977,7 @@ var tui_default = {
|
|
|
1748
1977
|
a: undefined,
|
|
1749
1978
|
o: undefined
|
|
1750
1979
|
});
|
|
1751
|
-
return _el$
|
|
1980
|
+
return _el$43;
|
|
1752
1981
|
})();
|
|
1753
1982
|
}
|
|
1754
1983
|
function showStatus(place = currentPlace()) {
|