feat(release): 정적 프런트엔드와 격리 빌더를 도입한다
Gateway와 프로필 릴리스가 불변 프런트엔드 아티팩트를 원자적으로 게시하고 실패 시 이전 포인터를 복구하도록 한다. 릴리스 빌드는 전용 builder protocol로 분리하고 성공한 Gateway 커밋을 재기동용 Git ref에 고정한다.
This commit is contained in:
@@ -37,6 +37,17 @@ const createReleaseWorkspace = async (): Promise<string> => {
|
||||
components: ['game-api', 'game-engine', 'game-frontend'],
|
||||
})
|
||||
);
|
||||
await fs.mkdir(path.join(workspace, '.release-dist', 'che_1010', 'game-frontend', 'assets'), {
|
||||
recursive: true,
|
||||
});
|
||||
await fs.writeFile(
|
||||
path.join(workspace, '.release-dist', 'che_1010', 'game-frontend', 'index.html'),
|
||||
'<!doctype html><title>static profile</title>'
|
||||
);
|
||||
await fs.writeFile(
|
||||
path.join(workspace, '.release-dist', 'che_1010', 'game-frontend', 'assets', 'app-deadbeef.js'),
|
||||
'console.log("static")'
|
||||
);
|
||||
return workspace;
|
||||
};
|
||||
|
||||
@@ -45,7 +56,7 @@ afterEach(async () => {
|
||||
});
|
||||
|
||||
describe('profile DEPLOY operation', () => {
|
||||
it('migrates and switches the selected release without executing the reset seed path', async () => {
|
||||
it('migrates and atomically switches a static frontend without executing the reset seed path', async () => {
|
||||
const workspace = await createReleaseWorkspace();
|
||||
const profile: GatewayProfileRecord = {
|
||||
profileName: 'che:1010',
|
||||
@@ -131,6 +142,7 @@ describe('profile DEPLOY operation', () => {
|
||||
'sammo:che:1010:battle-sim-worker',
|
||||
'sammo:che:1010:tournament-worker',
|
||||
];
|
||||
const backendProcessNames = processNames.filter((name) => !name.endsWith(':game-frontend'));
|
||||
const running = new Set(processNames);
|
||||
const processManager: ProcessManager = {
|
||||
list: async () => [...running].map((name) => ({ name, status: 'online' })),
|
||||
@@ -171,6 +183,9 @@ describe('profile DEPLOY operation', () => {
|
||||
redisKeyPrefix: 'sammo:test',
|
||||
gameTokenSecret: 'test-secret',
|
||||
gatewayInternalApiUrl: 'http://127.0.0.1:15001',
|
||||
frontendServeMode: 'static',
|
||||
frontendArtifactRoot: path.join(workspace, 'artifact-volume'),
|
||||
frontendReadinessOrigin: 'http://caddy',
|
||||
baseEnv: { DATABASE_URL: 'postgresql://user:pass@integration.invalid/sammo' },
|
||||
},
|
||||
reconcileIntervalMs: 60_000,
|
||||
@@ -218,6 +233,9 @@ describe('profile DEPLOY operation', () => {
|
||||
);
|
||||
expect(logs.map((entry) => entry.message).join('\n')).not.toContain('pass@integration.invalid');
|
||||
expect(logs.map((entry) => entry.message).join('\n')).toContain('[REDACTED]');
|
||||
expect([...running].sort()).toEqual([...processNames].sort());
|
||||
expect([...running].sort()).toEqual([...backendProcessNames].sort());
|
||||
expect(
|
||||
await fs.readFile(path.join(workspace, 'artifact-volume', 'che', 'current', 'index.html'), 'utf8')
|
||||
).toContain('static profile');
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user