fix: preserve PK01 Caddy host blocks

This commit is contained in:
Codex
2026-07-01 14:05:43 +00:00
parent e15c4eeac9
commit aec4151a5d
2 changed files with 102 additions and 2 deletions
+91
View File
@@ -0,0 +1,91 @@
import assert from "node:assert/strict";
import { spawnSync } from "node:child_process";
import { mkdtempSync, readFileSync, rmSync, writeFileSync } from "node:fs";
import { tmpdir } from "node:os";
import { join } from "node:path";
import { test } from "bun:test";
import { pk01CaddyMergeManagedBlocksPython } from "./pk01-caddy";
function mergeCaddyfiles(current: string, desired: string, legacyDomains: readonly string[] = []): { merged: string; summary: Record<string, unknown> } {
const dir = mkdtempSync(join(tmpdir(), "pk01-caddy-"));
try {
const currentPath = join(dir, "current.Caddyfile");
const desiredPath = join(dir, "desired.Caddyfile");
const mergedPath = join(dir, "merged.Caddyfile");
writeFileSync(currentPath, current, "utf8");
writeFileSync(desiredPath, desired, "utf8");
const result = spawnSync("python3", ["-", desiredPath, currentPath, mergedPath, ...legacyDomains], {
encoding: "utf8",
input: pk01CaddyMergeManagedBlocksPython(),
});
assert.equal(result.status, 0, result.stderr || result.stdout);
return {
merged: readFileSync(mergedPath, "utf8"),
summary: JSON.parse(result.stdout) as Record<string, unknown>,
};
} finally {
rmSync(dir, { recursive: true, force: true });
}
}
test("PK01 Caddy merge preserves monitor root nested managed block", () => {
const current = `{
email ops@pikapython.com
}
pikapython.com, www.pikapython.com {
reverse_proxy 127.0.0.1:18888
}
api2.pikapython.com {
reverse_proxy 127.0.0.1:18080
}
# BEGIN unidesk managed langbot
langbot.pikapython.com {
reverse_proxy 127.0.0.1:22097
}
# END unidesk managed langbot
# BEGIN unidesk managed sub2api-jd01
api2.pikapython.com {
reverse_proxy 127.0.0.1:22080
}
# END unidesk managed sub2api-jd01
monitor.pikapython.com {
# BEGIN unidesk managed hwlab-web-probe-sentinel-active-root
handle {
reverse_proxy 127.0.0.1:22098
}
# END unidesk managed hwlab-web-probe-sentinel-active-root
}
`;
const desired = `{
email ops@pikapython.com
}
pikapython.com, www.pikapython.com {
reverse_proxy 127.0.0.1:18888
}
# BEGIN unidesk managed sub2api-jd01
api2.pikapython.com {
reverse_proxy 127.0.0.1:22087
}
# END unidesk managed sub2api-jd01
`;
const { merged, summary } = mergeCaddyfiles(current, desired, ["api2.pikapython.com"]);
assert.equal(summary.baseSource, "current");
assert.match(merged, /monitor\.pikapython\.com \{/u);
assert.match(merged, /hwlab-web-probe-sentinel-active-root/u);
assert.match(merged, /reverse_proxy 127\.0\.0\.1:22098/u);
assert.match(merged, /# BEGIN unidesk managed langbot/u);
assert.match(merged, /# BEGIN unidesk managed sub2api-jd01[\s\S]*127\.0\.0\.1:22087/u);
assert.doesNotMatch(merged, /127\.0\.0\.1:22080/u);
assert.doesNotMatch(merged, /127\.0\.0\.1:18080/u);
});
+11 -2
View File
@@ -367,7 +367,10 @@ for source in (current, desired):
order.append(name)
blocks[name] = match.group(0).rstrip() + "\n"
base = pattern.sub("", desired)
# Preserve host-owned site blocks and nested managed blocks from the active
# Caddyfile; service-specific applies should only upsert top-level blocks.
base_source = "current" if current.strip() else "desired"
base = pattern.sub("", current if base_source == "current" else desired)
for domain in legacy_domains:
base = remove_site_blocks(base, domain)
base = base.rstrip()
@@ -376,7 +379,13 @@ next_text = base
if managed:
next_text = next_text + "\n\n" + managed
merged_path.write_text(next_text.rstrip() + "\n", encoding="utf-8")
print(json.dumps({"currentManagedBlocks": len(pattern.findall(current)), "desiredManagedBlocks": len(pattern.findall(desired)), "mergedManagedBlocks": len(blocks)}))`;
print(json.dumps({
"baseSource": base_source,
"legacyDomains": legacy_domains,
"currentManagedBlocks": len(pattern.findall(current)),
"desiredManagedBlocks": len(pattern.findall(desired)),
"mergedManagedBlocks": len(blocks),
}))`;
}
function managedBlockPattern(): RegExp {