Skip to content

Commit a17906d

Browse files
onspeedhpclaude
andcommitted
ci: port sbf-cluster-check workflow from lazorkit-protocol
Verifies the dual-cluster mechanism stays intact: 1. cargo build-sbf --features mainnet succeeds 2. cargo build-sbf --features devnet succeeds 3. The two .so binaries differ (catches a refactor that neutralises the cfg gate on declare_id!) 4. cargo build-sbf with no feature fails with the expected "pick exactly one cluster" compile_error 5. cargo build-sbf with both features fails the same way Workflow is byte-identical to upstream's. Triggers on PRs touching program/ or assertions/, and on pushes to main. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent 0a027d9 commit a17906d

1 file changed

Lines changed: 122 additions & 0 deletions

File tree

Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
name: SBF cluster feature check
2+
3+
# Verifies the Pattern D feature-flag mechanism in `assertions/src/lib.rs`:
4+
#
5+
# 1. `cargo build-sbf --features mainnet` succeeds and produces a binary
6+
# embedding the mainnet vanity ID.
7+
# 2. `cargo build-sbf --features devnet` succeeds and produces a binary
8+
# embedding the devnet ID.
9+
# 3. The two binaries differ (otherwise the feature flag has been
10+
# neutralised by a refactor and Pattern D no longer protects against
11+
# cross-cluster deploys).
12+
# 4. `cargo build-sbf` with no feature flag fails with the expected
13+
# `compile_error!` (otherwise nothing prevents an unflagged build
14+
# from silently embedding whichever ID happens to be the default).
15+
#
16+
# Runs on every PR touching the program / assertions crate or this workflow.
17+
18+
on:
19+
pull_request:
20+
paths:
21+
- 'program/**'
22+
- 'assertions/**'
23+
- '.github/workflows/sbf-cluster-check.yml'
24+
push:
25+
branches: [main]
26+
27+
jobs:
28+
cluster-check:
29+
runs-on: ubuntu-latest
30+
timeout-minutes: 15
31+
steps:
32+
- uses: actions/checkout@v4
33+
34+
- name: Install Solana toolchain
35+
run: |
36+
sh -c "$(curl -sSfL https://release.anza.xyz/stable/install)"
37+
echo "$HOME/.local/share/solana/install/active_release/bin" >> "$GITHUB_PATH"
38+
39+
- name: Cache cargo build
40+
uses: actions/cache@v4
41+
with:
42+
path: |
43+
~/.cargo/registry
44+
~/.cargo/git
45+
target
46+
key: sbf-${{ hashFiles('**/Cargo.lock') }}
47+
48+
- name: Build mainnet binary
49+
working-directory: program
50+
run: cargo build-sbf --features mainnet
51+
52+
- name: Record mainnet hash
53+
id: mainnet
54+
run: |
55+
M=$(shasum -a 256 target/deploy/lazorkit_program.so | awk '{print $1}')
56+
echo "sha=$M" >> "$GITHUB_OUTPUT"
57+
echo "mainnet SBF: $M"
58+
59+
- name: Build devnet binary
60+
working-directory: program
61+
run: cargo build-sbf --features devnet
62+
63+
- name: Record devnet hash
64+
id: devnet
65+
run: |
66+
D=$(shasum -a 256 target/deploy/lazorkit_program.so | awk '{print $1}')
67+
echo "sha=$D" >> "$GITHUB_OUTPUT"
68+
echo "devnet SBF: $D"
69+
70+
- name: Verify binaries differ
71+
run: |
72+
if [ "${{ steps.mainnet.outputs.sha }}" = "${{ steps.devnet.outputs.sha }}" ]; then
73+
echo "ERROR: mainnet + devnet SBF binaries are identical."
74+
echo " Pattern D's compile-time cluster switch has been"
75+
echo " neutralised — likely a refactor removed the cfg gate"
76+
echo " on declare_id! in assertions/src/lib.rs."
77+
exit 1
78+
fi
79+
echo "✓ binaries differ as expected"
80+
81+
- name: Verify no-feature build fails with compile_error!
82+
working-directory: program
83+
run: |
84+
# Capture exit code separately — `cmd | tee` returns tee's exit
85+
# (always 0), masking cargo's failure. `set -o pipefail` would
86+
# also work, but capturing to a file gives us the log to search
87+
# afterwards regardless of pipeline state.
88+
set +e
89+
cargo build-sbf > /tmp/build.log 2>&1
90+
BUILD_EXIT=$?
91+
set -e
92+
cat /tmp/build.log
93+
if [ "$BUILD_EXIT" -eq 0 ]; then
94+
echo "ERROR: cargo build-sbf without --features mainnet/devnet succeeded."
95+
echo " The compile_error! in assertions/src/lib.rs is no longer firing."
96+
exit 1
97+
fi
98+
if ! grep -q "pick exactly one cluster" /tmp/build.log; then
99+
echo "ERROR: build failed but not with the expected compile_error message."
100+
echo " Expected: 'pick exactly one cluster — --features mainnet OR --features devnet'"
101+
exit 1
102+
fi
103+
echo "✓ no-feature build correctly rejected by compile_error!"
104+
105+
- name: Verify both-features build fails
106+
working-directory: program
107+
run: |
108+
set +e
109+
cargo build-sbf --features mainnet --features devnet > /tmp/build-both.log 2>&1
110+
BUILD_EXIT=$?
111+
set -e
112+
cat /tmp/build-both.log
113+
if [ "$BUILD_EXIT" -eq 0 ]; then
114+
echo "ERROR: cargo build-sbf with BOTH features succeeded."
115+
echo " The compile_error! mutual-exclusion guard is broken."
116+
exit 1
117+
fi
118+
if ! grep -q "pick exactly one cluster" /tmp/build-both.log; then
119+
echo "ERROR: build failed but not with the expected compile_error message."
120+
exit 1
121+
fi
122+
echo "✓ both-features build correctly rejected"

0 commit comments

Comments
 (0)