Merge pull request #921 from maztah1/docs/wave-contributor-guide #1
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Contract Deployment Pipeline | |
| on: | |
| push: | |
| branches: [main, develop] | |
| paths: | |
| - 'contracts/**' | |
| - 'scripts/deploy_*.sh' | |
| - '.github/workflows/deploy.yml' | |
| workflow_dispatch: | |
| inputs: | |
| network: | |
| description: 'Target network' | |
| required: true | |
| type: choice | |
| options: [testnet, mainnet] | |
| rollback_artifact: | |
| description: 'Artifact run ID to roll back to (leave empty for normal deploy)' | |
| required: false | |
| type: string | |
| concurrency: | |
| group: deploy-${{ github.ref }} | |
| cancel-in-progress: false # never cancel an in-flight deploy | |
| env: | |
| WASM_PATH: target/wasm32-unknown-unknown/release/stellar_save.wasm | |
| WASM_SIZE_LIMIT_KB: 100 | |
| CONTRACT_NAME: stellar-save | |
| # ─── Job 1: Pre-deployment validation ──────────────────────────────────────── | |
| jobs: | |
| pre-deploy: | |
| name: Pre-deployment Validation | |
| runs-on: ubuntu-latest | |
| outputs: | |
| wasm_hash: ${{ steps.hash.outputs.wasm_hash }} | |
| wasm_size_kb: ${{ steps.hash.outputs.wasm_size_kb }} | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - name: Install Rust toolchain | |
| uses: dtolnay/rust-toolchain@stable | |
| with: | |
| targets: wasm32-unknown-unknown | |
| components: clippy | |
| - name: Cache Rust dependencies | |
| uses: Swatinem/rust-cache@v2 | |
| with: | |
| workspaces: ". -> target" | |
| - name: Run pre-deployment checks | |
| run: bash scripts/pre_deploy_check.sh | |
| env: | |
| WASM_SIZE_LIMIT_KB: ${{ env.WASM_SIZE_LIMIT_KB }} | |
| - name: Build optimised WASM | |
| run: | | |
| cargo build \ | |
| --manifest-path contracts/stellar-save/Cargo.toml \ | |
| --target wasm32-unknown-unknown \ | |
| --release | |
| - name: Compute WASM hash and size | |
| id: hash | |
| run: | | |
| HASH=$(sha256sum "${{ env.WASM_PATH }}" | awk '{print $1}') | |
| SIZE_KB=$(du -k "${{ env.WASM_PATH }}" | awk '{print $1}') | |
| echo "wasm_hash=${HASH}" >> "$GITHUB_OUTPUT" | |
| echo "wasm_size_kb=${SIZE_KB}" >> "$GITHUB_OUTPUT" | |
| echo "WASM hash : ${HASH}" | |
| echo "WASM size : ${SIZE_KB} KB" | |
| - name: Upload WASM artifact | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: wasm-${{ github.sha }} | |
| path: ${{ env.WASM_PATH }} | |
| retention-days: 90 # keep for rollback | |
| # ─── Job 2: Deploy to Testnet ───────────────────────────────────────────────── | |
| deploy-testnet: | |
| name: Deploy → Testnet | |
| needs: pre-deploy | |
| runs-on: ubuntu-latest | |
| if: | | |
| github.ref == 'refs/heads/develop' || | |
| (github.event_name == 'workflow_dispatch' && github.event.inputs.network == 'testnet') | |
| environment: | |
| name: testnet | |
| url: https://stellar.expert/explorer/testnet | |
| outputs: | |
| contract_id: ${{ steps.deploy.outputs.contract_id }} | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - name: Install Stellar CLI | |
| run: | | |
| curl -sSL https://github.com/stellar/stellar-cli/releases/download/v22.7.1/stellar-cli-22.7.1-x86_64-unknown-linux-gnu.tar.gz \ | |
| | tar -xz -C /usr/local/bin stellar | |
| stellar --version | |
| - name: Download WASM artifact | |
| uses: actions/download-artifact@v4 | |
| with: | |
| name: wasm-${{ github.sha }} | |
| path: wasm-artifact | |
| - name: Configure deployer identity | |
| run: | | |
| echo "${{ secrets.TESTNET_DEPLOYER_SECRET }}" \ | |
| | stellar keys add deployer --secret-key --stdin | |
| env: | |
| STELLAR_NETWORK: testnet | |
| - name: Deploy contract | |
| id: deploy | |
| run: | | |
| CONTRACT_ID=$(stellar contract deploy \ | |
| --wasm wasm-artifact/stellar_save.wasm \ | |
| --network testnet \ | |
| --source-account deployer \ | |
| --ignore-checks) | |
| echo "contract_id=${CONTRACT_ID}" >> "$GITHUB_OUTPUT" | |
| echo "Deployed contract ID: ${CONTRACT_ID}" | |
| env: | |
| STELLAR_NETWORK: testnet | |
| - name: Verify deployment | |
| run: bash scripts/verify_contract.sh | |
| env: | |
| STELLAR_NETWORK: testnet | |
| STELLAR_RPC_URL: https://soroban-testnet.stellar.org | |
| CONTRACT_ID: ${{ steps.deploy.outputs.contract_id }} | |
| EXPECTED_WASM_HASH: ${{ needs.pre-deploy.outputs.wasm_hash }} | |
| - name: Post-deploy smoke tests | |
| run: bash scripts/smoke_test_post_deploy.sh | |
| env: | |
| STELLAR_NETWORK: testnet | |
| STELLAR_RPC_URL: https://soroban-testnet.stellar.org | |
| CONTRACT_ID: ${{ steps.deploy.outputs.contract_id }} | |
| - name: Save deployment record | |
| run: | | |
| mkdir -p deployment-records | |
| cat > deployment-records/testnet-${{ github.sha }}.json <<EOF | |
| { | |
| "network": "testnet", | |
| "contract_id": "${{ steps.deploy.outputs.contract_id }}", | |
| "wasm_hash": "${{ needs.pre-deploy.outputs.wasm_hash }}", | |
| "wasm_size_kb": "${{ needs.pre-deploy.outputs.wasm_size_kb }}", | |
| "commit": "${{ github.sha }}", | |
| "deployed_at": "$(date -u +%Y-%m-%dT%H:%M:%SZ)", | |
| "deployed_by": "${{ github.actor }}" | |
| } | |
| EOF | |
| cat deployment-records/testnet-${{ github.sha }}.json | |
| - name: Upload deployment record | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: deployment-record-testnet-${{ github.sha }} | |
| path: deployment-records/ | |
| retention-days: 90 | |
| - name: Comment on PR | |
| if: github.event_name == 'pull_request' | |
| uses: actions/github-script@v7 | |
| with: | |
| script: | | |
| github.rest.issues.createComment({ | |
| issue_number: context.issue.number, | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| body: [ | |
| '## ✅ Testnet Deployment', | |
| `**Contract ID:** \`${{ steps.deploy.outputs.contract_id }}\``, | |
| `**WASM hash:** \`${{ needs.pre-deploy.outputs.wasm_hash }}\``, | |
| `**Explorer:** https://stellar.expert/explorer/testnet/contract/${{ steps.deploy.outputs.contract_id }}` | |
| ].join('\n') | |
| }); | |
| # ─── Job 3: Deploy to Mainnet (requires manual approval via environment) ────── | |
| deploy-mainnet: | |
| name: Deploy → Mainnet | |
| needs: pre-deploy | |
| runs-on: ubuntu-latest | |
| if: | | |
| github.ref == 'refs/heads/main' || | |
| (github.event_name == 'workflow_dispatch' && github.event.inputs.network == 'mainnet') | |
| environment: | |
| name: production # GitHub environment with required reviewers | |
| url: https://stellar.expert/explorer/mainnet | |
| outputs: | |
| contract_id: ${{ steps.deploy.outputs.contract_id }} | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - name: Install Stellar CLI | |
| run: | | |
| curl -sSL https://github.com/stellar/stellar-cli/releases/download/v22.7.1/stellar-cli-22.7.1-x86_64-unknown-linux-gnu.tar.gz \ | |
| | tar -xz -C /usr/local/bin stellar | |
| stellar --version | |
| - name: Download WASM artifact | |
| uses: actions/download-artifact@v4 | |
| with: | |
| name: wasm-${{ github.sha }} | |
| path: wasm-artifact | |
| - name: Configure deployer identity | |
| run: | | |
| echo "${{ secrets.MAINNET_DEPLOYER_SECRET }}" \ | |
| | stellar keys add deployer --secret-key --stdin | |
| env: | |
| STELLAR_NETWORK: mainnet | |
| - name: Deploy contract | |
| id: deploy | |
| run: | | |
| CONTRACT_ID=$(stellar contract deploy \ | |
| --wasm wasm-artifact/stellar_save.wasm \ | |
| --network mainnet \ | |
| --source-account deployer \ | |
| --ignore-checks) | |
| echo "contract_id=${CONTRACT_ID}" >> "$GITHUB_OUTPUT" | |
| echo "Deployed contract ID: ${CONTRACT_ID}" | |
| env: | |
| STELLAR_NETWORK: mainnet | |
| - name: Verify deployment | |
| run: bash scripts/verify_contract.sh | |
| env: | |
| STELLAR_NETWORK: mainnet | |
| STELLAR_RPC_URL: https://soroban-rpc.mainnet.stellar.gateway.fm | |
| CONTRACT_ID: ${{ steps.deploy.outputs.contract_id }} | |
| EXPECTED_WASM_HASH: ${{ needs.pre-deploy.outputs.wasm_hash }} | |
| - name: Post-deploy smoke tests | |
| run: bash scripts/smoke_test_post_deploy.sh | |
| env: | |
| STELLAR_NETWORK: mainnet | |
| STELLAR_RPC_URL: https://soroban-rpc.mainnet.stellar.gateway.fm | |
| CONTRACT_ID: ${{ steps.deploy.outputs.contract_id }} | |
| - name: Save deployment record | |
| run: | | |
| mkdir -p deployment-records | |
| cat > deployment-records/mainnet-${{ github.sha }}.json <<EOF | |
| { | |
| "network": "mainnet", | |
| "contract_id": "${{ steps.deploy.outputs.contract_id }}", | |
| "wasm_hash": "${{ needs.pre-deploy.outputs.wasm_hash }}", | |
| "wasm_size_kb": "${{ needs.pre-deploy.outputs.wasm_size_kb }}", | |
| "commit": "${{ github.sha }}", | |
| "deployed_at": "$(date -u +%Y-%m-%dT%H:%M:%SZ)", | |
| "deployed_by": "${{ github.actor }}" | |
| } | |
| EOF | |
| - name: Upload deployment record | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: deployment-record-mainnet-${{ github.sha }} | |
| path: deployment-records/ | |
| retention-days: 365 | |
| - name: Create GitHub release | |
| uses: actions/github-script@v7 | |
| with: | |
| script: | | |
| const tag = `contract-mainnet-${context.sha.slice(0,8)}`; | |
| await github.rest.git.createRef({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| ref: `refs/tags/${tag}`, | |
| sha: context.sha | |
| }); | |
| await github.rest.repos.createRelease({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| tag_name: tag, | |
| name: `Mainnet Deployment — ${new Date().toISOString().split('T')[0]}`, | |
| body: [ | |
| '## Mainnet Contract Deployment', | |
| `**Contract ID:** \`${{ steps.deploy.outputs.contract_id }}\``, | |
| `**WASM hash:** \`${{ needs.pre-deploy.outputs.wasm_hash }}\``, | |
| `**Commit:** \`${{ github.sha }}\``, | |
| `**Explorer:** https://stellar.expert/explorer/mainnet/contract/${{ steps.deploy.outputs.contract_id }}` | |
| ].join('\n'), | |
| prerelease: false | |
| }); | |
| # ─── Job 4: Rollback (manual trigger only) ─────────────────────────────────── | |
| rollback: | |
| name: Rollback Contract | |
| runs-on: ubuntu-latest | |
| if: | | |
| github.event_name == 'workflow_dispatch' && | |
| github.event.inputs.rollback_artifact != '' | |
| environment: | |
| name: ${{ github.event.inputs.network == 'mainnet' && 'production' || 'testnet' }} | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - name: Install Stellar CLI | |
| run: | | |
| curl -sSL https://github.com/stellar/stellar-cli/releases/download/v22.7.1/stellar-cli-22.7.1-x86_64-unknown-linux-gnu.tar.gz \ | |
| | tar -xz -C /usr/local/bin stellar | |
| - name: Execute rollback | |
| run: bash scripts/rollback.sh | |
| env: | |
| STELLAR_NETWORK: ${{ github.event.inputs.network }} | |
| STELLAR_RPC_URL: ${{ github.event.inputs.network == 'mainnet' && 'https://soroban-rpc.mainnet.stellar.gateway.fm' || 'https://soroban-testnet.stellar.org' }} | |
| ROLLBACK_ARTIFACT_RUN_ID: ${{ github.event.inputs.rollback_artifact }} | |
| DEPLOYER_SECRET: ${{ github.event.inputs.network == 'mainnet' && secrets.MAINNET_DEPLOYER_SECRET || secrets.TESTNET_DEPLOYER_SECRET }} | |
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| REPO: ${{ github.repository }} |