Custom CI image with PHP 8.4 baked in (avoid setup-php entirely) #17

Closed
opened 2026-06-10 20:05:59 +02:00 by myrmidex · 0 comments
Owner

Background

See #16: CI's "Set up PHP" step (shivammathur/setup-php@v2) takes 7m46s of a ~9min pipeline. Investigation found that actions/cache@v4 never successfully saves on this runner (root cause undetermined after ~2h investigation, deprioritized) — so caching /usr/local/php was never going to help anyway, separately from the cache backend issue (setup-php installs to /usr/bin/php, not /usr/local/php).

This ticket is the actual fix: build a custom CI image with PHP 8.4 + required extensions + composer already baked in, eliminating "Set up PHP" entirely — replaced by a docker pull of a (registry-cached) image layer.

Scope

  • New Dockerfile (e.g. .forgejo/ci.Dockerfile or similar location), based on catthehacker/ubuntu:act-latest, with PHP 8.4 + extensions (pdo_pgsql, mbstring, xml, dom, intl, pcov) + composer pre-installed
  • Build and push the image to this Forgejo instance's container registry
  • Update .forgejo/workflows/ci.yml: container.image points to the new custom image; remove "Set up PHP" step (already removed the dead cache steps as part of #16's pivot)
  • Document how to rebuild/republish the image when PHP version or extensions change (e.g. a small composer script or README note — keep it lightweight)

Verification

  • CI pipeline runs successfully against the new image
  • php -v, extensions, and composer version match what the workflow currently expects (PHP 8.4.x, pdo_pgsql/mbstring/xml/dom/intl/pcov enabled, composer 2.x)
  • Pipeline time for the PHP setup portion drops from ~7-8min to near-zero (image pull, cached after first run)

Result

Done. New .forgejo/ci/Dockerfile (PHP 8.4 + pdo_pgsql/mbstring/xml/dom/intl/pcov via ondrej/php PPA + Composer from composer:2, on top of catthehacker/ubuntu:act-latest), built and pushed to forge.lvl0.xyz/lvl0/rater-ci:latest by .forgejo/workflows/ci-image.yml (push-to-main only, path-filtered to the Dockerfile/workflow itself).

ci.yml now uses this image and no longer runs setup-php. Verified:

  • First run (cold pull): "Set up job" 5m6s
  • Second run (cached image layer): "Set up job" 16s
  • Total pipeline: ~9min → ~2.5min

Remaining cost is "Install dependencies" (composer install, ~1m27s, uncached due to #16's unresolved cache issue) — considered baking vendor/ into the image too, but rejected: dependency-bump commits would trigger a slow image rebuild, and PRs changing composer.lock would run against a stale baked-in vendor/, which is exactly the case where correctness matters most. Left for #16 to potentially address via a different caching approach later.

PLATFORM.md updated with the new CI image setup and rebuild instructions.

## Background See #16: CI's "Set up PHP" step (`shivammathur/setup-php@v2`) takes 7m46s of a ~9min pipeline. Investigation found that `actions/cache@v4` never successfully saves on this runner (root cause undetermined after ~2h investigation, deprioritized) — so caching `/usr/local/php` was never going to help anyway, separately from the cache backend issue (`setup-php` installs to `/usr/bin/php`, not `/usr/local/php`). This ticket is the actual fix: build a custom CI image with PHP 8.4 + required extensions + composer already baked in, eliminating "Set up PHP" entirely — replaced by a `docker pull` of a (registry-cached) image layer. ## Scope - New `Dockerfile` (e.g. `.forgejo/ci.Dockerfile` or similar location), based on `catthehacker/ubuntu:act-latest`, with PHP 8.4 + extensions (pdo_pgsql, mbstring, xml, dom, intl, pcov) + composer pre-installed - Build and push the image to this Forgejo instance's container registry - Update `.forgejo/workflows/ci.yml`: `container.image` points to the new custom image; remove "Set up PHP" step (already removed the dead cache steps as part of #16's pivot) - Document how to rebuild/republish the image when PHP version or extensions change (e.g. a small composer script or README note — keep it lightweight) ## Verification - CI pipeline runs successfully against the new image - `php -v`, extensions, and composer version match what the workflow currently expects (PHP 8.4.x, pdo_pgsql/mbstring/xml/dom/intl/pcov enabled, composer 2.x) - Pipeline time for the PHP setup portion drops from ~7-8min to near-zero (image pull, cached after first run) ## Result ✅ Done. New `.forgejo/ci/Dockerfile` (PHP 8.4 + pdo_pgsql/mbstring/xml/dom/intl/pcov via ondrej/php PPA + Composer from `composer:2`, on top of `catthehacker/ubuntu:act-latest`), built and pushed to `forge.lvl0.xyz/lvl0/rater-ci:latest` by `.forgejo/workflows/ci-image.yml` (push-to-main only, path-filtered to the Dockerfile/workflow itself). `ci.yml` now uses this image and no longer runs `setup-php`. Verified: - First run (cold pull): "Set up job" 5m6s - Second run (cached image layer): "Set up job" 16s - **Total pipeline: ~9min → ~2.5min** Remaining cost is "Install dependencies" (composer install, ~1m27s, uncached due to #16's unresolved cache issue) — considered baking `vendor/` into the image too, but rejected: dependency-bump commits would trigger a slow image rebuild, and PRs changing `composer.lock` would run against a stale baked-in `vendor/`, which is exactly the case where correctness matters most. Left for #16 to potentially address via a different caching approach later. PLATFORM.md updated with the new CI image setup and rebuild instructions.
myrmidex added this to the v0.1.0 MVP milestone 2026-06-10 20:05:59 +02:00
myrmidex added the
ci-cd
label 2026-06-10 20:05:59 +02:00
myrmidex self-assigned this 2026-06-10 23:25:38 +02:00
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference: lvl0/rater#17
No description provided.