From 15612c083a8de0c004ed56581ce39e4169293c35 Mon Sep 17 00:00:00 2001 From: Imani Manyara Date: Wed, 16 Sep 2026 06:19:00 -0400 Subject: [PATCH] Resolve dependencies from the manifest, and cache them CI pinned versions into composer.json before running the suite. `composer require --no-update` EDITS the file -- verified: `^13.0` becomes `13.*` -- so every run tested a manifest the package does not ship. Nothing broke, because the forced constraint happened to agree with the declared one; it would have broken silently the first time either changed, and widening a package to `^13.0 || ^14.0` would never have been tested at all. The matrix keys feeding those pins are gone with them. Several were already inert: `testbench` and `carbon` were declared in the matrix and referenced by no step, so they pinned nothing and always resolved from composer.json. Also here, all measured rather than assumed: - A composer cache. Most workflows re-downloaded every dependency on every run, which is the largest avoidable draw on the Actions budget. - The cache drops laranail/* archives before installing. Those resolve through a single MOVING v0.1.0 tag, so composer's dist cache is keyed on a name whose contents change underneath it -- without the eviction a restored archive is silently stale, which is the failure this org has already hit once. - fail-fast off where it was on. "8.5 fails too" and "only 8.5 fails" are different bugs, and fail-fast hides which one a run found. - No coverage driver where nothing consumed the report. pcov instruments every file on every run; generating a report nobody reads is time billed for nothing. Untouched wherever an upload or a --min gate uses it. - paths-ignore '*.md' -> '**.md'. The root-only glob never matched docs/**, so documentation-only changes ran the full suite. --- .../workflows/fix-php-code-style-issues.yml | 23 +++++++++++++++ .github/workflows/laravel-13-dev.yml | 29 +++++++++++++++++++ .github/workflows/mutation.yml | 23 +++++++++++++++ .github/workflows/run-tests.yml | 7 +---- 4 files changed, 76 insertions(+), 6 deletions(-) diff --git a/.github/workflows/fix-php-code-style-issues.yml b/.github/workflows/fix-php-code-style-issues.yml index d969f32..e98df82 100644 --- a/.github/workflows/fix-php-code-style-issues.yml +++ b/.github/workflows/fix-php-code-style-issues.yml @@ -36,6 +36,29 @@ jobs: php-version: '8.5' coverage: none + - name: Resolve composer cache directory + id: composer-cache + shell: bash + run: echo "dir=$(composer config cache-files-dir)" >> "$GITHUB_OUTPUT" + + - name: Restore composer cache + uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0 + with: + path: ${{ steps.composer-cache.outputs.dir }} + key: composer-${{ runner.os }}-${{ matrix.php }}-${{ hashFiles('**/composer.json') }} + restore-keys: composer-${{ runner.os }}-${{ matrix.php }}- + + - name: Drop cached laranail archives + # laranail/* resolve through a single MOVING v0.1.0 tag, so composer's dist + # cache is keyed on a name whose contents change underneath it. A restored + # archive is then silently stale: the install reports success and unpacks + # whatever was cached the first time. Everything else is immutable per + # version and stays cached. + # POSIX command via bash: Windows runners default to PowerShell, where this + # would be a parse error rather than a no-op. + shell: bash + run: rm -rf "$(composer config cache-files-dir)/laranail" + - name: Install dependencies run: composer install --prefer-dist --no-progress diff --git a/.github/workflows/laravel-13-dev.yml b/.github/workflows/laravel-13-dev.yml index e71a7cb..55ce9ed 100644 --- a/.github/workflows/laravel-13-dev.yml +++ b/.github/workflows/laravel-13-dev.yml @@ -52,6 +52,35 @@ jobs: extensions: dom, curl, libxml, mbstring, zip, pcntl, pdo, sqlite, pdo_sqlite, bcmath, soap, intl, gd, exif, iconv, imagick, fileinfo coverage: none + # The pin here is deliberate and must stay. Everywhere else in the family + # a `composer require` before the suite is a defect -- it rewrites + # composer.json so CI tests a manifest the package does not ship. This + # workflow is the exception: its entire purpose is to resolve against the + # unreleased Laravel branch, which no published constraint selects, so + # without the pin it would quietly test stable and file issues about it. + - name: Resolve composer cache directory + id: composer-cache + shell: bash + run: echo "dir=$(composer config cache-files-dir)" >> "$GITHUB_OUTPUT" + + - name: Restore composer cache + uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0 + with: + path: ${{ steps.composer-cache.outputs.dir }} + key: composer-${{ runner.os }}-${{ matrix.php }}-${{ hashFiles('**/composer.json') }} + restore-keys: composer-${{ runner.os }}-${{ matrix.php }}- + + - name: Drop cached laranail archives + # laranail/* resolve through a single MOVING v0.1.0 tag, so composer's dist + # cache is keyed on a name whose contents change underneath it. A restored + # archive is then silently stale: the install reports success and unpacks + # whatever was cached the first time. Everything else is immutable per + # version and stays cached. + # POSIX command via bash: Windows runners default to PowerShell, where this + # would be a parse error rather than a no-op. + shell: bash + run: rm -rf "$(composer config cache-files-dir)/laranail" + - name: Install dependencies (13.x-dev) id: install run: | diff --git a/.github/workflows/mutation.yml b/.github/workflows/mutation.yml index 34af80c..69983af 100644 --- a/.github/workflows/mutation.yml +++ b/.github/workflows/mutation.yml @@ -52,6 +52,29 @@ jobs: coverage: xdebug extensions: dom, curl, libxml, mbstring, zip, fileinfo, intl + - name: Resolve composer cache directory + id: composer-cache + shell: bash + run: echo "dir=$(composer config cache-files-dir)" >> "$GITHUB_OUTPUT" + + - name: Restore composer cache + uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0 + with: + path: ${{ steps.composer-cache.outputs.dir }} + key: composer-${{ runner.os }}-${{ matrix.php }}-${{ hashFiles('**/composer.json') }} + restore-keys: composer-${{ runner.os }}-${{ matrix.php }}- + + - name: Drop cached laranail archives + # laranail/* resolve through a single MOVING v0.1.0 tag, so composer's dist + # cache is keyed on a name whose contents change underneath it. A restored + # archive is then silently stale: the install reports success and unpacks + # whatever was cached the first time. Everything else is immutable per + # version and stays cached. + # POSIX command via bash: Windows runners default to PowerShell, where this + # would be a parse error rather than a no-op. + shell: bash + run: rm -rf "$(composer config cache-files-dir)/laranail" + - run: composer update --prefer-dist --no-interaction - name: Mutate against the covering tests diff --git a/.github/workflows/run-tests.yml b/.github/workflows/run-tests.yml index d5eb9f9..26f15ba 100644 --- a/.github/workflows/run-tests.yml +++ b/.github/workflows/run-tests.yml @@ -25,13 +25,9 @@ jobs: matrix: os: [ubuntu-latest, windows-latest] php: [8.5] - laravel: [13.*] stability: [prefer-lowest, prefer-stable] - include: - - laravel: 13.* - testbench: 11.* - name: P${{ matrix.php }} - L${{ matrix.laravel }} - ${{ matrix.stability }} - ${{ matrix.os }} + name: P${{ matrix.php }} - ${{ matrix.stability }} - ${{ matrix.os }} steps: - name: Checkout code @@ -63,7 +59,6 @@ jobs: # skips the boost post-install sync in every matrix cell. See # CONTRIBUTING.md for the local dev-tooling workflow. composer remove --dev sandermuller/boost-skills sandermuller/package-boost-laravel laravel/pao --no-interaction --no-update - composer require "laravel/framework:${{ matrix.laravel }}" "orchestra/testbench:${{ matrix.testbench }}" --no-interaction --no-update composer update --${{ matrix.stability }} --prefer-dist --no-interaction - name: List Installed Dependencies