Skip to content

revopush release-react --privateKeyPath generates .codepushrelease locally but does not upload it with the bundle #26

@varqasim

Description

@varqasim

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-push1.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

  1. Is there an additional flag we're missing that would actually package the .codepushrelease file into the upload?
  2. If not, is this a known CLI bug? A timeline or fix version would help us plan.
  3. 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!

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions