mirror of
https://github.com/stablyai/orca.git
synced 2026-09-25 08:02:31 +00:00
Fix flaky CI tests by adding retry logic and increasing timeouts (#15635)
* Fix flaky CI tests by adding retry logic and increasing timeouts Add Electron launch retry for CI runners where startup wedges before reaching 'ready', with fresh profile per attempt to avoid mid-init state. Increase skill install lock timeout from 100ms to 5s to account for fsync cost plus retry duration on loaded CI runners. * shorten comments
This commit is contained in:
@@ -16,6 +16,17 @@ afterAll(() => {
|
||||
}
|
||||
})
|
||||
|
||||
// Retry once when Electron startup times out before `ready`; keep later failures fatal.
|
||||
const FIXTURE_LAUNCH_ATTEMPTS = 2
|
||||
|
||||
function neverReachedElectronReady(fixtureResult: string): boolean {
|
||||
try {
|
||||
return (JSON.parse(fixtureResult) as { step?: string }).step === 'timed out after starting'
|
||||
} catch {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
type FixtureResult = {
|
||||
before: Record<string, unknown>
|
||||
after: Record<string, unknown>
|
||||
@@ -182,21 +193,27 @@ async function runFixture(): Promise<FixtureResult> {
|
||||
})
|
||||
writeFileSync(fixturePath, buildFixtureMain(importPath, resultPath, sourceCookiesPath))
|
||||
const { ELECTRON_RUN_AS_NODE: _electronRunAsNode, ...env } = process.env
|
||||
const electronArgs = [fixturePath, `--user-data-dir=${join(root, 'profile')}`]
|
||||
const executable = process.platform === 'linux' ? 'xvfb-run' : electronBinary
|
||||
const args =
|
||||
process.platform === 'linux'
|
||||
? ['--auto-servernum', electronBinary, ...electronArgs, '--no-sandbox']
|
||||
: electronArgs
|
||||
const run = spawnSync(executable, args, {
|
||||
encoding: 'utf8',
|
||||
env,
|
||||
timeout: 60_000
|
||||
})
|
||||
const fixtureResult = existsSync(resultPath) ? readFileSync(resultPath, 'utf8') : 'no result'
|
||||
expect(run.error).toBeUndefined()
|
||||
expect(run.status, `${fixtureResult}\n${run.stdout}\n${run.stderr}`).toBe(0)
|
||||
return JSON.parse(fixtureResult) as FixtureResult
|
||||
for (let attempt = 1; ; attempt += 1) {
|
||||
rmSync(resultPath, { force: true })
|
||||
// Why a fresh profile per attempt: a launch that never reached `ready` may have left the
|
||||
// Chromium profile mid-initialization, and reusing it would bias the retry.
|
||||
const electronArgs = [fixturePath, `--user-data-dir=${join(root, `profile-${attempt}`)}`]
|
||||
const run = spawnSync(
|
||||
executable,
|
||||
process.platform === 'linux'
|
||||
? ['--auto-servernum', electronBinary, ...electronArgs, '--no-sandbox']
|
||||
: electronArgs,
|
||||
{ encoding: 'utf8', env, timeout: 60_000 }
|
||||
)
|
||||
const fixtureResult = existsSync(resultPath) ? readFileSync(resultPath, 'utf8') : 'no result'
|
||||
if (attempt < FIXTURE_LAUNCH_ATTEMPTS && neverReachedElectronReady(fixtureResult)) {
|
||||
continue
|
||||
}
|
||||
expect(run.error).toBeUndefined()
|
||||
expect(run.status, `${fixtureResult}\n${run.stdout}\n${run.stderr}`).toBe(0)
|
||||
return JSON.parse(fixtureResult) as FixtureResult
|
||||
}
|
||||
}
|
||||
|
||||
describe('native Chromium excluded partition cookie under Electron', () => {
|
||||
@@ -220,5 +237,5 @@ describe('native Chromium excluded partition cookie under Electron', () => {
|
||||
'partitioned-google',
|
||||
'stale'
|
||||
])
|
||||
}, 90_000)
|
||||
}, 150_000)
|
||||
})
|
||||
|
||||
@@ -43,7 +43,9 @@ describe('skill install lock', () => {
|
||||
JSON.stringify({ token: 'dead-owner', pid: 2_147_483_647, createdAt: Date.now() })
|
||||
)
|
||||
|
||||
const release = await acquireSkillInstallLock({ path: lockPath, timeoutMs: 100 })
|
||||
// Why: reclaiming costs a fsync plus one 50ms retry, so a 100ms budget expires on a
|
||||
// loaded CI runner and surfaces the legacy file's rename ENOTDIR instead of reclaiming.
|
||||
const release = await acquireSkillInstallLock({ path: lockPath, timeoutMs: 5_000 })
|
||||
expect((await readPublishedOwner(lockPath)).token).not.toBe('dead-owner')
|
||||
await release()
|
||||
await expect(readdir(lockPath)).rejects.toMatchObject({ code: 'ENOENT' })
|
||||
|
||||
Reference in New Issue
Block a user