feat: add JD01 YAML-first deployment support

This commit is contained in:
Codex
2026-06-29 08:13:34 +00:00
parent fe917bec4a
commit 076c4b643d
49 changed files with 10909 additions and 5223 deletions
+8 -16
View File
@@ -7,10 +7,9 @@
// Responsibility: Persistent HTTP wrapper service for web-probe observe scheduling, index, health, metrics, maintenance, and dashboard.
import { Buffer } from "node:buffer";
import { createHash, randomUUID } from "node:crypto";
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
import { existsSync, mkdirSync, writeFileSync } from "node:fs";
import { join } from "node:path";
import { Database } from "bun:sqlite";
import { rootPath } from "./config";
import { renderWebProbeSentinelDashboardHtml, webProbeSentinelDashboardAssetResponse } from "./hwlab-node-web-sentinel-dashboard-assets";
import { webProbeSentinelConfigPlan, type WebProbeSentinelConfigPlan } from "./hwlab-node-web-sentinel-config";
import type { HwlabRuntimeLaneSpec } from "./hwlab-node-lanes";
@@ -91,12 +90,12 @@ export interface WebProbeSentinelService {
export function loadWebProbeSentinelServiceConfig(spec: HwlabRuntimeLaneSpec, options: Omit<WebProbeSentinelServiceOptions, "spec"> = {}): WebProbeSentinelServiceConfig {
const sentinel = resolveWebProbeSentinel(spec, options.sentinelId ?? null);
const plan = webProbeSentinelConfigPlan(spec, "status", sentinel.id);
const runtime = recordTarget(readSentinelConfigRefTarget(sentinel.configRefs.runtime));
const scenarios = scenarioArrayTarget(readSentinelConfigRefTarget(sentinel.configRefs.scenarios));
const reportViews = resolveReportViewsWithCheckCatalog(recordTarget(readSentinelConfigRefTarget(sentinel.configRefs.reportViews)));
const rawPublicExposure = recordTarget(readSentinelConfigRefTarget(sentinel.configRefs.publicExposure));
const runtime = recordTarget(readSentinelConfigRefTarget(sentinel.configRefs.runtime, spec));
const scenarios = scenarioArrayTarget(readSentinelConfigRefTarget(sentinel.configRefs.scenarios, spec));
const reportViews = resolveReportViewsWithCheckCatalog(recordTarget(readSentinelConfigRefTarget(sentinel.configRefs.reportViews, spec)), spec);
const rawPublicExposure = recordTarget(readSentinelConfigRefTarget(sentinel.configRefs.publicExposure, spec));
const publicExposure = effectiveWebProbeSentinelPublicExposure(spec, sentinel.id, rawPublicExposure);
const cicd = recordTarget(readSentinelConfigRefTarget(sentinel.configRefs.cicd));
const cicd = recordTarget(readSentinelConfigRefTarget(sentinel.configRefs.cicd, spec));
const stateRoot = options.stateRootOverride ?? stringAt(runtime, "stateRoot");
const yamlSqlitePath = stringAt(runtime, "sqlite.path");
return {
@@ -269,12 +268,12 @@ export function createWebProbeSentinelService(options: WebProbeSentinelServiceOp
return service;
}
function resolveReportViewsWithCheckCatalog(reportViews: Record<string, unknown>): Record<string, unknown> {
function resolveReportViewsWithCheckCatalog(reportViews: Record<string, unknown>, spec: HwlabRuntimeLaneSpec): Record<string, unknown> {
const ref = stringOrNull(reportViews.checkCatalogRef);
if (ref === null) return reportViews;
return {
...reportViews,
checkCatalog: recordTarget(readSentinelConfigRefTarget(ref)),
checkCatalog: recordTarget(readSentinelConfigRefTarget(ref, spec)),
};
}
@@ -694,13 +693,6 @@ function plannedRunBacklog(config: WebProbeSentinelServiceConfig, db: Database):
};
}
function readConfigRefTarget(ref: string): unknown {
const [file, path] = ref.split("#");
if (file === undefined || path === undefined) throw new Error(`invalid configRef: ${ref}`);
const text = readFileSync(rootPath(file), "utf8");
return valueAtPath(Bun.YAML.parse(text) as unknown, path);
}
function writeMetadata(db: Database, key: string, value: unknown): void {
db.query("INSERT INTO metadata (key, value_json, updated_at) VALUES (?, ?, ?) ON CONFLICT(key) DO UPDATE SET value_json = excluded.value_json, updated_at = excluded.updated_at")
.run(key, JSON.stringify(value), nowIso());