feat(pos-app): add production OTA update support#403
Conversation
|
Claude finished @ignaciosantise's task in 3m 20s —— View job PR Review: feat(pos-app): add production OTA update support
Subagent results: ✅ No license issues | ✅ No breaking changes | ✅ No data classification issues Found 3 issue(s)Issue 1: Silent immediate reload during active payment transactionID: use-ota-updates-silent-reload-a3f1 Context:
Recommendation: Check for an active payment route or expose an imperative API that the caller (layout) can use to defer the reload. At minimum, notify the user before reloading: // e.g., defer until the app returns to idle state
if (fetchResult.isNew) {
addLog("info", "OTA update ready — will apply on next launch", ...);
// store a flag and call Updates.reloadAsync() when no transaction is active
}Issue 2: Third-party GitHub Actions action pinned by tag, not commit SHAID: ota-update-pos-unpinned-action-b7c2 Context:
Recommendation: Pin to a specific commit SHA: uses: dawidd6/action-download-artifact@20319c5641d495c8a52e688b7dc5fada6c3a9fbc # v6.x.xIssue 3: External domain URL in app configurationID: app-json-external-domain-url-e9a4 🔒 External Domain URL (Non-blocking) This is the Expo Updates manifest endpoint, required for OTA updates to function. Verify the project ID ( |
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
…ading Restore the expo-asset plugin to ensure assets are embedded in native builds and included in OTA update manifests. Add patch for expo-updates to load .env files before config evaluation (upstream fix pending in expo/expo#43635). Defer API URL validation to request time to avoid crash when env vars load asynchronously. Add expo-channel-name header for production channel routing. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Resolve merge conflicts after Expo 55 upgrade on main. Update expo-updates to v55.0.12 and regenerate env loading patch for the new version. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The expo-updates fingerprint:generate command outputs a full JSON object
containing parentheses and special characters. When interpolated directly
into shell scripts via ${{ }}, this caused syntax errors. Fix by piping
through jq to extract just the hash, and using env blocks instead of
inline interpolation in the OTA workflow.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…rison Query fingerprints directly from EAS server using eas build:list and eas fingerprint:compare, eliminating the need to save/download fingerprint artifacts across workflows. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Capture eas CLI output before parsing with jq to gracefully handle cases where no builds exist yet and the CLI returns non-JSON output. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Required for eas CLI commands (build:list, fingerprint:compare) to identify the project in non-interactive mode. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
EAS fingerprint API only works with EAS Build, but we build natively with Gradle/Fastlane. Revert to artifact-based approach with the original fixes: jq hash extraction and env block for safe shell interpolation. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…facts Replace GitHub Actions artifacts (30-day retention limit) with a dedicated `fingerprints-dont-remove` branch for storing native build fingerprints. This ensures fingerprints never expire, so the OTA safety check always works regardless of time between releases. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Called workflows (release-android-base, release-ios-base) now require contents:write to push fingerprints to the fingerprints-dont-remove branch. All caller workflows must grant at least that level. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add updates.url, runtimeVersion (fingerprint policy), and embedded expo-channel-name to app.json so OTA is actually enabled in native builds (previously the config plugin wrote ENABLED=false). - Replace the single fingerprint push with a fetch+rebase+retry loop in the Android/iOS release workflows to avoid non-fast-forward failures when both jobs push to fingerprints-dont-remove concurrently. - Drop the dead EAS_UPDATE_CHANNEL env from the prebuild step. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
# Conflicts: # dapps/pos-app/app/payment-failure.tsx # dapps/pos-app/app/scan.tsx # dapps/pos-app/components/close-button.tsx # dapps/pos-app/components/settings-bottom-sheet.tsx # dapps/pos-app/package-lock.json # dapps/pos-app/package.json
…ompat expo-updates@55.0.12 declares expo-updates-interface "~55.1.3", which resolves to 55.1.6. 55.1.4+ added an abstract `getContext()` member to the UpdatesStateChangeSubscription interface that 55.0.12 does not implement, breaking :expo-updates:compileReleaseKotlin. Pin the interface to 55.1.3 (the SDK 55 tested combo) via overrides. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Bumps expo 55.0.4 -> 55.0.26 and runs `expo install --fix`, aligning all expo-* and react-native packages to the SDK-pinned versions (react-native 0.83.6, expo-updates 55.0.24, etc.). This replaces the earlier expo-updates-interface@55.1.3 override: the newer expo-updates 55.0.24 implements the UpdatesStateChangeSubscription `getContext()` member, so it is natively compatible with expo-updates-interface 55.1.6 and the override is no longer needed. Also: - Regenerate the @expo/env-load patch for expo-updates 55.0.24 - Add babel-preset-expo as a direct dep so it hoists (Metro resolves it from the project root; it was only nested under expo/node_modules) - Bump eslint-config-expo to 55.0.1 to satisfy expo-doctor Verified: `expo prebuild --clean` regenerates MainApplication.kt with the new ExpoReactHostFactory API, and a full release `assembleRelease` succeeds with OTA config embedded (updates URL, fingerprint runtime version, production channel). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
EAS Update requires the --environment flag on Expo SDK 55+. Add `--environment production` to the OTA workflow's eas update call and the README CLI example. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Summary
This PR adds production OTA update support for
dapps/pos-appwith Expo Updates, including runtime update checks, update metadata in Settings, and production-only channel configuration.It also wires release workflows to publish native fingerprint artifacts and adds a dedicated OTA publish workflow that blocks updates when Android or iOS native fingerprints drift.
Documentation was updated in
dapps/pos-app/README.mdanddapps/pos-app/AGENTS.mdto describe publish, rollback, and operational constraints for JS-only OTA releases.Validation run:
npm run lint,npx tsc --noEmit, andnpm test -- --watch=falseindapps/pos-app.OTA Flow
flowchart TD A[Release POS workflow] --> B[Expo prebuild with production channel] B --> C[Generate Android and iOS native fingerprints] C --> D[Upload fingerprint artifacts] E[Manual OTA workflow dispatch] --> F[Compute current Android and iOS fingerprints] F --> G[Download last production fingerprints] G --> H{Fingerprints match?} H -- No --> I[Block OTA publish] H -- Yes --> J[eas update --channel production]