149 lines
5.8 KiB
TypeScript
149 lines
5.8 KiB
TypeScript
import { afterEach, expect, test } from "bun:test";
|
|
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, selectCicdOtelRepository } from "./otel-runtime-config";
|
|
|
|
const roots: string[] = [];
|
|
|
|
afterEach(() => {
|
|
while (roots.length > 0) rmSync(roots.pop()!, { recursive: true, force: true });
|
|
});
|
|
|
|
test("unexpanded Repository inputs fall back to materialized owning YAML", () => {
|
|
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}}",
|
|
OTEL_EXPORTER_TIMEOUT_MS: "{{otel_exporter_timeout_ms}}",
|
|
});
|
|
expect(config).toMatchObject({
|
|
endpoint: "http://otel-collector.platform-infra.svc.cluster.local:4318/v1/traces",
|
|
endpointHostname: "otel-collector.platform-infra.svc.cluster.local",
|
|
serviceName: "unidesk-cicd-sentinel-nc01",
|
|
samplingRatio: 1,
|
|
timeoutMs: 300,
|
|
});
|
|
expect(config.fallbackCodes).toEqual([
|
|
"INVALID_ENDPOINT_INPUT",
|
|
"INVALID_SERVICE_INPUT",
|
|
"INVALID_SAMPLING_INPUT",
|
|
"INVALID_TIMEOUT_INPUT",
|
|
]);
|
|
});
|
|
|
|
test("valid but mismatched runtime inputs cannot override owning YAML", () => {
|
|
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",
|
|
OTEL_EXPORTER_TIMEOUT_MS: "600",
|
|
});
|
|
expect(config.endpointHostname).toBe("otel-collector.platform-infra.svc.cluster.local");
|
|
expect(config.serviceName).toBe("unidesk-cicd-sentinel-nc01");
|
|
expect(config.samplingRatio).toBe(1);
|
|
expect(config.timeoutMs).toBe(300);
|
|
expect(config.fallbackCodes).toEqual([
|
|
"MISMATCH_ENDPOINT_INPUT",
|
|
"MISMATCH_SERVICE_INPUT",
|
|
"MISMATCH_SAMPLING_INPUT",
|
|
"MISMATCH_TIMEOUT_INPUT",
|
|
]);
|
|
});
|
|
|
|
test("legal owning endpoint and non-blocking exporter failure share the bounded helper", async () => {
|
|
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",
|
|
OTEL_EXPORTER_TIMEOUT_MS: "300",
|
|
});
|
|
expect(config.fallbackCodes).toEqual([]);
|
|
const warning = await exportCicdOtelPayload(
|
|
config,
|
|
"00-11111111111111111111111111111111-2222222222222222-01",
|
|
"11111111111111111111111111111111",
|
|
{ resourceSpans: [] },
|
|
async () => { throw Object.assign(new TypeError("fetch failed"), { cause: { code: "ENOTFOUND" } }); },
|
|
);
|
|
expect(warning).toEqual({
|
|
event: "cicd.otel.export",
|
|
warning: true,
|
|
blocking: false,
|
|
causeCode: "ENOTFOUND",
|
|
endpointHostname: "otel-collector.platform-infra.svc.cluster.local",
|
|
timedOut: false,
|
|
errorType: "TypeError",
|
|
timeoutMs: 300,
|
|
traceId: "11111111111111111111111111111111",
|
|
valuesRedacted: true,
|
|
});
|
|
});
|
|
|
|
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);
|
|
expect(result.stderr).toContain('"event":"cicd.otel.config"');
|
|
expect(result.stderr).toContain('"blocking":false');
|
|
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) {
|
|
const outputDir = mkdtempSync(join(tmpdir(), "unidesk-render-sentinel-publish-"));
|
|
roots.push(outputDir);
|
|
const child = Bun.spawn({
|
|
cmd: [
|
|
process.execPath,
|
|
"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),
|
|
"--source-stage-ref", `refs/unidesk/snapshots/test/${"a".repeat(40)}`,
|
|
"--source-authority", "gitea-snapshot",
|
|
"--output-dir", outputDir,
|
|
],
|
|
cwd: rootPath(),
|
|
env: {
|
|
...process.env,
|
|
TRACEPARENT: traced ? "00-11111111111111111111111111111111-2222222222222222-01" : "",
|
|
OTEL_SERVICE_NAME: "unidesk-cicd-test",
|
|
OTEL_TRACES_SAMPLER_ARG: "1",
|
|
OTEL_EXPORTER_TIMEOUT_MS: "300",
|
|
...env,
|
|
},
|
|
stdout: "pipe",
|
|
stderr: "pipe",
|
|
});
|
|
const [exitCode, stdout, stderr] = await Promise.all([
|
|
child.exited,
|
|
new Response(child.stdout).text(),
|
|
new Response(child.stderr).text(),
|
|
]);
|
|
return {
|
|
exitCode,
|
|
stdout,
|
|
stderr,
|
|
outputDir,
|
|
};
|
|
}
|