feat(client): show app + server version at the bottom of settings #290

Merged
james merged 1 commit from 289-settings-version-display into main 2026-06-26 21:55:57 +00:00
Owner

Embeds the build version and surfaces it at the bottom of the account/settings screen, and fixes the release pipeline so the version actually updates per release.

Display (apps/client/app/(app)/account.tsx)

A new VersionFooter after <TokensCard />:

  • Web (PWA): one muted line — Carol <version> — from the bundle's expo.version via expo-constants. No network call.
  • Native (Android / Flatpak): two muted lines — App <version> (expo-constants) and Server <version> (from GET /api/health via a new useServerVersion hook in @carol/api-client). Shows Checking… while loading and Unknown on failure.

The underlying defect

The version was a static 0.0.0 everywhere — app.json expo.version, root package.json, apps/api/package.json — and the release workflows parsed the git tag but never wrote it before building. So /api/health always reported 0.0.0 and the Android versionName/versionCode never updated per release.

Both release workflows now stamp the tag version before building:

  • release.yml → writes the tag version into apps/api/package.json (+ root) before docker build, so /api/health reports the real version.
  • release-android.yml → writes expo.version + a monotonic expo.android.versionCode (MAJOR*1000000 + MINOR*1000 + PATCH, pre-release suffix stripped) into app.json before expo prebuild, so the APK/AAB carry the real versionName/versionCode.
  • Committed package.json/app.json stay at the 0.0.0 dev placeholder — CI is the only writer. build-android.sh notes this for local builders.

Notes / decisions

  • /api/health isn't in the generated OpenAPI surface (no zod schema), so useServerVersion calls it through the typed client with a narrow cast rather than hand-authoring the route into the spec / drift baseline.
  • versionCode formula assumes minor/patch < 1000 (documented in-workflow).
  • No new runtime env var → no README change. i18n strings under account.version.* (en only; siblings fall back per-key).

Verification

  • @carol/api-client typecheck ✓ · vitest 26/26 ✓
  • @carol/client typecheck ✓ · eslint ✓
  • @carol/api openapi:check — spec up to date ✓
  • actionlint on both edited workflows — clean ✓

Closes #289

🤖 Generated with Claude Code

Embeds the build version and surfaces it at the bottom of the account/settings screen, and fixes the release pipeline so the version actually updates per release. ## Display (`apps/client/app/(app)/account.tsx`) A new `VersionFooter` after `<TokensCard />`: - **Web (PWA):** one muted line — `Carol <version>` — from the bundle's `expo.version` via `expo-constants`. No network call. - **Native (Android / Flatpak):** two muted lines — `App <version>` (expo-constants) and `Server <version>` (from `GET /api/health` via a new `useServerVersion` hook in `@carol/api-client`). Shows `Checking…` while loading and `Unknown` on failure. ## The underlying defect The version was a static `0.0.0` everywhere — `app.json` `expo.version`, root `package.json`, `apps/api/package.json` — and the release workflows parsed the git tag but never wrote it before building. So `/api/health` always reported `0.0.0` and the **Android `versionName`/`versionCode` never updated** per release. Both release workflows now stamp the tag version before building: - `release.yml` → writes the tag version into `apps/api/package.json` (+ root) before `docker build`, so `/api/health` reports the real version. - `release-android.yml` → writes `expo.version` + a monotonic `expo.android.versionCode` (`MAJOR*1000000 + MINOR*1000 + PATCH`, pre-release suffix stripped) into `app.json` before `expo prebuild`, so the APK/AAB carry the real `versionName`/`versionCode`. - Committed `package.json`/`app.json` stay at the `0.0.0` dev placeholder — CI is the only writer. `build-android.sh` notes this for local builders. ## Notes / decisions - `/api/health` isn't in the generated OpenAPI surface (no zod schema), so `useServerVersion` calls it through the typed client with a narrow cast rather than hand-authoring the route into the spec / drift baseline. - `versionCode` formula assumes minor/patch < 1000 (documented in-workflow). - No new runtime env var → no README change. i18n strings under `account.version.*` (en only; siblings fall back per-key). ## Verification - `@carol/api-client` typecheck ✓ · vitest 26/26 ✓ - `@carol/client` typecheck ✓ · eslint ✓ - `@carol/api openapi:check` — spec up to date ✓ - `actionlint` on both edited workflows — clean ✓ Closes #289 🤖 Generated with [Claude Code](https://claude.com/claude-code)
feat(client): show app + server version at the bottom of settings
Some checks failed
Commits / Conventional Commits (pull_request) Successful in 5s
PR / OSV-Scanner (pull_request) Successful in 1m49s
PR / Static analysis (pull_request) Successful in 2m2s
PR / Typecheck (pull_request) Successful in 2m22s
PR / OpenAPI (pull_request) Successful in 2m30s
PR / Client (web export smoke) (pull_request) Successful in 2m38s
PR / pnpm audit (pull_request) Successful in 3m1s
PR / Build (pull_request) Successful in 3m8s
PR / Test (sqlite) (pull_request) Successful in 3m12s
PR / Lint (pull_request) Successful in 3m19s
PR / Package age policy (soft) (pull_request) Successful in 56s
Secrets / gitleaks (pull_request) Successful in 57s
PR / Test (postgres) (pull_request) Failing after 3m29s
PR / Trivy (image) (pull_request) Successful in 2m2s
PR / Coverage (soft) (pull_request) Successful in 2m2s
f06d68cf93
Surface the build version at the bottom of the account/settings screen:
web shows one line (Carol <version>) from the bundle's expo.version via
expo-constants; native shows both the app version and the server version
(new useServerVersion hook in @carol/api-client reading GET /api/health,
with Checking… / Unknown placeholders).

Also fix the release pipeline so the version actually updates per
release. It was a static 0.0.0 everywhere and the workflows parsed the
tag but never wrote it before building, so /api/health reported 0.0.0
and the Android versionName/versionCode never changed. release.yml now
stamps the tag version into apps/api/package.json (+ root) before docker
build; release-android.yml stamps expo.version + a monotonic
expo.android.versionCode into app.json before expo prebuild. Committed
package.json/app.json stay at the 0.0.0 dev placeholder; CI is the only
writer. No new env var.

Closes #289

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

📊 Test coverage

Patch coverage: no testable lines changed.

Overall (app/, lib/, db/, excluding UI per ADR-0019):

Metric Value Soft target
Lines 81.6% ≥ 50%
Branches 72.8% ⚠️ ≥ 75%
Functions 91.1% informational

Soft thresholds per ADR-0019. Coverage is informational and does not block merge.

<!-- coverage-comment --> ## 📊 Test coverage **Patch coverage:** no testable lines changed. **Overall** (`app/`, `lib/`, `db/`, excluding UI per ADR-0019): | Metric | Value | Soft target | |---|---|---| | Lines | 81.6% ✅ | ≥ 50% | | Branches | 72.8% ⚠️ | ≥ 75% | | Functions | 91.1% | informational | Soft thresholds per [ADR-0019](docs/adr/0019-coverage-soft-targets.md). Coverage is informational and does not block merge.
james merged commit a006ee5d56 into main 2026-06-26 21:55:57 +00:00
james deleted branch 289-settings-version-display 2026-06-26 21:55:57 +00:00
Sign in to join this conversation.
No description provided.