chore: sync backend and deployment changes
This commit is contained in:
@@ -32,6 +32,7 @@ type ServerDefinition = {
|
||||
commandWorkingDirectory: string;
|
||||
commandEnvironment: Record<string, string>;
|
||||
restartStrategy: 'wait' | 'deferred';
|
||||
deferredResponseMode?: 'wait-for-result' | 'accept-immediately';
|
||||
};
|
||||
|
||||
export type ServerCommandSnapshot = {
|
||||
@@ -135,11 +136,26 @@ const APP_BUILD_INFO_FILE_CANDIDATES = [
|
||||
'/tmp/ai-code-test-app-dist/manifest.webmanifest',
|
||||
'/tmp/ai-code-test-app-dist/assets',
|
||||
] as const;
|
||||
const APP_BUILD_STAMP_RELATIVE_PATH = '.server-command-test-app-built-at';
|
||||
const APP_SOURCE_EXCLUDED_PREFIXES = ['public/.codex_chat/'] as const;
|
||||
const APP_SOURCE_EXCLUDED_FILE_PATTERNS = [/\.test\.[^/]+$/i, /\.spec\.[^/]+$/i] as const;
|
||||
|
||||
export async function readAppBuildTimestamp(definition: ServerDefinition, options?: { allowLocal?: boolean }) {
|
||||
const allowLocal = options?.allowLocal ?? false;
|
||||
let latestBuiltAt: string | null = null;
|
||||
const mainProjectRoot = normalizePath(resolveMainProjectRoot());
|
||||
const buildStampCandidates = [
|
||||
path.join(mainProjectRoot, APP_BUILD_STAMP_RELATIVE_PATH),
|
||||
path.join(normalizePath(env.SERVER_COMMAND_PROJECT_ROOT), APP_BUILD_STAMP_RELATIVE_PATH),
|
||||
].filter((value, index, array) => array.indexOf(value) === index);
|
||||
|
||||
for (const targetPath of buildStampCandidates) {
|
||||
const candidate = allowLocal ? await readLocalBuildTimestamp(targetPath) : null;
|
||||
|
||||
if (candidate && (!latestBuiltAt || candidate > latestBuiltAt)) {
|
||||
latestBuiltAt = candidate;
|
||||
}
|
||||
}
|
||||
|
||||
for (const targetPath of APP_BUILD_INFO_FILE_CANDIDATES) {
|
||||
const candidates = [
|
||||
@@ -195,7 +211,13 @@ type SourceChangeInfo = {
|
||||
|
||||
function isExcludedAppSourcePath(rootPath: string, targetPath: string) {
|
||||
const relativePath = path.relative(rootPath, targetPath).replace(/\\/g, '/');
|
||||
return APP_SOURCE_EXCLUDED_PREFIXES.some((prefix) => relativePath === prefix.slice(0, -1) || relativePath.startsWith(prefix));
|
||||
|
||||
if (APP_SOURCE_EXCLUDED_PREFIXES.some((prefix) => relativePath === prefix.slice(0, -1) || relativePath.startsWith(prefix))) {
|
||||
return true;
|
||||
}
|
||||
|
||||
const baseName = path.basename(relativePath);
|
||||
return APP_SOURCE_EXCLUDED_FILE_PATTERNS.some((pattern) => pattern.test(baseName));
|
||||
}
|
||||
|
||||
async function findLatestSourceChangeInPath(rootPath: string, targetPath: string): Promise<SourceChangeInfo | null> {
|
||||
@@ -575,8 +597,10 @@ async function restartViaDockerSocket(definition: ServerDefinition) {
|
||||
}
|
||||
|
||||
function getServerDefinitions(): ServerDefinition[] {
|
||||
const projectRoot = normalizePath(env.SERVER_COMMAND_PROJECT_ROOT);
|
||||
const mainProjectRoot = normalizePath(resolveMainProjectRoot());
|
||||
const useLocalMainMode = Boolean(env.PLAN_LOCAL_MAIN_MODE);
|
||||
const projectRoot = normalizePath(useLocalMainMode ? mainProjectRoot : env.SERVER_COMMAND_PROJECT_ROOT);
|
||||
const scriptRootCandidates = [mainProjectRoot, projectRoot, '/workspace/main-project'];
|
||||
|
||||
return [
|
||||
{
|
||||
@@ -585,11 +609,11 @@ function getServerDefinitions(): ServerDefinition[] {
|
||||
summary: '메인 프로젝트의 테스트 앱 컨테이너',
|
||||
environment: 'test',
|
||||
publicUrl: normalizeUrl(env.SERVER_COMMAND_TEST_URL),
|
||||
checkUrl: normalizeUrl(env.SERVER_COMMAND_TEST_URL),
|
||||
checkUrl: normalizeUrl(env.SERVER_COMMAND_TEST_CHECK_URL || env.SERVER_COMMAND_TEST_URL),
|
||||
composeFile: path.join(mainProjectRoot, 'docker-compose.yml'),
|
||||
serviceName: env.SERVER_COMMAND_TEST_SERVICE,
|
||||
containerName: 'ai-code-app-app-1',
|
||||
commandScript: resolveCommandScriptPath('restart-test.sh', [projectRoot, mainProjectRoot, '/workspace/main-project']),
|
||||
commandScript: resolveCommandScriptPath('restart-test.sh', scriptRootCandidates),
|
||||
commandWorkingDirectory: mainProjectRoot,
|
||||
commandEnvironment: {
|
||||
MAIN_PROJECT_ROOT: mainProjectRoot,
|
||||
@@ -607,11 +631,11 @@ function getServerDefinitions(): ServerDefinition[] {
|
||||
summary: 'release 브랜치를 서비스하는 릴리즈 앱 컨테이너',
|
||||
environment: 'release',
|
||||
publicUrl: normalizeUrl(env.SERVER_COMMAND_REL_URL),
|
||||
checkUrl: normalizeUrl(env.SERVER_COMMAND_REL_URL),
|
||||
checkUrl: normalizeUrl(env.SERVER_COMMAND_REL_CHECK_URL || env.SERVER_COMMAND_REL_URL),
|
||||
composeFile: path.join(mainProjectRoot, 'docker-compose.yml'),
|
||||
serviceName: env.SERVER_COMMAND_REL_SERVICE,
|
||||
containerName: 'ai-code-app-release',
|
||||
commandScript: resolveCommandScriptPath('restart-rel.sh', [projectRoot, mainProjectRoot, '/workspace/main-project']),
|
||||
commandScript: resolveCommandScriptPath('restart-rel.sh', scriptRootCandidates),
|
||||
commandWorkingDirectory: mainProjectRoot,
|
||||
commandEnvironment: {
|
||||
MAIN_PROJECT_ROOT: mainProjectRoot,
|
||||
@@ -626,11 +650,11 @@ function getServerDefinitions(): ServerDefinition[] {
|
||||
summary: '프로덕션 앱 컨테이너',
|
||||
environment: 'production',
|
||||
publicUrl: normalizeUrl(env.SERVER_COMMAND_PROD_URL),
|
||||
checkUrl: normalizeUrl(env.SERVER_COMMAND_PROD_URL),
|
||||
checkUrl: normalizeUrl(env.SERVER_COMMAND_PROD_CHECK_URL || env.SERVER_COMMAND_PROD_URL),
|
||||
composeFile: path.join(mainProjectRoot, 'docker-compose.yml'),
|
||||
serviceName: env.SERVER_COMMAND_PROD_SERVICE,
|
||||
containerName: 'ai-code-app-prod',
|
||||
commandScript: resolveCommandScriptPath('restart-prod.sh', [projectRoot, mainProjectRoot, '/workspace/main-project']),
|
||||
commandScript: resolveCommandScriptPath('restart-prod.sh', scriptRootCandidates),
|
||||
commandWorkingDirectory: mainProjectRoot,
|
||||
commandEnvironment: {
|
||||
MAIN_PROJECT_ROOT: mainProjectRoot,
|
||||
@@ -639,6 +663,7 @@ function getServerDefinitions(): ServerDefinition[] {
|
||||
SERVER_COMMAND_CONTAINER_NAME: 'ai-code-app-prod',
|
||||
},
|
||||
restartStrategy: 'deferred',
|
||||
deferredResponseMode: 'wait-for-result',
|
||||
},
|
||||
{
|
||||
key: 'work-server',
|
||||
@@ -650,12 +675,13 @@ function getServerDefinitions(): ServerDefinition[] {
|
||||
composeFile: path.join(projectRoot, 'etc', 'servers', 'work-server', 'docker-compose.yml'),
|
||||
serviceName: env.SERVER_COMMAND_WORK_SERVER_SERVICE,
|
||||
containerName: 'work-server',
|
||||
commandScript: resolveCommandScriptPath('restart-work-server.sh', [projectRoot, mainProjectRoot, '/workspace/main-project']),
|
||||
commandWorkingDirectory: projectRoot,
|
||||
commandScript: resolveCommandScriptPath('restart-work-server.sh', scriptRootCandidates),
|
||||
commandWorkingDirectory: mainProjectRoot,
|
||||
commandEnvironment: {
|
||||
REPO_ROOT: projectRoot,
|
||||
REPO_ROOT: mainProjectRoot,
|
||||
},
|
||||
restartStrategy: 'deferred',
|
||||
deferredResponseMode: 'accept-immediately',
|
||||
},
|
||||
{
|
||||
key: 'command-runner',
|
||||
@@ -667,12 +693,13 @@ function getServerDefinitions(): ServerDefinition[] {
|
||||
composeFile: path.join(projectRoot, 'scripts', 'run-server-command-runner.mjs'),
|
||||
serviceName: 'server-command-runner',
|
||||
containerName: 'server-command-runner',
|
||||
commandScript: resolveCommandScriptPath('restart-server-command-runner.sh', [projectRoot, mainProjectRoot, '/workspace/main-project']),
|
||||
commandWorkingDirectory: projectRoot,
|
||||
commandScript: resolveCommandScriptPath('restart-server-command-runner.sh', scriptRootCandidates),
|
||||
commandWorkingDirectory: mainProjectRoot,
|
||||
commandEnvironment: {
|
||||
PROJECT_ROOT: projectRoot,
|
||||
PROJECT_ROOT: mainProjectRoot,
|
||||
},
|
||||
restartStrategy: 'deferred',
|
||||
deferredResponseMode: 'wait-for-result',
|
||||
},
|
||||
];
|
||||
}
|
||||
@@ -930,6 +957,14 @@ async function restartServerCommandDeferred(definition: ServerDefinition): Promi
|
||||
});
|
||||
});
|
||||
|
||||
if (definition.deferredResponseMode === 'accept-immediately') {
|
||||
return {
|
||||
server: buildAcceptedRestartSnapshot(definition),
|
||||
commandOutput: `${definition.label} 재기동 요청을 접수했습니다. 잠시 후 상태를 다시 확인해 주세요.`,
|
||||
restartState: 'accepted',
|
||||
};
|
||||
}
|
||||
|
||||
const commandOutput = await waitForDeferredRestartResult(definition, statusPath, logPath);
|
||||
|
||||
return {
|
||||
|
||||
Reference in New Issue
Block a user