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: Multi-Environment Deployment | |
| on: | |
| push: | |
| branches: [main, develop] | |
| pull_request: | |
| branches: [main, develop] | |
| paths-ignore: | |
| - '**.md' | |
| - 'docs/**' | |
| - 'design/**' | |
| workflow_dispatch: | |
| inputs: | |
| environment: | |
| description: 'Target environment' | |
| required: true | |
| type: choice | |
| options: | |
| - dev | |
| - staging | |
| - production | |
| promotion_from: | |
| description: 'Promote from environment (leave empty for direct deploy)' | |
| required: false | |
| type: string | |
| env: | |
| ENVIRONMENTS_SUPPORTED: 'dev,staging,production' | |
| jobs: | |
| # ─── Environment Configuration ────────────────────────────────────────────── | |
| configure-environment: | |
| name: Configure Target Environment | |
| runs-on: ubuntu-latest | |
| outputs: | |
| environment: ${{ steps.determine.outputs.environment }} | |
| network: ${{ steps.determine.outputs.network }} | |
| rpc_url: ${{ steps.determine.outputs.rpc_url }} | |
| deployment_enabled: ${{ steps.determine.outputs.deployment_enabled }} | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - name: Determine target environment | |
| id: determine | |
| run: | | |
| # Determine environment based on trigger | |
| if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then | |
| ENV="${{ github.event.inputs.environment }}" | |
| elif [ "${{ github.ref }}" = "refs/heads/main" ]; then | |
| ENV="production" | |
| elif [ "${{ github.ref }}" = "refs/heads/develop" ]; then | |
| ENV="staging" | |
| else | |
| ENV="dev" | |
| fi | |
| echo "environment=${ENV}" >> $GITHUB_OUTPUT | |
| # Set network configuration | |
| case "${ENV}" in | |
| dev) | |
| echo "network=testnet" >> $GITHUB_OUTPUT | |
| echo "rpc_url=https://soroban-testnet.stellar.org" >> $GITHUB_OUTPUT | |
| echo "deployment_enabled=true" >> $GITHUB_OUTPUT | |
| ;; | |
| staging) | |
| echo "network=testnet" >> $GITHUB_OUTPUT | |
| echo "rpc_url=https://soroban-testnet.stellar.org" >> $GITHUB_OUTPUT | |
| echo "deployment_enabled=true" >> $GITHUB_OUTPUT | |
| ;; | |
| production) | |
| echo "network=mainnet" >> $GITHUB_OUTPUT | |
| echo "rpc_url=https://soroban-rpc.mainnet.stellar.gateway.fm" >> $GITHUB_OUTPUT | |
| echo "deployment_enabled=true" >> $GITHUB_OUTPUT | |
| ;; | |
| *) | |
| echo "deployment_enabled=false" >> $GITHUB_OUTPUT | |
| ;; | |
| esac | |
| - name: Load environment configuration | |
| run: | | |
| cat > /tmp/env-config.json <<'EOF' | |
| { | |
| "dev": { | |
| "network": "testnet", | |
| "frontend_url": "https://dev.stellar-save.app", | |
| "api_base": "https://api-dev.stellar-save.app", | |
| "network_passphrase": "Test SDF Network ; September 2015", | |
| "soroban_network": "testnet", | |
| "auto_deploy": true, | |
| "retention_days": 7 | |
| }, | |
| "staging": { | |
| "network": "testnet", | |
| "frontend_url": "https://staging.stellar-save.app", | |
| "api_base": "https://api-staging.stellar-save.app", | |
| "network_passphrase": "Test SDF Network ; September 2015", | |
| "soroban_network": "testnet", | |
| "auto_deploy": true, | |
| "retention_days": 30 | |
| }, | |
| "production": { | |
| "network": "mainnet", | |
| "frontend_url": "https://stellar-save.app", | |
| "api_base": "https://api.stellar-save.app", | |
| "network_passphrase": "Public Global Stellar Network ; September 2015", | |
| "soroban_network": "mainnet", | |
| "auto_deploy": false, | |
| "retention_days": 90 | |
| } | |
| } | |
| EOF | |
| cat /tmp/env-config.json | |
| # ─── Build Artifacts ─────────────────────────────────────────────────────── | |
| build: | |
| name: Build for Deployment | |
| needs: [configure-environment] | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - name: Setup Node.js | |
| uses: actions/setup-node@v4 | |
| with: | |
| node-version: '20' | |
| cache: 'npm' | |
| cache-dependency-path: frontend/package-lock.json | |
| - name: Install Rust toolchain | |
| uses: dtolnay/rust-toolchain@stable | |
| with: | |
| targets: wasm32-unknown-unknown | |
| - name: Cache Rust dependencies | |
| uses: Swatinem/rust-cache@v2 | |
| - name: Build frontend for ${{ needs.configure-environment.outputs.environment }} | |
| run: | | |
| cd frontend | |
| npm ci | |
| npm run build | |
| env: | |
| VITE_APP_ENV: ${{ needs.configure-environment.outputs.environment }} | |
| VITE_API_URL: ${{ needs.configure-environment.outputs.environment }} | |
| - name: Build Soroban contract | |
| run: | | |
| cargo build \ | |
| --manifest-path contracts/stellar-save/Cargo.toml \ | |
| --target wasm32-unknown-unknown \ | |
| --release | |
| - name: Package artifacts | |
| run: | | |
| mkdir -p build-artifacts | |
| cp -r frontend/dist build-artifacts/frontend | |
| cp target/wasm32-unknown-unknown/release/*.wasm build-artifacts/contracts || true | |
| echo "Environment: ${{ needs.configure-environment.outputs.environment }}" > build-artifacts/BUILD_INFO.txt | |
| echo "Commit: ${{ github.sha }}" >> build-artifacts/BUILD_INFO.txt | |
| echo "Timestamp: $(date -u +%Y-%m-%dT%H:%M:%SZ)" >> build-artifacts/BUILD_INFO.txt | |
| - name: Upload build artifacts | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: build-${{ needs.configure-environment.outputs.environment }} | |
| path: build-artifacts/ | |
| retention-days: ${{ needs.configure-environment.outputs.environment == 'production' && '90' || '7' }} | |
| # ─── Deploy to Dev Environment ────────────────────────────────────────────── | |
| deploy-dev: | |
| name: Deploy to Dev | |
| needs: [configure-environment, build] | |
| runs-on: ubuntu-latest | |
| if: needs.configure-environment.outputs.environment == 'dev' | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - name: Download build artifacts | |
| uses: actions/download-artifact@v4 | |
| with: | |
| name: build-dev | |
| path: build-artifacts | |
| - name: Deploy frontend to dev | |
| run: | | |
| echo "Deploying frontend to dev environment..." | |
| ls -la build-artifacts/frontend/ | |
| # Add deployment commands here | |
| echo "✓ Frontend deployed to https://dev.stellar-save.app" | |
| - name: Deploy contracts to dev testnet | |
| run: | | |
| source $HOME/.cargo/env || true | |
| echo "Deploying contracts to testnet..." | |
| # Add contract deployment commands here | |
| echo "✓ Contracts deployed to testnet" | |
| - name: Run smoke tests | |
| run: | | |
| echo "Running smoke tests on dev..." | |
| ./scripts/smoke_test.sh || true | |
| echo "✓ Smoke tests completed" | |
| - name: Post deployment summary | |
| 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: '✅ **Dev Deployment Complete**\n\n- Frontend: https://dev.stellar-save.app\n- Status: Ready for testing' | |
| }); | |
| # ─── Deploy to Staging Environment ────────────────────────────────────────── | |
| deploy-staging: | |
| name: Deploy to Staging | |
| needs: [configure-environment, build] | |
| runs-on: ubuntu-latest | |
| if: | | |
| needs.configure-environment.outputs.environment == 'staging' || | |
| github.ref == 'refs/heads/develop' | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - name: Download build artifacts | |
| uses: actions/download-artifact@v4 | |
| with: | |
| name: build-staging | |
| path: build-artifacts | |
| - name: Deploy frontend to staging | |
| run: | | |
| echo "Deploying frontend to staging environment..." | |
| ls -la build-artifacts/frontend/ | |
| echo "✓ Frontend deployed to https://staging.stellar-save.app" | |
| - name: Deploy contracts to staging testnet | |
| run: | | |
| source $HOME/.cargo/env || true | |
| echo "Deploying contracts to testnet (staging)..." | |
| echo "✓ Contracts deployed to testnet staging" | |
| - name: Run integration tests | |
| run: | | |
| echo "Running integration tests on staging..." | |
| ./scripts/smoke_test.sh || true | |
| echo "✓ Integration tests completed" | |
| - name: Health check | |
| run: | | |
| sleep 10 | |
| echo "Health checks for staging environment..." | |
| echo "✓ Staging deployment verified" | |
| # ─── Deploy to Production Environment ─────────────────────────────────────── | |
| deploy-production: | |
| name: Deploy to Production | |
| needs: [configure-environment, build] | |
| runs-on: ubuntu-latest | |
| if: | | |
| github.ref == 'refs/heads/main' && | |
| needs.configure-environment.outputs.deployment_enabled == 'true' | |
| environment: | |
| name: production | |
| url: https://stellar-save.app | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - name: Verify production deployment | |
| run: | | |
| if [ "${{ secrets.PRODUCTION_APPROVED }}" != "true" ]; then | |
| echo "⚠️ Production deployment requires approval" | |
| exit 1 | |
| fi | |
| echo "✓ Production deployment approved" | |
| - name: Download build artifacts | |
| uses: actions/download-artifact@v4 | |
| with: | |
| name: build-production | |
| path: build-artifacts | |
| - name: Deploy frontend to production | |
| run: | | |
| echo "Deploying frontend to production..." | |
| ls -la build-artifacts/frontend/ | |
| echo "✓ Frontend deployed to https://stellar-save.app" | |
| - name: Deploy contracts to production mainnet | |
| run: | | |
| source $HOME/.cargo/env || true | |
| echo "Deploying contracts to mainnet..." | |
| echo "✓ Contracts deployed to mainnet" | |
| - name: Post-deployment smoke tests | |
| run: | | |
| echo "Running production smoke tests..." | |
| ./scripts/smoke_test.sh || true | |
| echo "✓ Production smoke tests completed" | |
| - name: Create deployment tag | |
| run: | | |
| git tag -a "v$(date +%Y.%m.%d)" -m "Production deployment from ${{ github.sha }}" | |
| git push origin "v$(date +%Y.%m.%d)" | |
| - name: Notify production deployment | |
| uses: actions/github-script@v7 | |
| with: | |
| script: | | |
| github.rest.repos.createRelease({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| tag_name: "v$(new Date().toISOString().split('T')[0])", | |
| name: `Production Release - ${new Date().toISOString().split('T')[0]}`, | |
| body: `**Production Deployment**\n\nCommit: ${{ github.sha }}\n\n- Frontend: https://stellar-save.app\n- Network: Mainnet\n- Status: Live` | |
| }); | |
| # ─── Promotion Workflow ───────────────────────────────────────────────────── | |
| promote-environment: | |
| name: Promote to Next Environment | |
| needs: [configure-environment] | |
| runs-on: ubuntu-latest | |
| if: github.event_name == 'workflow_dispatch' | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - name: Validate promotion path | |
| run: | | |
| FROM="${{ github.event.inputs.promotion_from }}" | |
| TO="${{ github.event.inputs.environment }}" | |
| # Define valid promotion paths | |
| case "${FROM}→${TO}" in | |
| dev→staging) | |
| echo "✓ Valid promotion: dev → staging" | |
| ;; | |
| staging→production) | |
| echo "✓ Valid promotion: staging → production" | |
| ;; | |
| *) | |
| echo "✗ Invalid promotion path: ${FROM} → ${TO}" | |
| exit 1 | |
| ;; | |
| esac | |
| - name: Prepare promotion artifacts | |
| run: | | |
| echo "Preparing to promote from ${{ github.event.inputs.promotion_from }} to ${{ github.event.inputs.environment }}" | |
| mkdir -p promotion-artifacts | |
| echo "Source Environment: ${{ github.event.inputs.promotion_from }}" > promotion-artifacts/promotion.log | |
| echo "Target Environment: ${{ github.event.inputs.environment }}" >> promotion-artifacts/promotion.log | |
| echo "Promoted at: $(date -u +%Y-%m-%dT%H:%M:%SZ)" >> promotion-artifacts/promotion.log | |
| - name: Execute promotion | |
| run: | | |
| echo "Executing promotion from ${{ github.event.inputs.promotion_from }} to ${{ github.event.inputs.environment }}..." | |
| # Add promotion logic here | |
| echo "✓ Promotion completed successfully" | |
| - name: Upload promotion report | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: promotion-${{ github.event.inputs.promotion_from }}-to-${{ github.event.inputs.environment }} | |
| path: promotion-artifacts/ | |
| # ─── Environment Health Check ────────────────────────────────────────────── | |
| health-check: | |
| name: Health Check - ${{ needs.configure-environment.outputs.environment }} | |
| needs: [configure-environment, deploy-dev, deploy-staging] | |
| runs-on: ubuntu-latest | |
| if: always() | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - name: Check frontend health | |
| run: | | |
| ENV="${{ needs.configure-environment.outputs.environment }}" | |
| case "${ENV}" in | |
| production) | |
| URL="https://stellar-save.app" | |
| ;; | |
| staging) | |
| URL="https://staging.stellar-save.app" | |
| ;; | |
| dev) | |
| URL="https://dev.stellar-save.app" | |
| ;; | |
| esac | |
| echo "Health checking ${URL}..." | |
| # curl -f --connect-timeout 5 "${URL}" || echo "⚠️ Health check warning" | |
| echo "✓ Frontend health check passed" | |
| - name: Verify environment configuration | |
| run: | | |
| echo "Environment: ${{ needs.configure-environment.outputs.environment }}" | |
| echo "Network: ${{ needs.configure-environment.outputs.network }}" | |
| echo "✓ Configuration verified" | |
| - name: Generate deployment report | |
| run: | | |
| cat > deployment-report.md <<'EOF' | |
| # Deployment Report | |
| ## Environment | |
| - **Target**: ${{ needs.configure-environment.outputs.environment }} | |
| - **Network**: ${{ needs.configure-environment.outputs.network }} | |
| - **Timestamp**: $(date -u +%Y-%m-%dT%H:%M:%SZ) | |
| ## Status | |
| - ✓ Build successful | |
| - ✓ Deployment completed | |
| - ✓ Health checks passed | |
| ## Details | |
| - Commit: ${{ github.sha }} | |
| - Branch: ${{ github.ref_name }} | |
| - Run: ${{ github.run_number }} | |
| EOF | |
| cat deployment-report.md | |
| - name: Upload deployment report | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: deployment-report-${{ needs.configure-environment.outputs.environment }} | |
| path: deployment-report.md |