fix(validation): return 422, add missing schemas and PATCH metadata e… #136
Workflow file for this run
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 | |
| on: | |
| push: | |
| branches: | |
| - main | |
| pull_request: | |
| types: | |
| - opened | |
| - reopened | |
| - synchronize | |
| branches: | |
| - main | |
| workflow_dispatch: | |
| inputs: | |
| environment: | |
| description: 'Deployment environment' | |
| required: true | |
| type: choice | |
| options: | |
| - testnet | |
| - staging | |
| - mainnet | |
| env: | |
| RUST_BACKTRACE: 1 | |
| jobs: | |
| # Testnet deployment - automatic on main branch merge | |
| deploy-testnet: | |
| name: Deploy to Testnet | |
| runs-on: ubuntu-latest | |
| if: github.event_name == 'push' && github.ref == 'refs/heads/main' | |
| environment: | |
| name: testnet | |
| url: https://stellar.expert/explorer/testnet | |
| outputs: | |
| contract_id: ${{ steps.deploy.outputs.contract_id }} | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v4 | |
| - name: Install Rust toolchain | |
| uses: dtolnay/rust-toolchain@stable | |
| with: | |
| targets: wasm32-unknown-unknown | |
| - name: Cache Cargo registry and build artifacts | |
| uses: actions/cache@v4 | |
| with: | |
| path: | | |
| ~/.cargo/registry | |
| ~/.cargo/git | |
| contracts/target | |
| key: ${{ runner.os }}-cargo-${{ hashFiles('contracts/Cargo.lock') }} | |
| restore-keys: | | |
| ${{ runner.os }}-cargo- | |
| - name: Install soroban-cli | |
| run: | | |
| cargo install soroban-cli --locked | |
| - name: Build contract | |
| working-directory: contracts | |
| run: | | |
| cargo build --target wasm32-unknown-unknown --release --no-default-features | |
| - name: Deploy to testnet | |
| id: deploy | |
| working-directory: contracts | |
| env: | |
| SECRET_KEY: ${{ secrets.TESTNET_SECRET_KEY }} | |
| NETWORK_PASSPHRASE: Test SDF Network ; September 2015 | |
| RPC_URL: https://soroban-testnet.stellar.org:443 | |
| run: | | |
| if [ -z "$SECRET_KEY" ]; then | |
| echo "Error: TESTNET_SECRET_KEY secret not configured" | |
| exit 1 | |
| fi | |
| echo "Deploying to testnet..." | |
| DEPLOY_OUTPUT=$(soroban contract deploy \ | |
| --wasm target/wasm32-unknown-unknown/release/stellar_goal_vault.wasm \ | |
| --source-account "$SECRET_KEY" \ | |
| --network testnet \ | |
| --network-passphrase "$NETWORK_PASSPHRASE" \ | |
| --rpc-url "$RPC_URL" \ | |
| 2>&1) | |
| DEPLOY_EXIT_CODE=$? | |
| if [ $DEPLOY_EXIT_CODE -ne 0 ]; then | |
| echo "Deployment failed: $DEPLOY_OUTPUT" | |
| exit 1 | |
| fi | |
| CONTRACT_ID=$(echo "$DEPLOY_OUTPUT" | grep -oE '[A-Z0-9]{56}' | head -n 1) | |
| if [ -z "$CONTRACT_ID" ]; then | |
| CONTRACT_ID=$(echo "$DEPLOY_OUTPUT" | tr -d '[:space:]') | |
| fi | |
| if [ ${#CONTRACT_ID} -ne 56 ]; then | |
| echo "Invalid contract ID format" | |
| exit 1 | |
| fi | |
| echo "contract_id=$CONTRACT_ID" >> $GITHUB_OUTPUT | |
| echo "Contract ID: $CONTRACT_ID" | |
| echo "TESTNET_CONTRACT_ID=$CONTRACT_ID" >> $GITHUB_ENV | |
| - name: Update testnet contract ID in repository | |
| uses: actions/github-script@v7 | |
| with: | |
| script: | | |
| const fs = require('fs'); | |
| const contractId = '${{ steps.deploy.outputs.contract_id }}'; | |
| // Update .env.example with new contract ID | |
| try { | |
| let envExample = fs.readFileSync('.env.example', 'utf8'); | |
| const updated = envExample.replace( | |
| /TESTNET_CONTRACT_ID=.*/, | |
| `TESTNET_CONTRACT_ID=${contractId}` | |
| ); | |
| fs.writeFileSync('.env.example', updated); | |
| } catch (e) { | |
| console.log('Could not update .env.example:', e.message); | |
| } | |
| - name: Commit and push contract ID update | |
| if: steps.deploy.outputs.contract_id != '' | |
| run: | | |
| git config --local user.email "github-actions[bot]@users.noreply.github.com" | |
| git config --local user.name "github-actions[bot]" | |
| git add .env.example | |
| git diff --staged --quiet || git commit -m "chore: update testnet contract ID [skip ci]" | |
| git push | |
| - name: Create deployment summary | |
| run: | | |
| echo "### Testnet Deployment Successful" >> $GITHUB_STEP_SUMMARY | |
| echo "" >> $GITHUB_STEP_SUMMARY | |
| echo "**Contract ID:** \`${{ steps.deploy.outputs.contract_id }}\`" >> $GITHUB_STEP_SUMMARY | |
| echo "" >> $GITHUB_STEP_SUMMARY | |
| echo "**Explorer:** [View on Stellar Expert](https://stellar.expert/explorer/testnet/contract/${{ steps.deploy.outputs.contract_id }})" >> $GITHUB_STEP_SUMMARY | |
| # Staging deployment - automatic on release PR | |
| deploy-staging: | |
| name: Deploy to Staging | |
| runs-on: ubuntu-latest | |
| if: | | |
| github.event_name == 'pull_request' && | |
| contains(github.event.pull_request.labels.*.name, 'release') && | |
| github.event.pull_request.draft == false | |
| environment: | |
| name: staging | |
| url: https://stellar.expert/explorer/testnet | |
| outputs: | |
| contract_id: ${{ steps.deploy.outputs.contract_id }} | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v4 | |
| - name: Install Rust toolchain | |
| uses: dtolnay/rust-toolchain@stable | |
| with: | |
| targets: wasm32-unknown-unknown | |
| - name: Cache Cargo registry and build artifacts | |
| uses: actions/cache@v4 | |
| with: | |
| path: | | |
| ~/.cargo/registry | |
| ~/.cargo/git | |
| contracts/target | |
| key: ${{ runner.os }}-cargo-${{ hashFiles('contracts/Cargo.lock') }} | |
| restore-keys: | | |
| ${{ runner.os }}-cargo- | |
| - name: Install soroban-cli | |
| run: | | |
| cargo install soroban-cli --locked | |
| - name: Build contract | |
| working-directory: contracts | |
| run: | | |
| cargo build --target wasm32-unknown-unknown --release --no-default-features | |
| - name: Deploy to staging (testnet) | |
| id: deploy | |
| working-directory: contracts | |
| env: | |
| SECRET_KEY: ${{ secrets.STAGING_SECRET_KEY }} | |
| NETWORK_PASSPHRASE: Test SDF Network ; September 2015 | |
| RPC_URL: https://soroban-testnet.stellar.org:443 | |
| run: | | |
| if [ -z "$SECRET_KEY" ]; then | |
| echo "Error: STAGING_SECRET_KEY secret not configured" | |
| exit 1 | |
| fi | |
| echo "Deploying to staging (testnet)..." | |
| DEPLOY_OUTPUT=$(soroban contract deploy \ | |
| --wasm target/wasm32-unknown-unknown/release/stellar_goal_vault.wasm \ | |
| --source-account "$SECRET_KEY" \ | |
| --network testnet \ | |
| --network-passphrase "$NETWORK_PASSPHRASE" \ | |
| --rpc-url "$RPC_URL" \ | |
| 2>&1) | |
| DEPLOY_EXIT_CODE=$? | |
| if [ $DEPLOY_EXIT_CODE -ne 0 ]; then | |
| echo "Deployment failed: $DEPLOY_OUTPUT" | |
| exit 1 | |
| fi | |
| CONTRACT_ID=$(echo "$DEPLOY_OUTPUT" | grep -oE '[A-Z0-9]{56}' | head -n 1) | |
| if [ -z "$CONTRACT_ID" ]; then | |
| CONTRACT_ID=$(echo "$DEPLOY_OUTPUT" | tr -d '[:space:]') | |
| fi | |
| if [ ${#CONTRACT_ID} -ne 56 ]; then | |
| echo "Invalid contract ID format" | |
| exit 1 | |
| fi | |
| echo "contract_id=$CONTRACT_ID" >> $GITHUB_OUTPUT | |
| echo "Contract ID: $CONTRACT_ID" | |
| echo "STAGING_CONTRACT_ID=$CONTRACT_ID" >> $GITHUB_ENV | |
| - name: Comment on PR with contract ID | |
| uses: actions/github-script@v7 | |
| if: steps.deploy.outputs.contract_id != '' | |
| with: | |
| script: | | |
| github.rest.issues.createComment({ | |
| issue_number: context.issue.number, | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| body: `## 🚀 Staging Deployment Successful\n\n**Contract ID:** \`${{ steps.deploy.outputs.contract_id }}\`\n\n**Explorer:** [View on Stellar Expert](https://stellar.expert/explorer/testnet/contract/${{ steps.deploy.outputs.contract_id }})\n\nThis deployment is on testnet for staging purposes.` | |
| }) | |
| - name: Create deployment summary | |
| run: | | |
| echo "### Staging Deployment Successful" >> $GITHUB_STEP_SUMMARY | |
| echo "" >> $GITHUB_STEP_SUMMARY | |
| echo "**Contract ID:** \`${{ steps.deploy.outputs.contract_id }}\`" >> $GITHUB_STEP_SUMMARY | |
| echo "" >> $GITHUB_STEP_SUMMARY | |
| echo "**Explorer:** [View on Stellar Expert](https://stellar.expert/explorer/testnet/contract/${{ steps.deploy.outputs.contract_id }})" >> $GITHUB_STEP_SUMMARY | |
| # Mainnet deployment - manual approval required | |
| deploy-mainnet: | |
| name: Deploy to Mainnet | |
| runs-on: ubuntu-latest | |
| if: | | |
| (github.event_name == 'workflow_dispatch' && github.event.inputs.environment == 'mainnet') || | |
| (github.event_name == 'push' && github.ref == 'refs/heads/main' && contains(github.event.head_commit.message, '[deploy-mainnet]')) | |
| environment: | |
| name: mainnet | |
| url: https://stellar.expert/explorer/public | |
| outputs: | |
| contract_id: ${{ steps.deploy.outputs.contract_id }} | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v4 | |
| - name: Install Rust toolchain | |
| uses: dtolnay/rust-toolchain@stable | |
| with: | |
| targets: wasm32-unknown-unknown | |
| - name: Cache Cargo registry and build artifacts | |
| uses: actions/cache@v4 | |
| with: | |
| path: | | |
| ~/.cargo/registry | |
| ~/.cargo/git | |
| contracts/target | |
| key: ${{ runner.os }}-cargo-${{ hashFiles('contracts/Cargo.lock') }} | |
| restore-keys: | | |
| ${{ runner.os }}-cargo- | |
| - name: Install soroban-cli | |
| run: | | |
| cargo install soroban-cli --locked | |
| - name: Build contract | |
| working-directory: contracts | |
| run: | | |
| cargo build --target wasm32-unknown-unknown --release --no-default-features | |
| - name: Deploy to mainnet | |
| id: deploy | |
| working-directory: contracts | |
| env: | |
| SECRET_KEY: ${{ secrets.MAINNET_SECRET_KEY }} | |
| NETWORK_PASSPHRASE: Public Global Stellar Network ; September 2015 | |
| RPC_URL: https://soroban-rpc.publicnode.stellar.org:443 | |
| run: | | |
| if [ -z "$SECRET_KEY" ]; then | |
| echo "Error: MAINNET_SECRET_KEY secret not configured" | |
| exit 1 | |
| fi | |
| echo "⚠️ DEPLOYING TO MAINNET - THIS IS IRREVERSIBLE ⚠️" | |
| echo "Contract ID: $CONTRACT_ID" | |
| sleep 10 | |
| echo "Deploying to mainnet..." | |
| DEPLOY_OUTPUT=$(soroban contract deploy \ | |
| --wasm target/wasm32-unknown-unknown/release/stellar_goal_vault.wasm \ | |
| --source-account "$SECRET_KEY" \ | |
| --network public \ | |
| --network-passphrase "$NETWORK_PASSPHRASE" \ | |
| --rpc-url "$RPC_URL" \ | |
| 2>&1) | |
| DEPLOY_EXIT_CODE=$? | |
| if [ $DEPLOY_EXIT_CODE -ne 0 ]; then | |
| echo "Deployment failed: $DEPLOY_OUTPUT" | |
| exit 1 | |
| fi | |
| CONTRACT_ID=$(echo "$DEPLOY_OUTPUT" | grep -oE '[A-Z0-9]{56}' | head -n 1) | |
| if [ -z "$CONTRACT_ID" ]; then | |
| CONTRACT_ID=$(echo "$DEPLOY_OUTPUT" | tr -d '[:space:]') | |
| fi | |
| if [ ${#CONTRACT_ID} -ne 56 ]; then | |
| echo "Invalid contract ID format" | |
| exit 1 | |
| fi | |
| echo "contract_id=$CONTRACT_ID" >> $GITHUB_OUTPUT | |
| echo "Contract ID: $CONTRACT_ID" | |
| echo "MAINNET_CONTRACT_ID=$CONTRACT_ID" >> $GITHUB_ENV | |
| - name: Update mainnet contract ID in repository | |
| uses: actions/github-script@v7 | |
| if: steps.deploy.outputs.contract_id != '' | |
| with: | |
| script: | | |
| const fs = require('fs'); | |
| const contractId = '${{ steps.deploy.outputs.contract_id }}'; | |
| // Update .env.example with new contract ID | |
| try { | |
| let envExample = fs.readFileSync('.env.example', 'utf8'); | |
| const updated = envExample.replace( | |
| /MAINNET_CONTRACT_ID=.*/, | |
| `MAINNET_CONTRACT_ID=${contractId}` | |
| ); | |
| fs.writeFileSync('.env.example', updated); | |
| } catch (e) { | |
| console.log('Could not update .env.example:', e.message); | |
| } | |
| - name: Commit and push contract ID update | |
| if: steps.deploy.outputs.contract_id != '' | |
| run: | | |
| git config --local user.email "github-actions[bot]@users.noreply.github.com" | |
| git config --local user.name "github-actions[bot]" | |
| git add .env.example | |
| git diff --staged --quiet || git commit -m "chore: update mainnet contract ID [skip ci]" | |
| git push | |
| - name: Create GitHub release | |
| if: steps.deploy.outputs.contract_id != '' | |
| uses: actions/create-release@v1 | |
| env: | |
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| with: | |
| tag_name: v${{ github.run_number }} | |
| release_name: Mainnet Contract Deployment v${{ github.run_number }} | |
| body: | | |
| ## Mainnet Contract Deployment | |
| **Contract ID:** `${{ steps.deploy.outputs.contract_id }}` | |
| **Explorer:** [View on Stellar Expert](https://stellar.expert/explorer/public/contract/${{ steps.deploy.outputs.contract_id }}) | |
| This contract has been deployed to the Stellar mainnet and is ready for production use. | |
| draft: false | |
| prerelease: false | |
| - name: Create deployment summary | |
| run: | | |
| echo "### 🎉 Mainnet Deployment Successful" >> $GITHUB_STEP_SUMMARY | |
| echo "" >> $GITHUB_STEP_SUMMARY | |
| echo "**Contract ID:** \`${{ steps.deploy.outputs.contract_id }}\`" >> $GITHUB_STEP_SUMMARY | |
| echo "" >> $GITHUB_STEP_SUMMARY | |
| echo "**Explorer:** [View on Stellar Expert](https://stellar.expert/explorer/public/contract/${{ steps.deploy.outputs.contract_id }})" >> $GITHUB_STEP_SUMMARY | |
| echo "" >> $GITHUB_STEP_SUMMARY | |
| echo "⚠️ **IMPORTANT:** This contract is now live on mainnet. All transactions are irreversible." >> $GITHUB_STEP_SUMMARY |