From b4113907f07ca942bec11ebdd6c664f04c5103ba Mon Sep 17 00:00:00 2001 From: lyon Date: Fri, 26 Jun 2026 16:58:51 +0800 Subject: [PATCH] fix: keep env-reuse boot commit current --- scripts/artifact-publish.mjs | 11 ++++----- scripts/gitops-render.mjs | 4 +-- scripts/gitops-render.test.ts | 46 ++++++++++++++++++++++++++++++++++- 3 files changed, 52 insertions(+), 9 deletions(-) diff --git a/scripts/artifact-publish.mjs b/scripts/artifact-publish.mjs index 08b17a01..08a03f9d 100644 --- a/scripts/artifact-publish.mjs +++ b/scripts/artifact-publish.mjs @@ -1401,6 +1401,7 @@ async function buildEnvReuseServiceWithBuildkit({ args, service, ref, buildCreat function withEnvReuseArtifactFields({ artifact, service, commitId, buildCreatedAt = null, buildSource = null }) { const environmentImage = artifact.image ?? service.environmentImage ?? null; const environmentDigest = artifact.digest ?? service.environmentDigest ?? "not_published"; + const bootCommit = commitId; return { ...artifact, runtimeMode: v02EnvReuseRuntimeMode, @@ -1414,14 +1415,14 @@ function withEnvReuseArtifactFields({ artifact, service, commitId, buildCreatedA environmentInputHash: service.environmentInputHash ?? null, codeInputHash: service.codeInputHash ?? null, bootRepo: service.bootRepo ?? "git@github.com:pikasTech/HWLAB.git", - bootCommit: service.bootCommit ?? commitId, + bootCommit, bootSh: service.bootSh ?? `deploy/runtime/boot/${service.serviceId}.sh`, image: environmentImage, imageTag: imageTagFromReference(environmentImage), digest: environmentDigest, buildCreatedAt: artifact.buildCreatedAt ?? buildCreatedAt, buildSource: artifact.buildSource ?? buildSource, - bootEnvEvidence: bootEnvEvidence({ service, commitId, environmentImage, environmentDigest }) + bootEnvEvidence: bootEnvEvidence({ service: { ...service, bootCommit }, commitId, environmentImage, environmentDigest }) }; } @@ -1770,9 +1771,7 @@ function artifactRecordForEnvReuseCatalogReuse({ service, catalogService, commit const environmentImage = service.environmentImage ?? catalogService?.environmentImage ?? null; const environmentDigest = service.environmentDigest ?? catalogService?.environmentDigest ?? "not_published"; const imageTag = imageTagFromReference(environmentImage); - const bootCommit = service.codeChanged === true || service.envChanged === true - ? service.bootCommit ?? commitId - : catalogService?.bootCommit ?? service.bootCommit ?? commitId; + const bootCommit = commitId; const base = { ...service, runtimeMode: v02EnvReuseRuntimeMode, @@ -1795,7 +1794,7 @@ function artifactRecordForEnvReuseCatalogReuse({ service, catalogService, commit buildSource: catalogService?.buildSource ?? null, buildBackend: "reused-env-catalog", repositoryDigest: service.repositoryDigest ?? repositoryDigestFor(environmentImage, environmentDigest) ?? catalogService?.repositoryDigest ?? null, - bootEnvEvidence: bootEnvEvidence({ service: { ...service, bootCommit }, commitId: bootCommit, environmentImage, environmentDigest }) + bootEnvEvidence: bootEnvEvidence({ service: { ...service, bootCommit }, commitId, environmentImage, environmentDigest }) }; if (!environmentImage || !imageTag || !shaDigestPattern.test(environmentDigest)) { return { diff --git a/scripts/gitops-render.mjs b/scripts/gitops-render.mjs index 461593fc..faad8eb2 100644 --- a/scripts/gitops-render.mjs +++ b/scripts/gitops-render.mjs @@ -572,7 +572,7 @@ function bootMetadataForService({ args, catalog, deployService, serviceId, sourc environmentInputHash: catalogService?.environmentInputHash ?? null, codeInputHash: catalogService?.codeInputHash ?? null, bootRepo: catalogService?.bootRepo ?? args.sourceRepo, - bootCommit: catalogService?.bootCommit ?? source.full, + bootCommit: source.full, bootSh: catalogService?.bootSh ?? bootShForService(deployService, serviceId) }; } @@ -693,7 +693,7 @@ function runtimeArtifactForService({ catalog, deploy, serviceId, source, registr return { image: runtimeImage, imageTag: imageTagFromReference(environmentImage) ?? source.imageTag ?? source.short, - commit: catalogService?.bootCommit ?? source.full, + commit: source.full, runtimeMode: v02EnvReuseRuntimeMode, environmentDigest: catalogService?.environmentDigest ?? catalogService?.digest ?? null }; diff --git a/scripts/gitops-render.test.ts b/scripts/gitops-render.test.ts index 7e693d88..693fa9c2 100644 --- a/scripts/gitops-render.test.ts +++ b/scripts/gitops-render.test.ts @@ -511,13 +511,46 @@ test("v02 render follows TypeScript runtime checks and does not self-patch boots test("v03 render keeps node identity as data instead of generated structure", async () => { const outDir = await mkdtemp(path.join(os.tmpdir(), "hwlab-v03-render-test-")); + const scratchDir = path.join(".tmp", `gitops-render-v03-${process.pid}-${Date.now()}`); + const staleCatalogPath = path.join(scratchDir, "artifact-catalog.v03.json"); try { + const head = spawnSync("git", ["rev-parse", "HEAD"], { cwd: process.cwd(), encoding: "utf8" }); + assert.equal(head.status, 0, head.stderr || head.stdout); + const sourceRevision = head.stdout.trim(); + const staleRevision = "0".repeat(40); + await mkdir(scratchDir, { recursive: true }); + await writeFile(staleCatalogPath, JSON.stringify({ + catalogVersion: "v1", + kind: "hwlab-artifact-catalog", + environment: "v03", + profile: "v03", + namespace: "hwlab-v03", + commitId: staleRevision.slice(0, 12), + artifactState: "ready", + services: [{ + serviceId: "hwlab-cloud-api", + runtimeMode: "env-reuse-git-mirror-checkout", + envReuse: true, + sourceCommitId: staleRevision, + commitId: staleRevision, + image: "127.0.0.1:5000/hwlab/hwlab-cloud-api-env:env-stale", + imageTag: "env-stale", + digest: `sha256:${"1".repeat(64)}`, + environmentImage: "127.0.0.1:5000/hwlab/hwlab-cloud-api-env:env-stale", + environmentDigest: `sha256:${"1".repeat(64)}`, + environmentInputHash: "e".repeat(64), + codeInputHash: "c".repeat(64), + bootRepo: "git@github.com:pikasTech/HWLAB.git", + bootCommit: staleRevision, + bootSh: "deploy/runtime/boot/hwlab-cloud-api.sh" + }] + }, null, 2)); const render = spawnSync(process.execPath, [ "scripts/run-bun.mjs", "scripts/gitops-render.mjs", "--lane", "v03", "--node", "G14", - "--catalog-path", "deploy/artifact-catalog.v03.json", + "--catalog-path", staleCatalogPath, "--image-tag-mode", "full", "--source-branch", "v0.3", "--gitops-branch", "v0.3-gitops", @@ -548,6 +581,16 @@ test("v03 render keeps node identity as data instead of generated structure", as assert.deepEqual(configMapNames, ["hwlab-v03-hwpod-preinstalled-specs", "hwlab-v03-project-management-bootstrap"]); const cloudApi = (workloadsJson.items ?? []).find((item) => item.kind === "Deployment" && item.metadata?.name === "hwlab-cloud-api"); const cloudApiContainer = collectContainersFromItem(cloudApi).find((container) => container.name === "hwlab-cloud-api"); + const cloudApiEnv = new Map((cloudApiContainer?.env ?? []).map((entry) => [entry.name, entry.value])); + assert.equal(cloudApi?.spec?.template?.metadata?.labels?.["hwlab.pikastech.local/source-commit"], sourceRevision); + assert.equal(cloudApi?.spec?.template?.metadata?.labels?.["hwlab.pikastech.local/artifact-source-commit"], sourceRevision); + assert.equal(cloudApi?.spec?.template?.metadata?.annotations?.["hwlab.pikastech.local/source-commit"], sourceRevision); + assert.equal(cloudApi?.spec?.template?.metadata?.annotations?.["hwlab.pikastech.local/boot-commit"], sourceRevision); + assert.equal(cloudApiEnv.get("HWLAB_COMMIT_ID"), sourceRevision); + assert.equal(cloudApiEnv.get("HWLAB_BOOT_COMMIT"), sourceRevision); + assert.equal(cloudApiEnv.get("HWLAB_GITOPS_SOURCE_COMMIT"), sourceRevision); + assert.equal(cloudApiEnv.get("HWLAB_CODE_AGENT_AGENTRUN_SOURCE_COMMIT"), sourceRevision); + assert.match(cloudApiEnv.get("HWLAB_ENVIRONMENT_IMAGE") ?? "", /hwlab-cloud-api-env:env-stale/u); assert.ok((cloudApi?.spec?.template?.spec?.volumes ?? []).some((volume) => volume.name === "hwpod-preinstalled-specs" && volume.configMap?.name === "hwlab-v03-hwpod-preinstalled-specs")); assert.ok((cloudApiContainer?.volumeMounts ?? []).some((mount) => mount.name === "hwpod-preinstalled-specs" && mount.mountPath === "/etc/hwlab/hwpod-specs")); assert.ok((cloudApiContainer?.env ?? []).some((entry) => entry.name === "HWLAB_HWPOD_SPEC_REGISTRY_DIRS" && entry.value === "/etc/hwlab/hwpod-specs")); @@ -580,5 +623,6 @@ test("v03 render keeps node identity as data instead of generated structure", as } finally { await rm(outDir, { recursive: true, force: true }); + await rm(scratchDir, { recursive: true, force: true }); } });