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