Production release flow. Keep it boring and repeatable.
developis the default branch; the team's feature/fix PRs target it. (This is our internal flow — the project doesn't take outside PRs; see CONTRIBUTING.md.)mainis production. A release is a single PR develop → main (norelease/*branch).- Merging to
maintriggers.github/workflows/release.yml.
- Bump the version on
developfirst. Editmobile/app.config.js→expo.version(the marketing version). Open a small PR intodevelopand merge it.- runtimeVersion (
expo.runtimeVersion) is the native-ABI identity. Leave it UNCHANGED for a JS-only release; bump it ONLY on a native change (new native module, URL scheme, permission, config plugin) — that requires a new APK.
- runtimeVersion (
- What's New card. Add an entry to
mobile/src/data/whatsNew.tsfor the new version. Features only — no bug fixes / UI tweaks / removals (issue #97). - Apply pending DB migrations to production (see below) before opening the release PR.
- Open the release PR develop → main. It must pass the required "Migrations applied check" and get its approval, then merge.
- On merge,
release.ymlpublishes the production + preview OTA, cuts thevX.Y.Ztag + GitHub Release, and dispatches the APK build (which skips unless runtimeVersion changed). Railway auto-deploys theapiservice frommain.
The deploy does not auto-migrate. Files in backend/migrations/*.sql must be run
by hand against the production Supabase DB, or the app queries columns/tables that
don't exist (this caused the pool-topup "column claimed_at does not exist" crash).
For each migration not yet applied to prod:
- Run it — Supabase → SQL Editor (paste the file), or
psql "$DIRECT_URL" -f backend/migrations/<file>(DIRECT_URL= the 5432 session pooler). - Add its filename to
backend/migrations/applied.txt.
.github/workflows/migrations.yml fails on main and on release PRs if any migration
isn't listed in applied.txt. It is a required check on main, so a release
cannot merge with an unapplied migration. Migrations are immutable once applied —
never edit an applied file; add a new one.
Installed apps update over the air on next launch — no reinstall. The stable APK download link in the README changes only on a native (runtimeVersion) release.
SUPABASE_ANON_KEYon the Railwayapiservice — the/reset-passwordpage needs it.- Supabase → Auth → Redirect URLs must include
<api-domain>/reset-password.