diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index e629c51..531a4af 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -2,7 +2,8 @@ Thanks for contributing to FileMorph! This checklist mirrors the project's standards. It is a reminder, not a hard gate — but the three required checks (lint-and-test, secret-scan, scope-check) WILL block the merge until they - are green. lockfile-drift and the veraPDF run are reported but not required. + are green. lockfile-drift, the veraPDF run and the Docker image smoke tests + are reported but not required. See CONTRIBUTING.md § "CI gates" for what each check runs. --> diff --git a/CHANGELOG.md b/CHANGELOG.md index c787024..2251691 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,47 @@ Versions follow [Semantic Versioning](https://semver.org/). ## [Unreleased] +### Added — pull requests build and smoke-test both Docker images + +`docker.yml` builds the images only after merge, and `notify-ops.yml` deploys +every successful main build, so a broken `Dockerfile`, `.dockerignore`, +`entrypoint.sh` or `requirements.lock` used to show up first on its way to +production. On 2026-05-26 a digest pin that BuildKit rejected (`FROM requires +either one or three arguments`) failed three main builds in a row before the +fix was merged. The new `.github/workflows/docker-pr.yml` builds the slim and +the office image on every pull request, without pushing them, and smoke-tests +each one: + +- The image holds `scripts/first_run.py`, the compiled German message catalogue + and `alembic.ini`, and not `.env`, `data/api_keys.json`, `.git`, `.github` or + `tests/`. A `.env` and a `data/api_keys.json` are planted in the checkout + before the build, so the check sees what `.dockerignore` does with a + self-hoster's working folder, not only with a clean checkout. A third planted + file, which nothing ignores, has to reach the image, so the check cannot pass + on a build that did not use that folder. +- The container starts the way `docker-compose.yml` runs it (all capabilities + dropped, no privilege escalation), answers `/api/v1/health` on the published + port and prints a first-run API key. `curl` inside the container, which the + Compose healthcheck uses, reaches it too, and it does not run as root. +- `ffmpeg` and Ghostscript run, and WeasyPrint renders a page. Start-up alone + would not show a missing one: the converters call them only for a conversion. +- In the office image, LibreOffice converts a text file to PDF the way the DOCX + converter calls it. + +It runs on every pull request, not only on changes to the Docker files: an app +change can break the image alone, and a workflow that a `paths:` filter skips +never reports, so it could not become a required check. It is not a required +check yet. + +Nothing in it can push, sign or deploy: its token is read-only and it uses no +secret. `notify-ops.yml` now also requires that the Docker run it follows was +started by a push or a manual dispatch in this repository, so a run for a pull +request never leads to a deploy. Tests pin both. A job in a workflow that +pull-request events trigger may hold neither a write token nor a secret; +`_privileged` in `tests/test_supply_chain_hygiene.py` now also recognises +`secrets['X']`, `toJSON(secrets)` and a reusable-workflow call's `secrets:`. +And `notify-ops.yml`'s condition and trigger are pinned word for word. + ### Fixed — self-hosting and security docs: systemd unit, licences and release facts The self-hosting, installation, development, security and licensing docs had diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index bce4ab5..831fdad 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -76,10 +76,12 @@ your change touches before you push: `secret-scan` runs the gitleaks secret scanner; `scope-check` rejects operations files and internal documents, which do not belong in this public -repository. Two more checks run on pull requests without blocking the merge: +repository. More checks run on pull requests without blocking the merge: `lockfile-drift` (`requirements.lock` must match `requirements.txt` — see -[docs/development.md](docs/development.md)) and the veraPDF validation of the -PDF/A-2b output. +[docs/development.md](docs/development.md)), the veraPDF validation of the +PDF/A-2b output, and `smoke-test (base)` and `smoke-test (office)` +([`docker-pr.yml`](.github/workflows/docker-pr.yml)), which build both Docker +images without pushing them and smoke-test each one. ---