Migrate from RevoPush
Move a React Native or Expo app from RevoPush to HotCodePush with the CodePush guide, plus the rows and gotchas where RevoPush differs.
A React Native or Expo app leaves RevoPush by replacing @revopush/react-native-code-push with @hotcodepush/react-native-code-push at its next store release. RevoPush keeps the CodePush API behind a forked client and CLI, so most of the CodePush guide applies. What differs, side by side, is on the site's RevoPush alternative page.
This page carries what differs: one app instead of one per platform, channels for deployments, the fingerprint for exact-version targeting. An Expo app imports from @hotcodepush/expo-ota-updates instead.
AI-assisted migration (recommended)
Install the HotCodePush skills:
npx skills add hotcodepush-team/skillsThen paste the prompt into your coding agent:
Migrate this app from RevoPush to HotCodePush: install the skills with `npx skills add hotcodepush-team/skills`, then run the hotcodepush-migrate skill, following https://hotcodepush.com/docs/migrate/revopush.The agent removes the RevoPush client, runs init, maps channels, the signing key and the binary ranges, and reports a checklist for the store release. It never touches RevoPush, and the first release waits for the store build. Agent skills explains what the agent does.
Prerequisites
- You have a HotCodePush account and an organization.
npx hotcodepush initcreates both, as the quickstart shows. - The app is a React Native app on the New Architecture, or an Expo app that runs in a development build. The minimum versions are on Supported versions. RevoPush ran on older versions, so upgrade first.
- You have the private key your RevoPush releases were signed with, if the app signed.
- A store release lies ahead, and Node.js is on every build machine, since the build step runs the CLI from an Xcode phase and a Gradle task.
Steps
If you already removed the client and ran init, skip to step 4.
1. Freeze a branch for the old builds
git branch revopush-fleetHotfixes for the old binaries come from this branch: a bundle built from the migrated code imports a native module they lack.
2. Remove the RevoPush client
npm uninstall @revopush/react-native-code-pushAn Expo app also uninstalls @revopush/expo-code-push-plugin and removes its entry from app.json. Drop the codePush() wrapper and every call per the SDK calls below. Then delete what the native projects carried:
CodePushDeploymentKeyandCodePushPublicKeyinInfo.plistandstrings.xml, the server URL,CodePushServerURLinInfo.plistandCodePushServerUrlinstrings.xml, and the App Transport Security exceptions for RevoPush's hosts.- the
codepush.gradleline inandroid/app/build.gradle, and theCODEPUSH_KEYbuild setting andresValuelines of a multi-deployment setup. - the
CodePush.bundleURL()line and thegetJSBundleFile()orjsBundleFilePathoverride: put both host files back to the template, whichinitrecognises (Installation).
3. Run init
npx hotcodepush initinit signs you in, creates one app for both platforms with its production channel, installs the package and wires the build step. The CodePush guide's step 2 has the React Native and Expo detail. Answer no to the signing key if you bring yours, and decline the first release.
Release after the store build, not before
A release created before a binary was built is never served to that binary. Create the release in step 7, after the store build of step 6.
4. Add your signing key
npx hotcodepush signing-key add --private-key-path private.pemsigning-key add takes an RSA key of at least 2,048 bits and fills publicKeys in hotcodepush.json, which replaces CodePushPublicKey. Skip the step if your releases were unsigned. The private key stays where it is, and CI holds its content as HOTCODEPUSH_SIGNING_KEY.
5. Create a channel per deployment
npx hotcodepush channel create --name staging --discoverableproduction exists, and Staging and every custom deployment become one channel each, lowercase. An app that came from App Center may hold appcenter_Staging and appcenter_Production beside the originals: collapse each pair into one channel. A build flavour that followed a deployment key sets HOTCODEPUSH_CHANNEL in its build environment instead (Set up environments and tenants).
6. Ship the store release that carries the SDK
Build the release as before. The build step registers the build as a binary with its fingerprint. The machine needs npx hotcodepush login or HOTCODEPUSH_TOKEN, and npx hotcodepush binary list shows the registered builds.
7. Release from your pipeline
npx hotcodepush release create --bundle-version "$(git rev-parse --short HEAD)" --yesOne call releases both platforms, and HOTCODEPUSH_TOKEN in the environment replaces the access key.
On a device running the new build the release applies within about a minute (How an update reaches a device). If nothing happens, see Troubleshooting.
8. Run both until the fleet moves
Old builds keep checking RevoPush with their deployment keys, so keep the RevoPush apps and plan alive while they have users. Release to them from the branch of step 1 only, with -t pinned to the old store versions.
Delete the RevoPush apps once the old builds are below the share you leave behind. RevoPush's Active metric and binary list show the shift.
CLI commands
Every row of the CodePush guide's CLI commands table holds with revopush in place of appcenter codepush. These rows are RevoPush's own:
| RevoPush | HotCodePush |
|---|---|
npm i -g @revopush/code-push-cli, revopush login | npm i -D hotcodepush, npx hotcodepush login |
app add MyApp-iOS, app add MyApp-Android | One app serves both platforms. init creates it, or app create --framework react_native by hand. |
app rename, app rm, app transfer | app update --name, app delete, app transfer --organization |
collaborator add <app> <email> | invitation create --email <address> --role member, per organization |
release-react MyApp-iOS ios, then release-react MyApp-Android android | release create releases both platforms in one call. |
release-react without -d, to Staging | release create without --channel releases to hotcodepush.json's channel, production by default. |
release-expo <app> android | release create. The upload runs expo export:embed itself. |
release-native <app> ios app.ipa, the base release | Nothing. The build step registers every store build with its fingerprint. |
-t left out, the exact store version | The fingerprint alone decides, every store version sharing it, while --binary-version "1.2.3" keeps one version. |
-t "~1.2.0", -t "^1.2.3", -t "1.2.3 - 1.2.7" | --binary-version ">=1.2.0 <1.3.0", ">=1.2.3 <2.0.0", ">=1.2.3 <=1.2.7". ~, ^ and hyphen ranges do not parse. |
-t 1.2.3 --buildNumber 100 | --binary-version "1.2.3.100". The build number is the version's fourth component. |
--force for an asset over 500 KiB | Nothing to pass. There is no limit below 512 MB per file. |
promote <app> Staging Production --label v33 | No flag is needed. release create --bundle <n> --channel production releases a bundle by number, which release list --channel staging shows. |
patch -t, patch --buildNumber | None. release update changes no condition, so create a new release and revoke the old one. |
deployment add <app> Staging -k <key> | Nothing to keep. A channel has no key. |
deployment clear | release revoke --all. Devices return to the embedded bundle. |
revopush/revopush-github-action@v1 with accessKey | A run: step runs npx hotcodepush release create --channel production, with HOTCODEPUSH_TOKEN and HOTCODEPUSH_SIGNING_KEY in its env (GitHub Actions). |
The CLI reference lists every command, and Compatibility has the range syntax.
SDK calls
The CodePush guide's SDK calls table applies row for row. Two rows are RevoPush's own:
| RevoPush | HotCodePush |
|---|---|
import codePush from "@revopush/react-native-code-push" | import { HotCodePush } from "@hotcodepush/react-native-code-push", or from @hotcodepush/expo-ota-updates |
notifyApplicationReady(), the alias of notifyAppReady() | nothing by default, or notifyReady() under readySignal: manual |
What differs
Staging is not the default here
RevoPush released to Staging when -d was left out. Here release create releases to the channel hotcodepush.json names, production by default, so a ported pipeline without --channel staging reaches every production device.
A release reaches every store version with the same fingerprint
RevoPush targeted the exact store version unless -t widened it. Here the fingerprint decides, and a release reaches every build sharing it. Add --binary-version "1.2.3" to keep a release on one version.
Rollouts and rollbacks move more freely
RevoPush blocked a new release while a rollout was active, and patch -r only raised the percentage. Here nothing blocks a new release, and release rollout moves the percentage in either direction. RevoPush's rollback copied the earlier release's flags, while release rollback is mandatory unless --mandatory false.
Next steps
- Migrate from CodePush has the full command and SDK tables, the before and after and the delta updates this page builds on.
- Ship every commit has the pipeline that releases every merge with the one CLI line.
- Roll out gradually: start small, let the release progress and let auto-pause stop a bad one.
- React Native SDK reference documents every
hotcodepush.jsonkey, method, event and type of the SDK you installed.
Last updated on
Migrate from Ionic Appflow
Choose Capawesome Cloud or HotCodePush for your Appflow app, then move Appflow Live Updates to the HotCodePush Capacitor SDK step by step.
Migrate from Stallion
Move a React Native or Expo app from Stallion to HotCodePush, with channels for projects, the fingerprint for app versions and useUpdates() for the hooks.