fix(deploy): replace both legacy and CI containers during cutover
CI / check (push) Successful in 1m0s
CI / deploy (push) Successful in 1m17s

This commit is contained in:
Simo committed 2026-09-07 21:40:26 +02:00
1 parent 6cbcb50191
commit fe1ee8a6fe
2 files changed
+51 -5

No files matched your search

+33 -1
View File
@@ -24,12 +24,17 @@ const bash =
.find((path) => existsSync(path)) ?? "bash")
: "bash";
const sha = "a".repeat(40);
function simulate(scenario: string, previous = "epicnext-cms-app") {
function simulate(
scenario: string,
previous = "epicnext-cms-app",
both = false,
) {
const dir = mkdtempSync(join(tmpdir(), "cms-deploy-test-"));
try {
mkdirSync(join(dir, "production"));
writeFileSync(join(dir, "production", ".env"), 'HOTEL_NAME="Test Hotel"\n');
if (previous) writeFileSync(join(dir, previous), "old\n");
if (both) writeFileSync(join(dir, "epicnext-cms-app"), "old\n");
const result = spawnSync(bash, [resolve(root, "scripts/ci-deploy.sh")], {
cwd: dir,
encoding: "utf8",
@@ -56,6 +61,7 @@ function simulate(scenario: string, previous = "epicnext-cms-app") {
: null,
previousRestored: previous ? existsSync(join(dir, previous)) : false,
backup: existsSync(join(dir, "epicnext-cms-rollback")),
secondaryBackup: existsSync(join(dir, "epicnext-cms-rollback-secondary")),
};
} finally {
rmSync(dir, { recursive: true, force: true });
@@ -133,3 +139,29 @@ describe("deployment transaction", () => {
expect(result.app).toBeNull();
});
});
describe("legacy and CI container coexistence", () => {
it("stops and preserves both before starting the candidate, then removes backups only after verification", () => {
const r = simulate("success", "epicnext-cms", true);
expect(r.status, r.output).toBe(0);
expect(r.calls).toContain("docker stop epicnext-cms-app");
expect(r.calls).toContain("docker stop epicnext-cms\n");
expect(r.calls.indexOf("docker stop epicnext-cms\n")).toBeLessThan(
r.calls.indexOf("docker run"),
);
expect(r.calls.indexOf("docker stop epicnext-cms-app")).toBeLessThan(
r.calls.indexOf("docker run"),
);
expect(r.backup).toBe(false);
expect(r.secondaryBackup).toBe(false);
expect(r.app).toBe("new");
});
it("restores both original containers when candidate release validation fails", () => {
const r = simulate("release-failure", "epicnext-cms", true);
expect(r.status, r.output).not.toBe(0);
expect(r.previousRestored).toBe(true);
expect(r.app).toBe("old");
expect(r.secondaryBackup).toBe(false);
expect(r.calls).toContain("docker start epicnext-cms");
});
});