merge: permit explicit controller protocol upgrades

This commit is contained in:
2026-08-11 00:01:51 +00:00
5 changed files with 32 additions and 6 deletions
@@ -31,7 +31,10 @@ const assertMigrationHead = async (workspaceRoot: string, directory: string, exp
}
};
export const readReleaseManifest = async (workspaceRoot: string): Promise<ReleaseManifest> => {
export const readReleaseManifest = async (
workspaceRoot: string,
options: { allowControllerUpgrade?: boolean } = {}
): Promise<ReleaseManifest> => {
const manifestPath = path.join(workspaceRoot, 'release-manifest.json');
const parsed = JSON.parse(await fs.readFile(manifestPath, 'utf8')) as unknown;
if (
@@ -46,7 +49,7 @@ export const readReleaseManifest = async (workspaceRoot: string): Promise<Releas
) {
throw new Error(`Invalid release manifest: ${manifestPath}`);
}
if (parsed.controllerProtocol > RELEASE_CONTROLLER_PROTOCOL) {
if (parsed.controllerProtocol > RELEASE_CONTROLLER_PROTOCOL && !options.allowControllerUpgrade) {
throw new Error(
`Release requires controller protocol ${parsed.controllerProtocol}; this controller supports ${RELEASE_CONTROLLER_PROTOCOL}.`
);
+18 -2
View File
@@ -8,7 +8,7 @@ import { readReleaseManifest, RELEASE_CONTROLLER_PROTOCOL } from '../src/orchest
const temporaryDirectories: string[] = [];
const createWorkspace = async (gatewayHead: string, gameHead: string): Promise<string> => {
const createWorkspace = async (gatewayHead: string, gameHead: string, controllerProtocol = 1): Promise<string> => {
const workspace = await fs.mkdtemp(path.join(os.tmpdir(), 'sammo-release-manifest-'));
temporaryDirectories.push(workspace);
await fs.mkdir(path.join(workspace, 'packages/infra/prisma/gateway-migrations', gatewayHead), {
@@ -19,7 +19,7 @@ const createWorkspace = async (gatewayHead: string, gameHead: string): Promise<s
path.join(workspace, 'release-manifest.json'),
JSON.stringify({
formatVersion: 1,
controllerProtocol: 1,
controllerProtocol,
gatewaySchemaHead: gatewayHead,
gameSchemaHead: gameHead,
components: ['gateway-api', 'gateway-frontend', 'game-api', 'game-engine', 'game-frontend'],
@@ -58,4 +58,20 @@ describe('readReleaseManifest', () => {
await expect(readReleaseManifest(workspace)).rejects.toThrow('does not match workspace head');
});
it('allows only the explicit controller self-upgrade boundary to cross protocol versions', async () => {
const futureProtocol = RELEASE_CONTROLLER_PROTOCOL + 1;
const workspace = await createWorkspace(
'20260801000000_gateway',
'20260801000000_game',
futureProtocol
);
await expect(readReleaseManifest(workspace)).rejects.toThrow(
`Release requires controller protocol ${futureProtocol}`
);
await expect(readReleaseManifest(workspace, { allowControllerUpgrade: true })).resolves.toMatchObject({
controllerProtocol: futureProtocol,
});
});
});
+3 -1
View File
@@ -86,4 +86,6 @@ rollback하려면 새 schema와의 하위 호환성을 릴리스 전에 확인
`release-manifest.json``controllerProtocol`이 올라간 릴리스는 controller를
먼저 self-upgrade해야 합니다. Protocol 2는 `GatewayReleaseLog` 진행 로그 저장을
요구합니다. 구형 controller로 새 Gateway만 배포하면 관리자 화면과 controller의
기능이 어긋날 수 있으므로, manifest protocol 검사를 우회하지 마세요.
기능이 어긋날 수 있으므로, 일반 배포의 manifest protocol 검사를 우회하지
마세요. Self-upgrade CLI만 다음 protocol을 허용하며 schema head와 component는
동일하게 검증합니다.
+4 -1
View File
@@ -65,7 +65,10 @@ export const upgradeReleaseController = async (options: {
}): Promise<{ commitSha: string; workspace: string }> => {
const commitSha = await options.workspaceManager.resolveCommit(options.sourceMode, options.sourceRef);
const workspace = await options.workspaceManager.prepare(commitSha);
const manifest = await readReleaseManifest(workspace.root);
// The target controller, rather than this bootstrap CLI, owns the target
// controller protocol. Keep all manifest/schema/component checks while
// allowing this explicit self-upgrade boundary to cross protocol versions.
const manifest = await readReleaseManifest(workspace.root, { allowControllerUpgrade: true });
assertReleaseComponents(manifest, ['release-controller']);
const build = await options.buildRunner.run(
buildReleaseControllerCommands(workspace.root, workspace.needsInstall, options.config)
+2
View File
@@ -204,6 +204,8 @@ release-controller가 `GatewayReleaseLog` 진행 로그를 저장하는 것이
로그 기능이 포함된 Gateway API/frontend만 먼저 배포하면 화면은 polling하지만
구형 controller는 로그를 만들 수 있으므로, protocol 변경 commit은 위
`self-upgrade`로 controller를 먼저 전환한 뒤 Gateway 배포를 요청해야 합니다.
명시적인 self-upgrade 경로만 다음 controller protocol의 manifest를 읽을 수 있고,
schema head·component 검사는 그대로 수행합니다.
## 운영 확인 목록