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,
ev1,
ev10,
ev20,
synSkillId,
ev20WithSyn,
})
}
// Clean any stale worktree/branch before creating // 2a. 12-way parallel Gitea screenshot upload + comment + closure for remaining skills
try { const CONCURRENCY = 12
if (existsSync(wtPath)) { let cursor = 0
runGit(['worktree', 'remove', '--force', wtPath]) let uploadedCount = 0
} async function giteaWorker(): Promise<void> {
} catch {} while (cursor < remaining.length) {
try { const idx = cursor++
runGit(['branch', '-D', branchName]) const entry = remaining[idx]!
} catch {} const data = precomputed.get(entry.skillId)!
const { id3, skill, implRelPath, testRelPath, ev1, ev10, ev20, ev20WithSyn } = data
// 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. 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,32 +589,72 @@ 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)
// 5. Merge feat/skill-<id3> into main (--no-ff, fixes #<issueNumber>)
runGit([
'merge',
'--no-ff',
branchName,
'-m',
`feat(skills): implement 1.13c ${skill.name} [Skill #${id3}] (fixes #${String(entry.issueNumber)})`,
])
// 6. Immediately remove worktree and branch
runGit(['worktree', 'remove', wtPath])
runGit(['branch', '-d', branchName])
// Ensure issue is closed on Gitea
await closeGiteaIssue(entry.issueNumber) await closeGiteaIssue(entry.issueNumber)
processedInBatch += 1 uploadedCount += 1
} if (uploadedCount % 25 === 0 || uploadedCount === remaining.length) {
console.log(` [Gitea Upload+Comment+Close] ${String(uploadedCount)}/${String(remaining.length)} completed`)
if (processedInBatch >= 25 || i === entries.length - 1) {
if (processedInBatch > 0) {
runGit(['push', 'origin', 'main'])
processedInBatch = 0
} }
updateProgressFile(i + 1, entries.length, `[Skill #${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)})`) }
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([
'merge',
'--no-ff',
branchName,
'-m',
`feat(skills): implement 1.13c ${skill.name} [Skill #${id3}] (fixes #${String(entry.issueNumber)})`,
])
// 5. Immediately remove worktree and branch
runGit(['worktree', 'remove', wtPath])
runGit(['branch', '-d', branchName])
completedTotal += 1
batchSincePush += 1
if (batchSincePush >= 25 || i === remaining.length - 1) {
runGit(['push', 'origin', 'main'])
batchSincePush = 0
updateProgressFile(completedTotal, 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)})`)
} }
} }