fix: preserve PK01 Caddy managed blocks

This commit is contained in:
Codex
2026-06-13 14:04:10 +00:00
parent 5574150c64
commit 153ffb4c47
6 changed files with 467 additions and 301 deletions
+10 -48
View File
@@ -4,6 +4,7 @@ import { join } from "node:path";
import { spawnSync } from "node:child_process";
import { rootPath, type UniDeskConfig } from "./config";
import type { RenderedCliResult } from "./output";
import { applyLocalCaddyManagedSite } from "./pk01-caddy";
import { runSshCommandCapture, type SshCaptureResult } from "./ssh";
import { runRemoteSshCommandCapture } from "./remote";
import { startJob } from "./jobs";
@@ -2506,37 +2507,20 @@ function applyAgentRunMasterCaddySite(exposure: AgentRunPublicExposure): Record<
if (!caddy.enabled) return { ok: true, action: "disabled-by-yaml", valuesPrinted: false };
const pathValue = caddy.configPath;
if (!existsSync(pathValue)) return { ok: false, error: "master-caddy-config-missing", path: pathValue, valuesPrinted: false };
const before = readFileSync(pathValue, "utf8");
const desiredBlock = renderAgentRunCaddySiteBlock(caddy.domain, caddy.upstreamBaseUrl, caddy.responseHeaderTimeoutSeconds);
const existing = caddySiteBlock(before, caddy.domain);
const alreadyConfigured = existing === desiredBlock;
let backupPath: string | null = null;
let action = "kept-existing";
if (!alreadyConfigured) {
const stamp = new Date().toISOString().replace(/[-:]/gu, "").replace(/\..*$/u, "Z");
backupPath = `${pathValue}.bak-agentrun-https-${stamp}`;
copyFileSync(pathValue, backupPath);
const next = existing === null ? `${before.replace(/\s*$/u, "")}\n\n${desiredBlock}\n` : before.replace(existing, desiredBlock);
writeFileSync(pathValue, next, "utf8");
chmodSync(pathValue, statSync(backupPath).mode & 0o777);
action = existing === null ? "added-site" : "updated-site";
}
const validate = spawnSync("caddy", ["validate", "--config", pathValue, "--adapter", "caddyfile"], { encoding: "utf8" });
const reload = validate.status === 0 && !alreadyConfigured ? spawnSync("systemctl", ["reload", caddy.serviceName], { encoding: "utf8" }) : null;
const active = spawnSync("systemctl", ["is-active", caddy.serviceName], { encoding: "utf8" });
const ok = validate.status === 0 && (reload === null || reload.status === 0) && active.status === 0 && String(active.stdout).trim() === "active";
const applied = applyLocalCaddyManagedSite({
serviceId: "agentrun",
markerName: "agentrun",
configPath: pathValue,
serviceName: caddy.serviceName,
siteBlock: desiredBlock,
legacySiteDomain: caddy.domain,
});
return {
ok,
action,
path: pathValue,
backupPath,
...applied,
domain: caddy.domain,
upstreamBaseUrl: caddy.upstreamBaseUrl,
serviceName: caddy.serviceName,
responseHeaderTimeoutSeconds: caddy.responseHeaderTimeoutSeconds,
validate: { exitCode: validate.status, stdoutTail: String(validate.stdout).slice(-1000), stderrTail: String(validate.stderr).slice(-2000) },
reload: reload === null ? null : { exitCode: reload.status, stdoutTail: String(reload.stdout).slice(-1000), stderrTail: String(reload.stderr).slice(-1000) },
active: { exitCode: active.status, stdoutTail: String(active.stdout).slice(-1000), stderrTail: String(active.stderr).slice(-1000) },
valuesPrinted: false,
};
}
@@ -2557,24 +2541,6 @@ function renderAgentRunCaddySiteBlock(domain: string, upstreamBaseUrl: string, r
}`;
}
function caddySiteBlock(text: string, domain: string): string | null {
const startMatch = new RegExp(`(^|\\n)${escapeRegExp(domain)}\\s*\\{`, "u").exec(text);
if (startMatch === null) return null;
const start = startMatch.index + (startMatch[1] === "\n" ? 1 : 0);
const open = text.indexOf("{", start);
if (open < 0) return null;
let depth = 0;
for (let index = open; index < text.length; index += 1) {
const ch = text[index];
if (ch === "{") depth += 1;
if (ch === "}") {
depth -= 1;
if (depth === 0) return text.slice(start, index + 1);
}
}
return null;
}
function frpsAllowPortExists(toml: string, port: number): boolean {
const sections = toml.split(/(?=\[\[allowPorts\]\])/u);
return sections.some((section) => {
@@ -2585,10 +2551,6 @@ function frpsAllowPortExists(toml: string, port: number): boolean {
});
}
function escapeRegExp(value: string): string {
return value.replace(/[.*+?^${}()|[\]\\]/gu, "\\$&");
}
async function triggerCurrent(config: UniDeskConfig, options: TriggerOptions): Promise<Record<string, unknown>> {
if (options.node !== null || options.lane !== null) {
const target = resolveAgentRunLaneTarget(options);