Move the CI image definitions to the shared ci-php repository
CI / Coding Standards (pull_request) Successful in 14s
CI / Tests (PHP 8.1) (pull_request) Successful in 30s
CI / Tests (PHP 8.2) (pull_request) Successful in 30s
CI / Tests (PHP 8.3) (pull_request) Successful in 29s
CI / No Debug Code (pull_request) Successful in 3s
CI / Tests (PHP 8.5) (pull_request) Successful in 21s
CI / Static Analysis (pull_request) Successful in 37s
CI / Build Plugin Zip (pull_request) Skipped
CI / Coding Standards (pull_request) Successful in 14s
CI / Tests (PHP 8.1) (pull_request) Successful in 30s
CI / Tests (PHP 8.2) (pull_request) Successful in 30s
CI / Tests (PHP 8.3) (pull_request) Successful in 29s
CI / No Debug Code (pull_request) Successful in 3s
CI / Tests (PHP 8.5) (pull_request) Successful in 21s
CI / Static Analysis (pull_request) Successful in 37s
CI / Build Plugin Zip (pull_request) Skipped
The image definition and its publishing workflow were only here because this was the first project to need them. They are project-agnostic, so they now live in Unsupervised/ci-php and any PHP project can consume the same tags. The registry path is unchanged — Gitea container images are named owner/image, not after the repository that pushes them — so nothing here needs repointing. Split the combined quality job into separate phpcs and phpstan jobs. They were folded together to halve the number of toolchain installs per run; with the toolchain in the image that saves nothing, and separating them means a coding-standards failure no longer hides the static analysis result. Rewrite the workflow comments to describe what the jobs do rather than the setup step they replaced, and cut docs/ci.md down to what is specific to this project — the image contents and publishing are documented in ci-php. Closes #187 Co-Authored-By: Claude Opus 5 <[email protected]> Claude-Session: https://claude.ai/code/session_01D9acV1mHktGAb1uyvNmrR2
This commit is contained in:
+28
-65
@@ -1,7 +1,7 @@
|
||||
# CI images
|
||||
# CI
|
||||
|
||||
CI and release jobs do not install PHP. They run inside prebuilt images
|
||||
published to the Gitea container registry:
|
||||
CI and release jobs do not install PHP. They run inside the shared images
|
||||
maintained in [Unsupervised/ci-php](https://git.unsupervised.ca/Unsupervised/ci-php):
|
||||
|
||||
```
|
||||
git.unsupervised.ca/unsupervised/ci-php:8.1
|
||||
@@ -10,73 +10,36 @@ 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.
|
||||
The `Unsupervised` org is public, so they pull anonymously — no registry
|
||||
credentials in any job here. What the images contain, how they are published,
|
||||
and how to add a PHP version are documented in that repository's README.
|
||||
|
||||
## Why
|
||||
## Which job runs where
|
||||
|
||||
`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).
|
||||
| Job | Runs in |
|
||||
|---|---|
|
||||
| Coding Standards (PHPCS) | `ci-php:8.3` |
|
||||
| Static Analysis (PHPStan) | `ci-php:8.3` |
|
||||
| Tests | `ci-php:${{ matrix.php }}` |
|
||||
| Build Plugin Zip | `ci-php:8.3` |
|
||||
| No Debug Code | runner image — no PHP, and it uses GNU `grep --include` |
|
||||
| Open next-version bump PR (release.yml) | runner image — no PHP |
|
||||
|
||||
## What is in the image
|
||||
PHPCS and PHPStan are separate jobs so a coding-standards failure still lets
|
||||
the static analysis result through. They run in parallel.
|
||||
|
||||
`.gitea/ci/Dockerfile` builds on `php:<version>-cli-alpine` and adds:
|
||||
## Composer
|
||||
|
||||
- **`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.
|
||||
`composer.lock` is committed, so every job installs the same dependency set
|
||||
and two builds of the same tag ship the same vendor tree. `bin/build-zip.sh`
|
||||
stages the lock into its build directory for the same reason, then removes it
|
||||
before writing the zip.
|
||||
|
||||
## Publishing
|
||||
The Composer download cache lives at `/composer/cache` — `COMPOSER_HOME` is
|
||||
`/composer` in the image — and is keyed on `composer.lock`.
|
||||
|
||||
`.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 a PHP version to the test matrix
|
||||
|
||||
## 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
|
||||
The image has to exist first. Add the version to the `php` matrix in
|
||||
`ci-php`'s `.gitea/workflows/publish.yml` and merge, then add it to the `test`
|
||||
matrix in `.gitea/workflows/ci.yml` here.
|
||||
|
||||
Reference in New Issue
Block a user