Files
mirror/.gitea/workflows/build-and-push.yml
T
ducoterra 7257fc3c0c
Build and Push Containers / test (push) Failing after 40s
Build and Push Containers / build-and-push-app (push) Skipped
ci: run the suite where the runner can actually start it
Run #1 died in Checkout, before a single command of ours ran: actions/checkout
is a JavaScript action, and the job's `container: python:3.13-slim` has no Node
runtime for it. The same actions succeed on this instance with no `container:`
key at all (Experimental/brain-of-reese run 264 is the proof), so the job stays
on the runner and shells into the interpreter it needs instead.

The suite now runs inside a pinned python:3.13-slim via whichever of podman or
docker the runner has — the same runtime the publish job builds with, which is
why "no runtime found" is a hard failure rather than a quiet fallback to
whatever python the runner image happens to ship. Falling back there would make
the gate depend on an interpreter nobody chose.

3.13 rather than the 3.14 of the dev venv: it is the floor declared in
pyproject's requires-python, so CI checks the floor. The image-build smoke step
lost its apt-get install podman for the same reason.

LLM-Generated: true
2026-11-01 18:07:00 -05:00

105 lines
3.8 KiB
YAML

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".
#
# The suite runs *inside* a pinned python:3.13-slim container rather than via a
# `container:` job key. That is not stylistic: actions/checkout is a JavaScript
# action and a python image has no Node runtime, so run #1 died in Checkout
# before running a single command. The runner itself has both (it is where
# build-push-action builds images), so the job stays on the runner and shells
# into the container it needs.
#
# 3.13 is deliberate: it is the floor declared in pyproject's requires-python,
# so CI verifies the floor while development happens on 3.14.
test:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Locate the container runtime
id: runtime
run: |
set -euo pipefail
runtime="$(command -v podman || command -v docker || true)"
if [ -z "$runtime" ]; then
echo "Neither podman nor docker is on this runner, so this job cannot"
echo "run the suite in a pinned interpreter. Fix here rather than"
echo "falling back to whatever python the runner image happens to ship."
exit 1
fi
echo "path=$runtime" >> "$GITHUB_OUTPUT"
echo "using $runtime"
# 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: Lint and test
run: |
set -euo pipefail
"${{ steps.runtime.outputs.path }}" run --rm \
-v "$GITHUB_WORKSPACE:/src" -w /src \
docker.io/library/python:3.13-slim \
/bin/bash -euo pipefail -c '
pip install --no-cache-dir -q .
pip install --no-cache-dir -q \
pytest pytest-asyncio pytest-cov pytest-timeout httpx ruff
ruff check .
ruff format --check .
pytest -q --no-cov --ignore=tests/e2e
'
- name: Smoke the image build
# Catches a broken Containerfile (a missing COPY source, a failing uv
# install step) here rather than in the publish job below.
run: |
set -euo pipefail
"${{ steps.runtime.outputs.path }}" build -t mirror:ci .
"${{ steps.runtime.outputs.path }}" 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 }}