Files
pikasTech-unidesk/scripts/src/deploy/entry.ts
T
Lyon edfddd2445 fix: YAML-first 治理 CI/CD target (#919)
* docs: specify cicd yaml target governance

* fix: resolve cicd targets from yaml

---------

Co-authored-by: Codex <codex@noreply.local>
2026-06-26 01:14:38 +08:00

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.");
}