edfddd2445
* docs: specify cicd yaml target governance * fix: resolve cicd targets from yaml --------- Co-authored-by: Codex <codex@noreply.local>
119 lines
8.0 KiB
TypeScript
119 lines
8.0 KiB
TypeScript
// SPEC: PJ2026-01060307 控制面模块化 draft-2026-06-25-p0. entry module for scripts/src/deploy.ts.
|
|
// SPEC: PJ2026-01060308 cicd-yaml-targets draft-2026-06-25-cicd-yaml-targets.
|
|
|
|
// Moved mechanically from scripts/src/deploy.ts:3528-3700 for #903.
|
|
|
|
import { createHash } from "node:crypto";
|
|
import { existsSync, mkdirSync, readFileSync } from "node:fs";
|
|
import { join, resolve } from "node:path";
|
|
import { pathToFileURL } from "node:url";
|
|
import { runCommand } from "../command";
|
|
import { type UniDeskConfig, type UniDeskMicroserviceConfig, repoRoot, rootPath } from "../config";
|
|
import { ensureGithubSshIdentityForProvider } from "../deploy-ssh-identity";
|
|
import { baiduNetdiskRuntimeSecretRequirements, runtimeSecretContractFromEnvText, type RuntimeSecretContract, runArtifactRegistryCommand } from "../artifact-registry";
|
|
import { startJob } from "../jobs";
|
|
import { coreInternalFetch } from "../microservices";
|
|
import { codeQueueSourceImportPreflight, codeQueueSourceSubdir } from "../code-queue-source-guard";
|
|
import { d601K3sGuardShellLines, d601NativeKubeconfig } from "../d601-k3s-guard";
|
|
import { composeRuntimeEnvValue } from "../runtime-env";
|
|
import {
|
|
compareDeployJsonExecutorMirrors,
|
|
deployJsonCommitImage,
|
|
deployJsonDriftResult,
|
|
deployJsonSourceOfTruth,
|
|
encodeDeployJsonServiceContract,
|
|
hasDeployJsonExecutorContract,
|
|
k3sManifestExecutorMirror,
|
|
parseDeployJsonServiceContract,
|
|
type DeployJsonExecutorMirror,
|
|
type DeployJsonServiceContract,
|
|
} from "../deploy-json-contract";
|
|
import { resolveArtifactRegistryTarget } from "../ops/targets";
|
|
|
|
import type { DeployAction } from "./types";
|
|
import { applyJob, devArtifactApplyJob, prodArtifactApplyJob, runApplyNow, runArtifactConsumerApplyNow, runProdArtifactApplyNow } from "./artifact-jobs";
|
|
import { blockedD601MaintenanceDeployServices, checkOrPlan, commitOverrideArtifactConsumerError, d601MaintenanceDeployBlockMessage, devArtifactLiveApplyBlockedResult, environmentDryRunPlan, prodArtifactConsumerLocalManifestResult, prodArtifactUnsupportedResult, prodArtifactUnsupportedServices, selectedDevArtifactServicesWithProdFallback, selectedDevTargetServices, selectedEnvironmentServices, unsupportedDevApplyServices } from "./check-plan";
|
|
import { readDeployManifest, readEnvironmentDeployManifest } from "./manifest";
|
|
import { deployHelp, isHelpArg, optionValue, parseOptions, resolveManifestCommits } from "./options";
|
|
import { devArtifactLiveApplyBlockedServiceIds, prodForbiddenTargetSideBuildServiceIds } from "./types";
|
|
|
|
export function runDeployGuardCommand(args: string[]): unknown {
|
|
const [guardName] = args;
|
|
if (guardName !== "code-queue-source") {
|
|
return {
|
|
ok: false,
|
|
supported: false,
|
|
error: "unsupported-deploy-guard",
|
|
guard: guardName ?? null,
|
|
supportedGuards: ["code-queue-source"],
|
|
};
|
|
}
|
|
const root = optionValue(args.slice(1), ["--root"]) ?? repoRoot;
|
|
return codeQueueSourceImportPreflight(root);
|
|
}
|
|
|
|
export async function runDeployCommand(config: UniDeskConfig | null, args: string[]): Promise<unknown> {
|
|
const [actionRaw = "check"] = args;
|
|
if (isHelpArg(actionRaw) || args.slice(1).some(isHelpArg)) return deployHelp(isHelpArg(actionRaw) ? undefined : actionRaw);
|
|
if (actionRaw === "guard") return runDeployGuardCommand(args.slice(1));
|
|
if (!["check", "plan", "apply"].includes(actionRaw)) throw new Error("deploy command must be one of: check, plan, apply, guard");
|
|
const action = actionRaw as DeployAction;
|
|
const options = parseOptions(args.slice(1));
|
|
if (options.environment !== null) {
|
|
const commitOverrideError = commitOverrideArtifactConsumerError(options);
|
|
if (commitOverrideError !== null) throw new Error(commitOverrideError);
|
|
const { manifest, source } = readEnvironmentDeployManifest(options.environment);
|
|
if (action === "check" || action === "plan") return environmentDryRunPlan(config, manifest, source, options, action);
|
|
if (options.environment === "prod") {
|
|
const unsupported = prodArtifactUnsupportedServices(manifest, options.serviceId);
|
|
if (unsupported.length > 0) return prodArtifactUnsupportedResult(unsupported);
|
|
if (options.dryRun || options.runNow) return await runProdArtifactApplyNow(manifest, options);
|
|
return prodArtifactApplyJob(args, options);
|
|
}
|
|
const unsupported = unsupportedDevApplyServices(manifest, options.serviceId);
|
|
if (unsupported.length > 0) {
|
|
throw new Error(`deploy apply --env dev currently supports auth-broker/backend-core/frontend/baidu-netdisk/decision-center/mdtodo/claudeqq/code-queue/project-manager/oa-event-flow/code-queue-mgr/todo-note/findjob/pipeline/met-nonlinear artifact consumers; unsupported selected services: ${unsupported.join(", ")}. Use ci run-dev-e2e for smoke verification.`);
|
|
}
|
|
const devArtifactServices = selectedDevArtifactServicesWithProdFallback(manifest, options.serviceId);
|
|
const devTargetServices = selectedDevTargetServices(manifest, options.serviceId);
|
|
if (devArtifactServices.length > 0 && devTargetServices.length > 0) {
|
|
throw new Error("deploy apply --env dev cannot mix artifact consumer services with target-side rollout services in one invocation; pass --service");
|
|
}
|
|
if (devArtifactServices.length > 0) {
|
|
const blocked = devArtifactServices.filter((service) => devArtifactLiveApplyBlockedServiceIds.has(service.id));
|
|
if (!options.dryRun && blocked.length > 0) return devArtifactLiveApplyBlockedResult(blocked);
|
|
if (options.dryRun || options.runNow) return await runArtifactConsumerApplyNow(manifest, options, "dev", devArtifactServices);
|
|
return devArtifactApplyJob(args, options);
|
|
}
|
|
if (config === null) throw new Error("deploy apply --env dev requires config.json");
|
|
if (!options.dryRun) {
|
|
const blocked = blockedD601MaintenanceDeployServices(config, manifest, options.serviceId).filter((serviceId) => serviceId !== "decision-center");
|
|
if (blocked.length > 0) throw new Error(d601MaintenanceDeployBlockMessage(blocked));
|
|
}
|
|
if (options.dryRun || options.runNow) return await runApplyNow(config, manifest, options);
|
|
return applyJob(config, args, options);
|
|
}
|
|
if (config === null) throw new Error("deploy local manifest mode requires config.json");
|
|
const rawManifest = await readDeployManifest(options.file);
|
|
if (action === "apply") {
|
|
const blocked = blockedD601MaintenanceDeployServices(config, rawManifest, options.serviceId);
|
|
if (blocked.length > 0) throw new Error(d601MaintenanceDeployBlockMessage(blocked));
|
|
}
|
|
const manifest = resolveManifestCommits(rawManifest, options.serviceId);
|
|
if (action === "check" || action === "plan") return await checkOrPlan(config, manifest, options, action);
|
|
const prodArtifactConsumers = selectedEnvironmentServices(manifest, options.serviceId)
|
|
.filter((service) => manifest.environment !== "dev" && prodForbiddenTargetSideBuildServiceIds.has(service.id));
|
|
if (prodArtifactConsumers.length > 0) return prodArtifactConsumerLocalManifestResult(prodArtifactConsumers);
|
|
if (options.dryRun || options.runNow) return await runApplyNow(config, manifest, options);
|
|
return applyJob(config, args, options);
|
|
}
|
|
|
|
export async function runCodeQueueDeployCompatCommand(_config: UniDeskConfig, args: string[]): Promise<unknown> {
|
|
if (args.includes("--skip-build")) throw new Error("codex deploy is disabled; --skip-build is not supported");
|
|
const selectedTarget = optionValue(args, ["--target", "--provider-id", "--provider"]);
|
|
if (selectedTarget === undefined) throw new Error("codex deploy compatibility path is a legacy adapter and requires explicit --target D601; it no longer falls back to a hidden provider default");
|
|
const target = resolveArtifactRegistryTarget(selectedTarget);
|
|
if (target.providerId !== "D601") throw new Error(`codex deploy compatibility path only supports D601; got ${target.providerId}`);
|
|
throw new Error("codex deploy is disabled because D601 maintenance-channel direct deployment must not deploy Code Queue. Use the dev-only artifact consumer with deploy apply --env dev --service code-queue or artifact-registry deploy-service --env dev --service code-queue; production Code Queue artifact deployment is unsupported.");
|
|
}
|