Files
pyWebLayout/Dockerfile.ci
T
dtourolleandClaude Opus 5 745fc8687e
Python CI / test (3.10) (push) Successful in 1m21s
Python CI / test (3.11) (push) Successful in 1m7s
Python CI / test (3.12) (push) Successful in 1m9s
Python CI / test (3.13) (push) Successful in 1m23s
ci: run tests in a prebuilt container image
Matches the convention used by pyPhotoAlbum and the other projects here:
runs-on: linux/amd64 with a container image from the Gitea registry,
instead of setup-python plus an ad-hoc `pip install pytest pytest-cov
flake8 coverage-badge interrogate` on a self-hosted runner.

pyWebLayout is a library, so the image carries all four interpreters
pyproject.toml claims to support - 3.10, 3.11, 3.12, 3.13 - each in its
own venv at /opt/py<version> with every dependency pre-installed. The
matrix picks one per job. A CI run now downloads nothing, and coverage
widens from 3.10/3.12/3.13 to the full declared range.

Ubuntu marks its system Python externally-managed, so per-interpreter
venvs are used rather than --break-system-packages; that also keeps the
four dependency sets isolated.

Two defects in the existing workflow are fixed while rewriting it:

- pytest runs under continue-on-error so the badge steps still execute,
  but nothing afterwards checked its outcome - the job reported green on
  a red suite. An explicit gate now fails the job.
- Every matrix leg ran the badge steps and force-pushed the badges
  branch, so three jobs raced to publish. Badges and artifacts are now
  produced by the 3.13 leg only.

setuptools is pinned below 81 in the image: that release dropped
pkg_resources, which coverage-badge imports at startup, and without the
pin the badge step dies with ModuleNotFoundError. Found by running the
workflow's own commands in the image rather than assuming they work.

Also raises the test Flask server's readiness budget from 5s to 30s.
Making that check raise instead of silently falling through (737cf07)
turned runner load into a hard failure; it showed up as 17 spurious
errors in one containerised run and did not reproduce in three repeats.
The loop still exits as soon as the server answers.

Verified locally: image builds, and tests/ passes 916 on each of 3.10,
3.11, 3.12 and 3.13 inside it. The publishing leg was run end to end -
clean-install dependency check, pytest with coverage, both badges,
coverage summary at 81.5%.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-08 14:10:05 +02:00

81 lines
3.1 KiB
Docker

# CI test image for pyWebLayout
# Build: docker build -f Dockerfile.ci -t gitea.tourolle.paris/dtourolle/pyweblayout-ci:latest .
# Push: docker push gitea.tourolle.paris/dtourolle/pyweblayout-ci:latest
#
# pyWebLayout is a library, so CI tests every interpreter pyproject.toml claims
# to support rather than just one. All four are in this image and the workflow
# matrix picks one per job; dependencies are pre-installed into each, so a CI
# run downloads nothing.
FROM ubuntu:24.04
ENV DEBIAN_FRONTEND=noninteractive
# deadsnakes carries the Python versions Ubuntu 24.04 does not ship
RUN apt-get update && apt-get install -y --no-install-recommends \
ca-certificates \
gnupg \
software-properties-common \
&& add-apt-repository -y ppa:deadsnakes/ppa \
&& apt-get update && apt-get install -y --no-install-recommends \
# Interpreters. 3.12 is Ubuntu 24.04's own; the rest come from deadsnakes.
python3.10 python3.10-venv \
python3.11 python3.11-venv \
python3.12 python3.12-venv \
python3.13 python3.13-venv \
# Pillow needs these at runtime for font rasterisation and image IO
libfreetype6 \
libjpeg-turbo8 \
libopenjp2-7 \
libtiff6 \
zlib1g \
# Used by the workflow itself
curl \
git \
nodejs \
&& rm -rf /var/lib/apt/lists/*
# One venv per interpreter at a predictable path, /opt/py<version>. Ubuntu marks
# its system Python externally-managed, so installing into venvs sidesteps that
# without --break-system-packages, and keeps the four dependency sets isolated.
#
# The package list is written once so versions cannot drift between
# interpreters. It mirrors pyproject.toml's runtime deps plus the test and dev
# extras; keep the two in step.
#
# Deliberately NOT installed: pyWebLayout itself. The workflow installs the
# checkout with --no-deps, so a job always tests the code under review.
#
# setuptools is pinned below 81 because that release dropped pkg_resources,
# which coverage-badge still imports at startup. Without the pin the badge step
# dies with ModuleNotFoundError. Revisit when coverage-badge stops using it.
RUN for v in 3.10 3.11 3.12 3.13; do \
python$v -m venv /opt/py$v && \
/opt/py$v/bin/pip install --no-cache-dir --upgrade pip wheel && \
/opt/py$v/bin/pip install --no-cache-dir --upgrade "setuptools<81" && \
/opt/py$v/bin/pip install --no-cache-dir \
Pillow \
numpy \
pyphen \
beautifulsoup4 \
lxml \
pytest \
pytest-cov \
flask \
werkzeug \
ebooklib \
requests \
flake8 \
coverage-badge \
interrogate \
; \
done
# Fail the build rather than ship an image whose dependencies do not import
RUN for v in 3.10 3.11 3.12 3.13; do \
echo "--- python$v ---" && \
/opt/py$v/bin/python -c \
"import sys, PIL, numpy, pyphen, bs4, pytest, flask, ebooklib, requests; \
print(sys.version.split()[0], 'deps OK')" \
; \
done