Repository navigation
Deploy to Cloudflare #699
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 Cloudflare | |
| permissions: | |
| contents: read | |
| deployments: write | |
| checks: write | |
| on: | |
| workflow_run: | |
| workflows: ["Test"] | |
| types: | |
| - completed | |
| branches: [main] | |
| concurrency: | |
| group: mcp-production-deploy | |
| cancel-in-progress: false | |
| jobs: | |
| deploy: | |
| name: Deploy to Cloudflare | |
| runs-on: ubuntu-latest | |
| environment: production | |
| if: >- | |
| ${{ github.event.workflow_run.conclusion == 'success' && | |
| github.event.workflow_run.event == 'push' && | |
| github.event.workflow_run.head_repository.id == github.event.repository.id && | |
| github.event.workflow_run.head_branch == 'main' }} | |
| steps: | |
| - uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4.4.0 | |
| with: | |
| ref: ${{ github.event.workflow_run.head_sha }} | |
| persist-credentials: false | |
| - name: Require tested revision on main | |
| env: | |
| GH_TOKEN: ${{ github.token }} | |
| EXPECTED_SHA: ${{ github.event.workflow_run.head_sha }} | |
| run: | | |
| current_sha="$(gh api "repos/$GITHUB_REPOSITORY/git/ref/heads/main" --jq '.object.sha')" | |
| if [[ "$current_sha" != "$EXPECTED_SHA" ]]; then | |
| echo 'The tested revision is no longer at main; refusing deployment.' >&2 | |
| exit 1 | |
| fi | |
| - name: Setup Node.js | |
| uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0 | |
| with: | |
| node-version: "22" | |
| # pnpm/action-setup@v4 | |
| - uses: pnpm/action-setup@a7487c7e89a18df4991f7f222e4898a00d66ddda | |
| name: Install pnpm | |
| with: | |
| run_install: false | |
| - name: Get pnpm store directory | |
| shell: bash | |
| run: | | |
| echo "STORE_PATH=$(pnpm store path --silent)" >> "$GITHUB_ENV" | |
| - uses: actions/cache@0400d5f644dc74513175e3cd8d07132dd4860809 # v4.2.4 | |
| name: Setup pnpm cache | |
| with: | |
| path: ${{ env.STORE_PATH }} | |
| key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }} | |
| restore-keys: | | |
| ${{ runner.os }}-pnpm-store- | |
| - name: Install dependencies | |
| run: pnpm install --frozen-lockfile | |
| # === BUILD AND DEPLOY CANARY WORKER === | |
| - name: Build | |
| run: pnpm --filter '@sentry/mcp-cloudflare...' run build | |
| env: | |
| SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }} | |
| VITE_SENTRY_DSN: ${{ secrets.VITE_SENTRY_DSN }} | |
| VITE_SENTRY_ENVIRONMENT: production | |
| - name: Deploy to Canary Worker | |
| id: deploy_canary | |
| working-directory: packages/mcp-cloudflare | |
| env: | |
| CLOUDFLARE_API_TOKEN: ${{ secrets.CLOUDFLARE_API_TOKEN }} | |
| CLOUDFLARE_ACCOUNT_ID: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }} | |
| run: pnpm exec wrangler deploy --config wrangler.canary.jsonc | |
| - name: Wait for Canary to Propagate | |
| if: success() | |
| run: | | |
| echo "Waiting 30 seconds for canary deployment to propagate..." | |
| sleep 30 | |
| # === SMOKE TEST CANARY === | |
| - name: Run Smoke Tests on Canary | |
| id: canary_smoke_tests | |
| if: success() | |
| env: | |
| PREVIEW_URL: https://sentry-mcp-canary.getsentry.workers.dev | |
| run: | | |
| echo "Running smoke tests against canary worker..." | |
| cd packages/smoke-tests | |
| pnpm test:ci | |
| - name: Publish Canary Smoke Test Report | |
| uses: mikepenz/action-junit-report@cf701569b05ccdd861a76b8607a66d76f6fd4857 | |
| if: always() && steps.canary_smoke_tests.outcome != 'skipped' | |
| with: | |
| report_paths: "packages/smoke-tests/tests.junit.xml" | |
| check_name: "Canary Smoke Test Results" | |
| fail_on_failure: false | |
| # === DEPLOY PRODUCTION WORKER (only if canary tests pass) === | |
| - name: Require tested revision on main before production | |
| if: steps.canary_smoke_tests.outcome == 'success' | |
| env: | |
| GH_TOKEN: ${{ github.token }} | |
| EXPECTED_SHA: ${{ github.event.workflow_run.head_sha }} | |
| run: | | |
| current_sha="$(gh api "repos/$GITHUB_REPOSITORY/git/ref/heads/main" --jq '.object.sha')" | |
| if [[ "$current_sha" != "$EXPECTED_SHA" ]]; then | |
| echo 'Main advanced during canary testing; refusing production deployment.' >&2 | |
| exit 1 | |
| fi | |
| - name: Capture active production version | |
| if: steps.canary_smoke_tests.outcome == 'success' | |
| env: | |
| CLOUDFLARE_API_TOKEN: ${{ secrets.CLOUDFLARE_API_TOKEN }} | |
| CLOUDFLARE_ACCOUNT_ID: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }} | |
| TESTED_SHA: ${{ github.event.workflow_run.head_sha }} | |
| run: node scripts/cloudflare-deployment.mjs capture | |
| - name: Deploy to Production Worker | |
| id: deploy_production | |
| if: steps.canary_smoke_tests.outcome == 'success' | |
| working-directory: packages/mcp-cloudflare | |
| env: | |
| CLOUDFLARE_API_TOKEN: ${{ secrets.CLOUDFLARE_API_TOKEN }} | |
| CLOUDFLARE_ACCOUNT_ID: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }} | |
| TESTED_SHA: ${{ github.event.workflow_run.head_sha }} | |
| run: pnpm exec wrangler deploy --message "toolkit-mcp:$GITHUB_RUN_ID:$GITHUB_RUN_ATTEMPT:$TESTED_SHA" | |
| - name: Verify production deployment ownership | |
| id: verify_production | |
| if: steps.deploy_production.outcome == 'success' | |
| env: | |
| CLOUDFLARE_API_TOKEN: ${{ secrets.CLOUDFLARE_API_TOKEN }} | |
| CLOUDFLARE_ACCOUNT_ID: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }} | |
| TESTED_SHA: ${{ github.event.workflow_run.head_sha }} | |
| run: node scripts/cloudflare-deployment.mjs verify | |
| - name: Wait for Production to Propagate | |
| if: steps.verify_production.outcome == 'success' | |
| run: | | |
| echo "Waiting 30 seconds for production deployment to propagate..." | |
| sleep 30 | |
| # === SMOKE TEST PRODUCTION === | |
| - name: Run Smoke Tests on Production | |
| id: production_smoke_tests | |
| if: steps.verify_production.outcome == 'success' | |
| env: | |
| PREVIEW_URL: https://mcp.sentry.dev | |
| run: | | |
| echo "Running smoke tests on production..." | |
| cd packages/smoke-tests | |
| pnpm test:ci | |
| - name: Publish Production Smoke Test Report | |
| uses: mikepenz/action-junit-report@cf701569b05ccdd861a76b8607a66d76f6fd4857 | |
| if: always() && steps.production_smoke_tests.outcome != 'skipped' | |
| with: | |
| report_paths: "packages/smoke-tests/tests.junit.xml" | |
| check_name: "Production Smoke Test Results" | |
| fail_on_failure: false | |
| - name: Recover captured previous version after smoke failure | |
| if: failure() && steps.production_smoke_tests.outcome == 'failure' && steps.verify_production.outcome == 'success' | |
| env: | |
| CLOUDFLARE_API_TOKEN: ${{ secrets.CLOUDFLARE_API_TOKEN }} | |
| CLOUDFLARE_ACCOUNT_ID: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }} | |
| TESTED_SHA: ${{ github.event.workflow_run.head_sha }} | |
| run: node scripts/cloudflare-deployment.mjs recover | |
| - name: Fail Job if Production Smoke Tests Failed | |
| if: failure() && steps.production_smoke_tests.outcome == 'failure' | |
| run: | | |
| echo 'Production smoke tests failed. Inspect the deployment before changing traffic.' >&2 | |
| exit 1 |