Files
xinmi/scripts/publish_public_api_context.test.cjs
yawan f7fc992f57
Anydoc / anydoc parser engine (push) Canceled after 0s
App / Format, vet, test, and build (push) Canceled after 0s
CLI / test (macos-latest / go 1.26) (push) Canceled after 0s
CLI / test (ubuntu-latest / go 1.26) (push) Canceled after 0s
CLI / test (windows-latest / go 1.26) (push) Canceled after 0s
Build and Push Docker Image / build-ui (push) Canceled after 0s
Build and Push Docker Image / build-docreader (push) Canceled after 0s
Build and Push Docker Image / build-sandbox (push) Canceled after 0s
Build and Push Docker Image / build-app (amd64, linux/amd64, ubuntu-latest) (push) Canceled after 0s
Build and Push Docker Image / build-app (arm64, linux/arm64, ubuntu-24.04-arm) (push) Canceled after 0s
DocReader / Python tests and Go client tests (push) Canceled after 0s
Build & Publish (dsh-weknora) / Typecheck, test, pack (push) Canceled after 0s
Build & Publish (dsh-weknora) / End-to-end inside dsh (pinned) (push) Canceled after 0s
Build & Publish (dsh-weknora) / End-to-end inside dsh (latest, advisory) (push) Canceled after 0s
Frontend / Test, type-check, and build (push) Canceled after 0s
Go Lint Cache / warm lint cache (.) (push) Canceled after 0s
Go Lint Cache / warm lint cache (cli) (push) Canceled after 0s
Go Lint Cache / warm lint cache (client) (push) Canceled after 0s
Build & Publish (mcp-server) / Test (Python 3.10) (push) Canceled after 0s
Build & Publish (mcp-server) / Test (Python 3.11) (push) Canceled after 0s
Build & Publish (mcp-server) / Test (Python 3.12) (push) Canceled after 0s
Build & Publish (mcp-server) / Test (Python 3.13) (push) Canceled after 0s
Build and Push Docker Image / merge (push) Canceled after 0s
Build & Publish (dsh-weknora) / Publish to npm (push) Canceled after 0s
Build & Publish (mcp-server) / Build sdist + wheel (push) Canceled after 0s
Build & Publish (mcp-server) / Publish to PyPI (push) Canceled after 0s
WeKnora deployment source with the reviewed wiki identity, summary and recovery fixes
2026-09-22 16:19:06 +08:00

110 lines
6.5 KiB
JavaScript

