feat: Implement admin router and orchestrator for managing profiles and builds

- Added `adminRouter` for handling profile management, including listing, upserting, and updating statuses.
- Introduced `BuildRunner` interface and `PnpmBuildRunner` class for executing build commands.
- Created `GatewayOrchestrator` to manage profile states, reconcile processes, and handle build queues.
- Implemented `Pm2ProcessManager` for managing processes using PM2.
- Developed `GatewayProfileRepository` for interacting with the database to manage profiles.
- Added utility functions for resolving workspace roots and managing process definitions.
- Included tests for profile reconciliation logic.
This commit is contained in:
2026-01-01 10:38:28 +00:00
parent 79819c4a1b
commit b46249dcbc
18 changed files with 2151 additions and 7 deletions
+38
View File
@@ -12,6 +12,12 @@ export interface GatewayApiConfig {
kakaoAdminKey?: string;
kakaoRedirectUri: string;
publicBaseUrl: string;
adminToken?: string;
orchestratorEnabled: boolean;
orchestratorReconcileIntervalMs: number;
orchestratorScheduleIntervalMs: number;
orchestratorBuildIntervalMs: number;
workspaceRootHint: string;
}
const parseNumber = (value: string | undefined, fallback: number, label: string): number => {
@@ -25,6 +31,20 @@ const parseNumber = (value: string | undefined, fallback: number, label: string)
return parsed;
};
const parseBoolean = (value: string | undefined, fallback: boolean): boolean => {
if (!value) {
return fallback;
}
const normalized = value.trim().toLowerCase();
if (['1', 'true', 'yes', 'y', 'on'].includes(normalized)) {
return true;
}
if (['0', 'false', 'no', 'n', 'off'].includes(normalized)) {
return false;
}
return fallback;
};
export const resolveGatewayApiConfigFromEnv = (
env: NodeJS.ProcessEnv = process.env
): GatewayApiConfig => {
@@ -61,5 +81,23 @@ export const resolveGatewayApiConfigFromEnv = (
kakaoAdminKey: env.KAKAO_ADMIN_KEY,
kakaoRedirectUri,
publicBaseUrl,
adminToken: env.GATEWAY_ADMIN_TOKEN,
orchestratorEnabled: parseBoolean(env.GATEWAY_ORCHESTRATOR_ENABLED, true),
orchestratorReconcileIntervalMs: parseNumber(
env.GATEWAY_ORCHESTRATOR_RECONCILE_MS,
15000,
'GATEWAY_ORCHESTRATOR_RECONCILE_MS'
),
orchestratorScheduleIntervalMs: parseNumber(
env.GATEWAY_ORCHESTRATOR_SCHEDULE_MS,
5000,
'GATEWAY_ORCHESTRATOR_SCHEDULE_MS'
),
orchestratorBuildIntervalMs: parseNumber(
env.GATEWAY_ORCHESTRATOR_BUILD_MS,
10000,
'GATEWAY_ORCHESTRATOR_BUILD_MS'
),
workspaceRootHint: env.GATEWAY_WORKSPACE_ROOT ?? process.cwd(),
};
};