@@ -22,8 +22,57 @@ permissions:
2222 pull-requests : read
2323
2424jobs :
25+ merge_queue_noop :
26+ name : Detect merge queue no-op
27+ runs-on : ubuntu-latest
28+ outputs :
29+ skip : ${{ steps.compare.outputs.skip }}
30+ steps :
31+ - name : Checkout merge queue commit
32+ uses : actions/checkout@v4
33+
34+ - name : Compare merge queue commit to PR head
35+ id : compare
36+ env :
37+ GH_TOKEN : ${{ secrets.GITHUB_TOKEN }}
38+ HEAD_REF : ${{ github.event.merge_group.head_ref }}
39+ shell : bash
40+ run : |
41+ set -euo pipefail
42+
43+ echo "skip=false" >>"$GITHUB_OUTPUT"
44+
45+ if [[ "${GITHUB_EVENT_NAME}" != "merge_group" ]]; then
46+ echo "Not a merge_group event; running CI normally."
47+ exit 0
48+ fi
49+
50+ if [[ ! "${HEAD_REF}" =~ /pr-([0-9]+)- ]]; then
51+ echo "Could not parse PR number from merge group head ref: ${HEAD_REF}"
52+ exit 0
53+ fi
54+
55+ pr_number="${BASH_REMATCH[1]}"
56+ pr_head_sha="$(gh api "repos/${GITHUB_REPOSITORY}/pulls/${pr_number}" --jq '.head.sha')"
57+ pr_head_repo="$(gh api "repos/${GITHUB_REPOSITORY}/pulls/${pr_number}" --jq '.head.repo.full_name')"
58+
59+ if [[ -z "${pr_head_sha}" || "${pr_head_sha}" == "null" || -z "${pr_head_repo}" || "${pr_head_repo}" == "null" ]]; then
60+ echo "Could not resolve PR head SHA for PR #${pr_number}; running CI normally."
61+ exit 0
62+ fi
63+
64+ git fetch --no-tags --depth=1 "https://github.com/${pr_head_repo}.git" "${pr_head_sha}"
65+
66+ if git diff --quiet "${pr_head_sha}" "${GITHUB_SHA}" --; then
67+ echo "Merge queue commit ${GITHUB_SHA} has the same tree as PR #${pr_number} head ${pr_head_sha}; skipping duplicate CI."
68+ echo "skip=true" >>"$GITHUB_OUTPUT"
69+ else
70+ echo "Merge queue commit ${GITHUB_SHA} differs from PR #${pr_number} head ${pr_head_sha}; running CI normally."
71+ fi
72+
2573 smoketests :
26- needs : [lints]
74+ needs : [merge_queue_noop, lints]
75+ if : ${{ needs.merge_queue_noop.outputs.skip != 'true' }}
2776 name : Smoketests (${{ matrix.name }})
2877 strategy :
2978 matrix :
@@ -176,8 +225,26 @@ jobs:
176225 }
177226 cargo ci smoketests -- --test-threads=1
178227
228+ # this is a no-op version of the above check with a trivially-passing body.
229+ # we can't just let the check be entirely skipped because each matrix target is a required check,
230+ # and skipping this check means that the matrix isn't "populated" so the required checks wouldn't be met.
231+ smoketests_noop :
232+ needs : [merge_queue_noop]
233+ if : ${{ needs.merge_queue_noop.outputs.skip == 'true' }}
234+ name : Smoketests (${{ matrix.name }})
235+ strategy :
236+ matrix :
237+ include :
238+ - name : Linux
239+ - name : Windows
240+ runs-on : ubuntu-latest
241+ steps :
242+ - name : Skip duplicate merge queue smoketest
243+ run : echo "Merge queue commit has the same tree as the PR head; smoketest already ran for the PR."
244+
179245 test :
180- needs : [lints]
246+ needs : [merge_queue_noop, lints]
247+ if : ${{ needs.merge_queue_noop.outputs.skip != 'true' }}
181248 name : Test Suite
182249 runs-on : spacetimedb-new-runner-2
183250
@@ -261,14 +328,18 @@ jobs:
261328
262329 wasm-bindgen --version
263330
331+ - name : Check engine simulation build
332+ run : cargo check -p spacetimedb-engine --no-default-features --features simulation
333+
264334 # Source emsdk environment to make emcc (Emscripten compiler) available in PATH.
265335 - name : Run tests
266336 run : |
267337 source ~/emsdk/emsdk_env.sh
268338 cargo ci test
269339
270340 keynote_bench :
271- needs : [lints]
341+ needs : [merge_queue_noop, lints]
342+ if : ${{ needs.merge_queue_noop.outputs.skip != 'true' }}
272343 name : Keynote Bench
273344 runs-on : spacetimedb-benchmark-runner
274345 concurrency :
@@ -329,7 +400,8 @@ jobs:
329400 run : cargo ci keynote-bench
330401
331402 index_scan_bench :
332- needs : [lints]
403+ needs : [merge_queue_noop, lints]
404+ if : ${{ needs.merge_queue_noop.outputs.skip != 'true' }}
333405 name : Index Scan Bench
334406 runs-on : spacetimedb-benchmark-runner
335407 concurrency :
@@ -373,6 +445,8 @@ jobs:
373445 run : cargo bench -p spacetimedb-bench --bench index_scan_gate
374446
375447 lints :
448+ needs : [merge_queue_noop]
449+ if : ${{ needs.merge_queue_noop.outputs.skip != 'true' }}
376450 name : Lints
377451 runs-on : spacetimedb-new-runner-2
378452 env :
@@ -413,6 +487,8 @@ jobs:
413487 run : cargo ci lint
414488
415489 wasm_bindings :
490+ needs : [merge_queue_noop]
491+ if : ${{ needs.merge_queue_noop.outputs.skip != 'true' }}
416492 name : Build and test wasm bindings
417493 runs-on : spacetimedb-new-runner-2
418494 env :
@@ -439,6 +515,8 @@ jobs:
439515 run : cargo ci wasm-bindings
440516
441517 publish_checks :
518+ needs : [merge_queue_noop]
519+ if : ${{ needs.merge_queue_noop.outputs.skip != 'true' }}
442520 name : Check that packages are publishable
443521 runs-on : spacetimedb-new-runner-2
444522 permissions : read-all
@@ -453,13 +531,14 @@ jobs:
453531 run : cargo ci publish-checks
454532
455533 update :
534+ needs : [merge_queue_noop]
535+ if : ${{ needs.merge_queue_noop.outputs.skip != 'true' }}
456536 name : Test spacetimedb-update flow (${{ matrix.target }})
457537 permissions : read-all
458538 strategy :
459539 matrix :
460540 include :
461541 - { target: x86_64-unknown-linux-gnu, runner: spacetimedb-new-runner-2 }
462- - { target: aarch64-unknown-linux-gnu, runner: arm-runner }
463542 - { target: aarch64-apple-darwin, runner: macos-latest }
464543 - { target: x86_64-pc-windows-msvc, runner: windows-latest }
465544 runs-on : ${{ matrix.runner }}
@@ -477,16 +556,30 @@ jobs:
477556 - name : Install rust target
478557 run : rustup target add ${{ matrix.target }}
479558
480- - name : Install packages
481- if : ${{ matrix.runner == 'arm-runner' }}
482- shell : bash
483- run : sudo apt install -y libssl-dev
484-
485559 - name : Test spacetimedb-update
486560 env :
487561 GITHUB_TOKEN : ${{ secrets.GITHUB_TOKEN }}
488562 run : cargo ci update-flow --target=${{ matrix.target }} --github-token-auth
489563
564+ # this is a no-op version of the above check with a trivially-passing body.
565+ # we can't just let the check be entirely skipped because each matrix target is a required check,
566+ # and skipping this check means that the matrix isn't "populated" so the required checks wouldn't be met.
567+ update_noop :
568+ needs : [merge_queue_noop]
569+ if : ${{ needs.merge_queue_noop.outputs.skip == 'true' }}
570+ name : Test spacetimedb-update flow (${{ matrix.target }})
571+ permissions : read-all
572+ strategy :
573+ matrix :
574+ include :
575+ - { target: x86_64-unknown-linux-gnu }
576+ - { target: aarch64-apple-darwin }
577+ - { target: x86_64-pc-windows-msvc }
578+ runs-on : ubuntu-latest
579+ steps :
580+ - name : Skip duplicate merge queue update test
581+ run : echo "Merge queue commit has the same tree as the PR head; update-flow already ran for the PR."
582+
490583 unreal_engine_tests :
491584 name : Unreal Engine Tests
492585 # This can't go on e.g. ubuntu-latest because that runner runs out of disk space. ChatGPT suggested that the general solution tends to be to use
@@ -581,6 +674,8 @@ jobs:
581674 '
582675
583676 ci_command_docs :
677+ needs : [merge_queue_noop]
678+ if : ${{ needs.merge_queue_noop.outputs.skip != 'true' }}
584679 name : Check CI command docs
585680 runs-on : spacetimedb-new-runner-2
586681 env :
@@ -612,6 +707,8 @@ jobs:
612707 run : cargo ci self-docs --check
613708
614709 cli_docs :
710+ needs : [merge_queue_noop]
711+ if : ${{ needs.merge_queue_noop.outputs.skip != 'true' }}
615712 name : Check CLI docs
616713 permissions : read-all
617714 runs-on : spacetimedb-new-runner-2
@@ -677,10 +774,10 @@ jobs:
677774 cargo ci cli-docs
678775
679776 unity-testsuite :
680- needs : [lints]
777+ needs : [merge_queue_noop, lints]
681778 # Skip if this is an external contribution.
682779 # The license secrets will be empty, so the step would fail anyway.
683- if : ${{ github.event_name != 'pull_request' || !github.event.pull_request.head.repo.fork }}
780+ if : ${{ needs.merge_queue_noop.outputs.skip != 'true' && ( github.event_name != 'pull_request' || !github.event.pull_request.head.repo.fork) }}
684781 permissions :
685782 contents : read
686783 checks : write
@@ -823,7 +920,8 @@ jobs:
823920 UNITY_SERIAL : ${{ secrets.UNITY_SERIAL }}
824921
825922 godot-testsuite :
826- needs : [lints]
923+ needs : [merge_queue_noop, lints]
924+ if : ${{ needs.merge_queue_noop.outputs.skip != 'true' }}
827925 permissions :
828926 contents : read
829927 runs-on : spacetimedb-new-runner-2
@@ -948,7 +1046,8 @@ jobs:
9481046 run : godot --headless --path demo/Blackholio/client-godot --scene res://tests/GodotPlayModeTests.tscn
9491047
9501048 csharp-testsuite :
951- needs : [lints]
1049+ needs : [merge_queue_noop, lints]
1050+ if : ${{ needs.merge_queue_noop.outputs.skip != 'true' }}
9521051 runs-on : spacetimedb-new-runner-2
9531052 timeout-minutes : 30
9541053 env :
@@ -1065,6 +1164,8 @@ jobs:
10651164 }
10661165
10671166 global_json_policy :
1167+ needs : [merge_queue_noop]
1168+ if : ${{ needs.merge_queue_noop.outputs.skip != 'true' }}
10681169 name : Verify global.json files are symlinks
10691170 runs-on : ubuntu-latest
10701171 permissions :
@@ -1104,6 +1205,8 @@ jobs:
11041205 run : cargo ci global-json-policy
11051206
11061207 smoketests_mod_rs_complete :
1208+ needs : [merge_queue_noop]
1209+ if : ${{ needs.merge_queue_noop.outputs.skip != 'true' }}
11071210 name : Check smoketests/mod.rs is complete
11081211 runs-on : ubuntu-latest
11091212 permissions :
@@ -1161,6 +1264,8 @@ jobs:
11611264 cargo ci smoketests check-mod-list
11621265
11631266 docs-build :
1267+ needs : [merge_queue_noop]
1268+ if : ${{ needs.merge_queue_noop.outputs.skip != 'true' }}
11641269 name : Docs build
11651270 runs-on : spacetimedb-new-runner-2
11661271 env :
@@ -1200,6 +1305,8 @@ jobs:
12001305 run : cargo ci docs
12011306
12021307 typescript-test :
1308+ needs : [merge_queue_noop]
1309+ if : ${{ needs.merge_queue_noop.outputs.skip != 'true' }}
12031310 name : TypeScript - Tests
12041311 runs-on : spacetimedb-new-runner-2
12051312 env :
0 commit comments