From 142933c067fe8d3a807847c01c95acd98c5b5396 Mon Sep 17 00:00:00 2001 From: "Aaron D. Lee" Date: Mon, 6 Jul 2026 15:34:33 -0400 Subject: [PATCH] =?UTF-8?q?ci:=20smoke=20job=20=E2=80=94=20all-in-one=20TL?= =?UTF-8?q?S=20sim=20call=20through=20real=20edge->FOB=20WS=20path=20(depl?= =?UTF-8?q?oy-B=20=C2=A79)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Adds the smoke job to .github/workflows/ci.yml, gated on image-build. Runs deploy/smoke/allinone_smoke.py against the freshly-built rutster-allinone:smoke image: * Boots the all-in-one container with RUTSTER_LOCAL_CERTS=true (Caddy internal CA, no ACME in CI per spec §9). * Extracts Caddy's internal-CA root cert from /data/caddy/pki/ authorities/local/root.crt via docker cp. * Opens wss:// WS to /twilio/media-stream using the extracted root (Python stdlib ssl + socket — no pip install required, CI runner- image ships Python 3 + ssl). * Sends Twilio's connected+start handshake frames (the same JSON sequence crates/rutster-trunk/tests/ws_ping.rs uses). * Streams 200 PCM-zeroed frames at 20ms cadence as Twilio Media events. * Asserts the engine replies with at least one text frame — proving the real edge->FOB WS path works end-to-end through TLS. The compose smoke + reload-during-call smoke (Task 9) gate on this job. Signed-off-by: Aaron D. Lee --- .github/workflows/ci.yml | 50 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index cf9748c..8a7107a 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -265,3 +265,53 @@ jobs: -v "$PWD/deploy/Caddyfile:/etc/caddy/Caddyfile:ro" \ rutster-edge:smoke \ caddy validate --config /etc/caddy/Caddyfile --adapter caddyfile + + # deploy-B §9 all-in-one smoke — boots rutster-allinone with + # RUTSTER_LOCAL_CERTS=true (Caddy internal CA, no ACME in CI), extracts + # the CA root cert from /data, opens wss:// to /twilio/media-stream, + # sends Twilio's connected+start handshake frames, streams 200 PCM-zeroed + # frames at 20ms cadence, asserts the engine replies with at least one + # text frame through the real edge->FOB WS path. Spec §9 acceptance: + # * "boots" + # * "Caddy terminates TLS via its internal CA (no ACME in CI)" + # * "full sim call through the real edge->FOB WS path" + # The reload-during-call smoke (Task 9 below) and compose smoke (Task 9) + # are separate jobs that depend on this one. + smoke: + name: smoke (all-in-one TLS sim call) + runs-on: ubuntu-latest + needs: [image-build] + steps: + - uses: actions/checkout@v4 + + - name: Set up Python (stdlib-only; no pip) + uses: actions/setup-python@v5 + with: + python-version: "3.x" + + # Pull the freshly-built image from the image-build job. Since + # jobs run on separate runners + `push: false` in image-build means + # the image isn't in any registry, the smoke job rebuilds from the + # GHA cache (warm — image-build populated it). This adds ~30s vs + # an image-download artifact, but avoids the registry-auth + image- + # save/load plumbing. + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + + - name: Rebuild rutster-allinone:smoke (warm cache from image-build) + uses: docker/build-push-action@v5 + with: + context: . + file: deploy/Dockerfile + target: rutster-allinone + tags: rutster-allinone:smoke + push: false + load: true + cache-from: type=gha,scope=rutster-allinone + + - name: Run all-in-one smoke (deploy/smoke/allinone_smoke.py) + run: | + python3 deploy/smoke/allinone_smoke.py + env: + RUTSTER_ALLINONE_IMAGE: rutster-allinone:smoke + RUTSTER_ALLINONE_PORT: "18443"