Releasing updates
Releasing updates
This guide explains how to publish and manage OTA updates, from the dashboard, the CLI, or CI.
- React Native
- Capacitor
If you use the CLI and do not have cmpatch yet, install it with npm install -g @codemagic/patch-cli (Node.js >=20), then run cmpatch init from your project root: it signs you in and links the project so the commands below need no --server-url or --app flags.
Capacitor apps use cmpatch-capacitor. To install it and sign in, see Native setup. The CLI has no project config file: pass the app and deployment as flags, and set the server with --server-url, CODEMAGIC_PATCH_SERVER_URL, or cmpatch-capacitor config set --server-url <url>.
Ways to publish
- React Native
- Capacitor
| Method | Best for |
|---|---|
| Dashboard → New release | Command builder (copy release-react) or .cmpatch bundle upload in the browser |
| CLI | Local dev, scripts, and pipelines (cmpatch release-react) |
| CI | Automated releases after build/test, CI integration |
| Method | Best for |
|---|---|
| Dashboard → New release | Generating a cmpatch-capacitor release create command to copy |
| CLI | Local dev, scripts, and pipelines (cmpatch-capacitor release create --bundle-path www) |
| CI | Automated releases after the web build, CI integration |
Dashboard: command builder or bundle upload
On a deployment page, New release offers options based on the app's framework:
- React Native
- Capacitor
Via CLI: the dashboard builds a cmpatch release-react command from your choices (platform, rollout %, target binary version, release notes, mandatory). Copy and run it from your project directory or CI. Patch does not compile the bundle in the browser.
Bundle upload: drag or select a .cmpatch file produced by cmpatch bundle. Set metadata and upload; the server ingests the artifact and queues processing.
Via CLI: for Capacitor apps, the dashboard generates a cmpatch-capacitor release create command from the bundle path, target binary version, rollout percentage, release notes, and mandatory flag. Bundle path and target binary version are required. Run the command after your web build, locally or in CI.
Bundle upload is not available for Capacitor apps. The dashboard accepts .cmpatch artifacts, which only the React Native CLI produces.
Full UI walkthrough: Web dashboard.
CLI: one-shot publish from source
- React Native
- Capacitor
From your React Native project root:
cmpatch release-react --platform ios --deployment Staging --release-notes "Fix onboarding crash" --yes
release-react bundles JS, resolves a target binary version, and uploads in one step.
From your Capacitor project root, after the web build:
cmpatch-capacitor release create --bundle-path www \
--app MyApp-iOS --deployment Staging --target-binary-version 1.2.3 \
--release-notes "Fix onboarding crash"
release create uploads the built directory. Publish one release per platform app. --target-binary-version is required.
Recommended workflow: Staging → Production
Use a Staging → Production promotion flow so every update is tested before reaching end users.
Step 1: Release to Staging
Via CLI:
- React Native
- Capacitor
cmpatch release-react --platform ios --deployment Staging --release-notes "Fix onboarding crash" --yes
cmpatch-capacitor release create --bundle-path www \
--app MyApp-iOS --deployment Staging --target-binary-version 1.2.3 \
--release-notes "Fix onboarding crash"
Or use New release in the dashboard.
At this stage:
- The update is not visible to production users
- You can validate functionality and stability
- Multiple iterations can be released without production impact
Step 2: Validate in Staging
Test thoroughly before promoting. Typical checks:
- App launch and navigation
- New features and UI changes
- Regression testing
- Crash-free behavior on target devices
- Compatibility with supported binary versions
Step 3: Promote to Production
After validation, promote the same release with no rebuild required.
CLI:
- React Native
- Capacitor
cmpatch release promote \
--app MyApp-iOS \
--source-deployment Staging \
--dest-deployment Production \
--label v4 \
--yes
cmpatch-capacitor release promote \
--app MyApp-iOS \
--source-deployment Staging \
--dest-deployment Production \
--label v4
The promoted release keeps the target binary version of the source release. You cannot change it during promotion; see Binary version compatibility.
Dashboard: open the release on Staging and use Promote, or use deployment actions. See Web dashboard.
Release to Staging → Internal testing & QA → Promote to Production
What gets uploaded
- React Native
- Capacitor
A Patch release includes:
- JavaScript bundle
- Static assets (images, fonts, etc.)
- Release metadata (deployment, binary version, rollout, etc.)
A Patch release includes:
- The Capacitor web build (
webDir, usuallywww/): HTML, JS, CSS, and images - Release metadata (deployment, binary version, rollout, etc.)
Patch does not include native binaries (.apk / .ipa). Any native code change must go through the app stores.
Version control
Patch uses a two-layer versioning model.
- Native app version (binary version)
The version from the App Store / Play Store (CFBundleShortVersionString on iOS, versionName on Android). This is the baseline the OTA update must be compatible with.
- Patch release version
Each release is a JavaScript + asset bundle on top of a native binary. Releases are ordered within a deployment history and can be rolled back independently of store releases.
Target binary version
- React Native
- Capacitor
cmpatch release-react auto-detects the target binary version from your native project. You can override it in the CLI or command builder:
cmpatch release-react \
--platform ios \
--deployment Staging \
--target-binary-version "1.2.0" \
--yes
--target-binary-version must be an exact version. Semantic ranges and wildcards (e.g. ^1.2.0, ~1.2.0) are rejected by both the CLI and the server.
Only apps whose running binary version matches the release's target receive the update. One exception widens delivery automatically: the release is also published to other binary versions whose recorded native fingerprint matches, so store builds with identical native code receive the same update. See Fingerprinting.
cmpatch-capacitor release create does not read native project files, so it cannot detect the version. Pass the installed app version (CFBundleShortVersionString / versionName):
cmpatch-capacitor release create --bundle-path www \
--app MyApp-iOS --deployment Staging --target-binary-version "1.2.0"
--target-binary-version must be an exact version. Semantic ranges and wildcards (e.g. ^1.2.0, ~1.2.0) are rejected by both the CLI and the server.
Only apps whose binary version matches the target receive the update. Capacitor releases have no native fingerprint, so delivery is never extended to other binary versions, and Patch does not check that the bundle is compatible with the native build. To ship the same bundle to several versions, publish it once per version. See Binary version compatibility.
Dry runs and inspection
Preview without uploading:
- React Native
- Capacitor
cmpatch release-react --platform ios --deployment Staging --dry-run
cmpatch-capacitor release create --bundle-path www \
--app MyApp-iOS --deployment Staging --target-binary-version 1.2.0 --dry-run
--dry-run validates and packages the bundle and prints its package hash without uploading.
Watch processing and inspect a release:
- React Native
- Capacitor
cmpatch release list --app MyApp-iOS --deployment Staging --format table
cmpatch release inspect --app MyApp-iOS --deployment Staging --label v1 --wait
cmpatch-capacitor release list --app MyApp-iOS --deployment Staging
cmpatch-capacitor release inspect --app MyApp-iOS --deployment Staging --label v1 --wait
In the dashboard, open the deployment or release detail page to see status and metrics.
Next steps
- React Native
- Capacitor
- Fingerprinting: block incompatible OTAs against a store-build baseline
- Binary version compatibility: how binary versions scope Capacitor releases
- Verify a test release: confirm devices receive Staging updates before promoting
- Web dashboard: UI overview, tokens, team management
- Production control: rollouts, mandatory updates, rollbacks
- CI integration: automate releases in pipelines
- Analytics: monitor adoption and failures