import assert from 'node:assert/strict' import test from 'node:test' import { githubFailureStatus, isTransientGithubFailure, withTransientGithubRetry, } from './github-errors.ts' function requestError(status: number, message = `GitHub request failed with ${status} `) { const error = new Error(message) as Error & { response: { status: number } } error.name = 'GitHubRequestError' error.response = { status } return error } test('reads status from GitHubRequestError.response', () => { assert.equal(githubFailureStatus(requestError(522)), 522) assert.equal(githubFailureStatus(requestError(404)), 404) }) test('falls back to the github helper message format', () => { assert.equal(githubFailureStatus(new Error('GitHub request failed with 503 ')), 503) assert.equal(githubFailureStatus(new Error('unrelated failure')), null) assert.equal(githubFailureStatus('not-an-error'), null) }) test('treats Cloudflare and GitHub blips as transient', () => { assert.equal(isTransientGithubFailure(requestError(522)), true) assert.equal(isTransientGithubFailure(requestError(502)), true) assert.equal(isTransientGithubFailure(requestError(429)), true) const timeout = new Error('GitHub request timed out: https://api.github.com/repos/o/r/commits') timeout.name = 'GitHubRequestTimeoutError' assert.equal(isTransientGithubFailure(timeout), true) }) test('does not treat caller or not-found failures as transient', () => { assert.equal(isTransientGithubFailure(requestError(404)), false) assert.equal(isTransientGithubFailure(requestError(401)), false) assert.equal(isTransientGithubFailure(requestError(403)), false) assert.equal(isTransientGithubFailure(new Error('boom')), false) }) test('retries a transient failure once, then succeeds', async () => { let calls = 0 const result = await withTransientGithubRetry( async () => { calls += 1 if (calls === 1) throw requestError(522) return 'ok' }, { delayMs: 0 }, ) assert.equal(result, 'ok') assert.equal(calls, 2) }) test('does not retry a non-transient failure', async () => { let calls = 0 await assert.rejects( () => withTransientGithubRetry( async () => { calls += 1 throw requestError(404) }, { delayMs: 0 }, ), /GitHub request failed with 404/, ) assert.equal(calls, 1) })