Advertisement

← vibesdk

.github/workflows/deploy-staging.yml

4.9 KB Download file
name: Deploy (staging)

on:
  push:
    branches: [staging]
  workflow_dispatch:

permissions:
  contents: read

concurrency:
  group: deploy-staging
  cancel-in-progress: false

jobs:
  test-build:
    runs-on: ubuntu-latest
    timeout-minutes: 30

    steps:
      - name: Checkout repository
        uses: actions/checkout@v4

      - name: Setup Bun
        uses: oven-sh/setup-bun@v1
        with:
          bun-version: latest

      - name: Cache Bun install cache
        uses: actions/cache@v4
        with:
          path: ~/.bun/install/cache
          key: ${{ runner.os }}-bun-${{ hashFiles('bun.lock') }}
          restore-keys: |
            ${{ runner.os }}-bun-

      - name: Install dependencies
        run: bun install --frozen-lockfile

      # Intentionally skipping lint/typecheck; CI already enforces those.
      - name: Test
        run: bun run test

  deploy:
    runs-on: ubuntu-latest
    timeout-minutes: 45
    needs: test-build

    # Skip deploy for forks (they won't have secrets anyway)
    if: github.repository_owner == 'cloudflare'

    env:
      CI: true
      WRANGLER_NON_INTERACTIVE: true

      # Target the staging wrangler config instead of the prod one.
      WRANGLER_CONFIG_PATH: wrangler.staging.jsonc

      # Staging runs on an account with Cloudflare Artifacts access. Keep the
      # ARTIFACTS binding: the deploy script drops it unless this is "true".
      ENABLE_ARTIFACTS: "true"

      # Staging-specific overrides. These take priority over wrangler.staging.jsonc vars.
      CUSTOM_DOMAIN: staging.build.cloudflare.dev
      CUSTOM_PREVIEW_DOMAIN: staging.build.cloudflare.dev
      DISPATCH_NAMESPACE: vibesdk-staging-namespace
      ENVIRONMENT: staging

      # Reuse repo-level config vars (same as prod). Anything staging-specific
      # is overridden above.
      # MAX_SANDBOX_INSTANCES intentionally not inherited: the prod quota
      # (vars.MAX_SANDBOX_INSTANCES) exceeds the staging account's allocation.
      # Falls back to the value in wrangler.staging.jsonc.
      SANDBOX_INSTANCE_TYPE: ${{ vars.SANDBOX_INSTANCE_TYPE }}
      TEMPLATES_REPOSITORY: ${{ vars.TEMPLATES_REPOSITORY }}
      ALLOCATION_STRATEGY: ${{ vars.ALLOCATION_STRATEGY }}
      PLATFORM_MODEL_PROVIDERS: ${{ vars.PLATFORM_MODEL_PROVIDERS }}
      USE_CLOUDFLARE_IMAGES: ${{ vars.USE_CLOUDFLARE_IMAGES }}
      CLOUDFLARE_AI_GATEWAY: ${{ vars.CLOUDFLARE_AI_GATEWAY }}
      CLOUDFLARE_AI_GATEWAY_TOKEN: ${{ secrets.CLOUDFLARE_AI_GATEWAY_TOKEN }}
      CLOUDFLARE_AI_GATEWAY_URL: ${{ vars.CLOUDFLARE_AI_GATEWAY_URL }}

    steps:
      - name: Checkout repository
        uses: actions/checkout@v4

      - name: Setup Node
        uses: actions/setup-node@v4
        with:
          node-version: 22

      - name: Setup Bun
        uses: oven-sh/setup-bun@v1
        with:
          bun-version: latest

      - name: Cache Bun install cache
        uses: actions/cache@v4
        with:
          path: ~/.bun/install/cache
          key: ${{ runner.os }}-bun-${{ hashFiles('bun.lock') }}
          restore-keys: |
            ${{ runner.os }}-bun-

      - name: Install dependencies
        run: bun install --frozen-lockfile

      - name: Add local binaries to PATH
        run: echo "${{ github.workspace }}/node_modules/.bin" >> "$GITHUB_PATH"

      - name: Deploy via deploy script
        env:
          # Secrets used by deploy script to create/sync .prod.vars.
          # Staging reuses the same Cloudflare account secrets as prod.
          CLOUDFLARE_API_TOKEN: ${{ secrets.CLOUDFLARE_API_TOKEN }}
          CLOUDFLARE_ACCOUNT_ID: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
          CLOUDFLARE_AI_GATEWAY: ${{ vars.CLOUDFLARE_AI_GATEWAY }}
          CLOUDFLARE_AI_GATEWAY_TOKEN: ${{ secrets.CLOUDFLARE_AI_GATEWAY_TOKEN }}
          CLOUDFLARE_AI_GATEWAY_URL: ${{ secrets.CLOUDFLARE_AI_GATEWAY_URL }}

          ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
          OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
          GOOGLE_AI_STUDIO_API_KEY: ${{ secrets.GOOGLE_AI_STUDIO_API_KEY }}
          OPENROUTER_API_KEY: ${{ secrets.OPENROUTER_API_KEY }}
          GROQ_API_KEY: ${{ secrets.GROQ_API_KEY }}

          GOOGLE_CLIENT_ID: ${{ secrets.GOOGLE_CLIENT_ID }}
          GOOGLE_CLIENT_SECRET: ${{ secrets.GOOGLE_CLIENT_SECRET }}
          GITHUB_CLIENT_ID: ${{ secrets.GITHUB_CLIENT_ID }}
          GITHUB_CLIENT_SECRET: ${{ secrets.GITHUB_CLIENT_SECRET }}
          CLOUDFLARE_OAUTH_CLIENT_ID: ${{ vars.STAGING_CLOUDFLARE_OAUTH_CLIENT_ID }}
          CLOUDFLARE_OAUTH_CLIENT_SECRET: ${{ secrets.STAGING_CLOUDFLARE_OAUTH_CLIENT_SECRET }}
          CF_OAUTH_ENCRYPTION_KEY: ${{ secrets.STAGING_CF_OAUTH_ENCRYPTION_KEY }}

          JWT_SECRET: ${{ secrets.STAGING_JWT_SECRET }}
          SENTRY_DSN: ${{ secrets.SENTRY_DSN }}
          AI_PROXY_JWT_SECRET: ${{ secrets.AI_PROXY_JWT_SECRET }}
        run: bun scripts/deploy.ts