From 8ea32b6d36ca8798d21ce80d2e449054b2246641 Mon Sep 17 00:00:00 2001 From: root Date: Thu, 16 Jul 2026 21:14:04 +0200 Subject: [PATCH] fix: bootstrap new services in artifact catalogs Co-Authored-By: Claude Opus 4.7 --- internal/protocol/index.mjs | 2 ++ scripts/refresh-artifact-catalog.mjs | 25 ++++++++++++++++++----- scripts/refresh-artifact-catalog.test.mjs | 25 ++++++++++++++++++++++- 3 files changed, 46 insertions(+), 6 deletions(-) diff --git a/internal/protocol/index.mjs b/internal/protocol/index.mjs index 3f020e1f..1fbb1074 100644 --- a/internal/protocol/index.mjs +++ b/internal/protocol/index.mjs @@ -6,6 +6,8 @@ export const DEV_FRONTEND_ENDPOINT = "http://74.48.78.17:16666"; export const JSON_RPC_VERSION = "2.0"; export const SERVICE_IDS = Object.freeze([ + "hwlab-tasktree-api", + "hwlab-tasktree-worker", "hwlab-cloud-api", "hwlab-cloud-web", "hwlab-gateway", diff --git a/scripts/refresh-artifact-catalog.mjs b/scripts/refresh-artifact-catalog.mjs index 957abcc0..f97d7450 100644 --- a/scripts/refresh-artifact-catalog.mjs +++ b/scripts/refresh-artifact-catalog.mjs @@ -327,12 +327,21 @@ function assertRuntimeLaneDeployAndCatalog(deploy, catalog, laneName) { assert.deepEqual((catalog.services ?? []).map((service) => service.serviceId), serviceIds, `catalog services must cover deploy.lanes.${laneName}.envReuseServices in order`); } -function normalizeCatalogForLane(catalog, lane, deploy) { - if (!catalog || !isRuntimeArtifactLane(lane)) return catalog; - const allowed = new Set(serviceIdsForLane(lane, deploy)); +function normalizeCatalogForLane(catalog, args, deploy, target, registryPrefix) { + if (!catalog) return catalog; + const serviceIds = isRuntimeArtifactLane(args.lane) + ? serviceIdsForLane(args.lane, deploy) + : SERVICE_IDS; + const allowed = new Set(serviceIds); + const environment = artifactEnvironment(args); + const namespace = artifactNamespace(args, deploy); + const existingById = new Map((catalog.services ?? []) + .filter((service) => allowed.has(service.serviceId)) + .map((service) => [service.serviceId, service])); return { ...catalog, - services: (catalog.services ?? []).filter((service) => allowed.has(service.serviceId)) + services: serviceIds.map((serviceId) => existingById.get(serviceId) + ?? catalogSkeletonService({ args, serviceId, target, registryPrefix, environment, namespace })) }; } @@ -570,7 +579,13 @@ async function main() { ]); let catalog = await readConfigIfPresent(args.catalogPath, null); if (!catalog && isRuntimeArtifactLane(args.lane)) catalog = artifactCatalogSkeleton({ args, deploy, target, registryPrefix: publishReport?.artifactPublish?.registryPrefix ?? defaultRegistryPrefix }); - catalog = normalizeCatalogForLane(catalog, args.lane, deploy); + catalog = normalizeCatalogForLane( + catalog, + args, + deploy, + target, + publishReport?.artifactPublish?.registryPrefix ?? defaultRegistryPrefix + ); assert.ok(catalog, `${args.catalogPath} is required for ${args.lane} catalog refresh`); assertLaneDeployAndCatalog(args, deploy, catalog); diff --git a/scripts/refresh-artifact-catalog.test.mjs b/scripts/refresh-artifact-catalog.test.mjs index 592f3738..999f1d97 100644 --- a/scripts/refresh-artifact-catalog.test.mjs +++ b/scripts/refresh-artifact-catalog.test.mjs @@ -333,7 +333,7 @@ test("v03 refresh accepts runtime lane config and env-reuse image tags", async ( const deployPath = path.join(tempDir, "deploy.yaml"); const catalogPath = path.join(tempDir, "artifact-catalog.v03.json"); const reportPath = path.join(tempDir, "v03-artifacts.json"); - const serviceIds = V02_SERVICE_IDS; + const serviceIds = [...V02_SERVICE_IDS, "hwlab-tasktree-api", "hwlab-tasktree-worker"]; await writeStructuredFile(tempDir, deployPath, { environment: "dev", namespace: "hwlab-dev", @@ -354,6 +354,29 @@ test("v03 refresh accepts runtime lane config and env-reuse image tags", async ( }, services: SERVICE_IDS.map((serviceId) => ({ serviceId })) }); + await writeFile(catalogPath, `${JSON.stringify({ + catalogVersion: "v1", + kind: "hwlab-artifact-catalog", + environment: "v03", + profile: "v03", + namespace: "hwlab-v03", + endpoint: "https://hwlab-v03.74-48-78-17.nip.io", + commitId, + artifactState: "published", + publish: { ciPublished: true, registryVerified: true, provenance: "previous-run" }, + allowedProfiles: ["v03"], + forbiddenProfiles: ["dev", "prod"], + services: V02_SERVICE_IDS.map((serviceId, index) => ({ + serviceId, + commitId, + sourceCommitId: commitId, + image: `127.0.0.1:5000/hwlab/${serviceId}:${commitId}`, + imageTag: commitId, + digest: digestFor(index), + profile: "v03", + namespace: "hwlab-v03" + })) + }, null, 2)}\n`); await writeFile(reportPath, `${JSON.stringify({ reportVersion: "v1", taskId: "v03-artifact-publish",