fix: remoteize backend-core publish preflight

This commit is contained in:
Codex
2026-05-21 10:08:56 +00:00
parent b69c2fe599
commit 1749897d1a
3 changed files with 535 additions and 88 deletions
+32 -29
View File
@@ -11,7 +11,7 @@ import {
buildArtifactRegistryReadonlyProbe,
parseArtifactRegistryOptions,
} from "./artifact-registry";
import { runCiPublishUserServiceDryRunPreflight } from "./ci";
import { runCiPublishBackendCoreDryRunPreflight, runCiPublishUserServiceDryRunPreflight } from "./ci";
export interface RemoteCliOptions {
host: string | null;
@@ -109,9 +109,9 @@ export function autoRemoteCiPublishUserServiceDryRunPlan(
env: NodeJS.ProcessEnv = process.env,
): AutoRemoteCiPublishPlan {
const [top, sub] = args;
const isPublishDryRun = top === "ci" && sub === "publish-user-service" && args.includes("--dry-run");
const isPublishDryRun = top === "ci" && (sub === "publish-user-service" || sub === "publish-backend-core") && args.includes("--dry-run");
if (!isPublishDryRun) {
return { enabled: false, host: null, reason: "not ci publish-user-service --dry-run", failureClassification: null, transport: "frontend", command: null };
return { enabled: false, host: null, reason: "not ci publish-user-service/publish-backend-core --dry-run", failureClassification: null, transport: "frontend", command: null };
}
if (truthyDisabled(env.UNIDESK_CI_PUBLISH_AUTO_REMOTE)) {
return { enabled: false, host: null, reason: "UNIDESK_CI_PUBLISH_AUTO_REMOTE disables automatic remote preflight", failureClassification: "local-docker-required", transport: "frontend", command: null };
@@ -721,36 +721,39 @@ async function remoteArtifactRegistry(session: FrontendSession, args: string[]):
async function remoteCi(session: FrontendSession, config: UniDeskConfig, args: string[]): Promise<unknown> {
const action = args[1] ?? "status";
if (action !== "publish-user-service" || !args.includes("--dry-run")) {
throw new Error("remote frontend transport supports only ci publish-user-service --dry-run preflight; real CI publication must run from the controlled main-server CLI after preflight is ready");
if ((action !== "publish-user-service" && action !== "publish-backend-core") || !args.includes("--dry-run")) {
throw new Error("remote frontend transport supports only ci publish-user-service --dry-run and ci publish-backend-core --dry-run preflight; real CI publication must run from the controlled main-server CLI after preflight is ready");
}
const transport = {
kind: "remote-frontend" as const,
remoteHost: session.baseUrl,
coreFetch: (path: string, init?: { method?: string; body?: unknown; maxResponseBytes?: number }) => frontendJson(session, path, init === undefined ? undefined : {
method: init.method,
body: init.body === undefined ? undefined : JSON.stringify(init.body),
}, 12_000, init?.maxResponseBytes ?? 500_000),
dispatchHostSsh: async (command: string, waitMs: number, remoteTimeoutMs: number) => {
const dispatched = await dispatchHostSshJson(session, "D601", command, remoteTimeoutMs, waitMs);
const task = dispatched.task;
const result = task?.result ?? {};
return {
ok: task?.status === "succeeded" && (typeof result.exitCode !== "number" || result.exitCode === 0) && dispatched.taskId !== null,
taskId: dispatched.taskId,
status: task?.status ?? null,
stdout: typeof result.stdout === "string" ? result.stdout : "",
stderr: typeof result.stderr === "string" ? result.stderr : "",
exitCode: typeof result.exitCode === "number" ? result.exitCode : null,
raw: task ?? dispatched.wait ?? dispatched.dispatch,
};
},
commandCwd: ".",
artifactRegistryCommand: (probe: ReturnType<typeof buildArtifactRegistryReadonlyProbe>) => ["frontend", "/api/dispatch", probe.providerId, "host.ssh", probe.action, dispatchedTaskShape(probe.remoteCommandShape)],
};
return {
transport: "frontend",
readonly: true,
result: await runCiPublishUserServiceDryRunPreflight(config, args.slice(1), {
kind: "remote-frontend",
remoteHost: session.baseUrl,
coreFetch: (path, init) => frontendJson(session, path, init === undefined ? undefined : {
method: init.method,
body: init.body === undefined ? undefined : JSON.stringify(init.body),
}, 12_000, init?.maxResponseBytes ?? 500_000),
dispatchHostSsh: async (command, waitMs, remoteTimeoutMs) => {
const dispatched = await dispatchHostSshJson(session, "D601", command, remoteTimeoutMs, waitMs);
const task = dispatched.task;
const result = task?.result ?? {};
return {
ok: task?.status === "succeeded" && (typeof result.exitCode !== "number" || result.exitCode === 0) && dispatched.taskId !== null,
taskId: dispatched.taskId,
status: task?.status ?? null,
stdout: typeof result.stdout === "string" ? result.stdout : "",
stderr: typeof result.stderr === "string" ? result.stderr : "",
exitCode: typeof result.exitCode === "number" ? result.exitCode : null,
raw: task ?? dispatched.wait ?? dispatched.dispatch,
};
},
commandCwd: ".",
artifactRegistryCommand: (probe) => ["frontend", "/api/dispatch", probe.providerId, "host.ssh", probe.action, dispatchedTaskShape(probe.remoteCommandShape)],
}),
result: action === "publish-backend-core"
? await runCiPublishBackendCoreDryRunPreflight(config, args.slice(1), transport)
: await runCiPublishUserServiceDryRunPreflight(config, args.slice(1), transport),
};
}