From 7b3cd19254b77fb1ac3f35a31ac90618f06a6611 Mon Sep 17 00:00:00 2001 From: Richard McDaniel <1130888+rmcdaniel@users.noreply.github.com> Date: Wed, 11 Nov 2026 23:50:04 +0000 Subject: [PATCH 1/3] Run the PostgreSQL feature suite on pull requests PR CI ran four smoke tests plus changed feature files, so a feature test could pass a PR and fail only on main, as #870 did (#1095). The six-shard PostgreSQL feature matrix, which collects no coverage, now also runs on pull requests and the build gate requires it there. MySQL keeps the coverage shards on main. Co-Authored-By: Claude Opus 5.5 --- .github/workflows/php.yml | 5 +++-- scripts/ci/test-build-routing.py | 9 ++++++++- scripts/ci/verify-feature-shards.php | 8 +++++--- 3 files changed, 16 insertions(+), 6 deletions(-) diff --git a/.github/workflows/php.yml b/.github/workflows/php.yml index cd79022e4..0d89c440f 100644 --- a/.github/workflows/php.yml +++ b/.github/workflows/php.yml @@ -1115,9 +1115,10 @@ jobs: name: laravel-log-mysql-${{ matrix.shard }} path: vendor/orchestra/testbench-core/laravel/storage/logs/laravel.log + # Runs on pull requests too, so a feature test cannot pass the PR and fail + # only after merge (#1095). MySQL keeps the coverage-collecting shards. feature-postgresql: needs: preflight - if: ${{ github.event_name != 'pull_request' }} runs-on: ubuntu-latest timeout-minutes: 20 @@ -1685,7 +1686,7 @@ jobs: test "${{ needs.pr-feature-mysql.result }}" = "success" test "${{ needs.feature-mysql.result }}" = "skipped" test "${{ needs.feature-mariadb.result }}" = "skipped" - test "${{ needs.feature-postgresql.result }}" = "skipped" + test "${{ needs.feature-postgresql.result }}" = "success" test "${{ needs.coverage-unit.result }}" = "skipped" test "${{ needs.coverage.result }}" = "skipped" test "${{ needs.laravel-embedded-upgrade-source.result }}" = "skipped" diff --git a/scripts/ci/test-build-routing.py b/scripts/ci/test-build-routing.py index 6f5b20201..f418f00c8 100644 --- a/scripts/ci/test-build-routing.py +++ b/scripts/ci/test-build-routing.py @@ -396,7 +396,6 @@ def test_target_branch_jobs_skip_pull_requests(self) -> None: for job in ( "feature-mysql", "feature-mariadb", - "feature-postgresql", "coverage-unit", "coverage", ): @@ -444,6 +443,14 @@ def test_pull_requests_run_the_same_unit_suite_as_coverage_unit(self) -> None: self.assertIn('test "${{ needs.pr-unit.result }}" = "success"', gate) self.assertIn('test "${{ needs.pr-unit.result }}" = "skipped"', gate) + def test_pull_requests_run_the_postgresql_feature_suite(self) -> None: + source = self.job_source("feature-postgresql") + self.assertNotIn("github.event_name != 'pull_request'", source) + self.assertIn("feature-postgresql", workflow_job_needs(self.build, "build")) + gate = self.job_source("build") + self.assertIn('test "${{ needs.feature-postgresql.result }}" = "success"', gate) + self.assertNotIn('test "${{ needs.feature-postgresql.result }}" = "skipped"', gate) + def test_combined_coverage_waits_for_both_producers_and_requires_every_report(self) -> None: self.assertEqual( {"preflight", "feature-mysql", "coverage-unit"}, diff --git a/scripts/ci/verify-feature-shards.php b/scripts/ci/verify-feature-shards.php index 54f825557..914a2ab24 100644 --- a/scripts/ci/verify-feature-shards.php +++ b/scripts/ci/verify-feature-shards.php @@ -94,13 +94,15 @@ function verify_workflow_job(string $workflow, string $job, string $profile): vo $expectedMatrix = implode(', ', range(0, FEATURE_SHARDS - 1)); $requirements = [ 'repository preflight dependency' => 'needs: preflight', - 'target-branch routing' => "github.event_name != 'pull_request'", 'complete shard matrix' => "shard: [{$expectedMatrix}]", 'splitter shard count' => '--shards=' . FEATURE_SHARDS, 'weight profile' => "--weight-profile={$profile}", ]; - + // MySQL collects coverage on main only. PostgreSQL also runs on pull + // requests, so a feature test cannot pass a PR and fail only after + // merge (#1095). if ($profile === 'mysql') { + $requirements['target-branch routing'] = "github.event_name != 'pull_request'"; $requirements['PCOV coverage driver'] = 'coverage: pcov'; $requirements['per-shard Clover report'] = '--coverage-clover "build/test-results/mysql-shard-${{ matrix.shard }}-coverage.xml"'; } @@ -121,7 +123,7 @@ function verify_gate_wiring(string $workflow, string $publicBoundaryWorkflow): v 'pr-tracing' => [PULL_REQUEST_CONDITION], 'pr-feature-mysql' => [PULL_REQUEST_CONDITION], 'feature-mysql' => ["github.event_name != 'pull_request'"], - 'feature-postgresql' => ["github.event_name != 'pull_request'"], + 'feature-postgresql' => [], 'feature-mariadb' => ["github.event_name != 'pull_request'"], 'coverage' => ["github.event_name != 'pull_request'"], ]; From b219a7d5db87afc11873887ee2102f89fc285033 Mon Sep 17 00:00:00 2001 From: Richard McDaniel <1130888+rmcdaniel@users.noreply.github.com> Date: Thu, 12 Nov 2026 00:07:16 +0000 Subject: [PATCH 2/3] Exclude fork pull requests from the PostgreSQL job's Composer cache Co-Authored-By: Claude Opus 5.5 --- .github/workflows/php.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/php.yml b/.github/workflows/php.yml index 0d89c440f..ed429641f 100644 --- a/.github/workflows/php.yml +++ b/.github/workflows/php.yml @@ -1150,6 +1150,7 @@ jobs: persist-credentials: false - name: Cache Composer packages + if: ${{ github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.repository }} uses: actions/cache@caa296126883cff596d87d8935842f9db880ef25 # v5 with: path: vendor From 1f7c45f85c163132847075f4a1387c333f7f7784 Mon Sep 17 00:00:00 2001 From: Richard McDaniel <1130888+rmcdaniel@users.noreply.github.com> Date: Thu, 12 Nov 2026 00:07:55 +0000 Subject: [PATCH 3/3] Check the PostgreSQL job-level condition precisely in the routing test Co-Authored-By: Claude Opus 5.5 --- scripts/ci/test-build-routing.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/ci/test-build-routing.py b/scripts/ci/test-build-routing.py index f418f00c8..8dc33b364 100644 --- a/scripts/ci/test-build-routing.py +++ b/scripts/ci/test-build-routing.py @@ -445,7 +445,7 @@ def test_pull_requests_run_the_same_unit_suite_as_coverage_unit(self) -> None: def test_pull_requests_run_the_postgresql_feature_suite(self) -> None: source = self.job_source("feature-postgresql") - self.assertNotIn("github.event_name != 'pull_request'", source) + self.assertNotIn(" if: ${{ github.event_name != 'pull_request' }}\n", source) self.assertIn("feature-postgresql", workflow_job_needs(self.build, "build")) gate = self.job_source("build") self.assertIn('test "${{ needs.feature-postgresql.result }}" = "success"', gate)