120 lines
4.3 KiB
TypeScript
120 lines
4.3 KiB
TypeScript
import { describe, expect, it } from 'vitest';
|
|
|
|
import path from 'node:path';
|
|
|
|
import {
|
|
buildProcessDefinitions,
|
|
buildWorkspaceCommands,
|
|
planProfileReconcile,
|
|
} from '../src/orchestrator/gatewayOrchestrator.js';
|
|
import type { GatewayProfileRecord } from '../src/orchestrator/profileRepository.js';
|
|
|
|
const buildProfile = (buildWorkspace?: string): GatewayProfileRecord => ({
|
|
profileName: 'che:2',
|
|
profile: 'che',
|
|
scenario: '2',
|
|
apiPort: 15003,
|
|
status: 'RUNNING',
|
|
buildStatus: 'SUCCEEDED',
|
|
buildCommitSha: '0123456789abcdef0123456789abcdef01234567',
|
|
buildWorkspace,
|
|
meta: {},
|
|
createdAt: '2026-07-25T00:00:00.000Z',
|
|
updatedAt: '2026-07-25T00:00:00.000Z',
|
|
});
|
|
|
|
describe('planProfileReconcile', () => {
|
|
it('starts missing processes for running profiles', () => {
|
|
expect(
|
|
planProfileReconcile('RUNNING', {
|
|
apiRunning: true,
|
|
daemonRunning: false,
|
|
})
|
|
).toEqual({ shouldStart: true, shouldStop: false });
|
|
});
|
|
|
|
it('starts processes for preopen profiles', () => {
|
|
expect(
|
|
planProfileReconcile('PREOPEN', {
|
|
apiRunning: false,
|
|
daemonRunning: false,
|
|
})
|
|
).toEqual({ shouldStart: true, shouldStop: false });
|
|
});
|
|
|
|
it('does nothing when running profile is healthy', () => {
|
|
expect(
|
|
planProfileReconcile('RUNNING', {
|
|
apiRunning: true,
|
|
daemonRunning: true,
|
|
})
|
|
).toEqual({ shouldStart: false, shouldStop: false });
|
|
});
|
|
|
|
it('stops processes for non-running profiles', () => {
|
|
expect(
|
|
planProfileReconcile('STOPPED', {
|
|
apiRunning: false,
|
|
daemonRunning: true,
|
|
})
|
|
).toEqual({ shouldStart: false, shouldStop: true });
|
|
});
|
|
|
|
it('keeps reserved profiles off', () => {
|
|
expect(
|
|
planProfileReconcile('RESERVED', {
|
|
apiRunning: false,
|
|
daemonRunning: false,
|
|
})
|
|
).toEqual({ shouldStart: false, shouldStop: false });
|
|
});
|
|
});
|
|
|
|
describe('buildProcessDefinitions', () => {
|
|
const processConfig = {
|
|
workspaceRoot: '/srv/sammo/main',
|
|
redisKeyPrefix: 'sammo:gateway',
|
|
gameTokenSecret: 'test-secret',
|
|
};
|
|
|
|
it('runs a built profile from its commit worktree', () => {
|
|
const buildWorkspace = '/srv/sammo/worktrees/0123456789abcdef';
|
|
const definitions = buildProcessDefinitions(buildProfile(buildWorkspace), processConfig);
|
|
|
|
expect(definitions.api.cwd).toBe(path.join(buildWorkspace, 'app', 'game-api'));
|
|
expect(definitions.api.script).toBe(path.join(buildWorkspace, 'app', 'game-api', 'dist', 'index.js'));
|
|
expect(definitions.api.env).toMatchObject({
|
|
GAME_TRPC_PATH: '/che/api/trpc',
|
|
GAME_API_EVENTS_PATH: '/che/api/events',
|
|
GAME_UPLOAD_PATH: '/che/api/uploads',
|
|
});
|
|
expect(definitions.daemon.cwd).toBe(path.join(buildWorkspace, 'app', 'game-engine'));
|
|
expect(definitions.daemon.script).toBe(path.join(buildWorkspace, 'app', 'game-engine', 'dist', 'index.js'));
|
|
});
|
|
|
|
it('keeps main as the runtime for profiles without a commit worktree', () => {
|
|
const definitions = buildProcessDefinitions(buildProfile(), processConfig);
|
|
|
|
expect(definitions.api.cwd).toBe(path.join(processConfig.workspaceRoot, 'app', 'game-api'));
|
|
expect(definitions.daemon.cwd).toBe(path.join(processConfig.workspaceRoot, 'app', 'game-engine'));
|
|
});
|
|
});
|
|
|
|
describe('buildWorkspaceCommands', () => {
|
|
it('installs and builds runtime dependencies before the profile processes', () => {
|
|
const workspaceRoot = '/srv/sammo/worktrees/0123456789abcdef';
|
|
const commands = buildWorkspaceCommands(workspaceRoot, true);
|
|
|
|
expect(commands.map(({ args }) => args)).toEqual([
|
|
['install'],
|
|
['--filter', '@sammo-ts/common', 'build'],
|
|
['--filter', '@sammo-ts/infra', 'prisma:generate'],
|
|
['--filter', '@sammo-ts/infra', 'build'],
|
|
['--filter', '@sammo-ts/logic', 'build'],
|
|
['--filter', '@sammo-ts/game-api', 'build'],
|
|
['--filter', '@sammo-ts/game-engine', 'build'],
|
|
]);
|
|
expect(commands.every(({ cwd }) => cwd === workspaceRoot)).toBe(true);
|
|
});
|
|
});
|