refactor: remove CI.json from G14 CI

This commit is contained in:
Codex
2026-05-26 23:02:54 +08:00
parent 3b7daa535a
commit 0c21e43d98
12 changed files with 145 additions and 215 deletions
+72 -33
View File
@@ -21,7 +21,6 @@ const defaultProdWebEndpoint = process.env.HWLAB_G14_PROD_WEB_ENDPOINT || "http:
const defaultProxyUrl = process.env.HWLAB_G14_PROXY_URL || "http://127.0.0.1:10808";
const defaultAllProxyUrl = process.env.HWLAB_G14_ALL_PROXY_URL || "socks5h://127.0.0.1:10808";
const defaultNoProxy = process.env.HWLAB_G14_NO_PROXY || "hyueapi.com,.hyueapi.com,127.0.0.1,localhost,::1,10.0.0.0/8,10.42.0.0/16,10.43.0.0/16,192.168.0.0/16,.svc,.cluster.local,kubernetes.default.svc,registry.hwlab-ci.svc,hwlab-registry.hwlab-ci.svc";
const ciJsonRunnerImage = process.env.HWLAB_G14_CI_JSON_IMAGE || "mcr.microsoft.com/playwright@sha256:b0ab6f3cb99aa7803adbc14d9027ec1785fc6e433b97e134e0f8fe61683b6b53";
const ciToolsRunnerImage = process.env.HWLAB_G14_CI_TOOLS_IMAGE || "127.0.0.1:5000/hwlab/hwlab-ci-node-tools:node22-alpine-v1";
const buildkitRunnerImage = process.env.HWLAB_G14_BUILDKIT_IMAGE || "moby/buildkit:rootless";
const defaultDevBaseImage = process.env.HWLAB_G14_DEV_BASE_IMAGE || "127.0.0.1:5000/hwlab/hwlab-node20-base:20-bookworm-slim";
@@ -50,6 +49,29 @@ const codexApiProfileBaseUrl = process.env.HWLAB_G14_CODEX_API_PROFILE_BASE_URL
const codexApiForwarderPort = process.env.HWLAB_G14_CODEX_API_FORWARDER_PORT || "49280";
const codexApiForwarderUpstreamBaseUrl = process.env.HWLAB_G14_CODEX_API_UPSTREAM_BASE_URL || "https://hyueapi.com";
const sourceCommitPattern = /^[a-f0-9]{7,40}$/u;
const primitiveValidationTasks = Object.freeze([
{
name: "repo-reports-guard",
commands: ["node scripts/repo-reports-guard.mjs"]
},
{
name: "g14-contract-check",
commands: [
"node --check scripts/g14-gitops-render.mjs",
"node scripts/g14-gitops-render.mjs --check",
"node --check scripts/artifact-publish.mjs",
"node --check scripts/g14-artifact-publish.mjs"
]
},
{
name: "codex-api-forwarder-check",
commands: [
"node --check cmd/hwlab-codex-api-responses-forwarder/main.mjs",
"node --check cmd/hwlab-codex-api-responses-forwarder/main.test.mjs",
"node --test cmd/hwlab-codex-api-responses-forwarder/main.test.mjs"
]
}
]);
function proxyEnv() {
return [
@@ -115,7 +137,7 @@ function usage() {
return [
"usage: node scripts/g14-gitops-render.mjs [options]",
"",
"Render G14-only Kubernetes-native CI/CD manifests from CI.json and deploy/deploy.json.",
"Render G14-only Kubernetes-native CI/CD manifests from built-in Tekton CI primitives, deploy/deploy.json, and deploy/k8s/*.",
"",
"options:",
` --out DIR default: ${defaultOutDir}`,
@@ -129,7 +151,7 @@ function usage() {
` --prod-runtime-endpoint URL default: ${defaultProdRuntimeEndpoint}`,
` --prod-web-endpoint URL default: ${defaultProdWebEndpoint}`,
" --use-deploy-images default: render workload images/env from deploy/deploy.json per service",
" --legacy-source-images compatibility fallback: render every workload with the source revision tag",
" --legacy-source-images render every workload with the source revision tag instead of per-service desired images",
" --check verify generated files are current without writing",
" --no-write plan and print generated file list without writing"
].join("\n");
@@ -590,20 +612,16 @@ curl_dependency_probe() {
}`;
}
function ciJsonScript(ci) {
const commands = ci.commands ?? [];
function prepareSourceScript() {
const lines = [
"#!/bin/sh",
"set -eu",
dependencyProxyProbeScript("ci-json-proxy-preflight", "http://deb.debian.org/debian/dists/bookworm/InRelease"),
dependencyProxyProbeScript("prepare-source-proxy-preflight", "http://deb.debian.org/debian/dists/bookworm/InRelease"),
curlDownloadProbeFunction(),
"echo '{\"event\":\"ci-base-image\",\"policy\":\"no-runtime-apt-or-playwright-install\"}'",
`echo '{"event":"ci-base-image","phase":"prepare-source","image":"${ciToolsRunnerImage}","policy":"no-runtime-apk"}'`,
"for tool in node npm git python3 ssh curl; do command -v \"$tool\" >/dev/null 2>&1 || { echo '{\"event\":\"ci-base-image\",\"ok\":false,\"reason\":\"missing-tool\",\"tool\":\"'\"$tool\"'\"}'; exit 31; }; done",
"export PLAYWRIGHT_BROWSERS_PATH=\"${PLAYWRIGHT_BROWSERS_PATH:-/ms-playwright}\"",
"test -d \"$PLAYWRIGHT_BROWSERS_PATH\" || { echo '{\"event\":\"ci-base-image\",\"ok\":false,\"reason\":\"missing-playwright-browsers-path\"}'; exit 32; }",
"find \"$PLAYWRIGHT_BROWSERS_PATH\" -maxdepth 2 -type d -name 'chromium-*' | grep -q . || { echo '{\"event\":\"ci-base-image\",\"ok\":false,\"reason\":\"missing-chromium-cache\"}'; exit 33; }",
"node -e 'console.log(JSON.stringify({event:\"ci-base-image\",ok:true,node:process.version,browsersPath:process.env.PLAYWRIGHT_BROWSERS_PATH}))'",
"curl_dependency_probe \"ci-json-pre-npm\" \"https://registry.npmjs.org/npm/latest\"",
"node -e 'console.log(JSON.stringify({event:\"ci-base-image\",phase:\"prepare-source\",ok:true,node:process.version}))'",
"curl_dependency_probe \"prepare-source-pre-npm\" \"https://registry.npmjs.org/npm/latest\"",
"mkdir -p /root/.ssh",
"cp /workspace/git-ssh/ssh-privatekey /root/.ssh/id_rsa",
"chmod 600 /root/.ssh/id_rsa",
@@ -611,24 +629,44 @@ function ciJsonScript(ci) {
"rm -rf /workspace/source/repo",
"git clone --branch \"$(params.source-branch)\" \"$(params.git-url)\" /workspace/source/repo",
"cd /workspace/source/repo",
"git config --global --add safe.directory /workspace/source/repo",
"git checkout \"$(params.revision)\"",
"test \"$(git rev-parse HEAD)\" = \"$(params.revision)\"",
"npm ci --ignore-scripts",
"playwright_browser_probe_url=\"$(node -e 'const fs=require(\"node:fs\"); let url=\"\"; try { const p=require.resolve(\"playwright-core/browsers.json\"); const data=JSON.parse(fs.readFileSync(p,\"utf8\")); const b=data.browsers.find((item)=>item.name===\"chromium\"); if (b?.revision) url=\"https://playwright.azureedge.net/builds/chromium/\"+b.revision+\"/chromium-linux.zip\"; } catch {} process.stdout.write(url);' 2>/dev/null || true)\"",
"if [ -n \"$playwright_browser_probe_url\" ]; then curl_dependency_probe \"ci-json-pre-playwright\" \"$playwright_browser_probe_url\"; fi",
"node - <<'NODE'\nconst fs = require(\"node:fs\");\nconst { chromium } = require(\"playwright\");\nconst executablePath = chromium.executablePath();\nfs.accessSync(executablePath, fs.constants.X_OK);\nconsole.log(JSON.stringify({ event: \"playwright-cache-check\", ok: true, executablePath, browsersPath: process.env.PLAYWRIGHT_BROWSERS_PATH || \"\" }));\nNODE",
`echo ${shellSingleQuote(`CI.json ${ci.name ?? "hwlab"} command count=${commands.length}`)}`
`echo ${shellSingleQuote(`G14 prepare-source complete; validation task count=${primitiveValidationTasks.length}`)}`
];
for (const command of commands) {
lines.push(`echo ${shellSingleQuote(`CI.json command: ${command.name}`)}`);
lines.push("(");
lines.push("set -eu");
lines.push(command.run);
lines.push(")");
}
return `${lines.join("\n")}\n`;
}
function sourceValidationScript(commands) {
return [
"#!/bin/sh",
"set -eu",
"git config --global --add safe.directory /workspace/source/repo",
"cd /workspace/source/repo",
"test \"$(git rev-parse HEAD)\" = \"$(params.revision)\"",
...commands
].join("\n") + "\n";
}
function primitiveValidationTaskNames() {
return primitiveValidationTasks.map((task) => task.name);
}
function primitiveValidationTask(task) {
return {
name: task.name,
runAfter: ["prepare-source"],
workspaces: [{ name: "source", workspace: "source" }],
taskSpec: {
params: [{ name: "revision" }],
workspaces: [{ name: "source" }],
steps: [{ name: task.name, image: ciToolsRunnerImage, env: proxyEnv(), script: sourceValidationScript(task.commands) }]
},
params: [{ name: "revision", value: "$(params.revision)" }]
};
}
function publishScript() {
return `#!/bin/sh
set -eu
@@ -1269,7 +1307,7 @@ function dockerSidecar() {
function legacyImagePublishTask() {
return {
name: "image-publish",
runAfter: ["ci-json"],
runAfter: primitiveValidationTaskNames(),
workspaces: [{ name: "source", workspace: "source" }],
taskSpec: {
params: [
@@ -1303,7 +1341,7 @@ function legacyImagePublishTask() {
function planArtifactsTask() {
return {
name: "plan-artifacts",
runAfter: ["ci-json"],
runAfter: primitiveValidationTaskNames(),
workspaces: [{ name: "source", workspace: "source" }],
taskSpec: {
params: [
@@ -1400,7 +1438,7 @@ function imagePublishTaskSet() {
];
}
function tektonPipeline(ci) {
function tektonPipeline() {
return {
apiVersion: "tekton.dev/v1",
kind: "Pipeline",
@@ -1412,7 +1450,8 @@ function tektonPipeline(ci) {
"hwlab.pikastech.local/gitops-target": "g14"
},
annotations: {
"hwlab.pikastech.local/source-config": "CI.json",
"hwlab.pikastech.local/source-config": "scripts/g14-gitops-render.mjs#tekton-native-primitive-ci",
"hwlab.pikastech.local/ci-contract": "tekton-native-primitive-tasks",
"hwlab.pikastech.local/policy": tektonSingleImagePublish ? "single-dind-image-publish-compat" : "native-per-service-taskrun-image-publish"
}
},
@@ -1433,7 +1472,7 @@ function tektonPipeline(ci) {
],
tasks: [
{
name: "ci-json",
name: "prepare-source",
workspaces: [
{ name: "source", workspace: "source" },
{ name: "git-ssh", workspace: "git-ssh" }
@@ -1445,7 +1484,7 @@ function tektonPipeline(ci) {
{ name: "revision" }
],
workspaces: [{ name: "source" }, { name: "git-ssh" }],
steps: [{ name: "ci-json", image: ciJsonRunnerImage, env: proxyEnv(), script: ciJsonScript(ci) }]
steps: [{ name: "prepare-source", image: ciToolsRunnerImage, env: proxyEnv(), script: prepareSourceScript() }]
},
params: [
{ name: "git-url", value: "$(params.git-url)" },
@@ -1453,6 +1492,7 @@ function tektonPipeline(ci) {
{ name: "revision", value: "$(params.revision)" }
]
},
...primitiveValidationTasks.map(primitiveValidationTask),
...imagePublishTaskSet(),
{
name: "gitops-promote",
@@ -2201,7 +2241,7 @@ function runtimeKustomization({ profile = "dev", includeDeviceAgent = profile ==
function readme({ source, args }) {
return `# HWLAB G14 GitOps CI/CD
This directory is generated from \`CI.json\`, \`deploy/deploy.json\`, and \`deploy/k8s/*\` by \`scripts/g14-gitops-render.mjs\`.
This directory is generated from built-in Tekton-native CI primitive declarations plus \`deploy/deploy.json\` and \`deploy/k8s/*\` by \`scripts/g14-gitops-render.mjs\`.
- Target: G14 k3s only.
- CI: Tekton Pipeline \`hwlab-ci/hwlab-g14-ci-image-publish\`.
@@ -2217,8 +2257,7 @@ This directory is generated from \`CI.json\`, \`deploy/deploy.json\`, and \`depl
}
async function plannedFiles(args) {
const [ci, deploy, namespaceTemplate, config, services, health, workloads] = await Promise.all([
readJson("CI.json"),
const [deploy, namespaceTemplate, config, services, health, workloads] = await Promise.all([
readJson("deploy/deploy.json"),
readJson("deploy/k8s/base/namespace.yaml"),
readJson("deploy/k8s/base/code-agent-codex-config.yaml"),
@@ -2264,7 +2303,7 @@ async function plannedFiles(args) {
putText("README.md", readme({ source, args }));
putJson("registry/registry.yaml", registryManifest());
putJson("tekton/rbac.yaml", tektonRbac());
putJson("tekton/pipeline.yaml", tektonPipeline(ci));
putJson("tekton/pipeline.yaml", tektonPipeline());
putJson("tekton/poller.yaml", tektonPollerCronJob(args));
putJson("tekton/control-plane-reconciler.yaml", tektonControlPlaneReconcilerCronJob(args));
putJson("tekton/pipelinerun.sample.yaml", tektonPipelineRunTemplate({ source, args }));