edfddd2445
* docs: specify cicd yaml target governance * fix: resolve cicd targets from yaml --------- Co-authored-by: Codex <codex@noreply.local>
192 lines
13 KiB
TypeScript
192 lines
13 KiB
TypeScript
// SPEC: PJ2026-01060307 控制面模块化 draft-2026-06-25-p0. entry module for scripts/src/artifact-registry.ts.
|
|
// SPEC: PJ2026-01060308 cicd-yaml-targets draft-2026-06-25-cicd-yaml-targets.
|
|
|
|
// Moved mechanically from scripts/src/artifact-registry.ts:3448-3700 for #903.
|
|
|
|
import { createHash } from "node:crypto";
|
|
import { existsSync, readFileSync, rmSync, writeFileSync } from "node:fs";
|
|
import { join } from "node:path";
|
|
import { runCommand, type CommandResult } from "../command";
|
|
import { readConfig, type UniDeskConfig, repoRoot, rootPath } from "../config";
|
|
import { startJob } from "../jobs";
|
|
import {
|
|
compareDeployJsonExecutorMirrors,
|
|
deployJsonCommitImage,
|
|
deployJsonDriftResult,
|
|
deployJsonSourceOfTruth,
|
|
hasDeployJsonExecutorContract,
|
|
k3sManifestExecutorMirror,
|
|
parseDeployJsonServiceContractBase64,
|
|
readDeployJsonServiceContractFromFile,
|
|
type DeployJsonExecutorMirror,
|
|
type DeployJsonServiceContract,
|
|
} from "../deploy-json-contract";
|
|
import { d601K3sGuardShellLines } from "../d601-k3s-guard";
|
|
import { composeRuntimeEnvValue } from "../runtime-env";
|
|
|
|
import type { ArtifactRegistryAction, ArtifactRegistryCommandRuntime, ArtifactRegistryOptions } from "./types";
|
|
import { renderBundle } from "./bundle";
|
|
import { deployBackendCoreJob, deployBackendCoreNow, deployComposeArtifactNow, deployD601ComposeArtifactNow, dryRunArtifactConsumerPlan, legacyDeployBackendCoreResult } from "./compose-deploy";
|
|
import { artifactConsumerLiveBlock, artifactConsumerSpec, artifactConsumerTarget, supportedArtifactConsumers, unsupportedEnvironment, unsupportedService } from "./consumer";
|
|
import { install, installDryRun } from "./install";
|
|
import { deployD601K3sArtifactNow, rollbackInfo } from "./k3s-deploy";
|
|
import { isHelpArg, parseArtifactRegistryOptions } from "./options";
|
|
import { runReadonlyStatusWithRemoteFallback } from "./readonly";
|
|
import { plan } from "./status";
|
|
import { defaultOptions, legacyDeployBackendCoreDisabled, supportedArtifactConsumerServices } from "./types";
|
|
|
|
export async function deployServiceNow(options: ArtifactRegistryOptions): Promise<Record<string, unknown>> {
|
|
if (options.serviceId === null) throw new Error("artifact-registry deploy-service requires --service <id>");
|
|
if (options.commit === null) throw new Error("artifact-registry deploy-service requires --commit <full-sha>");
|
|
const spec = artifactConsumerSpec(options.serviceId, options.environment);
|
|
if (spec === null) return unsupportedService(options.serviceId, options);
|
|
const target = artifactConsumerTarget(spec, options.environment);
|
|
if (target === null) return unsupportedEnvironment(spec, options);
|
|
if (options.dryRun) return dryRunArtifactConsumerPlan(options, spec, target, options.commit);
|
|
const liveBlock = artifactConsumerLiveBlock(spec, options);
|
|
if (liveBlock !== null) return liveBlock;
|
|
if (spec.kind === "compose") return deployComposeArtifactNow(options, spec, target);
|
|
if (spec.kind === "d601-compose") return deployD601ComposeArtifactNow(options, spec, target);
|
|
return deployD601K3sArtifactNow(options, spec, target);
|
|
}
|
|
|
|
export function deployServiceJob(args: string[], options: ArtifactRegistryOptions): Record<string, unknown> {
|
|
if (options.serviceId === null) throw new Error("artifact-registry deploy-service requires --service <id>");
|
|
if (options.commit === null) throw new Error("artifact-registry deploy-service requires --commit <full-sha>");
|
|
const spec = artifactConsumerSpec(options.serviceId, options.environment);
|
|
if (spec === null) return unsupportedService(options.serviceId, options);
|
|
const target = artifactConsumerTarget(spec, options.environment);
|
|
if (target === null) return unsupportedEnvironment(spec, options);
|
|
if (options.dryRun) return dryRunArtifactConsumerPlan(options, spec, target, options.commit);
|
|
const liveBlock = artifactConsumerLiveBlock(spec, options);
|
|
if (liveBlock !== null) return liveBlock;
|
|
const runArgs = args.includes("--run-now") ? args : [...args, "--run-now"];
|
|
const command = [process.execPath, rootPath("scripts", "cli.ts"), "artifact-registry", ...runArgs];
|
|
const job = startJob("artifact_registry_service_cd", command, `Pull and deploy ${options.environment ?? "prod"} ${options.serviceId} artifact ${options.commit} from D601 registry`);
|
|
return {
|
|
ok: true,
|
|
mode: "async-job",
|
|
serviceId: options.serviceId,
|
|
environment: options.environment ?? "prod",
|
|
job,
|
|
statusCommand: `bun scripts/cli.ts job status ${job.id}`,
|
|
tailCommand: `bun scripts/cli.ts job status ${job.id} --tail-bytes 30000`,
|
|
note: "User-service CD continues in the background: D601 registry health, commit-pinned artifact check, pull/import, rollout, image-label and live health commit verification.",
|
|
rollback: rollbackInfo(spec, target, options.environment ?? "prod", options.commit),
|
|
};
|
|
}
|
|
|
|
export function serviceIdFromDeployBackendCoreArgs(action: ArtifactRegistryAction, options: ArtifactRegistryOptions): string | null {
|
|
return action === "deploy-backend-core" ? "backend-core" : options.serviceId;
|
|
}
|
|
|
|
export function localHelp(): Record<string, unknown> {
|
|
return {
|
|
ok: true,
|
|
command: "artifact-registry plan|render|status|health|install|deploy-backend-core|deploy-service",
|
|
output: "json",
|
|
usage: [
|
|
"bun scripts/cli.ts artifact-registry plan [--target D601]",
|
|
"bun scripts/cli.ts artifact-registry render [--target D601]",
|
|
"bun scripts/cli.ts artifact-registry status [--target D601]",
|
|
"bun scripts/cli.ts artifact-registry health [--target D601]",
|
|
"bun scripts/cli.ts artifact-registry install [--target D601]",
|
|
"bun scripts/cli.ts artifact-registry deploy-service --service baidu-netdisk --commit <full-sha> [--dry-run] [--run-now] [--target D601]",
|
|
"bun scripts/cli.ts artifact-registry deploy-service --service frontend --env prod --commit <full-sha> [--dry-run] [--run-now] [--target D601]",
|
|
"bun scripts/cli.ts artifact-registry deploy-service --service frontend --env dev --commit <full-sha> [--dry-run] [--run-now] [--target D601]",
|
|
"bun scripts/cli.ts artifact-registry deploy-service --env dev --service decision-center --commit <full-sha> [--dry-run] [--run-now] [--target D601]",
|
|
"bun scripts/cli.ts artifact-registry deploy-service --env prod --service decision-center --commit <full-sha> [--dry-run] [--run-now] [--target D601]",
|
|
"bun scripts/cli.ts artifact-registry deploy-service --env prod --service project-manager --commit <full-sha> [--dry-run] [--run-now] [--target D601]",
|
|
"bun scripts/cli.ts artifact-registry deploy-service --env prod --service oa-event-flow --commit <full-sha> [--dry-run] [--run-now] [--target D601]",
|
|
"bun scripts/cli.ts artifact-registry deploy-service --env prod --service code-queue-mgr --commit <full-sha> --dry-run [--target D601]",
|
|
"bun scripts/cli.ts artifact-registry deploy-service --env prod --service todo-note --commit <full-sha> [--dry-run] [--run-now] [--target D601]",
|
|
"bun scripts/cli.ts artifact-registry deploy-service --env dev --service todo-note --commit <full-sha> [--dry-run] [--run-now] [--target D601]",
|
|
"bun scripts/cli.ts artifact-registry deploy-service --env dev --service findjob --commit <full-sha> [--dry-run] [--run-now] [--target D601]",
|
|
"bun scripts/cli.ts artifact-registry deploy-service --env prod --service findjob --commit <full-sha> [--dry-run] [--run-now] [--target D601]",
|
|
"bun scripts/cli.ts artifact-registry deploy-service --env dev --service pipeline --commit <full-sha> [--dry-run] [--run-now] [--target D601]",
|
|
"bun scripts/cli.ts artifact-registry deploy-service --env prod --service pipeline --commit <full-sha> [--dry-run] [--run-now] [--target D601]",
|
|
"bun scripts/cli.ts artifact-registry deploy-service --env dev --service met-nonlinear --commit <full-sha> --dry-run [--target D601]",
|
|
"bun scripts/cli.ts artifact-registry deploy-service --env prod --service met-nonlinear --commit <full-sha> --dry-run [--target D601]",
|
|
"bun scripts/cli.ts artifact-registry deploy-service --env prod --service k3sctl-adapter --commit <full-sha> --dry-run [--target D601]",
|
|
"bun scripts/cli.ts artifact-registry deploy-service --env dev --service mdtodo --commit <full-sha> [--dry-run] [--run-now] [--target D601]",
|
|
"bun scripts/cli.ts artifact-registry deploy-service --env prod --service mdtodo --commit <full-sha> [--dry-run] [--run-now] [--target D601]",
|
|
"bun scripts/cli.ts artifact-registry deploy-service --env dev --service claudeqq --commit <full-sha> [--dry-run] [--run-now] [--target D601]",
|
|
"bun scripts/cli.ts artifact-registry deploy-service --env prod --service claudeqq --commit <full-sha> [--dry-run] [--run-now] [--target D601]",
|
|
"bun scripts/cli.ts artifact-registry deploy-service --env dev --service code-queue --commit <full-sha> --dry-run [--target D601]",
|
|
],
|
|
firstStage: "install now writes the rendered systemd/Compose/config files and starts the registry",
|
|
artifactConsumers: {
|
|
supportedServices: supportedArtifactConsumerServices,
|
|
supportedConsumers: supportedArtifactConsumers(),
|
|
unsupportedPolicy: "return structured unsupported; never fall back to legacy maintenance-channel source builds",
|
|
prodCommands: [
|
|
"bun scripts/cli.ts deploy apply --env prod --service backend-core",
|
|
"bun scripts/cli.ts deploy apply --env prod --service baidu-netdisk",
|
|
"bun scripts/cli.ts deploy apply --env prod --service frontend",
|
|
"bun scripts/cli.ts deploy apply --env prod --service decision-center",
|
|
"bun scripts/cli.ts deploy apply --env prod --service project-manager",
|
|
"bun scripts/cli.ts deploy apply --env prod --service oa-event-flow",
|
|
"bun scripts/cli.ts deploy apply --env prod --service code-queue-mgr --dry-run",
|
|
"bun scripts/cli.ts deploy apply --env prod --service todo-note",
|
|
"bun scripts/cli.ts deploy apply --env prod --service findjob",
|
|
"bun scripts/cli.ts deploy apply --env prod --service pipeline",
|
|
"bun scripts/cli.ts deploy apply --env prod --service met-nonlinear --dry-run",
|
|
"bun scripts/cli.ts deploy apply --env prod --service k3sctl-adapter --dry-run",
|
|
"bun scripts/cli.ts deploy apply --env prod --service mdtodo",
|
|
"bun scripts/cli.ts deploy apply --env prod --service claudeqq",
|
|
],
|
|
devCommands: [
|
|
"bun scripts/cli.ts deploy apply --env dev --service frontend",
|
|
"bun scripts/cli.ts deploy apply --env dev --service decision-center",
|
|
"bun scripts/cli.ts deploy apply --env dev --service project-manager --dry-run",
|
|
"bun scripts/cli.ts deploy apply --env dev --service oa-event-flow --dry-run",
|
|
"bun scripts/cli.ts deploy apply --env dev --service code-queue-mgr --dry-run",
|
|
"bun scripts/cli.ts deploy apply --env dev --service todo-note",
|
|
"bun scripts/cli.ts deploy apply --env dev --service findjob --dry-run",
|
|
"bun scripts/cli.ts deploy apply --env dev --service pipeline --dry-run",
|
|
"bun scripts/cli.ts deploy apply --env dev --service met-nonlinear --dry-run",
|
|
"bun scripts/cli.ts deploy apply --env dev --service mdtodo",
|
|
"bun scripts/cli.ts deploy apply --env dev --service claudeqq",
|
|
"bun scripts/cli.ts deploy apply --env dev --service code-queue --dry-run",
|
|
],
|
|
devOnlyConsumers: ["code-queue"],
|
|
rollbackShape: "rerun the same artifact consumer with a previous commit-pinned image",
|
|
},
|
|
legacyEntrypoints: {
|
|
"deploy-backend-core": {
|
|
deprecated: true,
|
|
enabled: !legacyDeployBackendCoreDisabled,
|
|
replacement: "bun scripts/cli.ts deploy apply --env prod --service backend-core --commit <full-sha>",
|
|
},
|
|
},
|
|
defaults: defaultOptions,
|
|
};
|
|
}
|
|
|
|
export async function runArtifactRegistryCommand(args: string[], runtime: ArtifactRegistryCommandRuntime = {}): Promise<unknown> {
|
|
const action = args[0];
|
|
if (isHelpArg(action)) return localHelp();
|
|
if (action !== "plan" && action !== "render" && action !== "status" && action !== "health" && action !== "install" && action !== "deploy-backend-core" && action !== "deploy-service") {
|
|
throw new Error("artifact-registry usage: plan|render|status|health|install|deploy-backend-core|deploy-service");
|
|
}
|
|
const typedAction = action as ArtifactRegistryAction;
|
|
const options = parseArtifactRegistryOptions(args.slice(1));
|
|
if (action === "plan") return plan(options);
|
|
if (action === "render") return { ok: true, providerId: options.providerId, render: renderBundle(options) };
|
|
if (action === "status") return runReadonlyStatusWithRemoteFallback(options, false, runtime);
|
|
if (action === "health") return runReadonlyStatusWithRemoteFallback(options, true, runtime);
|
|
if (action === "install") {
|
|
return options.dryRun ? installDryRun(options) : install(options);
|
|
}
|
|
if (action === "deploy-backend-core") {
|
|
if (options.commit === null) throw new Error("artifact-registry deploy-backend-core requires --commit <full-sha>");
|
|
if (legacyDeployBackendCoreDisabled) return legacyDeployBackendCoreResult(options);
|
|
return options.runNow ? await deployBackendCoreNow(options) : deployBackendCoreJob(args, options);
|
|
}
|
|
if (action === "deploy-service") {
|
|
const serviceId = serviceIdFromDeployBackendCoreArgs(typedAction, options);
|
|
return options.runNow || options.dryRun ? await deployServiceNow({ ...options, serviceId }) : deployServiceJob(args, { ...options, serviceId });
|
|
}
|
|
throw new Error("unreachable artifact-registry action");
|
|
}
|