166 lines
8.5 KiB
TypeScript
166 lines
8.5 KiB
TypeScript
// SPEC: PJ2026-01060307 控制面模块化 draft-2026-06-25-p0. help module for scripts/src/ci.ts.
|
|
// SPEC: PJ2026-01060308 cicd-yaml-targets draft-2026-06-25-cicd-yaml-targets.
|
|
|
|
// Moved mechanically from scripts/src/ci.ts:3273-3409 for #903.
|
|
|
|
import { randomUUID } from "node:crypto";
|
|
import { existsSync, mkdtempSync, readFileSync, rmSync } from "node:fs";
|
|
import { tmpdir } from "node:os";
|
|
import { join, posix as posixPath } from "node:path";
|
|
import { blockedCatalogArtifactIds, catalogSummary, findCiCatalogArtifact, loadCiCatalog, supportedSourceBuildArtifactIds, type CiCatalogArtifact, type CiSourceBuildCatalogArtifact, type CiUpstreamImageCatalogArtifact } from "../ci-catalog";
|
|
import { runCommand } from "../command";
|
|
import { type UniDeskConfig, repoRoot, rootPath } from "../config";
|
|
import { ensureGithubSshIdentityForProvider, gitSshHttpConnectProxySource } from "../deploy-ssh-identity";
|
|
import { jobWithTail, listJobs, readJob, startJob } from "../jobs";
|
|
import { coreInternalFetch } from "../microservices";
|
|
import {
|
|
artifactRegistryReadonlyResultFromCommand,
|
|
buildArtifactRegistryReadonlyProbe,
|
|
parseArtifactRegistryOptions,
|
|
type ArtifactRegistryReadonlyProbe,
|
|
} from "../artifact-registry";
|
|
import { d601K3sGuardShellLines, d601NativeKubeconfig } from "../d601-k3s-guard";
|
|
import { runSshCommandCapture } from "../ssh";
|
|
|
|
import { g14CiPipelineManifest, tektonPipelineReleaseUrl, tektonPipelineVersion, tektonTriggersInterceptorsUrl, tektonTriggersReleaseUrl, tektonTriggersVersion } from "./types";
|
|
|
|
export function catalogArtifactDescriptor(artifact: CiCatalogArtifact): Record<string, unknown> {
|
|
if (artifact.kind === "source-build") {
|
|
return {
|
|
serviceId: artifact.serviceId,
|
|
kind: artifact.kind,
|
|
status: artifact.status,
|
|
producer: artifact.producer,
|
|
source: artifact.source,
|
|
image: artifact.image,
|
|
...(artifact.notes === undefined ? {} : { notes: artifact.notes }),
|
|
...(artifact.blockedReason === undefined ? {} : { blockedReason: artifact.blockedReason }),
|
|
};
|
|
}
|
|
return {
|
|
serviceId: artifact.serviceId,
|
|
kind: artifact.kind,
|
|
status: artifact.status,
|
|
producer: artifact.producer,
|
|
upstream: artifact.upstream,
|
|
blockedReason: artifact.blockedReason,
|
|
...(artifact.notes === undefined ? {} : { notes: artifact.notes }),
|
|
};
|
|
}
|
|
|
|
export function ciHelp(): Record<string, unknown> {
|
|
const catalog = loadCiCatalog();
|
|
return {
|
|
command: "ci install|status|github-ssh-identity|run|publish-backend-core|publish-user-service|run-dev-e2e|logs|cleanup-runs|cleanup-failed-pods",
|
|
description: "Manage native k3s Tekton CI on D601 or G14. CI may publish commit-pinned image artifacts, but it intentionally does not deploy CD.",
|
|
examples: [
|
|
"bun scripts/cli.ts ci install",
|
|
"bun scripts/cli.ts ci install --skip-prewarm",
|
|
"bun scripts/cli.ts ci install --skip-prewarm --skip-tekton-install",
|
|
"bun scripts/cli.ts ci install-status latest",
|
|
"bun scripts/cli.ts ci install --wait --skip-prewarm --skip-tekton-install",
|
|
"bun scripts/cli.ts ci plan --target D601",
|
|
"bun scripts/cli.ts ci github-ssh-identity plan --target D518",
|
|
"bun scripts/cli.ts ci github-ssh-identity ensure --target D518 --confirm",
|
|
"bun scripts/cli.ts ci install --target G14",
|
|
"bun scripts/cli.ts ci run --revision <commit>",
|
|
"bun scripts/cli.ts ci run --target G14 --revision <commit>",
|
|
"bun scripts/cli.ts ci publish-backend-core --commit <full-sha>",
|
|
"bun scripts/cli.ts ci publish-user-service --service baidu-netdisk --commit <full-sha>",
|
|
"bun scripts/cli.ts ci publish-user-service --service mdtodo --commit <full-sha>",
|
|
"bun scripts/cli.ts ci publish-user-service --service claudeqq --commit <full-sha>",
|
|
"bun scripts/cli.ts ci publish-user-service --service code-queue --commit <full-sha>",
|
|
"bun scripts/cli.ts ci publish-user-service --service decision-center --commit <full-sha>",
|
|
"bun scripts/cli.ts ci publish-user-service --service frontend --commit <full-sha>",
|
|
"bun scripts/cli.ts ci run-dev-e2e --wait-ms 600000",
|
|
"bun scripts/cli.ts ci logs <runId-or-pipelineRun> [--target G14] [--tail-lines 80]",
|
|
"bun scripts/cli.ts ci cleanup-runs --target D601 --min-age-minutes 60 --limit 50 --dry-run",
|
|
"bun scripts/cli.ts ci cleanup-runs --target D601 --min-age-minutes 60 --limit 50 --confirm",
|
|
"bun scripts/cli.ts ci cleanup-failed-pods --target D601 --namespace unidesk-ci --min-age-minutes 60 --dry-run",
|
|
"bun scripts/cli.ts ci cleanup-failed-pods --target D601 --namespace unidesk-ci --min-age-minutes 60 --confirm",
|
|
],
|
|
tekton: {
|
|
pipelineVersion: tektonPipelineVersion,
|
|
triggersVersion: tektonTriggersVersion,
|
|
sources: {
|
|
pipeline: tektonPipelineReleaseUrl,
|
|
triggers: tektonTriggersReleaseUrl,
|
|
interceptors: tektonTriggersInterceptorsUrl,
|
|
},
|
|
targets: {
|
|
default: "D601",
|
|
g14: {
|
|
providerId: "G14",
|
|
pipelineManifest: g14CiPipelineManifest,
|
|
nodeSelector: "unidesk.ai/node-id=G14",
|
|
},
|
|
},
|
|
},
|
|
install: {
|
|
defaultMode: "async-job",
|
|
waitFlag: "Use --wait only for explicit synchronous debugging; the default returns a .state/jobs job immediately with install-status follow-up.",
|
|
statusCommand: "bun scripts/cli.ts ci install-status <jobId|latest>",
|
|
prewarmDefault: true,
|
|
skipPrewarm: "Use --skip-prewarm only to refresh Tekton/CI manifests when runtime images are already present or prewarm is blocked by provider root/containerd permissions.",
|
|
skipTektonInstall: "Use --skip-tekton-install with --skip-prewarm only when Tekton is already installed and only UniDesk CI manifests/triggers need refreshing.",
|
|
},
|
|
backendCoreArtifact: {
|
|
producer: "D601 CI",
|
|
registry: "127.0.0.1:5000/unidesk/backend-core:<commit>",
|
|
cdCommand: "bun scripts/cli.ts deploy apply --env prod --service backend-core --commit <full-sha>",
|
|
},
|
|
userServiceArtifact: {
|
|
producer: "D601 CI",
|
|
command: "bun scripts/cli.ts ci publish-user-service --service <service-id> --commit <full-sha>",
|
|
transports: {
|
|
auto: "uses direct-docker for repo-owned code-queue artifacts and Tekton for the remaining services",
|
|
tekton: "D601 Tekton PipelineRun through backend-core/provider control plane",
|
|
directDocker: "repo-owned Docker artifact publish without backend-core/database dispatch; no deploy apply, rollout, restart, or active-task mutation",
|
|
},
|
|
supportedServices: supportedSourceBuildArtifactIds().filter((serviceId) => serviceId !== "backend-core"),
|
|
blockedServices: blockedCatalogArtifactIds(),
|
|
registry: "127.0.0.1:5000/unidesk/<service-id>:<commit>",
|
|
outputFields: ["serviceId", "sourceCommit", "sourceRepo", "dockerfile", "imageRef", "tag", "digest", "digestRef"],
|
|
summaryContract: catalog.summaryContract,
|
|
catalogSummary: catalogSummary(),
|
|
catalog: catalog.artifacts.map(catalogArtifactDescriptor),
|
|
boundary: "artifact producer only; no prod deploy and no production namespace mutation",
|
|
frontendNext: [
|
|
"bun scripts/cli.ts deploy apply --env dev --service frontend --commit <full-sha>",
|
|
"bun scripts/cli.ts deploy apply --env prod --service frontend --commit <full-sha>",
|
|
],
|
|
},
|
|
runDevE2E: {
|
|
defaultTriggerMode: "commit-pinned-ssh-launcher",
|
|
desiredState: "origin/master:deploy.json#environments.dev",
|
|
scriptSource: "origin/master:deploy.json#environments.dev.ci",
|
|
},
|
|
logs: {
|
|
defaultCapture: "ssh-stream",
|
|
dispatchTaskFallback: "--dispatch-task",
|
|
tailLines: "1..2000",
|
|
reason: "stream capture avoids backend-core task-result compactJson truncating CI log text before the CLI can extract failure hints",
|
|
},
|
|
cleanupRuns: {
|
|
defaultMode: "dry-run",
|
|
namespace: "unidesk-ci",
|
|
selector: "status.phase in Succeeded,Failed",
|
|
guard: "--confirm required for deletion; Running/Pending pods are never selected",
|
|
},
|
|
cleanupFailedPods: {
|
|
defaultNamespace: "unidesk-ci",
|
|
defaultMinAgeMinutes: 60,
|
|
defaultLimit: 50,
|
|
scope: "Kubernetes pods with status.phase=Failed only; does not touch Running/Pending pods, workloads, PVCs, Secrets, or Tekton resources",
|
|
defaultMode: "dry-run",
|
|
},
|
|
};
|
|
}
|
|
|
|
export function requireRunId(value: string): string {
|
|
if (!/^[a-z0-9]([-a-z0-9]{0,46}[a-z0-9])?$/u.test(value)) {
|
|
throw new Error("ci run-dev-e2e run id must be DNS-safe lowercase alnum/dash, max 48 chars");
|
|
}
|
|
return value;
|
|
}
|