ci: publish the image, but only past the test suite

One image (gitea.reeseapps.com/experimental/mirror), tagged :main on main and
a version tag on release, exactly like brain-of-reese — plus a `test` job the
publish job `needs`. A red pipeline therefore leaves :main on the last good
build, which is what podman auto-update keeps serving: red means nothing
shipped, not that production broke.

The test job runs unit + API only and --ignores tests/e2e rather than
deselecting it: -m filtering happens after collection, and tests/e2e/conftest.py
imports playwright, so a marker alone would not keep the browser suite out of a
container that has no browser. The e2e and realdisplay rungs stay local gates
(AGENTS.md), and pyright is not in CI either, since the python container has no
node to run it with — that asymmetry is written down rather than pretended
away.

The image sheds curl and its HEALTHCHECK: health belongs to the deployment
(HealthCmd in the quadlet, which probes with the python already in the image),
so the runtime image no longer ships a package that exists only to answer
/healthz — and no longer contains a way to make outbound requests, which is
consistent with a server that dials nothing. 171 MB to 157 MB. The image
source label points at the real repo now instead of example.invalid.

Verified locally with podman 5.8: the image builds, `mirror --help` exits 0,
and it serves on 8080 when MIRROR_PORT says 8080.

LLM-Generated: true
This commit is contained in:
2026-11-01 17:46:58 -05:00
parent 896cca2f23
commit 24cb10ee5c
2 changed files with 89 additions and 8 deletions
+82
View File
@@ -0,0 +1,82 @@
name: Build and Push Containers
on:
push:
branches:
- main
release:
types:
- published
jobs:
# Gate: the image is only published if the suite is green. A failing job here
# leaves :main on the last good build, which is what `podman auto-update`
# keeps serving on reeseapps-mirror — so red means "nothing shipped", not
# "production is broken".
test:
runs-on: ubuntu-latest
container:
image: python:3.13-slim
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Install the package and the test tooling
run: |
pip install --no-cache-dir --upgrade pip
pip install --no-cache-dir -e .
pip install --no-cache-dir \
pytest pytest-asyncio pytest-cov pytest-timeout httpx ruff
- name: Lint
run: |
ruff check .
ruff format --check .
# Unit + API only. tests/e2e drives a real Chromium through capture ->
# encode -> SRTP -> decode and needs a browser install and, for the
# realdisplay rung, an X server; both stay local gates (see AGENTS.md).
# --ignore keeps them out of collection entirely: -m filtering happens
# after import, and tests/e2e/conftest.py imports playwright.
- name: Test
run: pytest -q --no-cov --ignore=tests/e2e
- name: Smoke the image build
# Catches a broken Containerfile (a missing COPY source, a bad uv
# install) here rather than in the publish job below.
run: |
apt-get update -qq && apt-get install -y -qq --no-install-recommends podman
podman build -t mirror:ci .
podman run --rm mirror:ci --help >/dev/null
build-and-push-app:
needs: test
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Login to Gitea Container Registry
uses: docker/login-action@v3
with:
registry: gitea.reeseapps.com
username: ${{ secrets.REGISTRY_USERNAME }}
password: ${{ secrets.REGISTRY_PASSWORD }}
- name: Extract metadata
id: meta
uses: docker/metadata-action@v5
with:
images: gitea.reeseapps.com/experimental/mirror
tags: |
type=raw,value=main,enable=${{ github.ref == 'refs/heads/main' }}
type=ref,event=tag
- name: Build and push app image
uses: docker/build-push-action@v6
with:
context: .
file: Containerfile
push: true
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}