Files
unsupervised-scheduler/docs/ci.md
T
thatguygriffandClaude Opus 5 f8762e1095
CI Images / Build CI image (PHP 8.2) (pull_request) Successful in 3s
CI Images / Build CI image (PHP 8.5) (pull_request) Successful in 8s
CI / Tests (PHP 8.3) (pull_request) Successful in 30s
CI Images / Build CI image (PHP 8.3) (pull_request) Successful in 4s
CI / Tests (PHP 8.2) (pull_request) Successful in 23s
CI / Tests (PHP 8.1) (pull_request) Successful in 28s
CI / No Debug Code (pull_request) Successful in 4s
CI / Coding Standards & Static Analysis (pull_request) Successful in 43s
CI / Tests (PHP 8.5) (pull_request) Successful in 23s
CI / Build Plugin Zip (pull_request) Skipped
CI Images / Build CI image (PHP 8.1) (pull_request) Successful in 1m3s
Correct the registry auth docs: the Actions token does not work
docs/ci.md and the workflow comment both described secrets.GITHUB_TOKEN as
the working credential with REGISTRY_TOKEN as a fallback. That is backwards:
the task token is rejected by Gitea's container registry (go-gitea/gitea#23642)
and the first publish attempt failed on exactly that. REGISTRY_TOKEN is
required.

Part of #187

Co-Authored-By: Claude Opus 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01D9acV1mHktGAb1uyvNmrR2
2026-08-24 22:35:10 -03:00

83 lines
3.5 KiB
Markdown

# CI images
CI and release jobs do not install PHP. They run inside prebuilt images
published to the Gitea container registry:
```
git.unsupervised.ca/unsupervised/ci-php:8.1
git.unsupervised.ca/unsupervised/ci-php:8.2
git.unsupervised.ca/unsupervised/ci-php:8.3
git.unsupervised.ca/unsupervised/ci-php:8.5
```
The `Unsupervised` org is public, so the packages pull anonymously — jobs need
no registry credentials to use them.
## Why
`shivammathur/setup-php` installs PHP 8.3+ from apt/the ondrej PPA on these
arm64 runners. That was a ~145s floor against ~35s for 8.1 and 8.2, with a
tail that twice ran past the step timeout and failed the run outright
(#178). Caching the `.deb`s helped, but the apt step itself remained, and PHP
8.5 has the same shape of problem. Pulling a 67MB image from a registry
inside the cluster replaces the whole thing (#187).
## What is in the image
`.gitea/ci/Dockerfile` builds on `php:<version>-cli-alpine` and adds:
- **`bash` and `nodejs`** — act_runner runs JavaScript actions
(`actions/checkout`, `actions/cache`, `actions/upload-artifact`) *inside*
the job container and shells `run:` steps through bash. Without these, the
first step of every job fails.
- **`coreutils`, `gawk`, `grep`, `sed`, `tar`** — GNU versions, because the
workflow scripts use `tac` and `grep --include`, which busybox does not
provide. GNU `tar` matters most: `actions/cache` shells out to
`tar --posix -P`, and busybox rejects those flags, so every cache step fails
without it. `zstd` is what `actions/cache` reaches for over gzip when it is
installed.
- **`curl`, `jq`, `git`, `zip`, `unzip`** — used by `release.yml` and
`bin/build-zip.sh`.
- **`intl` and `zip` PHP extensions**, plus Composer 2. `mbstring` is already
compiled into the official images.
## Publishing
`.gitea/workflows/ci-images.yml` builds and pushes them. It runs when the
Dockerfile changes on `main`, weekly (so PHP patch releases and Alpine
security updates land on their own), and on `workflow_dispatch`. On a pull
request it builds without pushing, so a broken Dockerfile is caught before it
reaches `main`.
## Adding or dropping a PHP version
1. Add the version to the `php` matrix in `.gitea/workflows/ci-images.yml`.
2. Merge to `main`, or dispatch the workflow, and wait for the tag to appear.
3. Add the version to the `test` matrix in `.gitea/workflows/ci.yml`.
Steps 2 and 3 cannot be one commit: a job cannot run in an image that has not
been published yet.
## Architecture
The images are built natively on whichever runner picks the job, so they carry
that runner's architecture only. Every runner in the pool is arm64 today. If
one of a different architecture ever joins, it will overwrite these tags with
its own arch and the rest will fail to pull — at which point the build needs
`docker buildx` and a multi-arch manifest.
## Registry authentication
The build pushes with the `REGISTRY_TOKEN` secret, set at the organisation
level. **This is required, not optional.** Gitea's Actions task token
(`secrets.GITHUB_TOKEN`) is rejected by the container registry —
`docker login` fails with `Get "https://git.unsupervised.ca/v2/":
unauthorized`. That is [go-gitea/gitea#23642][], open since 2023.
`REGISTRY_TOKEN` is a personal access token with the `package` scope, Read
and Write. The workflow logs in as `github.actor`, which must be the account
that owns the token; if it ever needs to differ, set a `REGISTRY_USER`
variable and the workflow will prefer it.
[go-gitea/gitea#23642]: https://github.com/go-gitea/gitea/issues/23642