Hi RevoPush team,
We've set up CodePush bundle signing on our React Native app per the official Code Signing docs and have a reproducible case where the CLI claims to sign the release but the resulting bundle on the server has no signature file inside it. Devices with CodePushPublicKey configured then correctly reject the unsigned update.
Versions
@revopush/code-push-cli — latest, installed via npm install -g @revopush/code-push-cli on a clean macOS environment (also reproduced on Codemagic CI).
@revopush/react-native-code-push — 1.5.0.
- React Native —
0.82.1.
- Hermes enabled.
Setup
Standard, exactly as documented:
openssl genrsa -out private.pem 2048
openssl rsa -pubout -in private.pem -out public.pem
iOS Info.plist is populated at native build time with CodePushPublicKey containing the PEM contents (including -----BEGIN PUBLIC KEY----- / -----END PUBLIC KEY----- markers).
Reproduction
A throwaway deployment to isolate from the production / staging channels:
revopush deployment add myapp-ios SigningTest
revopush release-react myapp-ios ios \
--deploymentName SigningTest \
--outputDir ./build \
--sourcemapOutput ./sourcemap \
--description "Local signing test" \
--noDuplicateReleaseError \
--extra-hermes-flag="--emit-debug-info" \
--extraBundlerOption=--reset-cache \
--privateKeyPath /path/to/private.pem
CLI output
The relevant lines:
Signing the bundle:
Generated a release signature and wrote it to build/.codepushrelease
Releasing update contents to CodePush:
Release file path: ./build
Metadata: {"description":"Local signing test","isDisabled":false,"isMandatory":false,"isInitial":false,"bundleName":"main.jsbundle","outputDir":"./build","rollout":100,"appVersion":"1.0.0"}
Successfully released an update containing the "./build" directory to the "SigningTest" deployment of the "myapp-ios" app.
The CLI confirms it generated a signature, says it's uploading the ./build directory (which contains both main.jsbundle and .codepushrelease), and reports success.
What we observed instead
Pulled the resulting bundle URL from the deployment-history JSON and downloaded it:
revopush deployment history myapp-ios SigningTest --format json | jq '.[0].bundleBlobUrl'
# returned a https://blob.revopush.org/... URL
curl -sL '<bundleBlobUrl>' -o /tmp/signed.zip
unzip -l /tmp/signed.zip
Result:
Archive: /tmp/signed.zip
Length Date Time Name
--------- ---------- ----- ----
7486992 YYYY-MM-DD HH:MM build/main.jsbundle
--------- -------
7486992 1 file
The .codepushrelease signature file is not in the uploaded bundle. Locally on the machine running the CLI, ls -la ./build/.codepushrelease confirms the file did get created — so it's being filtered out (likely by dotfile globbing) before upload.
The deployment-history JSON record also has no signature-related field: bundleBlobUrl, manifestBlobUrl, assetBlobUrl are present, but no signatureBlobUrl or equivalent.
Device-side symptom
Devices with CodePushPublicKey populated in Info.plist correctly refuse to install the bundle:
Error! Public key was provided but there is no JWT signature within app bundle to verify.
Possible reasons, why that might happen:
1. You've been released CodePush bundle update using version of CodePush CLI that is not support code signing.
2. You've been released CodePush bundle update without providing --privateKeyPath option.
The error is correct — there genuinely is no signature in the bundle. But option (2) doesn't apply: we did pass --privateKeyPath, and the CLI's Signing the bundle: output proves it was honored locally. The signature simply doesn't make it to the server.
Binary verification
To rule out misconfiguration on the client side, we extracted the produced .ipa and verified:
Info.plist CodePushPublicKey is present, 451 bytes, well-formed PEM with intact BEGIN/END markers.
- SHA-256 of the binary's
CodePushPublicKey matches the SHA-256 of openssl rsa -pubout derived from the private key passed to revopush release-react. Byte-for-byte identical.
CodePushDeploymentKey in Info.plist is set to the correct deployment key shown in the RevoPush dashboard for this app/deployment.
CodePushServerURL is https://api.revopush.org.
So the binary is configured correctly and the rejection is entirely a function of the server-side bundle missing its signature.
Our workaround
We've temporarily emptied CodePushPublicKey in the binary so the channel is functional. We'd like to re-enable signing once this is fixed.
What we'd like to know
- Is there an additional flag we're missing that would actually package the
.codepushrelease file into the upload?
- If not, is this a known CLI bug? A timeline or fix version would help us plan.
- As a sanity check on your side — could you verify whether the bundle blob URL we got from the SigningTest deployment contains
.codepushrelease? It's possible the file is uploaded as a sibling blob and the CLI just isn't returning that URL in the history JSON.
Happy to share the exact deployment / bundle URLs privately if useful — we kept them out of this public-facing description.
Thanks!
Hi RevoPush team,
We've set up CodePush bundle signing on our React Native app per the official Code Signing docs and have a reproducible case where the CLI claims to sign the release but the resulting bundle on the server has no signature file inside it. Devices with
CodePushPublicKeyconfigured then correctly reject the unsigned update.Versions
@revopush/code-push-cli— latest, installed vianpm install -g @revopush/code-push-clion a clean macOS environment (also reproduced on Codemagic CI).@revopush/react-native-code-push—1.5.0.0.82.1.Setup
Standard, exactly as documented:
iOS
Info.plistis populated at native build time withCodePushPublicKeycontaining the PEM contents (including-----BEGIN PUBLIC KEY-----/-----END PUBLIC KEY-----markers).Reproduction
A throwaway deployment to isolate from the production / staging channels:
CLI output
The relevant lines:
The CLI confirms it generated a signature, says it's uploading the
./builddirectory (which contains bothmain.jsbundleand.codepushrelease), and reports success.What we observed instead
Pulled the resulting bundle URL from the deployment-history JSON and downloaded it:
Result:
The
.codepushreleasesignature file is not in the uploaded bundle. Locally on the machine running the CLI,ls -la ./build/.codepushreleaseconfirms the file did get created — so it's being filtered out (likely by dotfile globbing) before upload.The deployment-history JSON record also has no signature-related field:
bundleBlobUrl,manifestBlobUrl,assetBlobUrlare present, but nosignatureBlobUrlor equivalent.Device-side symptom
Devices with
CodePushPublicKeypopulated inInfo.plistcorrectly refuse to install the bundle:The error is correct — there genuinely is no signature in the bundle. But option (2) doesn't apply: we did pass
--privateKeyPath, and the CLI'sSigning the bundle:output proves it was honored locally. The signature simply doesn't make it to the server.Binary verification
To rule out misconfiguration on the client side, we extracted the produced
.ipaand verified:Info.plistCodePushPublicKeyis present, 451 bytes, well-formed PEM with intact BEGIN/END markers.CodePushPublicKeymatches the SHA-256 ofopenssl rsa -puboutderived from the private key passed torevopush release-react. Byte-for-byte identical.CodePushDeploymentKeyinInfo.plistis set to the correct deployment key shown in the RevoPush dashboard for this app/deployment.CodePushServerURLishttps://api.revopush.org.So the binary is configured correctly and the rejection is entirely a function of the server-side bundle missing its signature.
Our workaround
We've temporarily emptied
CodePushPublicKeyin the binary so the channel is functional. We'd like to re-enable signing once this is fixed.What we'd like to know
.codepushreleasefile into the upload?.codepushrelease? It's possible the file is uploaded as a sibling blob and the CLI just isn't returning that URL in the history JSON.Happy to share the exact deployment / bundle URLs privately if useful — we kept them out of this public-facing description.
Thanks!