import { BUILD_TIMEOUT_MS, readBuilderToken, readBuilderMessages, } from "./release-builder-security.mjs"; const builderUrl = process.env.RELEASE_BUILDER_URL ?? "http://builder:15100"; const coreRoot = process.env.GATEWAY_WORKSPACE_ROOT ?? "/srv/core/repository"; const publicBuildEnv = Object.fromEntries( Object.entries(process.env).filter( ([name, value]) => typeof value === "string" && /^(?:CI|NODE_OPTIONS|PROFILE_FRONTEND_BUILD_NODE_OPTIONS|RAYON_NUM_THREADS|RELEASE_TURBO_CONCURRENCY|TURBO_CACHE_DIR|TZ|VITE_[A-Z0-9_]+)$/.test( name, ), ), ); if (process.env.RELEASE_BUILD_NODE_OPTIONS) { publicBuildEnv.NODE_OPTIONS = process.env.RELEASE_BUILD_NODE_OPTIONS; } delete publicBuildEnv.RELEASE_BUILD_NODE_OPTIONS; const pnpm = (...args) => ({ command: "pnpm", args, cwd: coreRoot, env: publicBuildEnv, }); const commands = [ pnpm("install", "--frozen-lockfile"), pnpm("--filter", "@sammo-ts/common", "build"), pnpm("--filter", "@sammo-ts/infra", "prisma:generate"), pnpm("--filter", "@sammo-ts/infra", "build"), pnpm("--filter", "@sammo-ts/logic", "build"), pnpm("--filter", "@sammo-ts/game-engine", "build"), pnpm("--filter", "@sammo-ts/gateway-api", "build"), pnpm("--filter", "@sammo-ts/gateway-frontend", "build"), pnpm("--filter", "@sammo-ts/release-controller", "build"), ]; const response = await fetch(new URL("/v1/builds", builderUrl), { method: "POST", redirect: "error", signal: AbortSignal.timeout(BUILD_TIMEOUT_MS), headers: { "content-type": "application/json", "x-release-builder-token": readBuilderToken( process.env.RELEASE_BUILDER_TOKEN_FILE, ), }, body: JSON.stringify({ commands }), }); let result = null; for await (const message of readBuilderMessages(response)) { if (message.event?.type === "OUTPUT") { if ( !["stdout", "stderr"].includes(message.event.stream) || typeof message.event.message !== "string" || message.event.message.length > 2000 ) throw new Error("Invalid release build progress."); const output = `${message.event.message}\n`; if (message.event.stream === "stderr") process.stderr.write(output); else process.stdout.write(output); } if (message.result) { if ( typeof message.result.ok !== "boolean" || (message.result.ok && (message.result.exitCode !== 0 || message.result.aborted === true)) || typeof message.result.output !== "string" || message.result.output.length > 64 * 1024 ) throw new Error("Invalid release build result."); result = message.result; break; } } if (!result?.ok) throw new Error("Release builder did not produce a successful result.");