feat(cicd): add warning-only feature config validation

This commit is contained in:
Codex
2026-07-14 04:46:01 +02:00
parent 7eebc513b2
commit 90e5ad8e89
38 changed files with 1160 additions and 493 deletions
@@ -3,7 +3,7 @@ import { mkdtempSync, readFileSync, rmSync } from "node:fs";
import { tmpdir } from "node:os";
import { join } from "node:path";
import { rootPath } from "../../src/config";
import { exportCicdOtelPayload, loadCicdOtelRuntimeConfig } from "./otel-runtime-config";
import { exportCicdOtelPayload, loadCicdOtelRuntimeConfig, selectCicdOtelRepository } from "./otel-runtime-config";
const roots: string[] = [];
@@ -12,7 +12,7 @@ afterEach(() => {
});
test("unexpanded Repository inputs fall back to materialized owning YAML", () => {
const config = loadCicdOtelRuntimeConfig("NC01", "v03", {
const config = loadCicdOtelRuntimeConfig("sentinel-nc01-v03", {
OTEL_EXPORTER_OTLP_TRACES_ENDPOINT: "{{otel_traces_endpoint}}",
OTEL_SERVICE_NAME: "{{otel_service_name}}",
OTEL_TRACES_SAMPLER_ARG: "{{otel_sampling_ratio}}",
@@ -34,7 +34,7 @@ test("unexpanded Repository inputs fall back to materialized owning YAML", () =>
});
test("valid but mismatched runtime inputs cannot override owning YAML", () => {
const config = loadCicdOtelRuntimeConfig("NC01", "v03", {
const config = loadCicdOtelRuntimeConfig("sentinel-nc01-v03", {
OTEL_EXPORTER_OTLP_TRACES_ENDPOINT: "http://collector.example.invalid:4318/v1/traces",
OTEL_SERVICE_NAME: "different-service",
OTEL_TRACES_SAMPLER_ARG: "0.5",
@@ -53,7 +53,7 @@ test("valid but mismatched runtime inputs cannot override owning YAML", () => {
});
test("legal owning endpoint and non-blocking exporter failure share the bounded helper", async () => {
const config = loadCicdOtelRuntimeConfig("NC01", "v03", {
const config = loadCicdOtelRuntimeConfig("sentinel-nc01-v03", {
OTEL_EXPORTER_OTLP_TRACES_ENDPOINT: "http://otel-collector.platform-infra.svc.cluster.local:4318/v1/traces",
OTEL_SERVICE_NAME: "unidesk-cicd-sentinel-nc01",
OTEL_TRACES_SAMPLER_ARG: "1",
@@ -81,6 +81,14 @@ test("legal owning endpoint and non-blocking exporter failure share the bounded
});
});
test("repository identity selection fails closed on zero or multiple exact matches", () => {
expect(() => selectCicdOtelRepository([], "sentinel-nc01-v03")).toThrow("matched 0");
expect(() => selectCicdOtelRepository([
{ id: "sentinel-nc01-v03", params: {} },
{ id: "sentinel-nc01-v03", params: {} },
], "sentinel-nc01-v03")).toThrow("matched 2");
});
test("actual renderer replaces unexpanded inputs without changing business exit", async () => {
const result = await render({ OTEL_EXPORTER_OTLP_TRACES_ENDPOINT: "{{otel_traces_endpoint}}" }, false);
expect(result.exitCode).toBe(0);
@@ -89,6 +97,12 @@ test("actual renderer replaces unexpanded inputs without changing business exit"
expect(result.stderr).toContain('"endpointHostname":"otel-collector.platform-infra.svc.cluster.local"');
expect(result.stderr).not.toContain("{{otel_traces_endpoint}}");
expect(readFileSync(join(result.outputDir, "source.sh"), "utf8")).toContain("http://otel-collector.platform-infra.svc.cluster.local:4318/v1/traces");
const publish = readFileSync(join(result.outputDir, "publish.sh"), "utf8");
expect(publish).toContain("UNIDESK_PAC_CONSUMER='sentinel-nc01-v03'");
expect(publish).toContain("feature-config-schema-validation");
expect(publish).toContain("cicd.feature_config.schema");
expect(publish).toContain("OTEL_EXPORTER_TIMEOUT_MS='300'");
expect(publish).toContain("feature-config-validator-process-failure");
});
async function render(env: Record<string, string>, traced = true) {
@@ -100,6 +114,7 @@ async function render(env: Record<string, string>, traced = true) {
"scripts/native/cicd/render-sentinel-publish-task.ts",
"--node", "NC01",
"--lane", "v03",
"--repository-id", "sentinel-nc01-v03",
"--sentinel", "nc01-web-probe-sentinel",
"--pipeline-run", "hwlab-web-probe-sentinel-nc01-test",
"--source-commit", "a".repeat(40),