fix: support local D601 artifact deploy provider
This commit is contained in:
@@ -0,0 +1,46 @@
|
|||||||
|
import { readFileSync } from "node:fs";
|
||||||
|
|
||||||
|
function assertCondition(condition: unknown, message: string, detail: unknown = {}): void {
|
||||||
|
if (!condition) throw new Error(`${message}: ${JSON.stringify(detail)}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
const artifactRegistrySource = readFileSync("scripts/src/artifact-registry.ts", "utf8");
|
||||||
|
const deploySource = readFileSync("scripts/src/deploy.ts", "utf8");
|
||||||
|
|
||||||
|
assertCondition(
|
||||||
|
artifactRegistrySource.includes('function isLocalProvider(providerId: string): boolean'),
|
||||||
|
"artifact-registry must define an explicit local provider predicate",
|
||||||
|
);
|
||||||
|
assertCondition(
|
||||||
|
artifactRegistrySource.includes('providerId === "local"') && artifactRegistrySource.includes('providerId === "D601-local"'),
|
||||||
|
"local provider predicate must accept only explicit local aliases",
|
||||||
|
);
|
||||||
|
assertCondition(
|
||||||
|
artifactRegistrySource.includes('runCommand(["bash", "-lc", script], repoRoot, { timeoutMs })'),
|
||||||
|
"local provider must execute the generated artifact script directly with bash -lc",
|
||||||
|
);
|
||||||
|
assertCondition(
|
||||||
|
artifactRegistrySource.includes('local bash -lc <artifact-registry-${action}-readonly-script>'),
|
||||||
|
"readonly command shape must disclose local execution instead of host.ssh",
|
||||||
|
);
|
||||||
|
assertCondition(
|
||||||
|
deploySource.includes('providerId: string;'),
|
||||||
|
"deploy options must carry providerId for artifact consumers",
|
||||||
|
);
|
||||||
|
assertCondition(
|
||||||
|
deploySource.includes('providerId: optionValue(args, ["--provider-id", "--provider"]) ?? "D601"'),
|
||||||
|
"deploy apply must parse provider-id with D601 as the default",
|
||||||
|
);
|
||||||
|
assertCondition(
|
||||||
|
deploySource.includes('"--provider-id", options.providerId'),
|
||||||
|
"deploy apply must forward provider-id to artifact-registry deploy-service",
|
||||||
|
);
|
||||||
|
|
||||||
|
process.stdout.write(`${JSON.stringify({
|
||||||
|
ok: true,
|
||||||
|
checks: [
|
||||||
|
"artifact-registry supports an explicit local/D601-local provider for D601 host CLI execution",
|
||||||
|
"local provider runs the same generated scripts through bash -lc without provider SSH self-dispatch",
|
||||||
|
"deploy apply forwards --provider-id to artifact-registry consumers while defaulting to D601",
|
||||||
|
],
|
||||||
|
}, null, 2)}\n`);
|
||||||
@@ -1245,9 +1245,14 @@ function registryRecommendedAction(classification: ArtifactRegistryFailureClassi
|
|||||||
}
|
}
|
||||||
|
|
||||||
function readonlyRemoteCommandShape(action: "status" | "health", options: ArtifactRegistryOptions): string {
|
function readonlyRemoteCommandShape(action: "status" | "health", options: ArtifactRegistryOptions): string {
|
||||||
|
if (isLocalProvider(options.providerId)) return `local bash -lc <artifact-registry-${action}-readonly-script> timeoutMs=${options.timeoutMs}`;
|
||||||
return `host.ssh provider=${options.providerId} mode=exec argv=bash -lc <artifact-registry-${action}-readonly-script> timeoutMs=${options.timeoutMs}`;
|
return `host.ssh provider=${options.providerId} mode=exec argv=bash -lc <artifact-registry-${action}-readonly-script> timeoutMs=${options.timeoutMs}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function isLocalProvider(providerId: string): boolean {
|
||||||
|
return providerId === "local" || providerId === "D601-local";
|
||||||
|
}
|
||||||
|
|
||||||
function classifyProviderSshCommandFailure(command: CommandResult): ArtifactRegistryFailureClassification {
|
function classifyProviderSshCommandFailure(command: CommandResult): ArtifactRegistryFailureClassification {
|
||||||
const output = `${command.stderr}\n${command.stdout}`.toLowerCase();
|
const output = `${command.stderr}\n${command.stdout}`.toLowerCase();
|
||||||
if (command.timedOut || output.includes("timed out") || output.includes("timeout")) return "remote-command-timeout";
|
if (command.timedOut || output.includes("timed out") || output.includes("timeout")) return "remote-command-timeout";
|
||||||
@@ -1652,8 +1657,11 @@ function artifactRegistryDeployJsonMirrors(
|
|||||||
}
|
}
|
||||||
|
|
||||||
function runRemoteScript(options: ArtifactRegistryOptions, script: string, timeoutMs = options.timeoutMs, runtime: ArtifactRegistryCommandRuntime = {}): CommandResult {
|
function runRemoteScript(options: ArtifactRegistryOptions, script: string, timeoutMs = options.timeoutMs, runtime: ArtifactRegistryCommandRuntime = {}): CommandResult {
|
||||||
const command = [process.execPath, "scripts/cli.ts", "ssh", options.providerId, "argv", "bash", "-lc", script];
|
|
||||||
if (runtime.runRemoteScriptForTest !== undefined) return runtime.runRemoteScriptForTest(options, script, timeoutMs);
|
if (runtime.runRemoteScriptForTest !== undefined) return runtime.runRemoteScriptForTest(options, script, timeoutMs);
|
||||||
|
if (isLocalProvider(options.providerId)) {
|
||||||
|
return runCommand(["bash", "-lc", script], repoRoot, { timeoutMs });
|
||||||
|
}
|
||||||
|
const command = [process.execPath, "scripts/cli.ts", "ssh", options.providerId, "argv", "bash", "-lc", script];
|
||||||
return runCommand(command, repoRoot, { timeoutMs });
|
return runCommand(command, repoRoot, { timeoutMs });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -461,6 +461,7 @@ export async function runChecks(config: UniDeskConfig, options: CheckOptions = d
|
|||||||
fileItem("scripts/src/ci.ts"),
|
fileItem("scripts/src/ci.ts"),
|
||||||
fileItem("scripts/src/e2e.ts"),
|
fileItem("scripts/src/e2e.ts"),
|
||||||
fileItem("scripts/deploy-artifact-matrix-contract-test.ts"),
|
fileItem("scripts/deploy-artifact-matrix-contract-test.ts"),
|
||||||
|
fileItem("scripts/artifact-registry-local-provider-contract-test.ts"),
|
||||||
fileItem("scripts/decision-center-diary-summary-contract-test.ts"),
|
fileItem("scripts/decision-center-diary-summary-contract-test.ts"),
|
||||||
fileItem("scripts/decision-center-desired-state-contract-test.ts"),
|
fileItem("scripts/decision-center-desired-state-contract-test.ts"),
|
||||||
fileItem("scripts/code-queue-prompt-observation-test.ts"),
|
fileItem("scripts/code-queue-prompt-observation-test.ts"),
|
||||||
@@ -524,6 +525,7 @@ export async function runChecks(config: UniDeskConfig, options: CheckOptions = d
|
|||||||
items.push(await commandItem("provider:runner-triage-contract", ["bun", "scripts/provider-runner-triage-contract-test.ts"], 30_000, process.env, options.checkHeartbeatMs));
|
items.push(await commandItem("provider:runner-triage-contract", ["bun", "scripts/provider-runner-triage-contract-test.ts"], 30_000, process.env, options.checkHeartbeatMs));
|
||||||
items.push(await commandItem("ssh:argv-guidance-contract", ["bun", "scripts/ssh-argv-guidance-contract-test.ts"], 30_000, process.env, options.checkHeartbeatMs));
|
items.push(await commandItem("ssh:argv-guidance-contract", ["bun", "scripts/ssh-argv-guidance-contract-test.ts"], 30_000, process.env, options.checkHeartbeatMs));
|
||||||
items.push(await commandItem("deploy:artifact-matrix-contract", ["bun", "scripts/deploy-artifact-matrix-contract-test.ts"], 90_000, process.env, options.checkHeartbeatMs));
|
items.push(await commandItem("deploy:artifact-matrix-contract", ["bun", "scripts/deploy-artifact-matrix-contract-test.ts"], 90_000, process.env, options.checkHeartbeatMs));
|
||||||
|
items.push(await commandItem("artifact-registry:local-provider-contract", ["bun", "scripts/artifact-registry-local-provider-contract-test.ts"], 30_000, process.env, options.checkHeartbeatMs));
|
||||||
items.push(await commandItem("decision-center:diary-summary-contract", ["bun", "scripts/decision-center-diary-summary-contract-test.ts"], 30_000, process.env, options.checkHeartbeatMs));
|
items.push(await commandItem("decision-center:diary-summary-contract", ["bun", "scripts/decision-center-diary-summary-contract-test.ts"], 30_000, process.env, options.checkHeartbeatMs));
|
||||||
items.push(await commandItem("decision-center:desired-state-contract", ["bun", "scripts/decision-center-desired-state-contract-test.ts"], 30_000, process.env, options.checkHeartbeatMs));
|
items.push(await commandItem("decision-center:desired-state-contract", ["bun", "scripts/decision-center-desired-state-contract-test.ts"], 30_000, process.env, options.checkHeartbeatMs));
|
||||||
items.push(await commandItem("code-queue:active-run-heartbeat-visible", ["bun", "scripts/code-queue-liveness-diagnostics-test.ts", "--only", "code-queue:active-run-heartbeat-visible"], 30_000, process.env, options.checkHeartbeatMs));
|
items.push(await commandItem("code-queue:active-run-heartbeat-visible", ["bun", "scripts/code-queue-liveness-diagnostics-test.ts", "--only", "code-queue:active-run-heartbeat-visible"], 30_000, process.env, options.checkHeartbeatMs));
|
||||||
@@ -574,6 +576,7 @@ export async function runChecks(config: UniDeskConfig, options: CheckOptions = d
|
|||||||
items.push(skippedItem("provider:runner-triage-contract", "Provider runner triage contract is opt-in with script checks", "--scripts-typecheck or --full"));
|
items.push(skippedItem("provider:runner-triage-contract", "Provider runner triage contract is opt-in with script checks", "--scripts-typecheck or --full"));
|
||||||
items.push(skippedItem("ssh:argv-guidance-contract", "SSH argv guidance and failure hint contract is opt-in with script checks", "--scripts-typecheck or --full"));
|
items.push(skippedItem("ssh:argv-guidance-contract", "SSH argv guidance and failure hint contract is opt-in with script checks", "--scripts-typecheck or --full"));
|
||||||
items.push(skippedItem("deploy:artifact-matrix-contract", "deploy artifact matrix contract is opt-in with script checks", "--scripts-typecheck or --full"));
|
items.push(skippedItem("deploy:artifact-matrix-contract", "deploy artifact matrix contract is opt-in with script checks", "--scripts-typecheck or --full"));
|
||||||
|
items.push(skippedItem("artifact-registry:local-provider-contract", "artifact registry local provider contract is opt-in with script checks", "--scripts-typecheck or --full"));
|
||||||
items.push(skippedItem("decision-center:diary-summary-contract", "Decision Center diary summary contract is opt-in with script checks", "--scripts-typecheck or --full"));
|
items.push(skippedItem("decision-center:diary-summary-contract", "Decision Center diary summary contract is opt-in with script checks", "--scripts-typecheck or --full"));
|
||||||
items.push(skippedItem("decision-center:desired-state-contract", "Decision Center desired-state drift contract is opt-in with script checks", "--scripts-typecheck or --full"));
|
items.push(skippedItem("decision-center:desired-state-contract", "Decision Center desired-state drift contract is opt-in with script checks", "--scripts-typecheck or --full"));
|
||||||
items.push(skippedItem("code-queue:liveness-diagnostics-fixtures", "Code Queue liveness diagnostics fixtures are opt-in with script checks", "--scripts-typecheck or --full"));
|
items.push(skippedItem("code-queue:liveness-diagnostics-fixtures", "Code Queue liveness diagnostics fixtures are opt-in with script checks", "--scripts-typecheck or --full"));
|
||||||
|
|||||||
@@ -40,6 +40,7 @@ interface DeployOptions {
|
|||||||
environment: DeployEnvironment | null;
|
environment: DeployEnvironment | null;
|
||||||
serviceId: string | null;
|
serviceId: string | null;
|
||||||
commitOverride: string | null;
|
commitOverride: string | null;
|
||||||
|
providerId: string;
|
||||||
runNow: boolean;
|
runNow: boolean;
|
||||||
dryRun: boolean;
|
dryRun: boolean;
|
||||||
force: boolean;
|
force: boolean;
|
||||||
@@ -221,7 +222,7 @@ export function deployHelp(action: string | undefined = undefined): Record<strin
|
|||||||
usage: {
|
usage: {
|
||||||
check: "bun scripts/cli.ts deploy check [--file deploy.json | --env dev|prod] [--service id]",
|
check: "bun scripts/cli.ts deploy check [--file deploy.json | --env dev|prod] [--service id]",
|
||||||
plan: "bun scripts/cli.ts deploy plan [--file deploy.json | --env dev|prod] [--service id]",
|
plan: "bun scripts/cli.ts deploy plan [--file deploy.json | --env dev|prod] [--service id]",
|
||||||
apply: "bun scripts/cli.ts deploy apply [--file deploy.json | --env dev|prod] [--service id] [--commit full-sha] [--dry-run] [--force] [--timeout-ms N] [--run-now]",
|
apply: "bun scripts/cli.ts deploy apply [--file deploy.json | --env dev|prod] [--service id] [--commit full-sha] [--dry-run] [--force] [--timeout-ms N] [--provider-id D601|local] [--run-now]",
|
||||||
guard: "bun scripts/cli.ts deploy guard code-queue-source [--root /home/ubuntu/cq-deploy]",
|
guard: "bun scripts/cli.ts deploy guard code-queue-source [--root /home/ubuntu/cq-deploy]",
|
||||||
},
|
},
|
||||||
actions: {
|
actions: {
|
||||||
@@ -244,6 +245,7 @@ export function deployHelp(action: string | undefined = undefined): Record<strin
|
|||||||
{ name: "--dry-run", description: "Prepare and validate without mutating the target service." },
|
{ name: "--dry-run", description: "Prepare and validate without mutating the target service." },
|
||||||
{ name: "--force", description: "Redeploy even when the live commit appears up to date." },
|
{ name: "--force", description: "Redeploy even when the live commit appears up to date." },
|
||||||
{ name: "--timeout-ms <n>", default: defaultTimeoutMs, description: "Per-step timeout budget where supported." },
|
{ name: "--timeout-ms <n>", default: defaultTimeoutMs, description: "Per-step timeout budget where supported." },
|
||||||
|
{ name: "--provider-id <id>", default: "D601", description: "Provider used by artifact-registry consumers; use local only from the D601 host CLI." },
|
||||||
{ name: "--run-now", description: "Run apply in the foreground worker process; omit it for fire-and-forget async job mode." },
|
{ name: "--run-now", description: "Run apply in the foreground worker process; omit it for fire-and-forget async job mode." },
|
||||||
{ name: "guard code-queue-source --root <path>", description: "Validate Code Queue hostPath source relative imports before any scheduler rollout; failures report degradedReason and missing import targets." },
|
{ name: "guard code-queue-source --root <path>", description: "Validate Code Queue hostPath source relative imports before any scheduler rollout; failures report degradedReason and missing import targets." },
|
||||||
],
|
],
|
||||||
@@ -523,6 +525,7 @@ function parseOptions(args: string[]): DeployOptions {
|
|||||||
environment,
|
environment,
|
||||||
serviceId,
|
serviceId,
|
||||||
commitOverride: commitOverride?.toLowerCase() ?? null,
|
commitOverride: commitOverride?.toLowerCase() ?? null,
|
||||||
|
providerId: optionValue(args, ["--provider-id", "--provider"]) ?? "D601",
|
||||||
runNow: args.includes("--run-now"),
|
runNow: args.includes("--run-now"),
|
||||||
dryRun: args.includes("--dry-run"),
|
dryRun: args.includes("--dry-run"),
|
||||||
force: args.includes("--force"),
|
force: args.includes("--force"),
|
||||||
@@ -2882,6 +2885,7 @@ async function runDevArtifactConsumerService(
|
|||||||
"--commit", commit,
|
"--commit", commit,
|
||||||
"--source-repo", desired.repo,
|
"--source-repo", desired.repo,
|
||||||
"--timeout-ms", String(options.timeoutMs),
|
"--timeout-ms", String(options.timeoutMs),
|
||||||
|
"--provider-id", options.providerId,
|
||||||
"--run-now",
|
"--run-now",
|
||||||
...(options.dryRun ? ["--dry-run"] : []),
|
...(options.dryRun ? ["--dry-run"] : []),
|
||||||
];
|
];
|
||||||
@@ -3404,6 +3408,7 @@ async function runArtifactConsumerApplyNow(
|
|||||||
...(options.dryRun && hasDeployJsonExecutorContract(service) ? ["--deploy-json-service", encodeDeployJsonServiceContract(service)] : []),
|
...(options.dryRun && hasDeployJsonExecutorContract(service) ? ["--deploy-json-service", encodeDeployJsonServiceContract(service)] : []),
|
||||||
"--env", environment,
|
"--env", environment,
|
||||||
"--timeout-ms", String(options.timeoutMs),
|
"--timeout-ms", String(options.timeoutMs),
|
||||||
|
"--provider-id", options.providerId,
|
||||||
"--run-now",
|
"--run-now",
|
||||||
...(options.dryRun ? ["--dry-run"] : []),
|
...(options.dryRun ? ["--dry-run"] : []),
|
||||||
];
|
];
|
||||||
|
|||||||
Reference in New Issue
Block a user