checkout/__test__/warpbuild-mirror.test.ts
2026-07-08 13:50:46 +05:30

200 lines
6.2 KiB
TypeScript

import {
describe,
it,
expect,
beforeEach,
afterEach,
afterAll
} from '@jest/globals'
import {
SKIP_NOT_WARPBUILD,
computeDestinationRef,
getMirrorCacheSkipReason
} from '../src/warpbuild/mirror-cache.js'
import {lookupSnapshot, requestUploadURL} from '../src/warpbuild/backend-api.js'
import {IGitSourceSettings} from '../src/git-source-settings.js'
const WB_ENV = [
'WARPBUILD_RUNNER_VERIFICATION_TOKEN',
'WARPBUILD_HOST_URL',
'GITHUB_REPOSITORY_ID',
'GITHUB_REPOSITORY'
]
const savedEnv: {[key: string]: string | undefined} = {}
for (const key of WB_ENV) {
savedEnv[key] = process.env[key]
}
const SHA = 'cd5255d20e23e050238affc045ba9beee35eaaf7'
function settingsFor(
overrides: Partial<IGitSourceSettings> = {}
): IGitSourceSettings {
return {
repositoryOwner: 'octocat',
repositoryName: 'hello-world',
repositoryPath: '/tmp/does-not-matter',
ref: 'refs/heads/main',
commit: SHA,
fetchDepth: 1,
fetchTags: false,
filter: undefined,
sparseCheckout: undefined,
lfs: false,
...overrides
} as unknown as IGitSourceSettings
}
function setWarpBuildEnv(): void {
process.env['WARPBUILD_RUNNER_VERIFICATION_TOKEN'] = 'test-token'
process.env['WARPBUILD_HOST_URL'] = 'https://api.example.dev'
process.env['GITHUB_REPOSITORY_ID'] = '123456789'
process.env['GITHUB_REPOSITORY'] = 'octocat/hello-world'
}
describe('warpbuild snapshot cache', () => {
beforeEach(() => {
setWarpBuildEnv()
})
afterAll(() => {
for (const key of WB_ENV) {
if (savedEnv[key] === undefined) {
delete process.env[key]
} else {
process.env[key] = savedEnv[key]
}
}
})
describe('getMirrorCacheSkipReason', () => {
const winOnly = process.platform === 'win32' ? it.skip : it
winOnly('returns null for the default checkout shape', () => {
expect(getMirrorCacheSkipReason(settingsFor())).toBeNull()
})
it('reports a non-WarpBuild runner', () => {
delete process.env['WARPBUILD_RUNNER_VERIFICATION_TOKEN']
expect(getMirrorCacheSkipReason(settingsFor())).toBe(SKIP_NOT_WARPBUILD)
})
it('reports repository: inputs that are not the workflow repo', () => {
expect(
getMirrorCacheSkipReason(settingsFor({repositoryName: 'other-repo'}))
).toBe(
"repository 'octocat/other-repo' is not the workflow repository 'octocat/hello-world'"
)
})
it('requires an exact commit sha', () => {
expect(getMirrorCacheSkipReason(settingsFor({commit: ''}))).toBe(
'no exact commit sha to key on'
)
expect(getMirrorCacheSkipReason(settingsFor({commit: 'main'}))).toBe(
'no exact commit sha to key on'
)
})
it('only serves fetch-depth 1', () => {
expect(getMirrorCacheSkipReason(settingsFor({fetchDepth: 0}))).toBe(
'fetch-depth is 0, cache only serves fetch-depth 1'
)
expect(getMirrorCacheSkipReason(settingsFor({fetchDepth: 50}))).toBe(
'fetch-depth is 50, cache only serves fetch-depth 1'
)
})
it('skips fetch-tags, filters, sparse and lfs checkouts', () => {
expect(getMirrorCacheSkipReason(settingsFor({fetchTags: true}))).toBe(
'fetch-tags is enabled'
)
expect(getMirrorCacheSkipReason(settingsFor({filter: 'blob:none'}))).toBe(
'a fetch filter is configured'
)
expect(
getMirrorCacheSkipReason(settingsFor({sparseCheckout: ['src']}))
).toBe('sparse checkout is configured')
expect(getMirrorCacheSkipReason(settingsFor({lfs: true}))).toBe(
'lfs is enabled (lfs objects are not in the snapshot)'
)
})
winOnly('accepts sha-only checkouts (empty ref)', () => {
expect(getMirrorCacheSkipReason(settingsFor({ref: ''}))).toBeNull()
})
it('skips unqualified refs', () => {
expect(getMirrorCacheSkipReason(settingsFor({ref: 'main'}))).toBe(
"ref 'main' has no cacheable destination ref"
)
})
})
describe('computeDestinationRef', () => {
it('maps the refs the fetch would have created', () => {
expect(computeDestinationRef('refs/heads/main')).toBe(
'refs/remotes/origin/main'
)
expect(computeDestinationRef('refs/pull/42/merge')).toBe(
'refs/remotes/pull/42/merge'
)
expect(computeDestinationRef('refs/tags/v1.2.3')).toBe('refs/tags/v1.2.3')
expect(computeDestinationRef('')).toBe('')
expect(computeDestinationRef('main')).toBeNull()
})
})
describe('backend api http contract', () => {
const realFetch = globalThis.fetch
let lastUrl = ''
afterEach(() => {
globalThis.fetch = realFetch
})
function stubFetch(status: number, body: unknown): void {
globalThis.fetch = (async (input: unknown) => {
lastUrl = String(input)
return new Response(JSON.stringify(body), {status})
}) as typeof fetch
}
it('maps 200 to hit and keys by sha', async () => {
stubFetch(200, {url: 'https://s3/x', size_bytes: 42, created_at: 'now'})
const result = await lookupSnapshot('123', SHA)
expect(result.kind).toBe('hit')
expect(lastUrl).toContain(`sha=${SHA}`)
})
it('maps 404 to miss (upload after the stock fetch)', async () => {
stubFetch(404, {sub_code: 'NFE_GITMIRROR'})
expect((await lookupSnapshot('123', SHA)).kind).toBe('miss')
})
it('maps 403 to disabled (backend kill switch)', async () => {
stubFetch(403, {sub_code: 'PDE_GITMIRROR_DISABLED'})
expect((await lookupSnapshot('123', SHA)).kind).toBe('disabled')
expect((await requestUploadURL('123', SHA)).kind).toBe('disabled')
})
it('maps other statuses and network failures to error', async () => {
stubFetch(500, {})
expect((await lookupSnapshot('123', SHA)).kind).toBe('error')
globalThis.fetch = (async () => {
throw new Error('boom')
}) as typeof fetch
expect((await lookupSnapshot('123', SHA)).kind).toBe('error')
expect((await requestUploadURL('123', SHA)).kind).toBe('error')
})
it('maps 200 upload responses to ok', async () => {
stubFetch(200, {url: 'https://s3/put'})
expect(await requestUploadURL('123', SHA)).toEqual({
kind: 'ok',
url: 'https://s3/put'
})
})
})
})