HotCodePush

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.

Install the HotCodePush skills:

npx skills add hotcodepush-team/skills

Then 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 init creates 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-fleet

Hotfixes 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-push

An 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:

  • CodePushDeploymentKey and CodePushPublicKey in Info.plist and strings.xml, the server URL, CodePushServerURL in Info.plist and CodePushServerUrl in strings.xml, and the App Transport Security exceptions for RevoPush's hosts.
  • the codepush.gradle line in android/app/build.gradle, and the CODEPUSH_KEY build setting and resValue lines of a multi-deployment setup.
  • the CodePush.bundleURL() line and the getJSBundleFile() or jsBundleFilePath override: put both host files back to the template, which init recognises (Installation).

3. Run init

npx hotcodepush init

init 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.pem

signing-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 --discoverable

production 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)" --yes

One 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:

RevoPushHotCodePush
npm i -g @revopush/code-push-cli, revopush loginnpm i -D hotcodepush, npx hotcodepush login
app add MyApp-iOS, app add MyApp-AndroidOne app serves both platforms. init creates it, or app create --framework react_native by hand.
app rename, app rm, app transferapp 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 androidrelease create releases both platforms in one call.
release-react without -d, to Stagingrelease create without --channel releases to hotcodepush.json's channel, production by default.
release-expo <app> androidrelease create. The upload runs expo export:embed itself.
release-native <app> ios app.ipa, the base releaseNothing. The build step registers every store build with its fingerprint.
-t left out, the exact store versionThe 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 KiBNothing to pass. There is no limit below 512 MB per file.
promote <app> Staging Production --label v33No flag is needed. release create --bundle <n> --channel production releases a bundle by number, which release list --channel staging shows.
patch -t, patch --buildNumberNone. 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 clearrelease revoke --all. Devices return to the embedded bundle.
revopush/revopush-github-action@v1 with accessKeyA 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:

RevoPushHotCodePush
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.json key, method, event and type of the SDK you installed.

Last updated on

On this page