Managing Sentry releases for React Native CodePush updates that use semantic version


#1

My team are using CodePush to release React Native JS bundles for an app, and are now integrating with Sentry for crash/error reports.

We have a CI pipeline set up following the documentation (https://docs.sentry.io/clients/react-native/codepush/):

  1. CodePush release with output directory
  2. Sentry upload using the CodePush output

This generates a release in Sentry with a name like 2.1.3-codepush:v123.
In our app, we are setting the Sentry version as follows:

    CodePush.getUpdateMetadata(CodePush.UpdateState.RUNNING).then((update) => {
        if (update) {
            Sentry.setVersion(update.appVersion + '-codepush:' + update.label);
        }
    });

This will set the version to 2.1.3-codepush:v123 and sourcemaps etc will work in Sentry.

However, we are actually releasing our CodePush updates using semantic versioning, so the CodePush update with label v123 has a target binary version of e.g. ^2.1.0. This makes me think something like this could happen:

  • We have native app version 2.1.3 out, and have CodePushed v123 with target ^2.1.0
  • Sentry has a release 2.1.3-codepush:v123
  • We release app version 2.1.4, and CodePush v124 with target ^2.1.0
  • Sentry has a release 2.1.4-codepush:v124
  • User with 2.1.3 decides not to update the app, but are automatically updated to CodePush v124
  • User Sentry version is then set to 2.1.3-codepush:v124, which doesn’t exist as a release in Sentry
  • User crashes, no sourcemaps are available

I’m thinking of several ways to move forward:

  1. Not use semantic versioning.
  2. Use the semver target in both the Sentry version and the release: <target-release>-codepush:v123, e.g. ^2.1.0-codepush:v124 both in the upload and the setVersion() call
  3. Upload the appropriate releases to Sentry, 2.1.0-codepush:v124, 2.1.1-codepush:v124, 2.1.2-codepush:v124 and so on (perhaps do this only when we actually do a native release)
  4. Remove the app version from the Sentry release, e.g. codepush:v124
  5. This isn’t a problem, Sentry automatically handles this for CodePush (?)

Does anyone have experience of combining semantic versioning for CodePush updates and Sentry?


#2

Hey laserval,

First of all, thank you for your really detailed post :100:

The behavior you describe is indeed a problem we did not think of yet.
I am leaning towards solution 4 you proposed but I will discuss it internally and come up with a PR for it.
Stay tuned!

Daniel


#3

Great, thanks!

We are actually trying out solution 4 right now, and realised another potential issue:

We are using two deployments in CodePush: Staging and Production (the default ones). When we release, we first do a codepush release to Staging, and then promote that release to Production. Right now we are uploading to Sentry for both Staging and Production (in separate CI steps, storing the bundle generated for Staging and reusing it for Production).

Sentry will correctly set the label for the release when we specify the deployment, but the release will be named with just the label. So for Staging we get <app-version>-codepush:v123, but for Production we might get <app-version>-codepush:v12. If the Production label catches up with Staging we will have a problem. Before that happens, it is also confusing.

We were discussing adding the deployment to the Sentry release, but aren’t sure if that can be injected when using sentry-cli. Another, more temporary solution is to only upload for Production (since that’s where Sentry really shines for us).


#4

OK, so we briefly discussed it internally.

We will not have a perfect solution for this quickly.
I will explain what we probably gonna do (which still needs a lot of further discussions).

But first, the only workaround currently is to call
Sentry.setRelease('uniqueID')
and set a release identifier from javascript for your crashes.

Since we do not rely on release/dist matching for native crashes (iOS/Android) we only need to do this for javascript crashes.
This also implies that you have to change your build process and upload the sourcemaps of your codepush release with the same uniqueID and manually set it with sentry-cli.

This should fix the app version <-> codepush version mismatching, because the crash is only identified by the uniqueID from javascript.

The problem about all of this is that we currently only match the sourcemap to javascript crashes via the release/dist.
We basically have to make a similar system like on iOS where it doesn’t matter in which release the crash happened, we can match it via a UUID.

So bad news in a way but still, let me know if you need further help.


#5

Could you explain how to do that ? I can’t see any option to set a custom uniqueID when using sentry-cli react-native codepush ....


#6

I’m now struggling with this too.

Does sentry-cli react-native appcenter bind you into the documented way of using CodePush with version/release conventions? As above this doesn’t work, so also looking for a way to control release and version myself when codepush assets are uploaded. As per last comment there doesn’t seem to be a way to control the release/version/dist.

UPDATE: I discovered version and release are the same thing. Sentry.setVersion prefixes the version you define with the app package id. Sentry.setRelease just sets an explicit version. This is important to get Sentry using the same version scheme as defined when you upload artifacts for React Native.

I was able to set the desired version scheme for the artifacts by using sentry-cli releases files "{APP_PACKAGE_NAME}-${APP_VERSION_NAME}" upload-sourcemaps. This way I can build the bundles with AppCenter cli and then use this during build to embed in the app, as well as upload to Sentry. I don’t find the Sentry CodePush implementation useful, as we built artifacts only once, and when it’s promoted to production the label changes.