From ab609898d67e8959aab3df56941cff73bb38fba0 Mon Sep 17 00:00:00 2001 From: James Griffin Date: Mon, 24 Aug 2026 22:25:02 -0300 Subject: [PATCH] Run CI and release jobs inside the prebuilt CI images MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Replaces setup-php with `container:` in every job that needs PHP. The images published by ci-images.yml already carry PHP, Composer, the intl and zip extensions and the CLI tools the workflow scripts shell out to, so nothing installs PHP at job time any more. That removes the apt path #178 was about: a ~145s floor on 8.3 against ~35s on 8.1/8.2, with a tail that twice ran past the step timeout and failed the run. All three copies of the `Keep downloaded .debs` / `Cache apt packages` workaround go with it. no-debug and bump-version stay on the runner image — neither needs PHP, and no-debug wants the runner's GNU `grep --include`. The Composer cache moves to /composer/cache, which is COMPOSER_HOME in the image, and release.yml gains the cache step it never had. Also corrects the image size in docs/ci.md to the 67MB measured from the published manifest; the ~120MB in the original was an estimate. Closes #187 Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_01D9acV1mHktGAb1uyvNmrR2 --- .gitea/workflows/ci.yml | 134 +++++++---------------------------- .gitea/workflows/release.yml | 18 +++-- docs/ci.md | 2 +- 3 files changed, 39 insertions(+), 115 deletions(-) diff --git a/.gitea/workflows/ci.yml b/.gitea/workflows/ci.yml index 9a18a90..f8c0735 100644 --- a/.gitea/workflows/ci.yml +++ b/.gitea/workflows/ci.yml @@ -7,55 +7,33 @@ on: - develop pull_request: +# Every job that needs PHP runs inside a prebuilt image from the Gitea +# container registry (see docs/ci.md). Nothing installs PHP at job time: +# setup-php's apt path for 8.3+ was 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, #187). The images are published by ci-images.yml; the org is public, +# so they pull without credentials. +# +# The registry path is spelled out in full at each use because +# jobs..container.image cannot read the `env` context. + jobs: - # PHPCS and PHPStan share a job so the two of them draw once on Setup PHP - # rather than twice. That step is slow and intermittently fails on 8.3 - # (see #178), so every job that can be folded into another is one less - # chance for a run to fall over. They run as separate steps, and PHPCS - # failing stops the job before PHPStan reports. + # PHPCS and PHPStan share a job so the two of them install dependencies + # once rather than twice. They run as separate steps, and PHPCS failing + # stops the job before PHPStan reports. quality: name: Coding Standards & Static Analysis runs-on: ubuntu-latest + container: + image: git.unsupervised.ca/unsupervised/ci-php:8.3 steps: - uses: actions/checkout@v4 - # setup-php installs PHP 8.3+ through php-builder, which apt-installs ~70 - # -dev packages before unpacking the build (#178). Ubuntu's image deletes - # the .debs after install, so every job re-downloads them. Keeping them - # and restoring them from the cache server, which lives in the cluster, - # turns a WAN download into a local one. - # - # Keyed per PHP version because the install path differs by version and - # the package sets are not interchangeable: 8.3+ pulls the ~70 -dev - # packages through php-builder, while 8.1 and 8.2 come from the ondrej - # PPA as a handful of runtime packages. Sharing one key across both lets - # whichever job finishes first decide what the others restore, and 8.1 is - # always first. - # - # Only the .debs are cached, never /var/lib/apt/lists — a stale index is - # how you get 404s mid-install. - - name: Keep downloaded .debs - run: | - sudo rm -f /etc/apt/apt.conf.d/docker-clean - echo 'Binary::apt::APT::Keep-Downloaded-Packages "true";' \ - | sudo tee /etc/apt/apt.conf.d/99keep-downloaded-packages >/dev/null - - - name: Cache apt packages - uses: actions/cache@v4 - with: - path: /var/cache/apt/archives/*.deb - key: apt-php8.3-${{ runner.arch }}-v1 - - - name: Setup PHP - uses: shivammathur/setup-php@v2 - with: - php-version: '8.3' - tools: composer:v2 - + # COMPOSER_HOME is /composer in the CI image. - name: Cache Composer packages uses: actions/cache@v4 with: - path: ~/.composer/cache + path: /composer/cache key: composer-${{ hashFiles('composer.json') }} - name: Install dependencies @@ -70,9 +48,13 @@ jobs: test: name: Tests (PHP ${{ matrix.php }}) runs-on: ubuntu-latest + container: + image: git.unsupervised.ca/unsupervised/ci-php:${{ matrix.php }} strategy: fail-fast: false matrix: + # Adding a version here needs the matching image published first — + # see docs/ci.md. php: - '8.1' - '8.2' @@ -81,45 +63,10 @@ jobs: steps: - uses: actions/checkout@v4 - # setup-php installs PHP 8.3+ through php-builder, which apt-installs ~70 - # -dev packages before unpacking the build (#178). Ubuntu's image deletes - # the .debs after install, so every job re-downloads them. Keeping them - # and restoring them from the cache server, which lives in the cluster, - # turns a WAN download into a local one. - # - # Keyed per PHP version because the install path differs by version and - # the package sets are not interchangeable: 8.3+ pulls the ~70 -dev - # packages through php-builder, while 8.1 and 8.2 come from the ondrej - # PPA as a handful of runtime packages. Sharing one key across both lets - # whichever job finishes first decide what the others restore, and 8.1 is - # always first. - # - # Only the .debs are cached, never /var/lib/apt/lists — a stale index is - # how you get 404s mid-install. - - name: Keep downloaded .debs - run: | - sudo rm -f /etc/apt/apt.conf.d/docker-clean - echo 'Binary::apt::APT::Keep-Downloaded-Packages "true";' \ - | sudo tee /etc/apt/apt.conf.d/99keep-downloaded-packages >/dev/null - - - name: Cache apt packages - uses: actions/cache@v4 - with: - path: /var/cache/apt/archives/*.deb - key: apt-php${{ matrix.php }}-${{ runner.arch }}-v1 - - - name: Setup PHP - uses: shivammathur/setup-php@v2 - with: - php-version: ${{ matrix.php }} - extensions: mbstring, intl - coverage: none - tools: composer:v2 - - name: Cache Composer packages uses: actions/cache@v4 with: - path: ~/.composer/cache + path: /composer/cache key: ${{ matrix.php }}-composer-${{ hashFiles('composer.json') }} - name: Install dependencies @@ -128,6 +75,8 @@ jobs: - name: Run PHPUnit run: composer test + # No PHP needed, so this one stays on the runner image — and it wants GNU + # grep's --include, which the runner has. no-debug: name: No Debug Code runs-on: ubuntu-latest @@ -144,6 +93,8 @@ jobs: build: name: Build Plugin Zip runs-on: ubuntu-latest + container: + image: git.unsupervised.ca/unsupervised/ci-php:8.3 # Only build a shippable artifact once changes land on main, and only # after the quality gates pass. needs: [quality, test, no-debug] @@ -151,39 +102,6 @@ jobs: steps: - uses: actions/checkout@v4 - # setup-php installs PHP 8.3+ through php-builder, which apt-installs ~70 - # -dev packages before unpacking the build (#178). Ubuntu's image deletes - # the .debs after install, so every job re-downloads them. Keeping them - # and restoring them from the cache server, which lives in the cluster, - # turns a WAN download into a local one. - # - # Keyed per PHP version because the install path differs by version and - # the package sets are not interchangeable: 8.3+ pulls the ~70 -dev - # packages through php-builder, while 8.1 and 8.2 come from the ondrej - # PPA as a handful of runtime packages. Sharing one key across both lets - # whichever job finishes first decide what the others restore, and 8.1 is - # always first. - # - # Only the .debs are cached, never /var/lib/apt/lists — a stale index is - # how you get 404s mid-install. - - name: Keep downloaded .debs - run: | - sudo rm -f /etc/apt/apt.conf.d/docker-clean - echo 'Binary::apt::APT::Keep-Downloaded-Packages "true";' \ - | sudo tee /etc/apt/apt.conf.d/99keep-downloaded-packages >/dev/null - - - name: Cache apt packages - uses: actions/cache@v4 - with: - path: /var/cache/apt/archives/*.deb - key: apt-php8.3-${{ runner.arch }}-v1 - - - name: Setup PHP - uses: shivammathur/setup-php@v2 - with: - php-version: '8.3' - tools: composer:v2 - - name: Build plugin zip run: composer build diff --git a/.gitea/workflows/release.yml b/.gitea/workflows/release.yml index ff7e6b9..d3e1846 100644 --- a/.gitea/workflows/release.yml +++ b/.gitea/workflows/release.yml @@ -15,15 +15,14 @@ jobs: release: name: Build and Publish Release runs-on: ubuntu-latest + # Runs in the prebuilt CI image rather than installing PHP — see + # docs/ci.md and #187. The image carries composer, jq, curl and GNU + # coreutils, which is everything the steps below shell out to. + container: + image: git.unsupervised.ca/unsupervised/ci-php:8.3 steps: - uses: actions/checkout@v4 - - name: Setup PHP - uses: shivammathur/setup-php@v2 - with: - php-version: '8.3' - tools: composer:v2 - # A tag that disagrees with the plugin header would make sites see a # phantom update forever (or never see a real one), so fail fast. - name: Verify tag matches plugin version @@ -37,6 +36,13 @@ jobs: fi echo "version=${header_version}" >> "$GITHUB_OUTPUT" + # COMPOSER_HOME is /composer in the CI image. + - name: Cache Composer packages + uses: actions/cache@v4 + with: + path: /composer/cache + key: composer-${{ hashFiles('composer.json') }} + - name: Install dependencies run: composer install --prefer-dist --no-progress --no-interaction diff --git a/docs/ci.md b/docs/ci.md index 2c97eef..e9978b6 100644 --- a/docs/ci.md +++ b/docs/ci.md @@ -19,7 +19,7 @@ no registry credentials to use them. 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 ~120MB image from a registry +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