fix: Gateway 빌드와 마이그레이션 실행기를 분리

release build는 구성된 격리 builder로 보내고 Gateway DB migration은 runtime의 로컬 runner에서만 실행한다. 원격 build와 로컬 migration 명령 경계를 회귀 테스트로 고정한다.
This commit is contained in:
2026-08-22 10:28:16 +00:00
parent a3092bcfcc
commit 57c1d03ff6
3 changed files with 68 additions and 4 deletions
@@ -388,6 +388,70 @@ describe('GatewayReleaseController', () => {
);
});
it('runs release builds remotely while keeping Gateway migration on the runtime runner', async () => {
const workspace = await createReleaseWorkspace();
const harness = createRepository();
const localCommandGroups: string[][] = [];
const remoteRequests: Array<{ commands: Array<{ args: string[] }> }> = [];
const running = new Map(gatewayNames.map((name) => [name, '/srv/sammo/old']));
const localRunner: BuildRunner = {
run: async (commands) => {
localCommandGroups.push(commands.map((command) => command.args.join(' ')));
return { ok: true, exitCode: 0, output: '' };
},
};
const controller = new GatewayReleaseController(
harness.repository,
{
resolveCommit: async () => SHA,
prepare: async () => ({ root: workspace, created: true, needsInstall: true }),
} as unknown as GitWorkspaceManager,
localRunner,
{
list: async () =>
[...running].map(([name, cwd]) => ({
name,
cwd,
status: 'online',
restartCount: 0,
script: path.join(cwd, 'dist.js'),
})),
start: async (definition) => {
running.set(definition.name, definition.cwd);
},
stop: async () => {},
delete: async (name) => {
running.delete(name);
},
},
{ ...config, releaseBuilderUrl: 'http://builder:15100' },
() => new Date('2026-08-01T00:00:00.000Z'),
async (input, init) => {
if (String(input) === 'http://builder:15100/v1/builds') {
remoteRequests.push(JSON.parse(String(init?.body)) as { commands: Array<{ args: string[] }> });
return new Response(`${JSON.stringify({ result: { ok: true, exitCode: 0, output: '' } })}\n`, {
status: 200,
headers: { 'content-type': 'application/x-ndjson' },
});
}
return new Response('', { status: 200 });
}
);
await controller.runOnce();
expect(remoteRequests).toHaveLength(1);
expect(remoteRequests[0]?.commands.map((command) => command.args.join(' '))).toEqual(
expect.arrayContaining([
expect.stringContaining('install --frozen-lockfile'),
expect.stringContaining('turbo run build'),
expect.stringContaining('turbo run build:release'),
])
);
expect(localCommandGroups).toEqual([['--filter @sammo-ts/infra prisma:migrate:deploy:gateway']]);
expect(harness.completions).toEqual(['SUCCEEDED']);
});
it('restores the previous gateway processes when the new process set cannot start', async () => {
const workspace = await createReleaseWorkspace();
const harness = createRepository();