Skip to main content

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 buildEAS 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 pathPipelineProd target
apps/docs/**Docs PagesCloudflare Pages (/build)
server/**, packages/shared-types/**Server containerFly/Render/ECS
apps/mobile/**, packages/shared-types/**Mobile iOS (EAS)TestFlight