fix: 切换 HWLAB 投影实时权威

This commit is contained in:
Codex
2026-07-13 20:28:47 +02:00
parent d420251f2e
commit c1af68475e
6 changed files with 382 additions and 34 deletions
@@ -6,7 +6,7 @@ import path from "node:path";
const repoDir = process.cwd();
const overlay = readOverlay();
const runtimePath = requiredOverlayString("runtimePath");
const runtimePath = process.env.UNIDESK_RUNTIME_GITOPS_RUNTIME_PATH || requiredOverlayString("runtimePath");
const runtimeDir = path.resolve(repoDir, runtimePath);
const prometheusOperatorKinds = new Set(["ServiceMonitor", "PrometheusRule", "PodMonitor", "Probe"]);
@@ -20,26 +20,117 @@ emit({ ok: true, runtimePath, ...result });
function postprocessRuntimeGitops() {
const prometheusOperatorDisabled = overlay?.observability?.prometheusOperator === false;
if (!prometheusOperatorDisabled) {
return { observabilityPrometheusOperator: overlay?.observability?.prometheusOperator ?? null, observabilityWorkloadsChanged: false, kustomizationChanged: false };
}
const changedFiles = [];
const deletedFiles = [];
for (const file of listYamlFiles(runtimeDir)) {
const changed = stripPrometheusOperatorResourcesFromFile(file);
const changed = prometheusOperatorDisabled ? stripPrometheusOperatorResourcesFromFile(file) : "unchanged";
if (changed === "deleted") deletedFiles.push(path.relative(repoDir, file));
if (changed === "changed") changedFiles.push(path.relative(repoDir, file));
}
const kustomizationChanged = pruneMissingKustomizationResources();
const kustomizationChanged = prometheusOperatorDisabled ? pruneMissingKustomizationResources() : false;
const codeAgentRuntimeChanged = patchCodeAgentRuntimeWorkloads();
return {
observabilityPrometheusOperator: false,
observabilityPrometheusOperator: overlay?.observability?.prometheusOperator ?? null,
observabilityWorkloadsChanged: changedFiles.length > 0 || deletedFiles.length > 0,
kustomizationChanged,
codeAgentRuntimeChanged,
changedFiles,
deletedFiles,
};
}
function patchCodeAgentRuntimeWorkloads() {
const runtime = overlay?.codeAgentRuntime;
if (!runtime?.enabled || !runtime.kafkaEventBridge) return false;
const kafka = runtime.kafkaEventBridge;
let changed = false;
for (const file of listYamlFiles(runtimeDir)) {
const parsed = parseJsonDocument(readFileSync(file, "utf8"));
if (parsed === null) continue;
const items = isKubernetesList(parsed) ? parsed.items : [parsed];
let fileChanged = false;
for (const item of items) {
const workloadName = String(item?.metadata?.labels?.["app.kubernetes.io/name"] ?? item?.metadata?.name ?? "");
const containers = item?.spec?.template?.spec?.containers;
if (!Array.isArray(containers)) continue;
for (const container of containers) {
if (!Array.isArray(container?.env)) continue;
if (workloadName === "hwlab-cloud-api" && container.name === "hwlab-cloud-api") {
fileChanged = patchCloudApiKafkaEnv(container, kafka) || fileChanged;
}
if (workloadName === "hwlab-cloud-web" && container.name === "hwlab-cloud-web") {
fileChanged = setEnvValue(container, "HWLAB_WORKBENCH_LIVE_KAFKA_SSE_ENABLED", String(kafka.enabled && kafka.features.liveKafkaSse)) || fileChanged;
fileChanged = setEnvValue(container, "HWLAB_WORKBENCH_KAFKA_REFRESH_REPLAY_ENABLED", String(kafka.enabled && kafka.features.kafkaRefreshReplay)) || fileChanged;
fileChanged = setEnvValue(container, "HWLAB_WORKBENCH_PROJECTION_REALTIME_ENABLED", String(kafka.enabled && kafka.features.projectionRealtime)) || fileChanged;
}
}
}
if (fileChanged) {
writeFileSync(file, `${JSON.stringify(parsed, null, 2)}\n`, "utf8");
changed = true;
}
}
return changed;
}
function patchCloudApiKafkaEnv(container, kafka) {
let changed = false;
changed = setEnvValue(container, "HWLAB_KAFKA_ENABLED", String(kafka.enabled)) || changed;
changed = setEnvValue(container, "HWLAB_KAFKA_AGENTRUN_EVENT_CONSUME_ENABLED", String(kafka.enabled && (kafka.features.directPublish || kafka.features.transactionalProjector))) || changed;
changed = setEnvValue(container, "HWLAB_KAFKA_DIRECT_PUBLISH_ENABLED", String(kafka.enabled && kafka.features.directPublish)) || changed;
changed = setEnvValue(container, "HWLAB_WORKBENCH_LIVE_KAFKA_SSE_ENABLED", String(kafka.enabled && kafka.features.liveKafkaSse)) || changed;
changed = setEnvValue(container, "HWLAB_WORKBENCH_KAFKA_REFRESH_REPLAY_ENABLED", String(kafka.enabled && kafka.features.kafkaRefreshReplay)) || changed;
changed = setEnvValue(container, "HWLAB_KAFKA_TRANSACTIONAL_PROJECTOR_ENABLED", String(kafka.enabled && kafka.features.transactionalProjector)) || changed;
changed = setEnvValue(container, "HWLAB_KAFKA_PROJECTION_OUTBOX_RELAY_ENABLED", String(kafka.enabled && kafka.features.projectionOutboxRelay)) || changed;
changed = setEnvValue(container, "HWLAB_WORKBENCH_PROJECTION_REALTIME_ENABLED", String(kafka.enabled && kafka.features.projectionRealtime)) || changed;
changed = setEnvValue(container, "HWLAB_KAFKA_AGENTRUN_EVENT_GROUP_ID", String(kafka.directPublishConsumerGroupId)) || changed;
changed = setEnvValue(container, "HWLAB_KAFKA_PROJECTOR_GROUP_ID", String(kafka.transactionalProjectorConsumerGroupId)) || changed;
changed = setEnvValue(container, "HWLAB_KAFKA_HWLAB_EVENT_GROUP_ID", String(kafka.hwlabEventConsumerGroupId)) || changed;
changed = patchOptionalEnvGroup(container, kafka.enabled && kafka.features.transactionalProjector, {
HWLAB_KAFKA_PROJECTOR_HEARTBEAT_INTERVAL_MS: kafka.transactionalProjector?.heartbeatIntervalMs,
}) || changed;
changed = patchOptionalEnvGroup(container, kafka.enabled && kafka.features.projectionOutboxRelay, {
HWLAB_KAFKA_OUTBOX_RELAY_INTERVAL_MS: kafka.projectionOutboxRelay?.intervalMs,
HWLAB_KAFKA_OUTBOX_RELAY_BATCH_SIZE: kafka.projectionOutboxRelay?.batchSize,
HWLAB_KAFKA_OUTBOX_RELAY_LEASE_MS: kafka.projectionOutboxRelay?.leaseMs,
HWLAB_KAFKA_OUTBOX_RELAY_SEND_TIMEOUT_MS: kafka.projectionOutboxRelay?.sendTimeoutMs,
HWLAB_KAFKA_OUTBOX_RELAY_RETRY_BACKOFF_MS: kafka.projectionOutboxRelay?.retryBackoffMs,
}) || changed;
changed = patchOptionalEnvGroup(container, kafka.enabled && kafka.features.projectionRealtime, {
HWLAB_WORKBENCH_OUTBOX_TAIL_BATCH_SIZE: kafka.projectionRealtime?.outboxTailBatchSize,
HWLAB_WORKBENCH_SSE_HEARTBEAT_MS: kafka.projectionRealtime?.sseHeartbeatMs,
HWLAB_WORKBENCH_SSE_DRAIN_TIMEOUT_MS: kafka.projectionRealtime?.sseDrainTimeoutMs,
}) || changed;
return changed;
}
function patchOptionalEnvGroup(container, enabled, values) {
let changed = false;
for (const [name, value] of Object.entries(values)) {
changed = enabled ? setEnvValue(container, name, String(value)) || changed : removeEnvValue(container, name) || changed;
}
return changed;
}
function setEnvValue(container, name, value) {
const existing = container.env.find((item) => item?.name === name);
if (existing?.value === value && existing.valueFrom === undefined) return false;
if (existing) {
existing.value = value;
delete existing.valueFrom;
} else {
container.env.push({ name, value });
}
return true;
}
function removeEnvValue(container, name) {
const next = container.env.filter((item) => item?.name !== name);
if (next.length === container.env.length) return false;
container.env = next;
return true;
}
function stripPrometheusOperatorResourcesFromFile(file) {
const original = readFileSync(file, "utf8");
const jsonResult = stripPrometheusOperatorResourcesFromJsonFile(file, original);