1+ # Contract Deployment Workflow for FlowFi
2+ #
3+ # Compiles the Soroban stream contract to optimized WASM, runs contract tests,
4+ # and deploys + initializes the contract on Stellar Testnet on demand (or on
5+ # Mainnet for release tags). The resulting contract ID is surfaced in the job
6+ # summary and published as a release artifact.
7+ name : Deploy Soroban Contracts
8+
9+ on :
10+ release :
11+ types : [published]
12+ workflow_dispatch :
13+ inputs :
14+ network :
15+ description : " Target network (testnet|mainnet)"
16+ required : true
17+ default : " testnet"
18+ type : choice
19+ options :
20+ - testnet
21+ - mainnet
22+
23+ concurrency :
24+ group : ${{ github.workflow }}-${{ inputs.network || github.ref }}
25+ cancel-in-progress : true
26+
27+ permissions :
28+ contents : write
29+
30+ jobs :
31+ deploy :
32+ name : Build & Deploy stream_contract
33+ runs-on : ubuntu-latest
34+ environment : ${{ github.event_name == 'release' && 'production' || 'staging' }}
35+
36+ env :
37+ NETWORK : ${{ inputs.network || (github.event_name == 'release' && 'mainnet' || 'testnet') }}
38+ DEPLOYER_SECRET : ${{ secrets.DEPLOYER_SECRET }}
39+ ADMIN_ADDRESS : ${{ secrets.ADMIN_ADDRESS }}
40+ TREASURY_ADDRESS : ${{ secrets.TREASURY_ADDRESS }}
41+ FEE_RATE_BPS : ${{ secrets.FEE_RATE_BPS }}
42+
43+ steps :
44+ - name : Checkout code
45+ uses : actions/checkout@v4
46+
47+ - name : Setup Rust toolchain
48+ uses : dtolnay/rust-toolchain@stable
49+ with :
50+ toolchain : stable
51+ targets : wasm32-unknown-unknown
52+ components : rustfmt, clippy
53+
54+ - name : Rust Cache
55+ uses : Swatinem/rust-cache@v2
56+ with :
57+ workspace : " contracts -> target"
58+
59+ - name : Install Stellar CLI
60+ run : |
61+ curl -fsSL https://github.com/stellar/stellar-cli/raw/main/install.sh | sh -s -- --install-deps
62+ echo "$HOME/.stellar-cli/bin" >> $GITHUB_PATH
63+
64+ - name : Run Contract Tests
65+ run : cargo test --package stream_contract
66+ working-directory : contracts
67+
68+ - name : Build & Optimize WASM
69+ run : |
70+ set -euo pipefail
71+ cd contracts
72+ cargo build --target wasm32-unknown-unknown --release
73+ RELEASE_DIR="target/wasm32-unknown-unknown/release"
74+ for w in "$RELEASE_DIR"/stream_contract.wasm; do
75+ stellar contract optimize --wasm "$w" --wasm-out "$RELEASE_DIR/stream_contract.optimized.wasm"
76+ done
77+ ls -la "$RELEASE_DIR"/*.wasm
78+
79+ - name : Inspect Contract Interface & WASM Size
80+ run : |
81+ set -euo pipefail
82+ WASM=contracts/target/wasm32-unknown-unknown/release/stream_contract.optimized.wasm
83+ stellar contract inspect --wasm "$WASM"
84+ SIZE=$(stat -c%s "$WASM")
85+ echo "Optimized WASM size: $SIZE bytes"
86+ if [ "$SIZE" -ge 65536 ]; then
87+ echo "ERROR: optimized WASM exceeds 64KB budget ($SIZE bytes)"
88+ exit 1
89+ fi
90+ echo "WASM_WASM_PATH=$WASM" >> $GITHUB_ENV
91+
92+ - name : Deploy & Initialize Contract
93+ run : ./scripts/deploy.sh --network "$NETWORK"
94+
95+ - name : Read Deployed Contract ID
96+ id : contract
97+ run : |
98+ set -euo pipefail
99+ CONTRACT_ID=$(jq -r --arg net "$NETWORK" '.[$net].contractId' deployment-info.json)
100+ echo "contract_id=$CONTRACT_ID" >> $GITHUB_OUTPUT
101+ echo "deployment-json=$(jq -c . deployment-info.json)" >> $GITHUB_OUTPUT
102+
103+ - name : Emit Deployment Summary
104+ if : always()
105+ run : |
106+ {
107+ echo "## Deployment Summary"
108+ echo ""
109+ echo "- **Network**: \`$NETWORK\`"
110+ echo "- **Contract ID**: \`${{ steps.contract.outputs.contract_id }}\`"
111+ echo "- **WASM**: \`${{ env.WASM_WASM_PATH }}\`"
112+ echo "- **Deployment info**: "
113+ echo '```json'
114+ echo "${{ steps.contract.outputs.deployment-json }}"
115+ echo '```'
116+ } >> "$GITHUB_STEP_SUMMARY"
117+
118+ - name : Upload Optimized WASM Artifact
119+ uses : actions/upload-artifact@v4
120+ with :
121+ name : stream-contract-${{ env.NETWORK }}
122+ path : contracts/target/wasm32-unknown-unknown/optimized/*.wasm
123+ if-no-files-found : error
124+
125+ - name : Upload Deployment Info
126+ uses : actions/upload-artifact@v4
127+ with :
128+ name : deployment-info-${{ env.NETWORK }}
129+ path : deployment-info.json
130+ if-no-files-found : error
131+
132+ - name : Commit Deployment Info
133+ if : github.event_name == 'release'
134+ env :
135+ NETWORK : ${{ env.NETWORK }}
136+ run : |
137+ set -euo pipefail
138+ git config user.name "github-actions[bot]"
139+ git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
140+ git add deployment-info.json
141+ if git diff --cached --quiet; then
142+ echo "No deployment-info.json changes to commit"
143+ exit 0
144+ fi
145+ git commit -m "chore(contracts): record $NETWORK contract deployment"
146+ git push
0 commit comments