Release Flows
We ship each surface independently from the same monorepo using path‑filtered CI workflows.
- Docs → Cloudflare Pages
- Server (Fastify) → Container deploy (Fly/Render/ECS)
- Mobile (RN iOS) → EAS → TestFlight
1) Docs → Cloudflare Pages
Two supported paths:
A) Direct Git (monorepo root directory)
- Cloudflare Pages → Create project → Root directory =
apps/docs - Build command:
pnpm i --frozen-lockfile && pnpm build - Output directory:
build - Optional “Ignore builds” (skip when docs didn’t change):
if git diff --quiet $CF_PAGES_COMMIT_SHA^ $CF_PAGES_COMMIT_SHA -- apps/docs; then
echo "no-docs-changes"
fi
B) GitHub Action (direct upload)
Build in CI and upload the artifact.
name: Deploy Docs
on:
push:
branches: [main]
paths: ["apps/docs/**",".github/workflows/docs.yml"]
pull_request:
paths: ["apps/docs/**"]
jobs:
docs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: pnpm/action-setup@v3
with: { version: 9 }
- uses: actions/setup-node@v4
with: { node-version: 20, cache: 'pnpm' }
- run: pnpm install --frozen-lockfile
- run: pnpm build
working-directory: apps/docs
- uses: cloudflare/pages-action@v1
with:
apiToken: ${{ secrets.CF_API_TOKEN }}
accountId: ${{ secrets.CF_ACCOUNT_ID }}
projectName: ${{ secrets.CF_PAGES_PROJECT }}
directory: apps/docs/build
branch: ${{ github.ref_name }}
Docs release (Mermaid)
2) Server (Fastify) → Container
Trigger: changes under server/** (and shared packages).
Steps: install → typecheck → unit/integration → build Docker → push → run migrations → deploy → health checks → notify.
name: Deploy Server
on:
push:
branches: [main]
paths:
- "server/**"
- "packages/shared-types/**"
- ".github/workflows/server.yml"
jobs:
test-build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: pnpm/action-setup@v3
with: { version: 9 }
- uses: actions/setup-node@v4
with: { node-version: 20, cache: 'pnpm' }
- run: pnpm install --frozen-lockfile
- run: pnpm -w typecheck
- run: pnpm -w test
- name: Build Docker
run: docker build -t ghcr.io/yourorg/otherwhere-server:${{ github.sha }} server
- name: Push Docker
run: |
echo "${{ secrets.GHCR_TOKEN }}" | docker login ghcr.io -u USERNAME --password-stdin
docker push ghcr.io/yourorg/otherwhere-server:${{ github.sha }}
migrate-deploy:
needs: test-build
runs-on: ubuntu-latest
steps:
- name: Run DB migrations
env:
DATABASE_URL: ${{ secrets.DATABASE_URL }}
run: docker run --rm -e DATABASE_URL ghcr.io/yourorg/otherwhere-server:${{ github.sha }} node ./dist/scripts/migrate.js
- name: Deploy
run: ./infra/deploy.sh ghcr.io/yourorg/otherwhere-server:${{ github.sha }}
Server release (Mermaid)
Notes
- DB migrations: forward‑compatible & idempotent.
- Feature flags: default off; flip after health checks.
- Rollback: redeploy previous image tag; ship down migrations only when safe.
3) Mobile (RN iOS) → TestFlight (EAS)
Trigger: changes under apps/mobile/**.
Secrets: Expo token, Apple API key.
Steps: install → test/lint → EAS build → EAS submit → notify.
name: Build iOS (EAS)
on:
push:
branches: [main]
paths:
- "apps/mobile/**"
- "packages/shared-types/**"
- ".github/workflows/mobile.yml"
jobs:
ios:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: pnpm/action-setup@v3
with: { version: 9 }
- uses: actions/setup-node@v4
with: { node-version: 20, cache: 'pnpm' }
- run: pnpm install --frozen-lockfile
- run: pnpm -w typecheck && pnpm -w lint
- name: EAS build
run: npx eas build --platform ios --profile production --non-interactive
env:
EXPO_TOKEN: ${{ secrets.EXPO_TOKEN }}
- name: EAS submit
run: npx eas submit --platform ios --latest --non-interactive
env:
EXPO_TOKEN: ${{ secrets.EXPO_TOKEN }}
APPLE_APP_SPECIFIC_PASSWORD: ${{ secrets.APPLE_PW }}
Mobile release (Mermaid)
4) Environment strategy
- Branches:
main→ production; feature branches → PR previews (docs) and staging envs (server if desired). - Secrets: one source (Doppler/SSM). Inject via CI; never commit.
- Versioning: tag per surface:
server-v0.4.0,mobile-v0.3.2,docs-2025-01-12.
5) Rollback & health checks
- Docs: redeploy previous Pages build.
- Server: redeploy previous image; automated health checks (liveness/readiness, p95 guard).
- Mobile: revert build channel / roll back release in EAS (TestFlight).
6) What triggers which pipeline?
| Change path | Pipeline | Prod target |
|---|---|---|
apps/docs/** | Docs Pages | Cloudflare Pages (/build) |
server/**, packages/shared-types/** | Server container | Fly/Render/ECS |
apps/mobile/**, packages/shared-types/** | Mobile iOS (EAS) | TestFlight |