Repository navigation
Merge pull request #1429 from amandasmyths/main #73
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: Deploy to Staging | |
| on: | |
| push: | |
| branches: [main] | |
| workflow_dispatch: | |
| inputs: | |
| skip_smoke: | |
| description: "Skip smoke tests (useful for infrastructure-only changes)" | |
| required: false | |
| default: "false" | |
| type: boolean | |
| concurrency: | |
| group: staging-deploy | |
| cancel-in-progress: false # Never cancel an in-flight staging deploy | |
| permissions: | |
| contents: read | |
| deployments: write | |
| jobs: | |
| # ── Build and push Docker images ────────────────────────────────────────── | |
| build-images: | |
| name: Build & push images | |
| runs-on: ubuntu-latest | |
| outputs: | |
| sha_short: ${{ steps.meta.outputs.sha_short }} | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - name: Set image metadata | |
| id: meta | |
| run: echo "sha_short=$(git rev-parse --short HEAD)" >> "$GITHUB_OUTPUT" | |
| - name: Set up Docker Buildx | |
| uses: docker/setup-buildx-action@v3 | |
| - name: Log in to GitHub Container Registry | |
| uses: docker/login-action@v3 | |
| with: | |
| registry: ghcr.io | |
| username: ${{ github.actor }} | |
| password: ${{ secrets.GITHUB_TOKEN }} | |
| - name: Build & push backend image | |
| uses: docker/build-push-action@v6 | |
| with: | |
| context: ./backend | |
| file: ./backend/Dockerfile | |
| push: true | |
| tags: | | |
| ghcr.io/${{ github.repository }}/backend:staging | |
| ghcr.io/${{ github.repository }}/backend:${{ steps.meta.outputs.sha_short }} | |
| cache-from: type=gha | |
| cache-to: type=gha,mode=max | |
| - name: Build & push api image | |
| uses: docker/build-push-action@v6 | |
| with: | |
| context: ./api | |
| file: ./api/Dockerfile | |
| push: true | |
| tags: | | |
| ghcr.io/${{ github.repository }}/api:staging | |
| ghcr.io/${{ github.repository }}/api:${{ steps.meta.outputs.sha_short }} | |
| cache-from: type=gha | |
| cache-to: type=gha,mode=max | |
| - name: Build & push frontend image | |
| uses: docker/build-push-action@v6 | |
| with: | |
| context: ./frontend | |
| file: ./frontend/Dockerfile | |
| push: true | |
| tags: | | |
| ghcr.io/${{ github.repository }}/frontend:staging | |
| ghcr.io/${{ github.repository }}/frontend:${{ steps.meta.outputs.sha_short }} | |
| cache-from: type=gha | |
| cache-to: type=gha,mode=max | |
| # ── Deploy to staging VM via SSH ────────────────────────────────────────── | |
| deploy: | |
| name: Deploy to staging | |
| runs-on: ubuntu-latest | |
| needs: build-images | |
| environment: | |
| name: staging | |
| url: ${{ vars.STAGING_API_URL }} | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - name: Create GitHub deployment | |
| uses: chrnorm/deployment-action@v2 | |
| id: deployment | |
| with: | |
| token: ${{ secrets.GITHUB_TOKEN }} | |
| environment: staging | |
| ref: ${{ github.sha }} | |
| - name: Copy compose file to staging server | |
| uses: appleboy/scp-action@v0.1.7 | |
| with: | |
| host: ${{ secrets.STAGING_HOST }} | |
| username: ${{ secrets.STAGING_USER }} | |
| key: ${{ secrets.STAGING_SSH_KEY }} | |
| port: ${{ secrets.STAGING_SSH_PORT || 22 }} | |
| source: "docker-compose.yml,docker-compose.override.yml,.env.testnet" | |
| target: "~/swiftremit" | |
| - name: Deploy via Docker Compose | |
| uses: appleboy/ssh-action@v1.0.3 | |
| with: | |
| host: ${{ secrets.STAGING_HOST }} | |
| username: ${{ secrets.STAGING_USER }} | |
| key: ${{ secrets.STAGING_SSH_KEY }} | |
| port: ${{ secrets.STAGING_SSH_PORT || 22 }} | |
| script: | | |
| set -euo pipefail | |
| cd ~/swiftremit | |
| # Log into GHCR | |
| echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io -u ${{ github.actor }} --password-stdin | |
| # Export image tags so compose uses the freshly pushed images | |
| export BACKEND_IMAGE=ghcr.io/${{ github.repository }}/backend:${{ needs.build-images.outputs.sha_short }} | |
| export API_IMAGE=ghcr.io/${{ github.repository }}/api:${{ needs.build-images.outputs.sha_short }} | |
| export FRONTEND_IMAGE=ghcr.io/${{ github.repository }}/frontend:${{ needs.build-images.outputs.sha_short }} | |
| # Source testnet env overrides then deploy | |
| set -a; source .env.testnet; set +a | |
| docker compose pull | |
| docker compose up -d --remove-orphans | |
| # Give services a moment to start before smoke tests run | |
| sleep 10 | |
| docker compose ps | |
| - name: Mark deployment success | |
| if: success() | |
| uses: chrnorm/deployment-status@v2 | |
| with: | |
| token: ${{ secrets.GITHUB_TOKEN }} | |
| deployment-id: ${{ steps.deployment.outputs.deployment_id }} | |
| state: success | |
| environment-url: ${{ vars.STAGING_API_URL }} | |
| - name: Mark deployment failure | |
| if: failure() | |
| uses: chrnorm/deployment-status@v2 | |
| with: | |
| token: ${{ secrets.GITHUB_TOKEN }} | |
| deployment-id: ${{ steps.deployment.outputs.deployment_id }} | |
| state: failure | |
| # ── Smoke tests against the live staging environment ────────────────────── | |
| smoke-tests: | |
| name: Smoke tests | |
| runs-on: ubuntu-latest | |
| needs: deploy | |
| if: ${{ github.event.inputs.skip_smoke != 'true' }} | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - name: Run smoke tests | |
| env: | |
| STAGING_API_URL: ${{ vars.STAGING_API_URL }} | |
| STAGING_BACKEND_URL: ${{ vars.STAGING_BACKEND_URL }} | |
| run: bash scripts/smoke-test-staging.sh | |
| - name: Smoke test summary | |
| if: always() | |
| run: | | |
| echo "### Smoke test results" >> $GITHUB_STEP_SUMMARY | |
| echo "- API URL: \`${{ vars.STAGING_API_URL }}\`" >> $GITHUB_STEP_SUMMARY | |
| echo "- Backend URL: \`${{ vars.STAGING_BACKEND_URL }}\`" >> $GITHUB_STEP_SUMMARY | |
| echo "- Commit: \`${{ needs.build-images.outputs.sha_short }}\`" >> $GITHUB_STEP_SUMMARY |