CI: publish prebuilt CI images to the Gitea container registry #188

Merged
thatguygriff merged 1 commits from feature/187-ci-container-images into main 2026-08-25 01:05:35 +00:00
Owner

Step 1 of #187. Adds the CI images and the workflow that publishes them; nothing runs inside them yet.

shivammathur/setup-php installs PHP 8.3+ from apt/the ondrej PPA on these arm64 runners — a ~145s floor against ~35s for 8.1/8.2, with a tail that twice ran past the step timeout and failed the run (#178). The .deb cache softened that without removing the apt step, and 8.5 has the same shape of problem.

What this adds

  • .gitea/ci/Dockerfilephp:<version>-cli-alpine plus bash and nodejs (act_runner executes actions/checkout, actions/cache and actions/upload-artifact inside the job container), GNU coreutils/grep/sed (the workflow scripts use tac and grep --include, which busybox lacks), curl/jq/git/zip/unzip for release.yml and bin/build-zip.sh, the intl and zip extensions, and Composer 2.
  • .gitea/workflows/ci-images.yml — matrix build over 8.1/8.2/8.3/8.5, pushing git.unsupervised.ca/unsupervised/ci-php:<version>. Runs on Dockerfile changes to main, weekly, and on workflow_dispatch. On a pull request it builds without pushing, so this PR's own run proves the Dockerfile before it can move a tag.
  • docs/ci.md — what is in the image and why, how to add a PHP version, and the arch caveat.

The Unsupervised org is public, so the packages pull anonymously and the consuming jobs need no registry credentials.

Why two PRs

A job cannot run in an image that does not exist yet, so ci.yml and release.yml switch to container: only once these tags are published.

Things to watch on the first run

  • Docker in the job container. The build needs a usable daemon; act_runner provides one when container.docker_host is empty or set. The first step checks for it and says so plainly if it is missing.
  • Registry auth. It logs in with secrets.GITHUB_TOKEN. If Gitea refuses that for package writes, set a REGISTRY_TOKEN secret with a package:write PAT — the workflow already prefers it when present.

Tests

  • composer test — 966 tests, 2795 assertions, OK
  • composer lint and composer cs unaffected (no PHP source changed)
  • All three workflow files parse as YAML

No CHANGELOG.md entry: CI tooling only, nothing user-visible.

Step 1 of #187. Adds the CI images and the workflow that publishes them; nothing runs inside them yet. `shivammathur/setup-php` installs PHP 8.3+ from apt/the ondrej PPA on these arm64 runners — a ~145s floor against ~35s for 8.1/8.2, with a tail that twice ran past the step timeout and failed the run (#178). The `.deb` cache softened that without removing the apt step, and 8.5 has the same shape of problem. ## What this adds - **`.gitea/ci/Dockerfile`** — `php:<version>-cli-alpine` plus `bash` and `nodejs` (act_runner executes `actions/checkout`, `actions/cache` and `actions/upload-artifact` *inside* the job container), GNU `coreutils`/`grep`/`sed` (the workflow scripts use `tac` and `grep --include`, which busybox lacks), `curl`/`jq`/`git`/`zip`/`unzip` for `release.yml` and `bin/build-zip.sh`, the `intl` and `zip` extensions, and Composer 2. - **`.gitea/workflows/ci-images.yml`** — matrix build over 8.1/8.2/8.3/8.5, pushing `git.unsupervised.ca/unsupervised/ci-php:<version>`. Runs on Dockerfile changes to `main`, weekly, and on `workflow_dispatch`. On a pull request it builds without pushing, so this PR's own run proves the Dockerfile before it can move a tag. - **`docs/ci.md`** — what is in the image and why, how to add a PHP version, and the arch caveat. The `Unsupervised` org is public, so the packages pull anonymously and the consuming jobs need no registry credentials. ## Why two PRs A job cannot run in an image that does not exist yet, so `ci.yml` and `release.yml` switch to `container:` only once these tags are published. ## Things to watch on the first run - **Docker in the job container.** The build needs a usable daemon; act_runner provides one when `container.docker_host` is empty or set. The first step checks for it and says so plainly if it is missing. - **Registry auth.** It logs in with `secrets.GITHUB_TOKEN`. If Gitea refuses that for package writes, set a `REGISTRY_TOKEN` secret with a `package:write` PAT — the workflow already prefers it when present. ## Tests - `composer test` — 966 tests, 2795 assertions, OK - `composer lint` and `composer cs` unaffected (no PHP source changed) - All three workflow files parse as YAML No `CHANGELOG.md` entry: CI tooling only, nothing user-visible.
thatguygriff added 1 commit 2026-08-25 00:55:35 +00:00
Publish prebuilt CI images to the Gitea container registry
CI Images / Build CI image (PHP 8.2) (pull_request) Successful in 1m14s
CI Images / Build CI image (PHP 8.1) (pull_request) Successful in 1m26s
CI Images / Build CI image (PHP 8.3) (pull_request) Successful in 2m3s
CI Images / Build CI image (PHP 8.5) (pull_request) Successful in 2m9s
CI / Tests (PHP 8.2) (pull_request) Successful in 1m7s
CI / No Debug Code (pull_request) Successful in 2s
CI / Tests (PHP 8.3) (pull_request) Successful in 3m8s
CI / Tests (PHP 8.1) (pull_request) Successful in 5m55s
CI / Tests (PHP 8.5) (pull_request) Successful in 6m21s
CI / Coding Standards & Static Analysis (pull_request) Successful in 18m26s
CI / Build Plugin Zip (pull_request) Skipped
572aaf5b49
setup-php installs PHP 8.3+ from apt on these arm64 runners: a ~145s floor
against ~35s for 8.1/8.2, with a tail that twice ran past the step timeout
and failed the run (#178). Caching the .debs softened it without removing
the apt step, and 8.5 has the same problem.

Add a per-version CI image built on php:<version>-cli-alpine and a workflow
that publishes it to git.unsupervised.ca/unsupervised/ci-php:<version>. The
org is public, so the packages pull anonymously.

The image carries bash and nodejs because act_runner runs JavaScript actions
inside the job container, GNU coreutils/grep/sed because the workflow scripts
use `tac` and `grep --include`, and curl/jq/git/zip for release.yml and
bin/build-zip.sh. Composer 2 and the intl and zip extensions round it out.

Nothing consumes the images yet — ci.yml and release.yml switch over in a
follow-up, because a job cannot run in an image that has not been published.

Part of #187

Co-Authored-By: Claude Opus 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01D9acV1mHktGAb1uyvNmrR2
thatguygriff force-pushed feature/187-ci-container-images from 794df2cb4f to 572aaf5b49 2026-08-25 00:55:35 +00:00 Compare
thatguygriff merged commit e097b7a0bf into main 2026-08-25 01:05:35 +00:00
thatguygriff deleted branch feature/187-ci-container-images 2026-08-25 01:05:35 +00:00
Sign in to join this conversation.
No Reviewers
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: Unsupervised/unsupervised-scheduler#188