1111 paths :
1212 - ' ffi/**'
1313 - ' cartridges/**/ffi/**'
14+ - ' .github/workflows/zig-test.yml'
1415 pull_request :
1516 branches : [main]
1617 paths :
1718 - ' ffi/**'
1819 - ' cartridges/**/ffi/**'
20+ - ' .github/workflows/zig-test.yml'
1921
2022permissions :
2123 contents : read
@@ -26,22 +28,68 @@ jobs:
2628 runs-on : ubuntu-latest
2729 steps :
2830 - uses : actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
31+ with :
32+ # Needed so `git diff origin/<base>...HEAD` can identify the
33+ # cartridges actually changed in this PR. Full history is cheap
34+ # on this repo; cuts down on cross-cartridge false-positive
35+ # gating where a PR is blocked by pre-existing breakage in
36+ # unrelated cartridges (browser-mcp, orchestrator-lsp-mcp,
37+ # etc.). On push/main we keep the full per-cartridge sweep.
38+ fetch-depth : 0
2939
3040 - name : Install Zig
3141 uses : mlugg/setup-zig@d1434d08867e3ee9daa34448df10607b98908d29 # v2
3242 with :
3343 version : 0.15.2
3444
45+ - name : Determine cartridges to test
46+ id : scope
47+ env :
48+ EVENT : ${{ github.event_name }}
49+ BASE_REF : ${{ github.base_ref }}
50+ run : |
51+ set -euo pipefail
52+ all="$(ls -d cartridges/*/ffi/ 2>/dev/null | sed 's|cartridges/||;s|/ffi/||' | sort)"
53+ if [ "$EVENT" = "pull_request" ]; then
54+ git fetch --no-tags --depth=50 origin "$BASE_REF" || true
55+ changed="$(git diff --name-only "origin/${BASE_REF}...HEAD" -- 'cartridges/**' \
56+ | awk -F/ '{print $2}' | sort -u)"
57+ scope=""
58+ while IFS= read -r cart; do
59+ [ -z "$cart" ] && continue
60+ if printf '%s\n' "$changed" | grep -qx "$cart"; then
61+ scope="$scope$cart"$'\n'
62+ fi
63+ done <<< "$all"
64+ else
65+ scope="$all"
66+ fi
67+ {
68+ echo 'carts<<EOF'
69+ printf '%s' "$scope"
70+ echo
71+ echo 'EOF'
72+ } >> "$GITHUB_OUTPUT"
73+ echo "Cartridges in scope for this run:"
74+ printf ' • %s\n' $(printf '%s\n' "$scope" | grep -v '^$' || true)
75+
3576 - name : Run catalogue tests
3677 run : cd ffi/zig && zig build test --summary all
3778
3879 - name : Run readiness tests
3980 run : cd ffi/zig && zig build readiness --summary all
4081
41- - name : Run cartridge FFI tests (all 73 cartridges)
82+ - name : Run cartridge FFI tests
83+ env :
84+ CARTS : ${{ steps.scope.outputs.carts }}
4285 run : |
86+ if [ -z "$(printf '%s' "$CARTS" | tr -d '[:space:]')" ]; then
87+ echo "::notice::No cartridges changed in this PR — skipping per-cartridge FFI tests."
88+ exit 0
89+ fi
4390 failed=""
44- for cart in $(ls -d cartridges/*/ffi/ 2>/dev/null | sed 's|cartridges/||;s|/ffi/||' | sort); do
91+ while IFS= read -r cart; do
92+ [ -z "$cart" ] && continue
4593 echo "::group::Testing $cart..."
4694 if cd "cartridges/$cart/ffi" && zig build test --summary all 2>&1; then
4795 echo " ✓ $cart passed"
@@ -51,19 +99,26 @@ jobs:
5199 fi
52100 cd "$GITHUB_WORKSPACE"
53101 echo "::endgroup::"
54- done
102+ done <<< "$CARTS"
55103 if [ -n "$failed" ]; then
56104 echo "::error::Failed cartridges:$failed"
57105 exit 1
58106 fi
59107
60- - name : Build cartridge shared libraries (all 73 cartridges)
108+ - name : Build cartridge shared libraries
109+ env :
110+ CARTS : ${{ steps.scope.outputs.carts }}
61111 run : |
62- for cart in $(ls -d cartridges/*/ffi/ 2>/dev/null | sed 's|cartridges/||;s|/ffi/||' | sort); do
112+ if [ -z "$(printf '%s' "$CARTS" | tr -d '[:space:]')" ]; then
113+ echo "::notice::No cartridges changed in this PR — skipping per-cartridge .so build."
114+ exit 0
115+ fi
116+ while IFS= read -r cart; do
117+ [ -z "$cart" ] && continue
63118 echo "Building $cart .so..."
64119 cd "cartridges/$cart/ffi" && zig build
65120 cd "$GITHUB_WORKSPACE"
66- done
121+ done <<< "$CARTS"
67122
68123 - name : Build static library
69124 run : cd ffi/zig && zig build lib
0 commit comments