diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 8ed77e4..2d6aed3 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -1,12 +1,10 @@ -name: Deploy Cloudflare environment +name: Deploy Cloudflare production on: + push: + branches: + - master workflow_dispatch: - inputs: - confirm: - description: Type deploy-hackweek after operator review - required: true - type: string permissions: contents: read @@ -17,11 +15,11 @@ concurrency: jobs: verify: - if: inputs.confirm == 'deploy-hackweek' + if: github.ref == 'refs/heads/master' uses: ./.github/workflows/test.yml deploy: - name: Deploy reviewed configuration + name: Deploy production needs: verify runs-on: ubuntu-latest environment: hackweek-cloudflare @@ -38,8 +36,8 @@ jobs: CLOUDFLARE_ACCOUNT_ID: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }} run: | test -n "$CLOUDFLARE_API_TOKEN" || { echo 'Missing CLOUDFLARE_API_TOKEN'; exit 1; } - test "$CLOUDFLARE_ACCOUNT_ID" = '773afa1f62ff86c80db4f24f7ff1e9c8' || { echo 'Unexpected Cloudflare account'; exit 1; } - node -e "const c=require('./wrangler.production.json'); const videos=c.r2_buckets.find(x=>x.binding==='VIDEOS'); const workflow=c.workflows.find(x=>x.binding==='VIDEO_PROCESSING_WORKFLOW'); const container=c.containers.find(x=>x.class_name==='VideoProcessorContainer'); if (c.account_id !== '773afa1f62ff86c80db4f24f7ff1e9c8' || videos?.bucket_name !== 'hackweek-video-media-production' || workflow?.name !== 'hackweek-video-processing-production' || container?.name !== 'hackweek-video-processor-production' || container?.max_instances !== 5 || c.vars.VIDEO_PROCESSOR_CONCURRENCY !== '2') process.exit(1); for (const value of [c.d1_databases[0].database_id,c.r2_buckets[0].bucket_name,c.vars.APP_ORIGIN,c.vars.GOOGLE_REDIRECT_URI,c.vars.GOOGLE_CLIENT_ID]) if (!value || /replace.me/i.test(value) || value === '00000000-0000-0000-0000-000000000000') process.exit(1)" + test "$CLOUDFLARE_ACCOUNT_ID" = '20d94f53c7cab0b469521b703ff1923c' || { echo 'Unexpected Cloudflare account'; exit 1; } + node -e "const c=require('./wrangler.production.json'); const videos=c.r2_buckets.find(x=>x.binding==='VIDEOS'); const workflow=c.workflows.find(x=>x.binding==='VIDEO_PROCESSING_WORKFLOW'); const container=c.containers.find(x=>x.class_name==='VideoProcessorContainer'); if (c.account_id !== '20d94f53c7cab0b469521b703ff1923c' || videos?.bucket_name !== 'hackweek-video-media-production' || workflow?.name !== 'hackweek-video-processing-production' || container?.name !== 'hackweek-video-processor-production' || container?.max_instances !== 5 || c.vars.VIDEO_PROCESSOR_CONCURRENCY !== '2') process.exit(1); for (const value of [c.d1_databases[0].database_id,c.r2_buckets[0].bucket_name,c.vars.APP_ORIGIN,c.vars.GOOGLE_REDIRECT_URI,c.vars.GOOGLE_CLIENT_ID]) if (!value || /replace.me/i.test(value) || value === '00000000-0000-0000-0000-000000000000') process.exit(1)" - run: npm run build - name: Apply expand-compatible D1 migrations run: npx wrangler d1 migrations apply hackweek-db --remote --config wrangler.production.json --yes diff --git a/README.md b/README.md index 29d84c9..5b63c8b 100644 --- a/README.md +++ b/README.md @@ -9,11 +9,20 @@ Hackweek is an internal React + TypeScript application served by one Hono Cloudf - Docker with a running Linux engine (Docker Desktop or OrbStack) - `ffmpeg` and `ffprobe` 8.x on the host for generated local fixtures -No Cloudflare video resource or credential is required for local development. +## Deployment + +Every push to `master` runs the full verification suite, applies pending D1 migrations, and deploys the Worker and static assets to Cloudflare production through [`.github/workflows/deploy.yml`](.github/workflows/deploy.yml). The workflow can also be retried manually from `master`; other refs cannot deploy production. + +The workflow requires these GitHub Actions secrets: + +- `CLOUDFLARE_ACCOUNT_ID`: the Sentry Internal Cloudflare account ID. +- `CLOUDFLARE_API_TOKEN`: an account-scoped token with **Edit Cloudflare Workers** and **D1 Edit** permissions. + +Production deploys use [`wrangler.production.json`](wrangler.production.json) and the `hackweek-cloudflare` GitHub environment. Do not add Cloudflare credentials to the repository. ## Local video environment -Complete the one-time setup without replacing an existing `.dev.vars`: +No Cloudflare video resource or credential is required for local development. Complete the one-time setup without replacing an existing `.dev.vars`: ```bash npm ci diff --git a/worker-configuration.d.ts b/worker-configuration.d.ts index ae81371..80e765e 100644 --- a/worker-configuration.d.ts +++ b/worker-configuration.d.ts @@ -1,5 +1,5 @@ /* eslint-disable */ -// Generated by Wrangler by running `wrangler types --config=wrangler.production.json` (hash: bc092216b5e73ef63da8313b6c4a1921) +// Generated by Wrangler by running `wrangler types --config=wrangler.production.json` (hash: b4706c739f212cec96f09221af2ad9d7) // Runtime types generated with workerd@1.20260730.1 2026-08-03 interface __BaseEnv_Env { ATTACHMENTS: R2Bucket; @@ -8,8 +8,8 @@ interface __BaseEnv_Env { ASSETS: Fetcher; VIDEO_PROCESSOR_CONCURRENCY: "2"; VIDEO_PROCESSING_AUTOSTART: "true"; - APP_ORIGIN: "https://hackweek.sentry.new"; - GOOGLE_REDIRECT_URI: "https://hackweek.sentry.new/api/auth/callback"; + APP_ORIGIN: "https://hackweek.sentry-internal.workers.dev"; + GOOGLE_REDIRECT_URI: "https://hackweek.sentry-internal.workers.dev/api/auth/callback"; GOOGLE_CLIENT_ID: "694837489680-25m2umkr51lofdads5uvocgtcdqcs6c4.apps.googleusercontent.com"; ALLOWED_EMAIL_DOMAIN: "sentry.io"; VIDEO_PROCESSOR: DurableObjectNamespace; diff --git a/wrangler.production.json b/wrangler.production.json index 0cd6b2a..2d9c4c2 100644 --- a/wrangler.production.json +++ b/wrangler.production.json @@ -1,7 +1,7 @@ { "$schema": "./node_modules/wrangler/config-schema.json", "name": "hackweek", - "account_id": "773afa1f62ff86c80db4f24f7ff1e9c8", + "account_id": "20d94f53c7cab0b469521b703ff1923c", "main": "./src/worker/index.ts", "compatibility_date": "2026-08-03", "assets": { @@ -14,7 +14,7 @@ { "binding": "DB", "database_name": "hackweek-db", - "database_id": "7063a770-b791-4fcd-aedf-ddf5fff2e312", + "database_id": "c28c9eb5-7962-480e-8b3d-229fff5ca112", "migrations_dir": "migrations" } ],