const assert = require('node:assert/strict')
const test = require('node:test')
const fs = require('node:fs')
const os = require('node:os')
const path = require('node:path')
const vm = require('node:vm')
const { stagePublicAPIContext } = require('./stage_public_api_context.cjs')
const release = 'public-20260921-040700'
function publisher(t, action, failBuild = false) {
const root = fs.mkdtempSync(path.join(os.tmpdir(), 'public-api-publisher-'))
t.after(() => fs.rmSync(root, { recursive: true, force: true }))
const source = path.join(root, 'src')
for (const directory of ['scripts', 'migrations', 'frontend/dist']) fs.mkdirSync(path.join(source, directory), { recursive: true })
fs.mkdirSync(path.join(root, 'acceptance'))
fs.writeFileSync(path.join(source, 'scripts/Dockerfile.public-api'), fs.readFileSync(path.join(__dirname, 'Dockerfile.public-api')))
fs.writeFileSync(path.join(source, 'WeKnora-native-acceptance-next'), 'reviewed-api', { mode: 0o755 })
fs.writeFileSync(path.join(source, 'migrations/001.sql'), 'SELECT 1;\n')
fs.writeFileSync(path.join(root, 'acceptance/runtime.env'), 'DB_NAME=yawan_native_acceptance_20260915\n')
const directory = path.join(root, 'releases', release)
if (action === 'refreshAPI') {
fs.mkdirSync(directory, { recursive: true })
fs.writeFileSync(path.join(directory, 'manifest.json'), JSON.stringify({ release, stage: 'origin-ready',
api_image: 'yawan-api:previous', api_image_id: 'sha256:previous' }))
}
const calls = []
const module = { exports: {} }
const injectedRequire = name => {
if (name === 'node:fs') return { ...fs, copyFileSync(from, to, flags) {
if (from === '/Users/macclaw/.cloudflared/config.yml') {
calls.push({ kind: 'tunnel-backup', to })
return fs.writeFileSync(to, 'previous tunnel configuration\n')
}
return fs.copyFileSync(from, to, flags)
} }
if (name === 'node:child_process') return { execFileSync(binary, args) {
assert.equal(binary, 'docker')
assert.deepEqual(Array.from(args.slice(0, 2)), ['--context', 'colima-yawan'])
const command = Array.from(args.slice(2))
calls.push({ kind: 'docker', command })
if (command[0] === 'build' && command[2].startsWith('yawan-api:')) {
if (failBuild) throw new Error('stubbed API build failure')
assert.deepEqual(fs.readdirSync(command.at(-1)).sort(), ['Dockerfile', 'WeKnora-native-acceptance-next', 'migrations'])
}
return command[0] === 'image' ? 'sha256:built-image\n' : ''
} }
if (name === './preserve_frontend_assets.cjs') return { preserveFrontendAssets() { calls.push({ kind: 'retain-assets' }); return { retained: 7 } } }
if (name === './stage_public_api_context.cjs') return { stagePublicAPIContext }
return require(name)
}
const context = { require: injectedRequire, module, __dirname: path.join(source, 'scripts'), URL, AbortSignal,
fetch: async () => ({ ok: true }), console: { log() {} }, recordIdle: () => calls.push({ kind: 'idle' }) }
vm.runInNewContext(fs.readFileSync(path.join(__dirname, 'publish_public_runtime.cjs'), 'utf8')
+ '\n;idle = recordIdle; globalThis.actions = { prepare, refreshAPI };', context)
return { root, source, directory, calls, run: () => context.actions[action](release) }
}
test('prepare builds its API from the release snapshot after backups and retains frontend behavior', t => {
const value = publisher(t, 'prepare')
value.run()
const builds = value.calls.filter(call => call.kind === 'docker' && call.command[0] === 'build')
assert.deepEqual(builds.map(call => call.command), [
['build', '-t', `yawan-api:${release}`, path.join(value.directory, 'api-context')],
['build', '-t', `yawan-frontend:${release}`, path.join(value.source, 'frontend')],
])
const firstBuild = value.calls.indexOf(builds[0])
const backups = value.calls.filter(call => call.kind === 'docker' && call.command.includes('pg_dump'))
assert.equal(backups.length, 2)
assert.ok(backups.every(call => value.calls.indexOf(call) < firstBuild))
assert.ok(value.calls.find(call => call.kind === 'tunnel-backup'))
assert.ok(value.calls.find(call => call.kind === 'retain-assets'))
const manifest = JSON.parse(fs.readFileSync(path.join(value.directory, 'manifest.json')))
assert.equal(manifest.stage, 'prepared')
assert.equal(manifest.api_image_id, 'sha256:built-image')
assert.equal(manifest.frontend_image_id, 'sha256:built-image')
assert.equal(manifest.retained_assets.retained, 7)
})
test('refresh-api uses its immutable revision snapshot and preserves idle and image identity checks', async t => {
const value = publisher(t, 'refreshAPI')
await value.run()
const buildIndex = value.calls.findIndex(call => call.kind === 'docker' && call.command[0] === 'build')
const build = value.calls[buildIndex].command
const revision = build[2].match(/-api-(\d{17})$/)[1]
assert.deepEqual(build, ['build', '-t', `yawan-api:${release}-api-${revision}`, path.join(value.directory, `api-context-${revision}`)])
const idleIndexes = value.calls.flatMap((call, index) => call.kind === 'idle' ? [index] : [])
const stopIndex = value.calls.findIndex(call => call.kind === 'docker' && call.command[0] === 'stop')
assert.equal(idleIndexes.length, 2)
assert.ok(idleIndexes[0] < buildIndex && buildIndex < idleIndexes[1] && idleIndexes[1] < stopIndex)
const start = value.calls.find(call => call.kind === 'docker' && call.command[0] === 'run').command
assert.equal(start.at(-1), 'sha256:built-image')
assert.ok(start.includes('WEKNORA_REVIEWED_API_IMAGE=sha256:built-image'))
const manifest = JSON.parse(fs.readFileSync(path.join(value.directory, 'manifest.json')))
assert.equal(manifest.api_image_id, 'sha256:built-image')
assert.deepEqual(manifest.previous_apis, [{ image: 'yawan-api:previous', image_id: 'sha256:previous',
container: `yawan-native-acceptance-before-${revision}` }])
})
test('an API build failure retains the staged context and never stops the running API', async t => {
const value = publisher(t, 'refreshAPI', true)
await assert.rejects(value.run(), /stubbed API build failure/)
assert.equal(value.calls.some(call => call.kind === 'docker' && ['stop', 'rename', 'run'].includes(call.command[0])), false)
const build = value.calls.find(call => call.kind === 'docker' && call.command[0] === 'build').command
assert.equal(fs.readFileSync(path.join(build.at(-1), 'WeKnora-native-acceptance-next'), 'utf8'), 'reviewed-api')
const manifest = JSON.parse(fs.readFileSync(path.join(value.directory, 'manifest.json')))
assert.equal(manifest.api_image_id, 'sha256:previous')
assert.equal(manifest.stage, 'origin-ready')
})