diff --git a/README.md b/README.md index 12470c3..01ab6a4 100644 --- a/README.md +++ b/README.md @@ -1,79 +1,232 @@ -This is a new [**React Native**](https://reactnative.dev) project, bootstrapped using [`@react-native-community/cli`](https://github.com/react-native-community/cli). +# SnapBiodata โ€” React Native + EAS CI/CD Starter -# Getting Started +A production-ready [React Native](https://reactnative.dev) app (bare workflow, RN 0.81 / React 19) wired up with **three build flavors** and a full **EAS (Expo Application Services)** pipeline for building, submitting to the stores, and shipping over-the-air (OTA) updates. ->**Note**: Make sure you have completed the [React Native - Environment Setup](https://reactnative.dev/docs/environment-setup) instructions till "Creating a new application" step, before proceeding. +This README explains **how the flavors and EAS are set up** so you can build and ship any environment with a single command. -## Step 1: Start the Metro Server +> ๐Ÿ“– For the complete, step-by-step reference (one-time setup, troubleshooting, release flow) see **[`docs/EAS.md`](docs/EAS.md)** or run `yarn eas:help`. -First, you will need to start **Metro**, the JavaScript _bundler_ that ships _with_ React Native. +--- -To start Metro, run the following command from the _root_ of your React Native project: +## Table of contents -```bash -# using npm -npm start +- [The three environments (flavors)](#the-three-environments-flavors) +- [How a flavor is defined on each platform](#how-a-flavor-is-defined-on-each-platform) +- [Environment config (`.env` files)](#environment-config-env-files) +- [Running locally](#running-locally) +- [EAS: build, submit, update](#eas-build-submit-update) +- [OTA update vs. new build](#ota-update-vs-new-build) +- [CI/CD (GitHub Actions)](#cicd-github-actions) +- [One-time setup](#one-time-setup) + +--- + +## The three environments (flavors) + +Every build belongs to one of three environments. Each one is fully isolated โ€” its own app ID, its own OTA channel, its own store track โ€” so `development`, `staging`, and `production` can all be installed **side-by-side on the same device** without clashing. + +| | **development** | **staging** | **production** | +|---|---|---|---| +| Android applicationId | `com.snapbiodata.app.development` | `com.snapbiodata.app.staging` | `com.snapbiodata.app` | +| iOS bundle identifier | `com.snapbiodata.app.development` | `com.snapbiodata.app.staging` | `com.snapbiodata.app` | +| API URL | `dev.snapbiodata.com` | `staging.snapbiodata.com` | `snapbiodata.com` | +| OTA channel | `development` | `staging` | `production` | +| iOS scheme | `development` | `staging` | `production` | +| Android task | `bundleDevelopmentRelease` | `bundleStagingRelease` | `bundleProductionRelease` | +| Play Store track | `internal` | `alpha` | `production` | +| iOS distribution | TestFlight (internal) | TestFlight (external) | App Store | +| Audience | Dev team | QA / stakeholders | Everyone | + +> An OTA update pushed to `staging` will **never** reach `development` or `production` โ€” each binary bakes its channel in at build time. + +--- + +## How a flavor is defined on each platform + +The same three environments are expressed in **four coordinated places**. The magic is that they all line up by name: + +``` + โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” + โ”‚ development / staging / production + โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ + โ”‚ โ”‚ โ”‚ โ”‚ + โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ”‚ โ”‚ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” + โ–ผ โ–ผ โ–ผ โ–ผ + Android productFlavor iOS scheme EAS profile .env. + (android/app/build.gradle) (Xcode) (eas.json) (react-native-config) +``` + +- **Android** โ€” three `productFlavors` in `android/app/build.gradle`. `production` keeps the real ID; `development` and `staging` add an `applicationIdSuffix` so they install alongside it. +- **iOS** โ€” three shared schemes (`development`, `staging`, `production`) under `ios/*.xcodeproj/xcshareddata/xcschemes/`. +- **EAS** โ€” three build/submit profiles in `eas.json`. Each profile points at the matching Android `gradleCommand` and iOS `scheme`, and carries the OTA `channel`. +- **Runtime config** โ€” one `.env.` file per environment, read by [`react-native-config`](https://github.com/lugg/react-native-config). -# OR using Yarn +Because the names match everywhere, choosing an environment is always just picking the profile name. + +--- + +## Environment config (`.env` files) + +Each environment has an env file at the repo root: + +- `.env.development` โ†’ `ENV=development`, `API_URL=https://dev.snapbiodata.com` +- `.env.staging` โ†’ `ENV=staging`, `API_URL=https://staging.snapbiodata.com` +- `.env.production` โ†’ `ENV=production`, `API_URL=https://snapbiodata.com` + +> โš ๏ธ **These values are PUBLIC.** `react-native-config` bakes them into the app binary, where anyone can extract them by reverse-engineering the app. Put **only non-secret** config here. +> +> Secrets live elsewhere: +> - Android signing keystore โ†’ `.env.signing` (gitignored, copy from `.env.signing.example`) or GitHub/EAS secrets +> - Play service account JSON โ†’ GitHub Actions secret +> - Expo / App Store tokens โ†’ EAS / GitHub secrets + +--- + +## Running locally + +Start Metro in one terminal: + +```bash yarn start ``` -## Step 2: Start your Application +Then run any environment (each script sets `ENVFILE` and picks the right flavor/scheme automatically): -Let Metro Bundler run in its _own_ terminal. Open a _new_ terminal from the _root_ of your React Native project. Run the following command to start your _Android_ or _iOS_ app: +**Android** -### For Android +```bash +yarn android:dev # development debug +yarn android:staging # staging debug +yarn android:prod # production debug + +yarn android:dev-release # release variants +yarn android:staging-release +yarn android:prod-release +``` + +**iOS** ```bash -# using npm -npm run android +yarn ios:dev # development scheme +yarn ios:staging # staging scheme +yarn ios:prod # production scheme -# OR using Yarn -yarn android +yarn ios:dev-release # release configuration +yarn ios:staging-release +yarn ios:prod-release ``` -### For iOS +--- + +## EAS: build, submit, update + +All EAS commands are wrapped as `yarn` scripts. Every build first runs a version check (`yarn eas:version:check`) that fails fast if `package.json`, `build.gradle`, and the iOS project disagree on the version number. + +**Build** (produces store-ready AAB / IPA on Expo's servers): ```bash -# using npm -npm run ios +yarn eas:build:development # all platforms, dev +yarn eas:build:staging # all platforms, staging +yarn eas:build:production # all platforms, production -# OR using Yarn -yarn ios +yarn eas:build:android:staging # single platform +yarn eas:build:ios:staging ``` -If everything is set up _correctly_, you should see your new app running in your _Android Emulator_ or _iOS Simulator_ shortly provided you have set up your emulator/simulator correctly. +**Submit** (uploads the latest build to the store, on the right track): -This is one way to run your app โ€” you can also run it directly from within Android Studio and Xcode respectively. +```bash +yarn eas:submit:development +yarn eas:submit:staging +yarn eas:submit:production +``` -## Step 3: Modifying your App +**OTA update** (push JS/asset changes instantly โ€” no store review): -Now that you have successfully run the app, let's modify it. +```bash +yarn eas:update:development +yarn eas:update:staging +yarn eas:update:production + +# with a custom changelog message +MESSAGE="Fix login crash" yarn eas:update:staging +``` + +**Version helpers:** + +```bash +yarn eas:version:get # show version across package.json / gradle / pbxproj +yarn eas:version:check # exit 1 if any of them mismatch +``` -1. Open `App.tsx` in your text editor of choice and edit some lines. -2. For **Android**: Press the R key twice or select **"Reload"** from the **Developer Menu** (Ctrl + M (on Window and Linux) or Cmd โŒ˜ + M (on macOS)) to see your changes! +--- - For **iOS**: Hit Cmd โŒ˜ + R in your iOS Simulator to reload the app and see your changes! +## OTA update vs. new build -## Congratulations! :tada: +> **Rule of thumb:** if Metro can bundle the change, an OTA update is enough. + +| Change | Needs | +|---|---| +| JS / TypeScript code | โœ… OTA update | +| Images, fonts, JSON assets | โœ… OTA update | +| New JS-only dependency | โœ… OTA update | +| New native (Kotlin/Swift) code | ๐Ÿ” New build | +| New native dependency | ๐Ÿ” New build | +| New / changed permissions | ๐Ÿ” New build | +| `runtimeVersion` bump | ๐Ÿ” New build | + +--- + +## CI/CD (GitHub Actions) + +Workflows live in `.github/workflows/` and are triggered manually from the **Actions** tab (pick the environment/profile as an input): + +| Workflow | What it does | +|---|---| +| `eas-build-submit.yml` | Build **and** submit in one run (recommended) | +| `eas-build.yml` | Build only | +| `eas-submit.yml` | Submit the latest build | +| `eas-update.yml` | Push an OTA update (no build) | +| `ci.yml` | Lint / typecheck / tests on push & PR | + +**Required secret:** `EXPO_TOKEN` (create at expo.dev โ†’ Account Settings โ†’ Access Tokens, then add under repo Settings โ†’ Secrets โ†’ Actions). + +Duplicate runs for the same profile are cancelled automatically; an in-flight release build is always allowed to finish. + +--- + +## Release flow + +``` +โ‘  development โ”€โ”€โ–บ build + submit โ”€โ”€โ–บ Internal testing (dev team) + โ”‚ + โ–ผ (QA sign-off) +โ‘ก staging โ”€โ”€โ–บ build + submit โ”€โ”€โ–บ Closed / alpha (QA, stakeholders) + โ”‚ + โ–ผ (stakeholder sign-off) +โ‘ข production โ”€โ”€โ–บ build + submit โ”€โ”€โ–บ Play Store / App Store (everyone) +``` -You've successfully run and modified your React Native App. :partying_face: +JS-only change at any stage? Skip the build โ€” just run `yarn eas:update:`. -### Now what? +--- -- If you want to add this new React Native code to an existing application, check out the [Integration guide](https://reactnative.dev/docs/integration-with-existing-apps). -- If you're curious to learn more about React Native, check out the [Introduction to React Native](https://reactnative.dev/docs/getting-started). +## One-time setup -# Troubleshooting +Short version (full details in [`docs/EAS.md`](docs/EAS.md)): -If you can't get this to work, see the [Troubleshooting](https://reactnative.dev/docs/troubleshooting) page. +1. `npm install -g eas-cli` +2. `eas login` +3. `eas init` โ€” fills in `owner` + `projectId` in `app.config.js` +4. Put your numeric App Store App ID in `eas.json` (`ascAppId`) +5. Add the `EXPO_TOKEN` secret in GitHub +6. (Local signed builds only) `cp .env.signing.example .env.signing` and fill it in +7. Verify: `yarn eas:version:get` and `eas build:list` -# Learn More +--- -To learn more about React Native, take a look at the following resources: +## Learn more -- [React Native Website](https://reactnative.dev) - learn more about React Native. -- [Getting Started](https://reactnative.dev/docs/environment-setup) - an **overview** of React Native and how setup your environment. -- [Learn the Basics](https://reactnative.dev/docs/getting-started) - a **guided tour** of the React Native **basics**. -- [Blog](https://reactnative.dev/blog) - read the latest official React Native **Blog** posts. -- [`@facebook/react-native`](https://github.com/facebook/react-native) - the Open Source; GitHub **repository** for React Native. +- [`docs/EAS.md`](docs/EAS.md) โ€” complete EAS reference & troubleshooting (`yarn eas:help`) +- [React Native docs](https://reactnative.dev) +- [EAS Build](https://docs.expo.dev/build/introduction/) ยท [EAS Submit](https://docs.expo.dev/submit/introduction/) ยท [EAS Update](https://docs.expo.dev/eas-update/introduction/)