From 219df74466b32cdb483fca3a0c187daa28d8c563 Mon Sep 17 00:00:00 2001 From: "Aaron D. Lee" Date: Mon, 6 Jul 2026 15:32:24 -0400 Subject: [PATCH] =?UTF-8?q?ci:=20image-build=20job=20=E2=80=94=20builds=20?= =?UTF-8?q?the=20four=20first-party=20Docker=20images=20(deploy-B=20=C2=A7?= =?UTF-8?q?6.1)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Extends .github/workflows/ci.yml with an image-build job, gated on the existing fmt/clippy/test/deny/sim-bench matrix (needs: [fmt, clippy, test, deny, sim-bench]). Builds all four images via docker buildx against deploy/Dockerfile's named --targets, with type=gha caching scoped per image so warm caches take image-build from ~6min to ~90s. Tags the freshly-built :ci- images as :smoke too, for the downstream smoke job to consume. Runs `caddy validate` inside the freshly-built rutster-edge as a cheap Caddyfile-syntax regression. No changes to the existing fmt/clippy/test/deny/sim-bench/twilio-live jobs — those stay the cargo-side source of truth. Signed-off-by: Aaron D. Lee --- .github/workflows/ci.yml | 97 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 97 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 9187a76..cf9748c 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -168,3 +168,100 @@ jobs: RUTSTER_TWILIO_TEST_TO: ${{ secrets.TWILIO_TEST_TO }} RUTSTER_TWILIO_TEST_FROM: ${{ secrets.TWILIO_TEST_FROM }} run: cargo test --all --features=twilio-live -- --include-ignored + + # deploy-B §6.1 image-build — builds all four first-party images via + # `docker buildx build --target` against deploy/Dockerfile. Runs AFTER the + # fmt/clippy/test/deny/sim-bench matrix gates: the smoke job downstream + # depends on these built images. + # + # Single builder invocation that builds all four --targets would be ideal + # (shared cache), but buildx's `--target` is one-per-invocation — so four + # build steps share the GHA cache via `cache-from/cache-to: type=gha`. + # Warm caches take image-build from ~6 min to ~90s. + image-build: + name: image-build (4 images) + runs-on: ubuntu-latest + needs: [fmt, clippy, test, deny, sim-bench] + steps: + - uses: actions/checkout@v4 + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + + # libopus-dev — the headers the `opus` crate's build.rs expects. + # (The builder stage of deploy/Dockerfile already installs this + # inside the build image; this is a belt-and-braces step so a local + # buildx cache root has the headers if the cache misses.) + - name: Build-time host deps (belt-and-braces) + run: sudo apt-get update && sudo apt-get install -y libopus-dev + + - name: Build rutster-engine image + uses: docker/build-push-action@v5 + with: + context: . + file: deploy/Dockerfile + target: rutster-engine + tags: rutster-engine:ci-${{ github.sha }} + push: false + load: true + cache-from: type=gha,scope=rutster-engine + cache-to: type=gha,mode=max,scope=rutster-engine + + - name: Build rutster-brain image + uses: docker/build-push-action@v5 + with: + context: . + file: deploy/Dockerfile + target: rutster-brain + tags: rutster-brain:ci-${{ github.sha }} + push: false + load: true + cache-from: type=gha,scope=rutster-brain + cache-to: type=gha,mode=max,scope=rutster-brain + + - name: Build rutster-edge image + uses: docker/build-push-action@v5 + with: + context: . + file: deploy/Dockerfile + target: rutster-edge + tags: rutster-edge:ci-${{ github.sha }} + push: false + load: true + cache-from: type=gha,scope=rutster-edge + cache-to: type=gha,mode=max,scope=rutster-edge + + - name: Build rutster-allinone image + uses: docker/build-push-action@v5 + with: + context: . + file: deploy/Dockerfile + target: rutster-allinone + tags: rutster-allinone:ci-${{ github.sha }} + push: false + load: true + cache-from: type=gha,scope=rutster-allinone + cache-to: type=gha,mode=max,scope=rutster-allinone + + - name: Smoke-tag the images for the downstream smoke job + # The smoke job references images as `:smoke` + # (deploy/smoke/compose_smoke.sh tags images with the + # RUTSTER_IMAGES_TAG env). Tag the freshly-built :ci- images as + # :smoke too, so the smoke job picks them up. + run: | + for img in rutster-engine rutster-brain rutster-edge rutster-allinone; do + docker tag "${img}:ci-${{ github.sha }}" "${img}:smoke" + done + docker images | grep rutster + + - name: caddy validate + # Validate the Caddyfile inside the freshly-built rutster-edge image. + # Cheap regression against malformed Caddyfile (the local `caddy + # validate` in Task 3 is optional; this one is mandatory in CI). + run: | + docker run --rm \ + -e RUTSTER_DOMAIN=pbx.example.com \ + -e RUTSTER_ACME_EMAIL=test@example.com \ + -v "$PWD/deploy/Caddyfile:/etc/caddy/Caddyfile:ro" \ + rutster-edge:smoke \ + caddy validate --config /etc/caddy/Caddyfile --adapter caddyfile