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

The Linux Meson 64-bit job often determines CI latency because its
ASAN test suite takes much longer than its cached build and generally
longer than other jobs.

Run the setup suite on both runners and divide the remaining Meson tests
round-robin.  The CI image has Meson 1.7, so derive the slices from
"meson test --list" instead of using the Meson 1.8 --slice option.

Use separate ccache save keys and failure-log artifact names for the
matrix jobs.

ci-os-only: linux
---
 .github/workflows/pg-ci.yml | 51 ++++++++++++++++++++++++++++++++++---
 1 file changed, 48 insertions(+), 3 deletions(-)

diff --git a/.github/workflows/pg-ci.yml b/.github/workflows/pg-ci.yml
index a2629c8335a..8c13baf36b0 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,45 @@ 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 |
+            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
+      - 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
-- 
That's all, folks. May the source be with you.

