From 2789d582049ea60cb14e882c4cc3d968e07f71a1 Mon Sep 17 00:00:00 2001
From: Andrey Borodin <amborodin@acm.org>
Date: Sun, 6 Sep 2026 21:38:01 +0500
Subject: [PATCH v2] Split Linux ASAN and MinGW tests across runners

The Linux Meson 64-bit and Windows MinGW jobs often determine CI
latency because their test suites take much longer than their cached
builds.

Split each test suite across two runners while running the setup suite
on both.  Use Meson's native --slice support for MinGW.  The Linux CI
image has Meson 1.7, so derive a deterministically sorted test list
there instead of using the Meson 1.8 --slice option.

Use separate ccache save keys and failure-log artifact names for matrix
jobs.  Share the slice-specific upload step with the existing Windows
Visual Studio matrix, whose jobs otherwise use the same artifact name.

ci-os-only: linux windows mingw
---
 .github/workflows/pg-ci.yml | 73 ++++++++++++++++++++++++++++++++++---
 1 file changed, 67 insertions(+), 6 deletions(-)

diff --git a/.github/workflows/pg-ci.yml b/.github/workflows/pg-ci.yml
index a2629c8335a..6ec10fabca1 100644
--- a/.github/workflows/pg-ci.yml
+++ b/.github/workflows/pg-ci.yml
@@ -625,10 +625,11 @@ jobs:
   # - Uses address sanitizer, (sanitizer failures are typically printed in the
   #   server log). We test asan with meson rather than autoconf, as it's a bit
   #   faster at running the tests.
+  # - Splits the tests across two runners
   # - Uses io_method=io_uring
   # - Uses meson feature autodetection
   linux-meson-64:
-    name: Linux - Meson (64-bit)
+    name: Linux - Meson (64-bit) - Slice ${{ matrix.slice}}/${{ matrix.num_slices}}
     needs: [setup, sanity-check]
     if: *linux_job_if
     runs-on: *linux_runs_on
@@ -636,6 +637,12 @@ jobs:
     timeout-minutes: 60
     env: *linux_env
 
+    strategy:
+      fail-fast: false
+      matrix:
+        num_slices: [2]
+        slice: [1, 2]
+
     steps:
       - name: Update Environment
         env:
@@ -643,6 +650,9 @@ jobs:
           PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring
         run: *linux_update_config_cmd
 
+      - name: Distinguish ccache slice
+        run: echo "CACHE_SUFFIX=${CACHE_SUFFIX}:${{ matrix.slice }}" >> "$GITHUB_ENV"
+
       - *nix_sysinfo_step
       - *checkout_step
       - *ccache_restore_default_step
@@ -668,10 +678,47 @@ jobs:
 
       - name: Test world
         shell: *su_postgres_shell
-        run: *meson_test_world_cmd
+        run: |
+          ulimit -c unlimited
+
+          echo ::group::test_setup
+          meson test ${{env.MTEST_ARGS}} --suite setup --logbase setup || exit 1
+          echo ::endgroup::
+
+          # The system Meson is older than 1.8, which introduced --slice.
+          # Emulate its round-robin slicing using the test list instead.
+          readarray -t test_names < <(
+            meson test ${{env.MTEST_ARGS}} ${{env.MTEST_TARGET}} \
+              --list --no-suite setup |
+            sort |
+            awk -F ' - ' \
+              -v slice=${{ matrix.slice}} \
+              -v slices=${{ matrix.num_slices}} \
+              '(NR - 1) % slices == slice - 1 {
+                 name = $NF
+                 sub(/:[^ ]+ \/ /, ":", name)
+                 print name
+               }'
+          )
+          meson test ${{env.MTEST_ARGS}} \
+            --num-processes ${{env.TEST_JOBS}} \
+            --no-suite setup "${test_names[@]}"
 
       - *linux_collect_cores_step
-      - *upload_logs_step
+      - &upload_logs_sliced_step
+        name: Upload logs
+        if: failure() && !cancelled()
+        uses: actions/upload-artifact@v7
+        with:
+          name: logs-${{ github.job }}-${{ matrix.slice }}-${{ github.run_id }}-${{ github.run_attempt }}
+          path: |
+              **/*.log
+              **/*.diffs
+              **/regress_log_*
+              **/crashlog-*.txt
+              build/meson-logs/**
+              **/config.log
+          if-no-files-found: ignore
 
 
   # Job: macOS - Meson
@@ -1024,12 +1071,12 @@ jobs:
             call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64
         run: *meson_test_world_cmd
 
-      - *upload_logs_step
+      - *upload_logs_sliced_step
 
 
   # Job: Windows - MinGW - Meson
   windows-mingw:
-    name: Windows - MinGW - Meson
+    name: Windows - MinGW - Meson - Slice ${{ matrix.slice}}/${{ matrix.num_slices}}
     needs: [setup, sanity-check]
     if: |
       !cancelled() &&
@@ -1037,6 +1084,15 @@ jobs:
       needs.sanity-check.result != 'failure'
     runs-on: windows-2022
     timeout-minutes: 60
+
+    # MinGW is generally one of the slowest CI jobs.  Split its tests across
+    # two runners, as is already done for the Visual Studio job.
+    strategy:
+      fail-fast: false
+      matrix:
+        num_slices: [2]
+        slice: [1, 2]
+
     env:
       # Avoid port conflicts between concurrent tap tests
       PG_TEST_USE_UNIX_SOCKETS: 1
@@ -1120,6 +1176,9 @@ jobs:
 
       - *windows_setup_debugger_step
 
+      - name: Distinguish ccache slice
+        run: echo "CACHE_SUFFIX=${CACHE_SUFFIX}:${{ matrix.slice }}" >> "$GITHUB_ENV"
+
       - *ccache_restore_default_step
       - *ccache_restore_branch_step
 
@@ -1140,9 +1199,11 @@ jobs:
       - *ccache_save_step
 
       - name: Test world
+        env:
+          MTEST_TARGET: --slice ${{ matrix.slice}}/${{ matrix.num_slices}} ${{env.MTEST_TARGET}}
         run: *meson_test_world_cmd
 
-      - *upload_logs_step
+      - *upload_logs_sliced_step
 
 
   # Job: CompilerWarnings
-- 
That's all, folks. May the source be with you.

