Swasti · mForm V2→V3

14 — Repos, environments & deployment

This note is the operational reference for where the code lives and how it gets released. Two repos, four environments, two distribution channels (Firebase + Play Store). All builds happen on an engineer’s laptop — no CI release pipeline yet.


1. Repos

RepoURLWhat it holds
Frappe appdhwani-ris/frappe_mform_swastiServer-side Frappe v16 app: doctypes (Member, Scheme Master, Document Master, Document Application, Health Screening, …), permissions, fixtures, seeders, mobile sync API.
Flutter appdhwani-ris/frappe_mform_swasti_appSurveyor mobile app: form rendering, offline outbox, sync engine, design system, per-form schemas.

Both repos are private to the Dhwani-RIS org. Engineering team has push access to staging only; uat and main are PR-gated.


2. Branch flow

staging  ─PR→  uat  ─PR→  main
BranchDirect push?Purpose
staging✅ yesActive development. All feature work merges here.
uat❌ PR onlyRelease candidates for client UAT. Updated by promoting from staging via PR.
main❌ PR onlyProduction. Updated by promoting from uat via PR.

Hard rule: the only branch that accepts direct pushes is staging. Hotfixes that need to bypass staging require explicit approval, not a force push.


3. Environments

EnvMobile app IDFrappe backend URLAudience
devcom.dhwani.swasti.devhttp://10.0.2.2:8001 (emulator-localhost)Engineers, local emulator
stagingcom.dhwani.swasti.staginghttps://swasti-staging.dhwaniris.com (placeholder)Internal testers via Firebase App Distribution
uatcom.dhwani.swasti.uathttps://swasti-uat.dhwaniris.com (placeholder)Swasti team via Play Store internal/closed track
prodcom.dhwani.swastihttps://swasti.dhwaniris.com (placeholder)Field surveyors via Play Store production

Each environment gets a distinct Android applicationId so QA can have all four installed side-by-side on one device. The base ID com.dhwani.swasti follows the Dhwani org convention (com.dhwani.* always). Non-prod builds show a coloured banner in the top-right corner (DEV yellow, STAGING blue, UAT orange) so testers always know which env they’re looking at.

Real DevOps-provisioned URLs for staging / uat / prod will replace the swasti-*.dhwaniris.com placeholders in apps/swasti_flutter/env/<env>.json when those domains land. One file edit per env, no code changes.


4. Mobile build commands

A single helper script wraps the env-aware flutter build:

cd apps/swasti_flutter

./scripts/build_apk.sh dev debug         # current emulator iteration
./scripts/build_apk.sh staging release   # Firebase distribution build
./scripts/build_apk.sh uat release       # Play Store internal/closed track
./scripts/build_apk.sh prod release      # Play Store production

Or via make:

make dev                  # = build_apk.sh dev debug
make staging-release      # = build_apk.sh staging release
make uat-release
make prod-release

Each invocation reads env/<env>.json (e.g. env/staging.json) for the FRAPPE_URL and ENV_NAME constants and bakes them into the binary at build time via --dart-define-from-file.


5. Release workflow

App releases happen from the engineer’s local machine, not CI. This avoids managing signing keys + service accounts in a CI environment we don’t yet have.

EnvDistribution mechanismSteps
devLocal emulator / USB device./scripts/build_apk.sh dev debugadb install
stagingFirebase App Distribution./scripts/build_apk.sh staging release → upload via firebase appdistribution:distribute (API), testers get an email link
uatPlay Store internal/closed track./scripts/build_apk.sh uat release produces an .aab; hand off to DevOps for Play Console upload
prodPlay Store production./scripts/build_apk.sh prod release produces an .aab; hand off to DevOps for Play Console upload

A scripts/release.sh wrapper that bundles the build + Firebase API call for staging is on the TODO list — currently the engineer runs build + firebase CLI separately.

Signing config: still a TODO. Today’s android/app/build.gradle.kts release build type falls back to the debug keystore. Before any Play Store submission DevOps needs to provide an upload keystore + alias + passwords.

iOS: not in scope yet — Android-only flavors configured. iOS schemes get set up when iOS distribution becomes a deliverable.


6. Frappe backend

EnvWhere it runs
devEngineer’s laptop, bench at ~/frappe-bench-swasti, site swasti.local on port 8001 (emulator reaches it via http://10.0.2.2:8001)
stagingDevOps-managed VM at swasti-staging.dhwaniris.com (placeholder, awaiting provisioning)
uatDevOps-managed VM at swasti-uat.dhwaniris.com (placeholder, awaiting provisioning)
prodDevOps-managed VM at swasti.dhwaniris.com (placeholder, awaiting provisioning)

Each Frappe deploy is a bench get-app against dhwani-ris/frappe_mform_swasti at the appropriate branch. Migrations apply via bench --site <site> migrate. Bootstrapping a fresh site means installing the app, running the seeders (Donor Master CSV, Document Master unify, Scheme Master CSV), and confirming frappe.get_installed_apps() includes mform_swasti.

DevOps owns the actual server provisioning + cron + nginx + SSL.


7. Standing TODOs

  1. Real env URLs — DevOps to provision and replace the *.dhwaniris.com placeholders in env/staging.json, env/uat.json, env/prod.json.
  2. Release signing key — generate/obtain Play Store upload keystore; wire into android/app/build.gradle.kts release build type. Required before any .aab can be submitted to Play.
  3. scripts/release.sh — wrap the staging Firebase distribution call (firebase appdistribution:distribute) so it’s one command instead of two.
  4. iOS schemes — when iOS distribution lands, mirror the Android flavor setup in Xcode build configurations.
  5. First Frappe deploy — DevOps to set up the staging Frappe bench, install mform_swasti from origin staging, run the seeders, and confirm the mobile app can reach it.

This note is the source of truth for the dev/distribution surface. Anything that changes about repos, branch policy, env URLs, or release mechanics should land here first.


Last updated 2026-05-04