Skip to main content

Migrating from CodePush

Migrating from CodePush

This guide covers moving from any CodePush-compatible client and server (community forks, hosted successors, or a self-hosted CodePush-compatible API) to self-hosted Codemagic Patch. The wire protocol and package names differ by fork; the apps / deployments / sync() mental model usually transfers. For trade-offs, see How Patch compares.

warning

The Patch SDK ships in the native binary. Plan a store release (or internal distribution build) that embeds Patch before OTA updates can run through your Patch server. You cannot swap the update client purely over the air.

Concept mapping

CodePush fork (typical)Codemagic Patch
Hosted or self-hosted CodePush-compatible serverSelf-hosted Patch stack on your domains
App access key / service tokenGitHub OAuth (dashboard) + cm_pat_… API tokens (CLI/CI)
Deployment key in native configCodemagicPatchDeploymentKey (same idea)
Staging / Production deploymentsSame channel names by default
codePush.sync() / HOC wrappersync() from @codemagic/react-native-patch
release-react (CodePush CLI)cmpatch release-react
--mandatory, rollout, target binary versionSame flags on cmpatch release-react / release patch
notifyAppReady()Called automatically by sync(); manual if not using sync()

Install modes (ON_NEXT_RESTART, IMMEDIATE, etc.) and mandatoryInstallMode map closely, see Applying updates.

1. Stand up Patch

Follow Install (or the Local quickstart to try the stack locally first). You need:

  • API URL → CodemagicPatchApiUrl
  • Download base URL → CodemagicPatchDownloadBaseUrl

Create apps and deployments to mirror your CodePush layout (one app per platform is the usual pattern):

cmpatch app create --name MyApp-iOS
cmpatch app create --name MyApp-Android
cmpatch deployment list --app MyApp-iOS --format table

Copy each deployment key into native config when you integrate the SDK.

2. Replace the client SDK

Remove your CodePush client package and native wiring (package name varies by fork):

yarn remove @code-push-next/react-native-code-push # or your fork's package
yarn add @codemagic/react-native-patch
cd ios && pod install && cd ..

Wire Patch per Native setup: bare RN (Info.plist / strings.xml + bundle selection) or Expo (config plugin + prebuild).

Replace CodePush calls in JS (example uses @code-push-next; adjust the import for your fork):

// Before (CodePush)
import codePush from "@code-push-next/react-native-code-push";
codePush.sync({ installMode: codePush.InstallMode.ON_NEXT_RESTART });

// After (Patch)
import { sync } from "@codemagic/react-native-patch";
void sync({ installMode: "ON_NEXT_RESTART" });

Remove the codePush(...)(App) HOC if you used it, call sync() from a useEffect or app entry instead. Class-component HOC hooks (codePushDownloadDidProgress, etc.) have no direct equivalent; use sync(options, onProgress) or manual control.

3. Point CI at Patch

Install and authenticate the Patch CLI:

npm install -g @codemagic/patch-cli
cmpatch config set server-url https://updates.example.com
cmpatch token create --name ci # store cm_pat_… as a CI secret

Swap your fork's release / release-react CI steps for:

cmpatch release-react \
--platform ios \
--deployment Production \
--release-notes "…" \
--yes

See CI integration.

4. Cut over

  1. Publish a native build with the Patch SDK and deployment keys embedded (Staging first).
  2. Publish an OTA release to that deployment with cmpatch release-react targeting the same binary version users install.
  3. Validate on Staging, then repeat for Production.
  4. Decommission the old CodePush server or SaaS once no active binaries still call it.

Checklist

  • Patch server running with HTTPS and GitHub OAuth configured
  • Apps and deployments created; keys copied into native config
  • CodePush package and native wiring removed; Patch SDK integrated
  • sync() (or manual API) replaces CodePush sync/HOC
  • CI secrets and release commands updated to cmpatch
  • New store/internal binary shipped; OTA tested on Staging before Production