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:
@@ -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 }}
|
||||||
+7
-8
@@ -6,6 +6,11 @@
|
|||||||
# The image serves the app; it does not capture anything. Capture happens in the
|
# The image serves the app; it does not capture anything. Capture happens in the
|
||||||
# viewer's and sharer's own browsers, so there is no display, D-Bus, or PipeWire
|
# viewer's and sharer's own browsers, so there is no display, D-Bus, or PipeWire
|
||||||
# socket to pass in.
|
# socket to pass in.
|
||||||
|
#
|
||||||
|
# Deliberately no HTTP client and no HEALTHCHECK: health checks belong to the
|
||||||
|
# deployment (see HealthCmd in the reeseapps/mirror quadlet), and shipping curl
|
||||||
|
# only to answer /healthz adds a package and a way for someone inside the
|
||||||
|
# container to make requests the image otherwise cannot make.
|
||||||
|
|
||||||
FROM docker.io/library/python:3.13-slim AS builder
|
FROM docker.io/library/python:3.13-slim AS builder
|
||||||
|
|
||||||
@@ -23,12 +28,8 @@ FROM docker.io/library/python:3.13-slim
|
|||||||
|
|
||||||
LABEL org.opencontainers.image.title="mirror" \
|
LABEL org.opencontainers.image.title="mirror" \
|
||||||
org.opencontainers.image.description="Browser-only screen mirroring for the local network" \
|
org.opencontainers.image.description="Browser-only screen mirroring for the local network" \
|
||||||
org.opencontainers.image.source="https://example.invalid/mirror"
|
org.opencontainers.image.source="https://gitea.reeseapps.com/experimental/mirror" \
|
||||||
|
org.opencontainers.image.licenses="MIT"
|
||||||
# curl is for the HEALTHCHECK only; nothing else in the runtime image reaches out.
|
|
||||||
RUN apt-get update \
|
|
||||||
&& apt-get install -y --no-install-recommends curl \
|
|
||||||
&& rm -rf /var/lib/apt/lists/*
|
|
||||||
|
|
||||||
COPY --from=builder /opt/venv /opt/venv
|
COPY --from=builder /opt/venv /opt/venv
|
||||||
ENV PATH="/opt/venv/bin:${PATH}" \
|
ENV PATH="/opt/venv/bin:${PATH}" \
|
||||||
@@ -43,8 +44,6 @@ USER mirror
|
|||||||
WORKDIR /home/mirror
|
WORKDIR /home/mirror
|
||||||
|
|
||||||
EXPOSE 8055
|
EXPOSE 8055
|
||||||
HEALTHCHECK --interval=20s --timeout=3s --start-period=5s --retries=3 \
|
|
||||||
CMD curl -fsS http://127.0.0.1:8055/healthz || exit 1
|
|
||||||
|
|
||||||
ENTRYPOINT ["mirror"]
|
ENTRYPOINT ["mirror"]
|
||||||
CMD ["serve"]
|
CMD ["serve"]
|
||||||
|
|||||||
Reference in New Issue
Block a user