ci: smoke-compose + smoke-reload jobs — T2 four-service boot + caddy reload-during-call (deploy-B §9)

smoke-compose (gated on image-build):
* Rebuilds rutster-edge/engine/brain:smoke from warm GHA cache.
* Runs deploy/smoke/compose_smoke.sh — `docker compose up -d --wait`,
  asserts all four services State=running, curls /healthz + /readyz
  through Caddy TLS (internal CA). Lighter than the all-in-one smoke
  (which already proved the WS path) — its job is the orchestrator
  shape + the network_mode: "service:engine" brain->engine tap posture.

smoke-reload (gated on smoke):
* Reuses rutster-allinone:smoke + the allinone_smoke.py WS helpers.
* Runs deploy/smoke/reload_during_call.py — holds a live WS streaming
  frames at 20ms while a concurrent `caddy reload` fires mid-call;
  asserts zero frames dropped + WS survives across the reload.
  Regresses the stream_close_delay 24h mitigation against caddy #6420/
  #7222 (TLS brief §5 risk 1; spec §9 reload-during-call smoke).

Both jobs run on ubuntu-latest — separate runners for clearer failure
attribution + parallelism (the smoke gate is the failing CI signal,
not a single serial run).

Signed-off-by: Aaron D. Lee <himself@adlee.work>
This commit is contained in:
2026-07-06 15:36:53 -04:00
parent 142933c067
commit 6be53af5f3

View File

@@ -315,3 +315,96 @@ jobs:
env:
RUTSTER_ALLINONE_IMAGE: rutster-allinone:smoke
RUTSTER_ALLINONE_PORT: "18443"
# deploy-B §9 compose smoke — T2 four-service compose stack boots + all
# services healthy + Caddy TLS /healthz + /readyz. Lighter than the
# all-in-one smoke (which already proved the WS path) — its job is the
# orchestrator shape + the network_mode: "service:engine" brain->engine tap
# posture across the four services.
smoke-compose:
name: smoke (T2 compose four-service)
runs-on: ubuntu-latest
needs: [image-build]
steps:
- uses: actions/checkout@v4
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
# Rebuild all three first-party images from the warm GHA cache
# populated by image-build. Valkey is upstream (no rebuild needed).
- name: Rebuild rutster-edge:smoke
uses: docker/build-push-action@v5
with:
context: .
file: deploy/Dockerfile
target: rutster-edge
tags: rutster-edge:smoke
push: false
load: true
cache-from: type=gha,scope=rutster-edge
- name: Rebuild rutster-engine:smoke
uses: docker/build-push-action@v5
with:
context: .
file: deploy/Dockerfile
target: rutster-engine
tags: rutster-engine:smoke
push: false
load: true
cache-from: type=gha,scope=rutster-engine
- name: Rebuild rutster-brain:smoke
uses: docker/build-push-action@v5
with:
context: .
file: deploy/Dockerfile
target: rutster-brain
tags: rutster-brain:smoke
push: false
load: true
cache-from: type=gha,scope=rutster-brain
# jq is pre-installed on ubuntu-latest GHA runners.
- name: Run compose smoke (deploy/smoke/compose_smoke.sh)
run: bash deploy/smoke/compose_smoke.sh
env:
RUTSTER_IMAGES_TAG: smoke
# deploy-B §9 + spec §3.2 + TLS brief §5 risk 1: Caddy config-reload
# during a live simulated call, asserting zero frame drops. The
# stream_close_delay 24h mitigation in deploy/Caddyfile is the load-
# bearing fixture; caddy #6420 / #7222 are open upstream bugs — the
# smoke is "don't trust untested" made CI-regressed.
smoke-reload:
name: smoke (caddy reload during live call, zero drops)
runs-on: ubuntu-latest
needs: [smoke] # reuses the rutster-allinone:smoke image, warm cache
steps:
- uses: actions/checkout@v4
- name: Set up Python (stdlib-only; no pip)
uses: actions/setup-python@v5
with:
python-version: "3.x"
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Rebuild rutster-allinone:smoke (warm cache)
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 reload-during-call smoke (deploy/smoke/reload_during_call.py)
run: python3 deploy/smoke/reload_during_call.py
env:
RUTSTER_ALLINONE_IMAGE: rutster-allinone:smoke
RUTSTER_ALLINONE_PORT: "18444"