Files
gold_land_server/scripts/trial-production-smoke.mjs
safavimohadeseh78andCursor dfb20ca92c
Backend CI / type-check, build, tests (push) Successful in 1m0s
feat: prepare six-lesson trial backend with reliable rewards and operations
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-10-12 14:35:42 +03:30

103 lines
2.8 KiB
JavaScript

/**
* Smoke-test production env on a temp DB (no deploy).
* Requires: npm run build first.
*/
import { spawn, spawnSync } from 'node:child_process'
import { mkdtempSync, rmSync, existsSync } from 'node:fs'
import { tmpdir } from 'node:os'
import { join, dirname } from 'node:path'
import { fileURLToPath } from 'node:url'
const backendRoot = join(dirname(fileURLToPath(import.meta.url)), '..')
if (!existsSync(join(backendRoot, 'dist', 'main.js'))) {
console.error('Run npm run build before trial-production-smoke.mjs')
process.exit(1)
}
const tempDir = mkdtempSync(join(tmpdir(), 'cgl-prod-smoke-'))
const dbPath = join(tempDir, 'app.db')
const port = String(3020 + Math.floor(Math.random() * 100))
const secret = `trial-smoke-${'x'.repeat(40)}`
function fail(msg) {
console.error(msg)
rmSync(tempDir, { recursive: true, force: true })
process.exit(1)
}
const bad = spawnSync(process.execPath, ['dist/main.js'], {
cwd: backendRoot,
env: {
...process.env,
NODE_ENV: 'production',
PORT: port,
DB_PATH: dbPath,
JWT_SECRET: 'gold-land-dev-secret-change-in-production',
CORS_ORIGIN: 'http://127.0.0.1:8080',
},
stdio: 'pipe',
encoding: 'utf8',
timeout: 8000,
})
if (bad.status === 0) {
fail('Expected startup failure with dev JWT placeholder in production')
}
async function waitForReady() {
await new Promise((resolve, reject) => {
const child = spawn(process.execPath, ['dist/main.js'], {
cwd: backendRoot,
env: {
...process.env,
NODE_ENV: 'production',
PORT: port,
DB_PATH: dbPath,
JWT_SECRET: secret,
CORS_ORIGIN: 'http://127.0.0.1:8080',
},
stdio: 'pipe',
})
const timer = setTimeout(() => {
child.kill()
reject(new Error('startup timeout'))
}, 20_000)
const poll = async () => {
try {
const live = await fetch(`http://127.0.0.1:${port}/health`)
const ready = await fetch(`http://127.0.0.1:${port}/health/ready`)
if (live.ok && ready.ok) {
clearTimeout(timer)
child.kill()
resolve(undefined)
return
}
} catch {
// retry
}
setTimeout(poll, 300)
}
setTimeout(poll, 500)
})
}
await waitForReady().catch((e) => fail(String(e)))
const demoCheck = spawnSync(
process.execPath,
[
'-e',
`const D=require('better-sqlite3');const d=new D(${JSON.stringify(dbPath)});const row=d.prepare("SELECT COUNT(*) as c FROM auth_accounts WHERE username='demo'").get();console.log(row.c);d.close();`,
],
{ cwd: backendRoot, encoding: 'utf8' },
)
const demoCount = Number(demoCheck.stdout.trim())
if (demoCount !== 0) {
fail(`Expected no demo account in production DB, found ${demoCount}`)
}
rmSync(tempDir, { recursive: true, force: true })
console.log('trial-production-smoke passed')