#!/usr/bin/env bash # ci/l1.sh — Stage 4: L1 rendering checks. Runs in CI WITHOUT a cluster # (docs/14: "L1 rendering assertions run in CI without a cluster"). # # L1 asserts ServiceDefinition -> rendered resources match golden expectations # (e.g. `egress: vpn` renders the kill-switched egress path). The actual render # + assert is Chainsaw's L1 layer, owned by the conformance harness (T-0.4). # CI just invokes the runner filtered to the L1 layer and the touched subset. set -euo pipefail CI_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" # shellcheck disable=SC1091 source "${CI_DIR}/lib.sh" log "Stage: L1 rendering checks (no cluster)" mkartifacts if ! entrypoint_ready "$CONFORMANCE_CMD"; then skip "conformance runner not present at '${CONFORMANCE_CMD}' (T-0.4 / conformance/ not delivered yet) — UNWIRED, not green" summary "- l1-render: **SKIPPED** (conformance runner missing — T-0.4)" exit 3 fi # Touched-requirement subset (R-TEST-03). Empty subset => run all L1 as a sanity net. mapfile -t reqs < <("${CI_DIR}/touched-requirements.sh" || true) req_args=() if [ "${#reqs[@]}" -gt 0 ]; then log "touched requirements: ${reqs[*]}" req_args=(--requirements "$(IFS=,; echo "${reqs[*]}")") fi # RECONCILED (PM 2026-08-16): conformance/run.sh's real interface is `--layer ` # [--requirements R-A,R-B]; it ALWAYS writes artifacts to a FIXED location # (conformance/_artifacts/) and does NOT accept --junit/--coverage. Invoke by layer + # touched subset, then COLLECT its artifacts into the CI artifact dirs. "$CONFORMANCE_CMD" --layer l1 "${req_args[@]}" CONF_ART="$(dirname "$CONFORMANCE_CMD")/_artifacts" if [ -f "${CONF_ART}/report.junit.xml" ]; then cp "${CONF_ART}/report.junit.xml" "${JUNIT_DIR}/l1.junit.xml" fi if [ -d "${CONF_ART}/coverage" ]; then cp -r "${CONF_ART}/coverage/." "${COVERAGE_DIR}/" fi ok "L1 rendering checks passed" summary "- l1-render: **passed**"