Manually-triggered, build-only GitHub Actions workflow on GitHub-hosted runners. Inputs: environment (staging/prod), target (all/customer/mitra/ backend/control_center), platform (android/ios/both). Runner split: iOS app jobs run on macos-latest, all else on ubuntu-latest. Apps build debug-signed APKs; control_center bakes VITE_API_BASE_URL; backend exports a docker-save tarball. iOS jobs await per-flavor Xcode schemes + signing. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
66 lines
4.6 KiB
Markdown
66 lines
4.6 KiB
Markdown
# CI Workflows
|
||
|
||
## `build.yml` — parameterized build
|
||
|
||
Manually-triggered, **build-only** pipeline (no push, no deploy). Produces downloadable artifacts.
|
||
|
||
### How to run
|
||
1. GitHub → **Actions** tab → **Build** (left sidebar) → **Run workflow**.
|
||
2. Pick:
|
||
- **environment** — `staging` or `prod`
|
||
- **target** — `all`, `customer`, `mitra`, `backend`, or `control_center`
|
||
- **platform** — `android`, `ios`, or `both` (only affects the customer/mitra apps; ignored for backend/control_center)
|
||
3. **Run workflow**. Open the run; artifacts appear at the bottom of the summary page when it finishes.
|
||
|
||
(You can also trigger it from the CLI: `gh workflow run build.yml -f environment=staging -f target=all -f platform=android`.)
|
||
|
||
### Runner split (Linux vs macOS)
|
||
iOS can only be built on macOS, so the workflow routes jobs accordingly:
|
||
|
||
| Job | Runner |
|
||
|---|---|
|
||
| `customer-ios`, `mitra-ios` | `macos-latest` |
|
||
| `customer-android`, `mitra-android`, `backend`, `control_center` | `ubuntu-latest` |
|
||
|
||
> ⚠️ **macOS runner minutes bill at ~10× Linux.** That's why `platform` defaults to `android`. Choose `ios`/`both` deliberately.
|
||
|
||
### What each target produces
|
||
|
||
| Target | Platform | Tool | Artifact | Notes |
|
||
|---|---|---|---|---|
|
||
| `customer` | android | Flutter | `customer-<env>-android-apk` → `app-<env>-release.apk` | Debug-signed (no keystore in repo). Fine for internal/Firebase App Distribution. |
|
||
| `customer` | ios | Flutter | `customer-<env>-ios-app` (`Runner.app`) | **Unsigned** (`--no-codesign`). See iOS prerequisites below. |
|
||
| `mitra` | android | Flutter | `mitra-<env>-android-apk` | Same as customer-android. |
|
||
| `mitra` | ios | Flutter | `mitra-<env>-ios-app` | Same caveats as customer-ios. |
|
||
| `control_center` | — | Vite | `control-center-<env>-dist` (the `dist/` folder) | `VITE_API_BASE_URL` baked in at build time — see below. |
|
||
| `backend` | — | Docker | `backend-<env>-image` (`*.tar.gz`) | Env-**agnostic** image (config is runtime env vars). Load with `docker load`. |
|
||
|
||
`all` runs every selected job in parallel; each is independent, so one failing doesn't block the others.
|
||
|
||
### ⚠️ iOS prerequisites (not satisfied yet)
|
||
The iOS jobs are wired but will **fail until two things are done**:
|
||
1. **Per-flavor Xcode schemes** (`staging`, `prod`) must exist in `ios/Runner.xcodeproj`. Today there's only the default `Runner` scheme, so `flutter build ios --flavor staging` errors with *"The Xcode project does not define custom schemes"*. This mirrors the Android flavor setup but on the iOS side (schemes + build configurations + per-config bundle IDs).
|
||
2. **Code signing** for a distributable `.ipa`: Apple Developer certificate + provisioning profiles stored as GitHub secrets. The current jobs use `--no-codesign`, which only validates that the app **compiles** and produces an unsigned `Runner.app` (not installable on devices).
|
||
|
||
Until then, `platform=ios`/`both` is useful only once the schemes land. `platform=android` works today.
|
||
|
||
### Environment specifics
|
||
- **Apps (customer/mitra):** `environment` selects the Flutter flavor + entrypoint + `env/<env>.json` (`--flavor`, `-t lib/main_<env>.dart`, `--dart-define-from-file`). Reminder: `env/staging.json` still has a **placeholder API URL** until the staging backend is deployed.
|
||
- **control_center:** `VITE_API_BASE_URL` is compiled in. Defaults: prod → `https://internal.halobestie.com`, staging → `https://staging-internal.halobestie.com`. Override without editing the workflow by setting repo **Variables** (Settings → Secrets and variables → Actions → Variables): `CC_API_BASE_URL_PROD`, `CC_API_BASE_URL_STAGING`.
|
||
- **backend:** the image is identical across environments; env/secrets are supplied at `docker run` time (see [backend/DEPLOY.md](../../backend/DEPLOY.md)). The `<env>` in the artifact name is just a label.
|
||
|
||
### Deploying a build artifact (manual, since we don't push yet)
|
||
- **Backend:** download `backend-<env>-image`, copy to the host, then:
|
||
```bash
|
||
gunzip -c halobestie-backend-<env>.tar.gz | docker load
|
||
# then run per backend/DEPLOY.md
|
||
```
|
||
- **control_center:** download `control-center-<env>-dist`, serve the `dist/` behind Nginx (internal-only).
|
||
- **Apps:** download the APK and install / upload to Firebase App Distribution.
|
||
|
||
### Pinned versions
|
||
Flutter `3.41.9`, JDK `17`, Node `20` (see `env:` block in [build.yml](build.yml)). Bump them there when the team upgrades.
|
||
|
||
### Not included yet (by design)
|
||
Pushing images to a registry and deploying are intentionally out of scope for this first iteration. When you're ready, the natural next step is a `release.yml` that pushes to GHCR and (optionally, via a self-hosted runner or SSH) deploys to the VPS.
|