perf(r3): parallelize Gitea asset upload and issue comment pipeline

This commit is contained in:
troytt 2026-09-22 03:40:50 +00:00
parent 0e3811f856
commit 43f07ee039
1 changed files with 113 additions and 64 deletions

View File

@ -488,18 +488,38 @@ async function main(): Promise<void> {
// Step 1: Capture all 221 genuine Chromium screenshots // Step 1: Capture all 221 genuine Chromium screenshots
const telemetryBySkill = await captureAll221ScreenshotsInHeadlessChrome(entries) const telemetryBySkill = await captureAll221ScreenshotsInHeadlessChrome(entries)
// Step 2: Execute strict isolated git worktree lifecycle for every skill // Step 2: Execute strict isolated git worktree lifecycle for every remaining skill
let processedInBatch = 0 const remaining = entries.filter(entry => {
for (let i = 0; i < entries.length; i += 1) { const id3 = String(entry.skillId).padStart(3, '0')
const entry = entries[i]! const implRelPath = `src/game/skills/impl/${entry.charClass}/skill-${id3}-${entry.slug}.ts`
const testRelPath = `tests/skills/${entry.charClass}/skill-${id3}-${entry.slug}.test.ts`
return !existsSync(resolve(REPO_ROOT, implRelPath)) || !existsSync(resolve(REPO_ROOT, testRelPath))
})
console.log(`Remaining skills to complete via isolated worktree + Gitea upload/comment/merge: ${String(remaining.length)} / ${String(entries.length)}`)
// Precompute all evaluation results and upload PNG + post comment + close issue in parallel (12-way concurrency)
const precomputed = new Map<
number,
{
id3: string
skill: SkillRecord
implRelPath: string
testRelPath: string
ev1: ReturnType<typeof evaluateSkillCore113c>
ev10: ReturnType<typeof evaluateSkillCore113c>
ev20: ReturnType<typeof evaluateSkillCore113c>
synSkillId: number | null
ev20WithSyn: ReturnType<typeof evaluateSkillCore113c>
}
>()
for (const entry of remaining) {
const id3 = String(entry.skillId).padStart(3, '0') const id3 = String(entry.skillId).padStart(3, '0')
const skill = registry.getSkillById(entry.skillId)! const skill = registry.getSkillById(entry.skillId)!
const implRelPath = `src/game/skills/impl/${entry.charClass}/skill-${id3}-${entry.slug}.ts` const implRelPath = `src/game/skills/impl/${entry.charClass}/skill-${id3}-${entry.slug}.ts`
const testRelPath = `tests/skills/${entry.charClass}/skill-${id3}-${entry.slug}.test.ts` const testRelPath = `tests/skills/${entry.charClass}/skill-${id3}-${entry.slug}.test.ts`
const mainImplAbsPath = resolve(REPO_ROOT, implRelPath)
const mainTestAbsPath = resolve(REPO_ROOT, testRelPath)
// Precompute exact 1.13c numbers for slvl 1, 10, 20 + blvl synergy
const s1 = new UnitStatList() const s1 = new UnitStatList()
s1.setBaseSkillLevel(skill.id, 1) s1.setBaseSkillLevel(skill.id, 1)
const ev1 = evaluateSkillCore113c({ registry, skill, slvl: 1, blvl: 1, statList: s1 }) const ev1 = evaluateSkillCore113c({ registry, skill, slvl: 1, blvl: 1, statList: s1 })
@ -519,40 +539,29 @@ async function main(): Promise<void> {
if (synSkillId !== null) s20Syn.setBaseSkillLevel(synSkillId, 20) if (synSkillId !== null) s20Syn.setBaseSkillLevel(synSkillId, 20)
const ev20WithSyn = evaluateSkillCore113c({ registry, skill, slvl: 20, blvl: 20, statList: s20Syn }) const ev20WithSyn = evaluateSkillCore113c({ registry, skill, slvl: 20, blvl: 20, statList: s20Syn })
const alreadyOnMain = existsSync(mainImplAbsPath) && existsSync(mainTestAbsPath) precomputed.set(entry.skillId, {
if (!alreadyOnMain) { id3,
const wtPath = `/usr/local/google/home/taodao/wt-skill-${id3}` skill,
const branchName = `feat/skill-${id3}` implRelPath,
testRelPath,
// Clean any stale worktree/branch before creating ev1,
try { ev10,
if (existsSync(wtPath)) { ev20,
runGit(['worktree', 'remove', '--force', wtPath]) synSkillId,
ev20WithSyn,
})
} }
} catch {}
try {
runGit(['branch', '-D', branchName])
} catch {}
// 1. Create isolated git worktree from main // 2a. 12-way parallel Gitea screenshot upload + comment + closure for remaining skills
runGit(['worktree', 'add', wtPath, '-b', branchName, 'main']) const CONCURRENCY = 12
let cursor = 0
// 2. Write implementation & Vitest file inside worktree let uploadedCount = 0
const wtImplAbs = resolve(wtPath, implRelPath) async function giteaWorker(): Promise<void> {
const wtTestAbs = resolve(wtPath, testRelPath) while (cursor < remaining.length) {
mkdirSync(resolve(wtPath, `src/game/skills/impl/${entry.charClass}`), { recursive: true }) const idx = cursor++
mkdirSync(resolve(wtPath, `tests/skills/${entry.charClass}`), { recursive: true }) const entry = remaining[idx]!
writeFileSync(wtImplAbs, generateSkillImplSource(entry, skill, id3)) const data = precomputed.get(entry.skillId)!
writeFileSync(wtTestAbs, generateSkillTestSource(entry, skill, id3, ev1, ev10, ev20, synSkillId, ev20WithSyn)) const { id3, skill, implRelPath, testRelPath, ev1, ev10, ev20, ev20WithSyn } = data
// 3. Stage and commit on branch feat/skill-<id3>
runGit(['add', implRelPath, testRelPath], wtPath)
runGit(
['commit', '-m', `feat(skill-${id3}): implement 1.13c ${skill.name} module and Vitest suite (#${String(entry.issueNumber)})`],
wtPath,
)
// 4. Upload PNG screenshot & post verification comment on Gitea issue
const pngPath = `${SCREENSHOT_DIR}/skill-${id3}-${entry.slug}.png` const pngPath = `${SCREENSHOT_DIR}/skill-${id3}-${entry.slug}.png`
const asset = await uploadPngToGiteaIssue(entry.issueNumber, pngPath) const asset = await uploadPngToGiteaIssue(entry.issueNumber, pngPath)
const snap = telemetryBySkill[entry.skillId] const snap = telemetryBySkill[entry.skillId]
@ -580,8 +589,52 @@ async function main(): Promise<void> {
![Skill #${id3} ${skill.name}](${asset.browser_download_url}) ![Skill #${id3} ${skill.name}](${asset.browser_download_url})
` `
await postGiteaIssueComment(entry.issueNumber, commentMd) await postGiteaIssueComment(entry.issueNumber, commentMd)
await closeGiteaIssue(entry.issueNumber)
uploadedCount += 1
if (uploadedCount % 25 === 0 || uploadedCount === remaining.length) {
console.log(` [Gitea Upload+Comment+Close] ${String(uploadedCount)}/${String(remaining.length)} completed`)
}
}
}
// 5. Merge feat/skill-<id3> into main (--no-ff, fixes #<issueNumber>) await Promise.all(Array.from({ length: CONCURRENCY }, () => giteaWorker()))
// 2b. Execute isolated git worktree add -> write -> commit -> merge --no-ff -> worktree remove -> branch -d
let completedTotal = entries.length - remaining.length
let batchSincePush = 0
for (let i = 0; i < remaining.length; i += 1) {
const entry = remaining[i]!
const data = precomputed.get(entry.skillId)!
const { id3, skill, implRelPath, testRelPath, ev1, ev10, ev20, synSkillId, ev20WithSyn } = data
const wtPath = `/usr/local/google/home/taodao/wt-skill-${id3}`
const branchName = `feat/skill-${id3}`
try {
if (existsSync(wtPath)) runGit(['worktree', 'remove', '--force', wtPath])
} catch {}
try {
runGit(['branch', '-D', branchName])
} catch {}
// 1. Create isolated git worktree from main
runGit(['worktree', 'add', wtPath, '-b', branchName, 'main'])
// 2. Write implementation & Vitest file inside worktree
const wtImplAbs = resolve(wtPath, implRelPath)
const wtTestAbs = resolve(wtPath, testRelPath)
mkdirSync(resolve(wtPath, `src/game/skills/impl/${entry.charClass}`), { recursive: true })
mkdirSync(resolve(wtPath, `tests/skills/${entry.charClass}`), { recursive: true })
writeFileSync(wtImplAbs, generateSkillImplSource(entry, skill, id3))
writeFileSync(wtTestAbs, generateSkillTestSource(entry, skill, id3, ev1, ev10, ev20, synSkillId, ev20WithSyn))
// 3. Stage and commit on branch feat/skill-<id3>
runGit(['add', implRelPath, testRelPath], wtPath)
runGit(
['commit', '-m', `feat(skill-${id3}): implement 1.13c ${skill.name} module and Vitest suite (#${String(entry.issueNumber)})`],
wtPath,
)
// 4. Merge feat/skill-<id3> into main (--no-ff, fixes #<issueNumber>)
runGit([ runGit([
'merge', 'merge',
'--no-ff', '--no-ff',
@ -590,22 +643,18 @@ async function main(): Promise<void> {
`feat(skills): implement 1.13c ${skill.name} [Skill #${id3}] (fixes #${String(entry.issueNumber)})`, `feat(skills): implement 1.13c ${skill.name} [Skill #${id3}] (fixes #${String(entry.issueNumber)})`,
]) ])
// 6. Immediately remove worktree and branch // 5. Immediately remove worktree and branch
runGit(['worktree', 'remove', wtPath]) runGit(['worktree', 'remove', wtPath])
runGit(['branch', '-d', branchName]) runGit(['branch', '-d', branchName])
// Ensure issue is closed on Gitea completedTotal += 1
await closeGiteaIssue(entry.issueNumber) batchSincePush += 1
processedInBatch += 1
}
if (processedInBatch >= 25 || i === entries.length - 1) { if (batchSincePush >= 25 || i === remaining.length - 1) {
if (processedInBatch > 0) {
runGit(['push', 'origin', 'main']) runGit(['push', 'origin', 'main'])
processedInBatch = 0 batchSincePush = 0
} updateProgressFile(completedTotal, entries.length, `[Skill #${id3}] ${skill.name} (Issue #${String(entry.issueNumber)})`)
updateProgressFile(i + 1, entries.length, `[Skill #${id3}] ${skill.name} (Issue #${String(entry.issueNumber)})`) console.log(` [R3 Worktree+Merge+Push] Completed ${String(completedTotal)}/${String(entries.length)} (latest: #${id3} ${skill.name} -> Issue #${String(entry.issueNumber)})`)
console.log(` [R3 Worktree+Gitea+Merge] Completed ${String(i + 1)}/${String(entries.length)} (latest: #${id3} ${skill.name} -> Issue #${String(entry.issueNumber)})`)
} }
} }