|
| 1 | +import { upsertStackComment } from "../github/comments"; |
| 2 | +import { updatePR } from "../github/pr-actions"; |
| 3 | +import { batchGetPRsForBranches } from "../github/pr-status"; |
| 4 | +import { getStack, getTrunk } from "../jj"; |
| 5 | +import { ok, type Result } from "../result"; |
| 6 | +import { |
| 7 | + generateStackComment, |
| 8 | + mapReviewDecisionToStatus, |
| 9 | + type StackEntry, |
| 10 | +} from "../stack-comment"; |
| 11 | + |
| 12 | +export async function updateStackComments(): Promise< |
| 13 | + Result<{ updated: number }> |
| 14 | +> { |
| 15 | + const trunk = await getTrunk(); |
| 16 | + const stackResult = await getStack(); |
| 17 | + if (!stackResult.ok) return stackResult; |
| 18 | + if (stackResult.value.length === 0) { |
| 19 | + return ok({ updated: 0 }); |
| 20 | + } |
| 21 | + |
| 22 | + const stack = [...stackResult.value].reverse(); |
| 23 | + |
| 24 | + const bookmarkMap = new Map< |
| 25 | + string, |
| 26 | + { change: (typeof stack)[0]; bookmark: string } |
| 27 | + >(); |
| 28 | + const allBookmarks: string[] = []; |
| 29 | + for (const change of stack) { |
| 30 | + const bookmark = change.bookmarks[0]; |
| 31 | + if (!bookmark) continue; |
| 32 | + bookmarkMap.set(change.changeId, { change, bookmark }); |
| 33 | + allBookmarks.push(bookmark); |
| 34 | + } |
| 35 | + |
| 36 | + const prsResult = await batchGetPRsForBranches(allBookmarks); |
| 37 | + const prCache = prsResult.ok ? prsResult.value : new Map(); |
| 38 | + |
| 39 | + const prInfos: Array<{ |
| 40 | + changeId: string; |
| 41 | + prNumber: number; |
| 42 | + change: (typeof stack)[0]; |
| 43 | + bookmark: string; |
| 44 | + currentBase: string; |
| 45 | + }> = []; |
| 46 | + |
| 47 | + for (const change of stack) { |
| 48 | + const entry = bookmarkMap.get(change.changeId); |
| 49 | + if (!entry) continue; |
| 50 | + const { bookmark } = entry; |
| 51 | + const prItem = prCache.get(bookmark); |
| 52 | + if (prItem) { |
| 53 | + prInfos.push({ |
| 54 | + changeId: change.changeId, |
| 55 | + prNumber: prItem.number, |
| 56 | + change, |
| 57 | + bookmark, |
| 58 | + currentBase: prItem.baseRefName, |
| 59 | + }); |
| 60 | + } |
| 61 | + } |
| 62 | + |
| 63 | + if (prInfos.length === 0) { |
| 64 | + return ok({ updated: 0 }); |
| 65 | + } |
| 66 | + |
| 67 | + const statuses = new Map< |
| 68 | + number, |
| 69 | + { |
| 70 | + reviewDecision: |
| 71 | + | "APPROVED" |
| 72 | + | "CHANGES_REQUESTED" |
| 73 | + | "REVIEW_REQUIRED" |
| 74 | + | null; |
| 75 | + state: "OPEN" | "CLOSED" | "MERGED"; |
| 76 | + } |
| 77 | + >(); |
| 78 | + for (const [, prItem] of prCache) { |
| 79 | + statuses.set(prItem.number, { |
| 80 | + reviewDecision: prItem.reviewDecision ?? null, |
| 81 | + state: prItem.state, |
| 82 | + }); |
| 83 | + } |
| 84 | + |
| 85 | + for (let i = 0; i < prInfos.length; i++) { |
| 86 | + const prInfo = prInfos[i]; |
| 87 | + const expectedBase = i === 0 ? trunk : prInfos[i - 1].bookmark; |
| 88 | + if (prInfo.currentBase !== expectedBase) { |
| 89 | + await updatePR(prInfo.prNumber, { base: expectedBase }); |
| 90 | + } |
| 91 | + } |
| 92 | + |
| 93 | + const commentUpserts = prInfos.map((prInfo, i) => { |
| 94 | + const stackEntries: StackEntry[] = prInfos.map((p, idx) => { |
| 95 | + const prStatus = statuses.get(p.prNumber); |
| 96 | + let entryStatus: StackEntry["status"] = "waiting"; |
| 97 | + |
| 98 | + if (idx === i) { |
| 99 | + entryStatus = "this"; |
| 100 | + } else if (prStatus) { |
| 101 | + entryStatus = mapReviewDecisionToStatus( |
| 102 | + prStatus.reviewDecision, |
| 103 | + prStatus.state, |
| 104 | + ); |
| 105 | + } |
| 106 | + |
| 107 | + return { |
| 108 | + prNumber: p.prNumber, |
| 109 | + title: p.change.description || `Change ${p.changeId.slice(0, 8)}`, |
| 110 | + status: entryStatus, |
| 111 | + }; |
| 112 | + }); |
| 113 | + |
| 114 | + const comment = generateStackComment({ stack: stackEntries }); |
| 115 | + return upsertStackComment(prInfo.prNumber, comment); |
| 116 | + }); |
| 117 | + |
| 118 | + await Promise.all(commentUpserts); |
| 119 | + |
| 120 | + return ok({ updated: prInfos.length }); |
| 121 | +} |
0 commit comments