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
const telemetryBySkill = await captureAll221ScreenshotsInHeadlessChrome(entries)
// Step 2: Execute strict isolated git worktree lifecycle for every skill
let processedInBatch = 0
for (let i = 0; i < entries.length; i += 1) {
const entry = entries[i]!
// Step 2: Execute strict isolated git worktree lifecycle for every remaining skill
const remaining = entries.filter(entry => {
const id3 = String(entry.skillId).padStart(3, '0')
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 skill = registry.getSkillById(entry.skillId)!
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 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()
s1.setBaseSkillLevel(skill.id, 1)
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)
const ev20WithSyn = evaluateSkillCore113c({ registry, skill, slvl: 20, blvl: 20, statList: s20Syn })
const alreadyOnMain = existsSync(mainImplAbsPath) && existsSync(mainTestAbsPath)
if (!alreadyOnMain) {
const wtPath = `/usr/local/google/home/taodao/wt-skill-${id3}`
const branchName = `feat/skill-${id3}`
precomputed.set(entry.skillId, {
id3,
skill,
implRelPath,
testRelPath,
ev1,
ev10,
ev20,
synSkillId,
ev20WithSyn,
})
}
// Clean any stale worktree/branch before creating
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. Upload PNG screenshot & post verification comment on Gitea issue
// 2a. 12-way parallel Gitea screenshot upload + comment + closure for remaining skills
const CONCURRENCY = 12
let cursor = 0
let uploadedCount = 0
async function giteaWorker(): Promise<void> {
while (cursor < remaining.length) {
const idx = cursor++
const entry = remaining[idx]!
const data = precomputed.get(entry.skillId)!
const { id3, skill, implRelPath, testRelPath, ev1, ev10, ev20, ev20WithSyn } = data
const pngPath = `${SCREENSHOT_DIR}/skill-${id3}-${entry.slug}.png`
const asset = await uploadPngToGiteaIssue(entry.issueNumber, pngPath)
const snap = telemetryBySkill[entry.skillId]
@ -580,32 +589,72 @@ async function main(): Promise<void> {
![Skill #${id3} ${skill.name}](${asset.browser_download_url})
`
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)
processedInBatch += 1
}
if (processedInBatch >= 25 || i === entries.length - 1) {
if (processedInBatch > 0) {
runGit(['push', 'origin', 'main'])
processedInBatch = 0
uploadedCount += 1
if (uploadedCount % 25 === 0 || uploadedCount === remaining.length) {
console.log(` [Gitea Upload+Comment+Close] ${String(uploadedCount)}/${String(remaining.length)} completed`)
}
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)})`)
}
}