diff --git a/deploy/deploy.yaml b/deploy/deploy.yaml index 6a48f4b0..989d07ce 100644 --- a/deploy/deploy.yaml +++ b/deploy/deploy.yaml @@ -291,7 +291,7 @@ lanes: - skills/hwlab-agent-runtime/ env: HWLAB_METRICS_NAMESPACE: hwlab-v03 - HWLAB_OBSERVABILITY_CONFIG_REVISION: PJ2026-01060505-20260617 + HWLAB_OBSERVABILITY_CONFIG_REVISION: PJ2026-01060505-20260617-render-env observable: true hwlab-user-billing: runtimeKind: go-service diff --git a/scripts/gitops-render.mjs b/scripts/gitops-render.mjs index ba640357..d17eb579 100644 --- a/scripts/gitops-render.mjs +++ b/scripts/gitops-render.mjs @@ -1,4 +1,5 @@ #!/usr/bin/env node +// SPEC: PJ2026-01060505 Workbench Performance; PJ2026-0106 平台运维 import assert from "node:assert/strict"; import { execFile } from "node:child_process"; import { createHash } from "node:crypto"; @@ -911,21 +912,44 @@ function deployServicesForProfile(deploy, profile) { const allowed = new Set(serviceIdsForProfile(profile, deploy)); const services = new Map((deploy.services ?? []) .filter((service) => allowed.has(service.serviceId)) - .map((service) => [service.serviceId, cloneJson(service)])); + .map((service) => { + const copy = cloneJson(service); + copy.env = mergeEnvMaps(copy.env, serviceDeclarationEnvForProfile(deploy, profile, service.serviceId)); + return [service.serviceId, copy]; + })); const laneServices = isRuntimeLane(profile) && Array.isArray(deploy.lanes?.[profile]?.services) ? deploy.lanes[profile].services : []; for (const override of laneServices) { - const existing = services.get(override.serviceId) ?? { serviceId: override.serviceId }; + const existing = services.get(override.serviceId) ?? { + serviceId: override.serviceId, + env: serviceDeclarationEnvForProfile(deploy, profile, override.serviceId) + }; services.set(override.serviceId, { ...existing, ...cloneJson(override), - env: { ...(existing.env ?? {}), ...(override.env ?? {}) } + env: mergeEnvMaps(existing.env, override.env) }); } return services; } +function serviceDeclarationEnvForProfile(deploy, profile, serviceId) { + if (!isRuntimeLane(profile)) return {}; + const env = deploy?.lanes?.[profile]?.serviceDeclarations?.[serviceId]?.env; + if (!env || typeof env !== "object" || Array.isArray(env)) return {}; + return cloneJson(env); +} + +function mergeEnvMaps(...values) { + const result = {}; + for (const value of values) { + if (!value || typeof value !== "object" || Array.isArray(value)) continue; + Object.assign(result, value); + } + return result; +} + function runtimeNodeIdForProfile(deploy, profile, fallback = "node") { if (!isRuntimeLane(profile)) return fallback; const nodeId = deploy?.lanes?.[profile]?.node;