audio streaming app plyr.fm
38
fork

Configure Feed

Select the types of activity you want to include in your feed.

fix: correct deployment docs and use upgrade head everywhere (#78)

* docs: fix deployment documentation - remove incorrect cloudflare branch setup

* fix: use alembic upgrade head everywhere for consistency

* docs: remove all stamp head references from environments.md

authored by

nate nowack and committed by
GitHub
5883ad75 b336063a

+70 -246
-143
docs/deployment/cloudflare-pages-setup.md
··· 1 - # cloudflare pages environment setup 2 - 3 - manual configuration steps for setting up staging and production frontend environments. 4 - 5 - ## overview 6 - 7 - relay uses branch-based frontend deployments: 8 - - **staging branch** → `staging.relay-4i6.pages.dev` 9 - - **production branch** → `relay-4i6.pages.dev` 10 - 11 - this gives you static URLs for both environments while maintaining full separation. 12 - 13 - ## prerequisites 14 - 15 - ✅ staging branch created and pushed to GitHub 16 - ✅ production branch created and pushed to GitHub 17 - 18 - ## cloudflare dashboard configuration 19 - 20 - ### step 1: update production branch 21 - 22 - 1. navigate to [cloudflare pages dashboard](https://dash.cloudflare.com/8feb33b5fb57ce2bc093bc6f4141f40a/pages) 23 - 2. click on **relay** project 24 - 3. go to **settings** → **builds & deployments** 25 - 4. under **production deployments**, click **configure production deployments** 26 - 5. change production branch from `main` to `production` 27 - 6. click **save** 28 - 29 - **result**: only commits to `production` branch will deploy to `relay-4i6.pages.dev` 30 - 31 - ### step 2: configure branch deployments 32 - 33 - 1. in **settings** → **builds & deployments** 34 - 2. under **preview deployments**, select **custom branches** 35 - 3. add branch pattern: `staging` 36 - 4. optionally add: `main` (for testing main before production) 37 - 5. click **save** 38 - 39 - **result**: commits to `staging` branch deploy to `staging.relay-4i6.pages.dev` 40 - 41 - ### step 3: set environment variables for staging 42 - 43 - 1. go to **settings** → **environment variables** 44 - 2. click **add variable** 45 - 3. set the following for **preview** environment: 46 - - variable name: `PUBLIC_API_URL` 47 - - value: `https://relay-api-staging.fly.dev` 48 - - environment: **preview** (check the box) 49 - 4. click **save** 50 - 51 - **result**: staging frontend connects to staging backend 52 - 53 - ### step 4: set environment variables for production 54 - 55 - 1. in **settings** → **environment variables** 56 - 2. click **add variable** (or edit existing if already set) 57 - 3. set the following for **production** environment: 58 - - variable name: `PUBLIC_API_URL` 59 - - value: `https://relay-api.fly.dev` 60 - - environment: **production** (check the box) 61 - 4. click **save** 62 - 63 - **result**: production frontend connects to production backend 64 - 65 - ### step 5: trigger initial deployments 66 - 67 - 1. go back to **deployments** tab 68 - 2. find the latest deployment for `staging` branch 69 - 3. click **...** → **retry deployment** (if needed) 70 - 4. repeat for `production` branch 71 - 72 - ## verification 73 - 74 - after configuration: 75 - 76 - **staging**: 77 - - url: https://staging.relay-4i6.pages.dev 78 - - backend: https://relay-api-staging.fly.dev 79 - - should show empty state (staging database is empty) 80 - 81 - **production**: 82 - - url: https://relay-4i6.pages.dev 83 - - backend: https://relay-api.fly.dev 84 - - should show existing data 85 - 86 - ## workflow 87 - 88 - ### deploying to staging 89 - 90 - ```bash 91 - # push changes to main 92 - git checkout main 93 - git add . 94 - git commit -m "feat: new feature" 95 - git push 96 - 97 - # backend deploys automatically to staging (relay-api-staging) 98 - 99 - # sync staging branch with main for frontend 100 - git checkout staging 101 - git merge main 102 - git push 103 - 104 - # frontend deploys automatically to staging.relay-4i6.pages.dev 105 - ``` 106 - 107 - ### deploying to production 108 - 109 - ```bash 110 - # after validating in staging, promote to production 111 - git checkout production 112 - git merge main 113 - git push 114 - 115 - # frontend deploys automatically to relay-4i6.pages.dev 116 - 117 - # create release tag for backend 118 - gh release create v1.0.0 --title "v1.0.0" --notes "release notes" 119 - 120 - # backend deploys automatically to production (relay-api) 121 - ``` 122 - 123 - ## troubleshooting 124 - 125 - **staging frontend not updating?** 126 - - check that `staging` branch is in custom branches list 127 - - verify `PUBLIC_API_URL` is set for preview environment 128 - - check cloudflare pages build logs 129 - 130 - **production frontend still on main?** 131 - - verify production branch is set to `production` in settings 132 - - redeploy production branch if needed 133 - 134 - **CORS errors?** 135 - - verify `PUBLIC_API_URL` matches the backend you're trying to reach 136 - - check backend CORS configuration in fly.io secrets 137 - 138 - ## cleanup (optional) 139 - 140 - **delete old preview deployments**: 141 - - wrangler CLI doesn't support this 142 - - manually delete from cloudflare dashboard → deployments → filter by preview → delete individually 143 - - old previews don't cost anything, just clutter the list
+69 -102
docs/deployment/environments.md
··· 1 1 # environment separation strategy 2 2 3 - relay uses a three-tier deployment strategy: development → staging → production. 3 + relay uses a simple three-tier deployment strategy: development → staging → production. 4 4 5 5 ## environments 6 6 7 7 | environment | trigger | backend app | backend URL | database | frontend | storage | 8 8 |-------------|---------|-------------|-------------|----------|----------|---------| 9 9 | **development** | local | local server | localhost:8000 | relay-dev (neon) | localhost:5173 | relay-dev (r2) | 10 - | **staging** | push to main (backend) <br> push to staging (frontend) | relay-api-staging | relay-api-staging.fly.dev | relay-staging (neon) | staging.relay-4i6.pages.dev | relay-stg (r2) | 11 - | **production** | github release (backend) <br> push to production (frontend) | relay-api | relay-api.fly.dev | relay (neon) | relay-4i6.pages.dev | relay (r2) | 10 + | **staging** | push to main | relay-api-staging | relay-api-staging.fly.dev | relay-staging (neon) | cloudflare pages (main) | relay-stg (r2) | 11 + | **production** | github release | relay-api | relay-api.fly.dev | relay (neon) | cloudflare pages (main) | relay (r2) | 12 12 13 13 ## workflow 14 14 ··· 16 16 17 17 ```bash 18 18 # start backend 19 - uv run uvicorn backend.main:app --reload --port 8000 19 + uv run uvicorn relay.main:app --reload --port 8000 20 20 21 21 # start frontend 22 22 cd frontend && bun run dev 23 23 ``` 24 24 25 - connects to `relay-dev` neon database. 25 + connects to `relay-dev` neon database and uses `app.relay-dev` atproto namespace. 26 26 27 - ### staging deployment 27 + ### staging deployment (automatic) 28 28 29 - **backend (automatic on main push)**: 29 + **trigger**: push to `main` branch 30 30 31 - 1. push to `main` branch 32 - 2. github actions runs `.github/workflows/deploy-backend.yml` 33 - 3. deploys to `relay-api-staging` fly app using `fly.staging.toml` 34 - 4. runs database migrations via `release_command` 35 - 5. backend available at `https://relay-api-staging.fly.dev` 31 + **backend**: 32 + 1. github actions runs `.github/workflows/deploy-backend.yml` 33 + 2. deploys to `relay-api-staging` fly app using `fly.staging.toml` 34 + 3. runs `alembic upgrade head` via `release_command` 35 + 4. backend available at `https://relay-api-staging.fly.dev` 36 36 37 - **frontend (manual sync)**: 38 - 39 - ```bash 40 - # sync staging branch with main 41 - git checkout staging 42 - git merge main 43 - git push 44 - ``` 45 - 46 - cloudflare pages automatically deploys to `https://staging.relay-4i6.pages.dev` 37 + **frontend**: 38 + - cloudflare pages automatically deploys from `main` branch 39 + - uses preview environment with `PUBLIC_API_URL=https://relay-api-staging.fly.dev` 40 + - available at cloudflare-generated preview URL 47 41 48 42 **testing**: 49 - - frontend: `https://staging.relay-4i6.pages.dev` (static URL) 50 43 - backend: `https://relay-api-staging.fly.dev/docs` 51 44 - database: `relay-staging` (neon) 52 45 - storage: `relay-stg` (r2) 46 + - atproto namespace: `app.relay-staging` 53 47 54 - ### production deployment 55 - 56 - **frontend (manual promotion)**: 48 + ### production deployment (manual) 57 49 58 - ```bash 59 - # after validating staging, promote to production 60 - git checkout production 61 - git merge main 62 - git push 63 - ``` 50 + **trigger**: create github release (e.g., `v1.0.0`) 64 51 65 - cloudflare pages automatically deploys to `https://relay-4i6.pages.dev` 52 + **backend**: 53 + 1. github actions runs `.github/workflows/deploy-production.yml` 54 + 2. deploys to `relay-api` fly app using `fly.toml` 55 + 3. runs `alembic upgrade head` via `release_command` 56 + 4. backend available at `https://relay-api.fly.dev` 66 57 67 - **backend (github release)**: 58 + **frontend**: 59 + - cloudflare pages production environment serves `main` branch 60 + - uses production environment with `PUBLIC_API_URL=https://relay-api.fly.dev` 61 + - available at `https://relay-4i6.pages.dev` 68 62 63 + **creating a release**: 69 64 ```bash 70 - # create release tag 71 - gh release create v1.2.3 --title "v1.2.3" --notes "release notes here" 65 + # after validating changes in staging: 66 + gh release create v1.0.0 --title "v1.0.0" --notes "release notes here" 72 67 ``` 73 68 74 69 or via github UI: releases → draft new release → create tag → publish 75 70 76 - **process**: 77 - 1. github actions detects release publication 78 - 2. runs `.github/workflows/deploy-production.yml` 79 - 3. deploys to `relay-api` fly app using `fly.toml` 80 - 4. runs database migrations via `release_command` 81 - 5. backend available at `https://relay-api.fly.dev` 82 - 83 71 **testing**: 84 - - frontend: `https://relay-4i6.pages.dev` (static URL) 72 + - frontend: `https://relay-4i6.pages.dev` 85 73 - backend: `https://relay-api.fly.dev/docs` 86 74 - database: `relay` (neon) 87 75 - storage: `relay` (r2) 76 + - atproto namespace: `app.relay` 88 77 89 78 ## configuration files 90 79 91 - ### fly.io configurations 80 + ### backend 92 81 93 82 **fly.staging.toml**: 94 83 - app: `relay-api-staging` 95 - - database: neon staging connection string 96 - - OAuth redirect: `https://relay-api-staging.fly.dev/auth/callback` 97 - - environment: staging 84 + - release_command: `uv run alembic upgrade head` (runs migrations) 85 + - environment variables configured in fly.io 98 86 99 87 **fly.toml**: 100 88 - app: `relay-api` 101 - - database: neon production connection string 102 - - OAuth redirect: `https://relay-api.fly.dev/auth/callback` 103 - - environment: production 89 + - release_command: `uv run alembic upgrade head` (runs migrations) 90 + - environment variables configured in fly.io 91 + 92 + ### frontend 93 + 94 + **cloudflare pages**: 95 + - framework: sveltekit 96 + - build command: `cd frontend && bun run build` 97 + - build output: `frontend/build` 98 + - environment variables: 99 + - preview: `PUBLIC_API_URL=https://relay-api-staging.fly.dev` 100 + - production: `PUBLIC_API_URL=https://relay-api.fly.dev` 104 101 105 102 ### secrets management 106 103 107 - **staging secrets** (set via `scripts/setup-staging-secrets.sh`): 104 + **staging secrets** (set via `flyctl secrets set`): 108 105 - `DATABASE_URL` → neon staging connection string 109 106 - `ATPROTO_CLIENT_ID` → `https://relay-api-staging.fly.dev/client-metadata.json` 110 107 - `ATPROTO_REDIRECT_URI` → `https://relay-api-staging.fly.dev/auth/callback` 111 - - `ATPROTO_APP_NAMESPACE` → `app.relay-staging` (isolated ATProto collection) 112 - - `OAUTH_ENCRYPTION_KEY` → unique key for staging 113 - - `AWS_ACCESS_KEY_ID`, `AWS_SECRET_ACCESS_KEY` → same as production (shared R2) 114 - - `LOGFIRE_WRITE_TOKEN` → logfire token 115 - - `LOGFIRE_ENVIRONMENT` → `staging` 108 + - `ATPROTO_APP_NAMESPACE` → `app.relay-staging` 109 + - `OAUTH_ENCRYPTION_KEY` → unique 44-char base64 fernet key 110 + - `AWS_ACCESS_KEY_ID`, `AWS_SECRET_ACCESS_KEY` → r2 credentials 111 + - `LOGFIRE_WRITE_TOKEN`, `LOGFIRE_ENABLED`, `LOGFIRE_ENVIRONMENT` 112 + - `FRONTEND_URL` → cloudflare pages preview URL 116 113 117 114 **production secrets** (already configured): 118 115 - same structure but with production URLs and database 119 - - `ATPROTO_APP_NAMESPACE` → not set (uses default `app.relay`) 116 + - `ATPROTO_APP_NAMESPACE` → not set (defaults to `app.relay`) 117 + - additional: `NOTIFY_BOT_HANDLE`, `NOTIFY_BOT_PASSWORD`, `NOTIFY_ENABLED` 120 118 121 119 **local dev (.env)**: 122 - - `ATPROTO_APP_NAMESPACE` → `app.relay-dev` (throwaway collection for testing) 120 + - `ATPROTO_APP_NAMESPACE` → `app.relay-dev` 123 121 124 122 ## database migrations 125 123 126 - migrations run automatically on deploy via fly.io `release_command`: 127 - ```toml 128 - [deploy] 129 - release_command = "uv run alembic upgrade head" 130 - ``` 124 + migrations run automatically on deploy via fly.io `release_command`. 131 125 132 - **staging**: migrations run on every push to main (low risk) 133 - **production**: migrations run on release (review migrations before releasing) 126 + **both environments**: 127 + - use `alembic upgrade head` to run migrations 128 + - migrations run before deployment completes 129 + - alembic tracks applied migrations via `alembic_version` table 134 130 135 131 ### rollback strategy 136 132 ··· 140 136 - revert via alembic: `uv run alembic downgrade -1` 141 137 - or restore database from neon backup 142 138 143 - ## cloudflare pages 144 - 145 - **configuration** (see [cloudflare-pages-setup.md](./cloudflare-pages-setup.md) for detailed instructions): 146 - 147 - **branches**: 148 - - `production` branch → `relay-4i6.pages.dev` (production URL) 149 - - `staging` branch → `staging.relay-4i6.pages.dev` (staging URL) 150 - 151 - **environment variables**: 152 - - staging (`preview` environment): `PUBLIC_API_URL=https://relay-api-staging.fly.dev` 153 - - production (`production` environment): `PUBLIC_API_URL=https://relay-api.fly.dev` 154 - 155 - **manual configuration required**: 156 - 1. change production branch from `main` to `production` in cloudflare dashboard 157 - 2. add `staging` to custom branch deployments 158 - 3. set environment variables for each environment 159 - 4. trigger initial deployments 160 - 161 - see [cloudflare-pages-setup.md](./cloudflare-pages-setup.md) for step-by-step instructions. 162 - 163 139 ## monitoring 164 140 165 141 **staging**: ··· 172 148 173 149 ## costs 174 150 175 - **before**: ~$5-6/month (1 fly app, 2 neon databases) 176 - 177 - **after**: ~$10-11/month 151 + **current**: ~$10-11/month 178 152 - fly.io production: $5/month (shared-cpu-1x) 179 153 - fly.io staging: $5/month (shared-cpu-1x) 180 154 - neon dev: free tier ··· 187 161 188 162 - **safe testing**: catch bugs in staging before production 189 163 - **migration validation**: test database changes in production-like environment 190 - - **rollback capability**: releases enable version-based rollbacks 191 - - **team validation**: team can test changes before user-facing deployment 164 + - **rollback capability**: releases enable version-based rollbacks via github 192 165 - **clear release process**: explicit versioning via github releases 166 + - **single branch**: no branch management - just `main` and feature branches 193 167 194 168 ## deployment history 195 169 196 - 1. ✅ staging and production branches created 197 - 2. ✅ R2 storage separated by environment (relay-dev, relay-stg, relay) 198 - 3. ✅ staging backend deployed and validated (2025-11-06) 170 + 1. ✅ staging backend deployed and validated (2025-11-06) 199 171 - backend: https://relay-api-staging.fly.dev 200 172 - database: relay-staging (neon) 201 173 - storage: relay-stg (r2) 202 - 4. **next: configure cloudflare pages** (see [cloudflare-pages-setup.md](./cloudflare-pages-setup.md)) 203 - 5. sync staging branch with main for first frontend deploy 204 - 6. validate full staging environment: 205 - - frontend: https://staging.relay-4i6.pages.dev 206 - - backend: https://relay-api-staging.fly.dev 207 - 7. promote to production when ready: 208 - - frontend: merge main → production 209 - - backend: create github release 174 + - atproto namespace: `app.relay-staging` 175 + 2. ✅ production deployment workflow exists (`.github/workflows/deploy-production.yml`) 176 + 3. **next**: create first github release to deploy to production
+1 -1
fly.staging.toml
··· 9 9 [build] 10 10 11 11 [deploy] 12 - release_command = 'uv run alembic stamp head' 12 + release_command = 'uv run alembic upgrade head' 13 13 14 14 [env] 15 15 ATPROTO_PDS_URL = 'https://pds.zzstoatzz.io'