refactor: make v0.3 runtime node-scoped

This commit is contained in:
Codex Agent
2026-06-08 22:19:30 +08:00
parent e8ab452b10
commit 187fb80a5d
38 changed files with 549 additions and 450 deletions
@@ -141,7 +141,7 @@ export function evaluateArtifactRuntimeReadiness({
pass: commitsMatch(catalog.commitId, target.commitId),
type: "observability_blocker",
summary: `Artifact catalog commit=${catalog.shortCommitId}; target=${target.shortCommitId}.`,
nextTask: "Do not refresh source desired-state. Let G14 Tekton promotion write artifact catalog identity to G14-gitops, then verify Argo/runtime revision."
nextTask: "Do not refresh source desired-state. Let node Tekton promotion write artifact catalog identity to the configured GitOps branch, then verify Argo/runtime revision."
});
addCheck(checks, {
id: "artifact-report-catalog-match",
@@ -162,7 +162,7 @@ export function evaluateArtifactRuntimeReadiness({
pass: desiredState.matchesTarget,
type: "observability_blocker",
summary: `Desired-state deploy=${desiredState.deployCommitId}; target=${target.shortCommitId}; convergence=${desiredState.targetConvergence.state}; pending=${desiredState.targetConvergence.pendingTargetFields}.`,
nextTask: `Run node scripts/deploy-desired-state-plan.mjs --promotion-commit ${target.shortCommitId} --check as a read-only review, then rely on G14 Tekton promotion for catalog writes.`
nextTask: `Run node scripts/deploy-desired-state-plan.mjs --promotion-commit ${target.shortCommitId} --check as a read-only review, then rely on node Tekton promotion for catalog writes.`
});
addCheck(checks, {
id: "rollout-read-access",
@@ -303,7 +303,7 @@ export function buildArtifactRuntimeReadinessReport({
sourceContract: {
status: "pass",
documents: [
"docs/reference/g14-gitops-cicd.md"
"docs/reference/node-gitops-cicd.md"
],
summary: "Target commit, artifact publish/catalog identity, desired-state convergence, API runtime identity, and Cloud Web served runtime identity are separate gates."
},
@@ -1220,7 +1220,7 @@ function nextCommands({ canPublish, canApply, blockedReasons }) {
return [
"bun run --cwd web/hwlab-cloud-web build",
"bun run --cwd web/hwlab-cloud-web check",
"node scripts/g14-artifact-publish.mjs --preflight --no-report",
"node scripts/artifact-publish.mjs --preflight --no-report",
"node scripts/refresh-artifact-catalog.mjs --target-ref origin/main --blocked --no-write",
guardCommand
];
@@ -1229,7 +1229,7 @@ function nextCommands({ canPublish, canApply, blockedReasons }) {
return [
"node scripts/deploy-desired-state-plan.mjs --target-ref origin/main --pretty",
"node scripts/deploy-desired-state-plan.mjs --promotion-commit <origin-main-sha> --check",
"node scripts/g14-gitops-render.mjs --no-write",
"node scripts/gitops-render.mjs --no-write",
guardCommand
];
}
@@ -1241,7 +1241,7 @@ function nextCommands({ canPublish, canApply, blockedReasons }) {
];
}
return [
"node scripts/g14-gitops-render.mjs --no-write",
"node scripts/gitops-render.mjs --no-write",
"node scripts/artifact-runtime-readiness-guard.mjs --target-ref origin/main --check --live --no-report"
];
}
+2 -2
View File
@@ -101,8 +101,8 @@ export const checkProfiles = Object.freeze({
{ id: "check-090-deploy-refresh-artifact-catalog", group: "deploy", command: ["node","--check","scripts/refresh-artifact-catalog.mjs"] },
{ id: "check-091-deploy-refresh-artifact-catalog-test", group: "deploy", command: ["node","--check","scripts/refresh-artifact-catalog.test.mjs"] },
{ id: "check-092-artifact-artifact-publish", group: "artifact", command: ["node","--check","scripts/artifact-publish.mjs"] },
{ id: "check-093-artifact-g14-artifact-publish", group: "artifact", command: ["node","--check","scripts/g14-artifact-publish.mjs"] },
{ id: "check-093a-artifact-g14-gitops-render-test", group: "artifact", command: ["node","scripts/run-bun.mjs","test","scripts/g14-gitops-render.test.ts"] },
{ id: "check-093-artifact-artifact-publish", group: "artifact", command: ["node","--check","scripts/artifact-publish.mjs"] },
{ id: "check-093a-artifact-gitops-render-test", group: "artifact", command: ["node","scripts/run-bun.mjs","test","scripts/gitops-render.test.ts"] },
{ id: "check-094-artifact-dev-runtime-base-image", group: "artifact", command: ["node","--check","scripts/dev-runtime-base-image.mjs"] },
{ id: "check-095-artifact-dev-artifact-services", group: "artifact", command: ["node","--check","scripts/src/dev-artifact-services.mjs"] },
{ id: "check-096-artifact-registry-capabilities", group: "artifact", command: ["node","--check","scripts/src/registry-capabilities.mjs"] },
@@ -7,7 +7,7 @@ import { readStructuredFileIfPresent } from "./structured-config.mjs";
const execFileAsync = promisify(execFile);
export const G14_CI_PLAN_VERSION = "v1";
export const CI_PLAN_VERSION = "v1";
export const ENV_REUSE_RUNTIME_MODE = "env-reuse-git-mirror-checkout";
export const V02_ENV_REUSE_RUNTIME_MODE = ENV_REUSE_RUNTIME_MODE;
@@ -41,12 +41,12 @@ export const DEFAULT_DOCS_ONLY_PATHS = Object.freeze([
export const DEFAULT_GITOPS_ONLY_PATHS = Object.freeze([
"deploy/gitops/",
"deploy/frp/",
"scripts/g14-gitops-render.mjs",
"scripts/gitops-render.mjs",
"scripts/src/runtime-lane.ts",
"tsconfig.gitops.json"
]);
export async function createG14CiPlan(options = {}) {
export async function createCiPlan(options = {}) {
const repoRoot = options.repoRoot ?? process.cwd();
const deployConfigPath = options.deployConfigPath ?? "deploy/deploy.yaml";
const targetRef = options.targetRef ?? "HEAD";
@@ -218,7 +218,7 @@ export async function createG14CiPlan(options = {}) {
const buildServices = services.filter((service) => service.buildRequired).map((service) => service.serviceId);
const reusedServices = services.filter((service) => !service.affected).map((service) => service.serviceId);
return {
planVersion: G14_CI_PLAN_VERSION,
planVersion: CI_PLAN_VERSION,
sourceCommitId,
shortCommitId,
baseRef,
@@ -227,7 +227,7 @@ export async function createG14CiPlan(options = {}) {
deployConfig: deployConfigPath,
artifactCatalog: artifactCatalog ? artifactCatalogPath : null,
lane,
ciContractSource: "scripts/g14-gitops-render.mjs",
ciContractSource: "scripts/gitops-render.mjs",
mode: "advisory-read-only",
currentRenderCompatible: true,
plannerMutatesDeployJson: false,
@@ -595,7 +595,7 @@ function resolveServiceIds({ options, laneConfig, lane }) {
const serviceIds = uniqueSorted(options.services.map(String));
const unknownServiceIds = serviceIds.filter((serviceId) => !allowedServiceIds.has(serviceId));
if (unknownServiceIds.length > 0) {
throw new Error(`unknown service IDs for G14 CI plan: ${unknownServiceIds.join(", ")}`);
throw new Error(`unknown service IDs for node CI plan: ${unknownServiceIds.join(", ")}`);
}
return { source: "cli-services", serviceIds };
}
+1 -1
View File
@@ -974,7 +974,7 @@ export async function buildDesiredStatePlan(options = {}) {
humanAuthoredTruth: [deployPath, workloadsPath],
artifactIdentityTruth: [catalogPath],
nonAuthoritativeEvidence: [artifactReportPath],
note: "This planner is read-only. deploy.yaml is human-authored config; artifact-catalog carries generated image identity and is written by G14 Tekton promotion only to G14-gitops. It does not prove image existence, registry reachability, a real DEV apply, or M3 DEV-LIVE hardware-loop evidence."
note: "This planner is read-only. deploy.yaml is human-authored config; artifact-catalog carries generated image identity and is written by node Tekton promotion only to the configured GitOps branch. It does not prove image existence, registry reachability, a real DEV apply, or M3 DEV-LIVE hardware-loop evidence."
},
cloudApiDb: cloudApiDb ?? {
status: "blocked",
+1 -1
View File
@@ -67,7 +67,7 @@ function provisionPlan({ exactBlocker = null, envValue = recommendedNode20Image,
`${envVarName}=${recommendedNode20Image} node scripts/preflight-dev-base-image.mjs`
],
artifactPublishDryRun: [
`${envVarName}=${envValue} node scripts/g14-artifact-publish.mjs --preflight --no-report`
`${envVarName}=${envValue} node scripts/artifact-publish.mjs --preflight --no-report`
]
}
};
+1 -1
View File
@@ -168,7 +168,7 @@ async function createDevGateReport(edgeHealth) {
documents: [
"docs/reference/dev-runtime-boundary.md",
"docs/reference/spec-v02-documentation-governance.md",
"docs/reference/g14-gitops-cicd.md",
"docs/reference/node-gitops-cicd.md",
"deploy/frp/README.md",
"deploy/master-edge/README.md"
],
@@ -327,7 +327,7 @@ function buildEvidence() {
category: "repository-governance",
level: "SOURCE",
status: "pass",
sources: ["scripts/repo-reports-guard.mjs", "package.json", "scripts/g14-gitops-render.mjs"],
sources: ["scripts/repo-reports-guard.mjs", "package.json", "scripts/gitops-render.mjs"],
commands: ["node scripts/repo-reports-guard.mjs"],
summary: "Repository report files are removed and guarded against recurrence."
})
+6 -6
View File
@@ -70,7 +70,7 @@ const artifactBuildInputFiles = new Set([
"package.json",
"package-lock.json",
"npm-shrinkwrap.json",
"scripts/g14-artifact-publish.mjs",
"scripts/artifact-publish.mjs",
"scripts/src/dev-artifact-services.mjs"
]);
@@ -674,10 +674,10 @@ async function validateLocalContracts(reporter, contracts, optionalReports, targ
function validateArtifactPublishReport(reporter, artifactReport, artifactIdentity, targetShortCommit, targetCommit, targetRef) {
if (!artifactReport) {
reporter.check("g14-artifact-publish-report", "registry", "blocked", "No G14 artifact publish report is present.");
reporter.check("artifact-publish-report", "registry", "blocked", "No node artifact publish report is present.");
reporter.block({
type: "runtime_blocker",
scope: "g14-artifact-publish",
scope: "artifact-publish",
summary: `${defaultArtifactReportPath} is missing, so the preflight has no publish evidence for HWLAB runtime artifacts.`,
nextTask: `Run the DEV artifact publish workflow and keep its temporary JSON at ${defaultArtifactReportPath}; do not commit report output.`
});
@@ -721,7 +721,7 @@ function validateArtifactPublishReport(reporter, artifactReport, artifactIdentit
const summary = sourceMatchesTarget
? "DEV artifact publish report covers all required enabled service IDs with immutable digests for the target commit, and records disabled service reasons."
: `DEV artifact publish report covers artifact source ${artifactIdentity.artifactSource.shortCommitId}; target ${targetRef} ${targetShortCommit} has no artifact build input changes since that source.`;
reporter.check("g14-artifact-publish-report", "registry", "pass", summary, [artifactIdentity?.targetCoverage].filter(Boolean));
reporter.check("artifact-publish-report", "registry", "pass", summary, [artifactIdentity?.targetCoverage].filter(Boolean));
return;
}
@@ -731,14 +731,14 @@ function validateArtifactPublishReport(reporter, artifactReport, artifactIdentit
? `source states resolved: ${sourcePresentCount} source-present, ${intentionallyDisabledCount} intentionally-disabled`
: "source states are not fully resolved";
reporter.check(
"g14-artifact-publish-report",
"artifact-publish-report",
"registry",
"blocked",
`DEV artifact publish report status is ${artifactPublish?.status ?? "missing"} with ${publishedCount}/${requiredServices.length || serviceCount} required services published for source ${artifactPublish?.sourceCommitId ?? artifactReport.commitId ?? "unknown"}; ${sourceSummary}.`
);
reporter.block({
type: "runtime_blocker",
scope: "g14-artifact-publish",
scope: "artifact-publish",
summary: `${defaultArtifactReportPath} does not prove all required HWLAB service artifacts for ${targetRef} ${targetShortCommit}; current status is ${artifactPublish?.status ?? "missing"} with ${publishedCount}/${requiredServices.length || serviceCount} required services published and ${sourceSummary}.`,
nextTask: "Complete DEV artifact publishing for every enabled required HWLAB service at the artifact source commit, or prove the target commit has no artifact build input changes; keep disabled services marked not_published with reasons."
});
+4 -4
View File
@@ -60,8 +60,8 @@ export type DeployConfig = {
lanes?: Record<string, RuntimeLaneConfig | undefined>;
};
const defaultNodeId = "G14";
const defaultGitopsRoot = "deploy/gitops/g14";
const defaultNodeId = "node";
const defaultGitopsRoot = "deploy/gitops/node";
const defaultPublicHost = "74.48.78.17";
export function isRuntimeLane(lane: unknown): lane is string {
@@ -143,8 +143,8 @@ export function applyRuntimeLaneDeployConfig(args: GitOpsRenderArgs, deploy: Dep
const configuredEndpoint = laneConfig.endpoint ?? defaultEndpoint;
const configuredWebEndpoint = laneConfig.publicEndpoints?.frontend ?? configuredEndpoint;
const configuredRuntimeEndpoint = laneConfig.publicEndpoints?.api ?? configuredEndpoint;
const defaultBranch = defaults.defaultBranch ?? "G14";
const defaultGitopsBranch = defaults.defaultGitopsBranch ?? "G14-gitops";
const defaultBranch = defaults.defaultBranch ?? "node";
const defaultGitopsBranch = defaults.defaultGitopsBranch ?? "node-gitops";
const defaultCatalogPath = defaults.defaultCatalogPath ?? "deploy/artifact-catalog.dev.json";
const defaultRuntimeEndpoint = defaults.defaultRuntimeEndpoint ?? "http://74.48.78.17:17667";
const defaultWebEndpoint = defaults.defaultWebEndpoint ?? "http://74.48.78.17:17666";