perf(r3): parallelize Gitea asset upload and issue comment pipeline
This commit is contained in:
parent
0e3811f856
commit
43f07ee039
|
|
@ -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> {
|
|||

|
||||
`
|
||||
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)})`)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue