Caddy가 불변 아티팩트를 직접 제공하고 runtime과 builder의 자원·비밀 경계를 분리한다. Gateway active release ref를 재기동에 복원하고 production/development/smoke 모델 검증을 확장한다.
58 lines
2.2 KiB
JavaScript
58 lines
2.2 KiB
JavaScript
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',
|
|
headers: { 'content-type': 'application/json' },
|
|
body: JSON.stringify({ commands }),
|
|
});
|
|
if (!response.ok || !response.body) {
|
|
throw new Error((await response.text()) || `Release builder returned HTTP ${response.status}.`);
|
|
}
|
|
const decoder = new TextDecoder();
|
|
let buffer = '';
|
|
let result = null;
|
|
const handleLine = (line) => {
|
|
if (!line.trim()) return;
|
|
const message = JSON.parse(line);
|
|
if (message.event?.type === 'OUTPUT') {
|
|
const output = `${message.event.message}\n`;
|
|
if (message.event.stream === 'stderr') process.stderr.write(output);
|
|
else process.stdout.write(output);
|
|
}
|
|
if (message.result) result = message.result;
|
|
};
|
|
for await (const chunk of response.body) {
|
|
buffer += decoder.decode(chunk, { stream: true });
|
|
const lines = buffer.split('\n');
|
|
buffer = lines.pop() ?? '';
|
|
for (const line of lines) handleLine(line);
|
|
}
|
|
handleLine(buffer);
|
|
if (!result?.ok) {
|
|
throw new Error(result?.output || 'Release builder closed without a successful result.');
|
|
}
|