Sentry-react-native: How can I integrate the codepush CLI with Sentry, to push new sourcemaps?

Created on 1 Jun 2017  路  14Comments  路  Source: getsentry/sentry-react-native

Hi,

I've seen this documentation: https://docs.sentry.io/clients/react-native/codepush/

I've set up this code in my app, but I'm confused about what I should be doing after I deploy a new release with CodePush. How can I get CodePush to send the new sourcemaps to Sentry?

Is there a Sentry integration for the codepush-cli, or a separate script I can run?

Most helpful comment

Thanks, I think I figured it out. For anyone else who comes across this, here's the full script you can use to build a new release version, push it to CodePush, and push the source maps to Sentry:

  rm -rf build/ios
  mkdir -p build/ios

  react-native bundle \
    --dev false \
    --platform ios \
    --entry-file index.ios.js \
    --bundle-output build/ios/main.jsbundle \
    --sourcemap-output build/ios/main.jsbundle.map \
    --assets-dest build/ios

  code-push release <codepush app> build/ios <target version> \
    --deploymentName Production

  sentry-cli react-native codepush <codepush app> ios build/ios \
    --deployment Production \
    --org <sentry org> \
    --project <sentry project>

@mitsuhiko Thanks for your help, and please let me know if I'm missing anything in there!

All 14 comments

Hi @HazAT, sorry to bother you, but I was wondering if you could give me any advice about this?

I'm getting a lot of crashes on iOS and Android, and I can't fix any of them because the source maps are not being uploaded or linked properly... Was wondering if you could let me know the proper way to push sourcemaps after releasing a new CodePush deployment? Thanks!

@ndbroadbent this command should get you started:

sentry-cli react-native codepush NameOfYourCodePushApp -p PLATFORM ./path/to/assets ./path/to/sourcemaps

You will need to generate a codepush release and also dump out bundles and sourcemaps and then provide that to sentry-cli. PLATFORM is either ios or android. And you need to run the command in the root of the project.

Hi @mitsuhiko, thanks for the tip! Would you be able to provide an example command that generates the codepush release, and then passes in the paths to the sentry-cli command? I'm not sure how to get the paths working in a script.

EDIT: Ah I found some examples for react-native bundle in the codepush cli docs.

We will put some proper docs in place, but the link you saw is basically how you do it. Just make sure to also generate sourcemaps.

Thanks, I think I figured it out. For anyone else who comes across this, here's the full script you can use to build a new release version, push it to CodePush, and push the source maps to Sentry:

  rm -rf build/ios
  mkdir -p build/ios

  react-native bundle \
    --dev false \
    --platform ios \
    --entry-file index.ios.js \
    --bundle-output build/ios/main.jsbundle \
    --sourcemap-output build/ios/main.jsbundle.map \
    --assets-dest build/ios

  code-push release <codepush app> build/ios <target version> \
    --deploymentName Production

  sentry-cli react-native codepush <codepush app> ios build/ios \
    --deployment Production \
    --org <sentry org> \
    --project <sentry project>

@mitsuhiko Thanks for your help, and please let me know if I'm missing anything in there!

Small addition to the above script. I had to add AUTH_TOKEN to the command for upload to succeed. This worked for me

sentry-cli --auth-token {AUTH_TOKEN} react-native codepush <codepush app> ios build/ios \
    --deployment Production \
    --org <sentry org> \
    --project <sentry project>

Alternatively you could put all the above options in .sentryclirc in the root of your project as mentioned here https://docs.sentry.io/learn/cli/configuration/#configuration-file

On my end, @ndbroadbent's solution works for iOS but not for Android. I'm using the same auth token for two sentry projects (myproject-ios and myproject-android), can that be a problem?

Why does it not work for android? What is the issue exactly?

Going to open this temporarily to track the change from #250

I just can't get this to work, no matter what weird combination of the commands' parameters that @ndbroadbent mentioned in his comment I use. Using sentry-cli 1.43.0 and code-push 2.1.9.

My .sentryclirc file looks like this:

defaults.url=https://sentry.io/
defaults.org=nerdybirdy
defaults.project=reimmund3-ios
auth.token=馃攽-AUTH-TOKEN-REPLACED-FOR-GITHUB
cli.executable=node_modules/@sentry/cli/bin/sentry-cli

Here's what happens:

1 - react-native bundle

Command:
react-native bundle --dev false --platform ios --entry-file index.js --bundle-output build/ios/main.jsbundle --sourcemap-output build/ios/main.jsbundle.map --assets-dest build/ios

Terminal Output:

Scanning folders for symlinks in /Users/steff/Github/reimmund/app/node_modules (22ms)
Scanning folders for symlinks in /Users/steff/Github/reimmund/app/node_modules (19ms)
Loading dependency graph, done.
bundle: start
bundle: finish
bundle: Writing bundle output to: build/ios/main.jsbundle
bundle: Writing sourcemap output to: build/ios/main.jsbundle.map
bundle: Done writing bundle output
bundle: Done writing sourcemap output
bundle: Copying 5 asset files
bundle: Done copying assets

File System:
Folder build/ios contains files main.jsbundle, main.jsbundle.map, main.jsbundle.meta and assets/ folder.

2 - code-push release

Command:
code-push release reimmund3-ios build/ios 2.0.0 --deploymentName Production

Terminal Output:

Upload progress:[==================================================] 100% 0.0s
Successfully released an update containing the "build/ios" directory to the "Production" deployment of the "reimmund3-ios" app.

3 - sentry-cli

Command:
sentry-cli --auth-token=MY-AUTH-TOKEN-REPLACED-FOR-GITHUB --log-level=debug react-native codepush reimmund3-ios ios build/ios --deployment=Production --org=nerdybirdy --project=reimmund3-ios

Terminal Output:

  INFO    2019-05-16 11:52:51.093490 +02:00 Loaded config from /Users/steff/Github/reimmund/app/.sentryclirc
  DEBUG   2019-05-16 11:52:51.094 +02:00 sentry-cli version: 1.42.0, platform: "darwin", architecture: "x86_64"
  INFO    2019-05-16 11:52:51.094021 +02:00 sentry-cli was invoked with the following command line: "/Users/steff/Github/reimmund/app/node_modules/@sentry/cli/sentry-cli" "--auth-token=MY-AUTH-TOKEN-REPLACED-FOR-GITHUB" "--log-level=debug" "react-native" "codepush" "reimmund3-ios" "ios" "build/ios" "--deployment=Production" "--org=nerdybirdy" "--project=reimmund3-ios"
> Fetching latest code-push package info
  DEBUG   2019-05-16 11:52:55.175907 +02:00 error: running update nagger
error: EOF while parsing a value at line 1 column 0
  DEBUG   2019-05-16 11:52:55.176707 +02:00 client close; no transport to shut down  (from sentry)

Does anybody have an idea what could be the issue here? This is driving me crazy. Thanks!

PS: The exact same commands for Android (with android instead of ios on all occurrences in the commands) work just fine, only iOS sh*ts the bed.

Hi there, I just edited this for you. Please never post your auth token in public places like Github, Stack Overflow or the support forum. Doing so might give others access to sensitive data in your account.

@skizzo Same problem here, did you fix it?

I think I figured it out after all. Since I struggled quite a bit in order to get this to work, here's a quite detailed explanation of how to do it. Also note that in order to make this work properly with the provided script, be sure to follow the naming conventions given in this post.

Environment

Tested and working using these versions:

Example data

For the steps in How-To, I use an app with the name 'reimmund' (and bundle ID com.nerdybirdy.reimmund3) for both iOS and Android platforms, using the organization name 'nerdybirdy' to push a CodePush deployment with the name 'Production' to the app's binary version 2.1.0.

How-To

  1. Let's assume you have Sentry (Sentry.init({..))) and CodePush already properly integrated into your React Native project. In your app's JS code, make sure to also hook up CodePush with Sentry:
import CodePush from "react-native-code-push"
import * as Sentry from "@sentry/react-native"
// ...
CodePush.checkForUpdate()
  .then((update) => {
    if (!!update) {
      Sentry.setRelease(update.appVersion + "-codepush:" + update.label) // <- this
      CodePush.sync({updateDialog: false, installMode: CodePush.InstallMode.IMMEDIATE})
    }
  })
  .catch(console.error)
// ...
  1. For the project you want to use Codepush+Sentry for, make sure to have a Sentry organization set up:

    • The organization name will be used in the next steps for the AppCenter app owner(s) as well, in my example this is the name of my company: 'nerdybirdy'.
    • Write down the Auth Token somewhere, we'll need this in the next step too (馃攽). The token can be created/shown on https://sentry.io/settings/account/api/auth-tokens/.
  2. Be sure to have valid Sentry configuration files:

    • .sentryclirc (in project root):

      defaults.url=https://sentry.io/
      defaults.org=nerdybirdy
      defaults.project=reimmund-ios
      auth.token=馃攽
      cli.executable=node_modules/@sentry/cli/bin/sentry-cli
      
      [auth]
      token=馃攽
      
    • ios/sentry.properties:

      defaults.url=https://sentry.io/
      defaults.org=nerdybirdy
      defaults.project=reimmund-ios
      auth.token=馃攽
      cli.executable=node_modules/@sentry/cli/bin/sentry-cli
      
    • android/sentry.properties:

      defaults.url=https://sentry.io/
      defaults.org=nerdybirdy
      defaults.project=reimmund-android
      auth.token=馃攽
      cli.executable=node_modules/@sentry/cli/bin/sentry-cli
      
  3. For each platform you want to deploy your app to (iOS/Android), make sure to have:

    • An existing Sentry React Native project with these properties:

      • Project Name, follows the format "<AppName>-<Platform>", e.g. reimmund-ios
    • An existing AppCenter app. Write down the following properties, we'll need these later on:

      • Owner (e.g. 'nerdybirdy')
      • App Name (e.g. 'reimmund')
      • Platform (e.g. 'ios')
      • 'Production' Deployment (created with e.g. appcenter codepush deployment add Production -a nerdybirdy/reimmund-ios)
      • 'Production' Deployment Key (can be determined with e.g. appcenter codepush deployment list --app nerdybirdy/reimmund-ios --displayKeys)
  4. Create 2 entries in your package.json's scripts section:

scripts: {
   ...
   "codepush:ios": "PLATFORM=ios node scripts/codepush-release.js",
   "codepush:android": "PLATFORM=android node scripts/codepush-release.js",
   ...
},
  1. Create a file scripts/codepush-release.js (I put all my scripts into a "scripts" folder for convenience) with the following content:
const execSync = require("child_process").execSync

const platform = process.env.PLATFORM || "none" // parameter from NPM / Terminal
const codepushOwner = "nerdybirdy"
const codepushDeployment = "Production"
const appName = "reimmund"
const bundleName = "com.nerdybirdy.reimmund3"
const binaryVersion = "2.1.0"
const sentryOrganization = "nerdybirdy"

console.log(`codepush-release.js: Releasing CodePush deployment`)

// Helper Functions
const outputCmd = (cmd) => console.log("\n===================================================\n> " + cmd)
const outputAndExecSync = (cmd) => {
  outputCmd(cmd)
  execSync(cmd, {stdio: [0, 1, 2]})
}
const getLatestCodepushLabel = ({owner, appName, platform}) => {
  let latestCodepushLabel = null
  let deploymentInfos = execSync(`appcenter codepush deployment list --app ${owner}/${appName}-${platform} --output json`)
  const deploymentInfosJSON = JSON.parse(deploymentInfos)
  deploymentInfosJSON.map((entry) => {
    // const deploymentName = entry[0]
    const labelComplete = entry[1]
    const labelCompleteFirstRow = labelComplete.split("\n")[0]
    const begin = "Label: "
    latestCodepushLabel = labelCompleteFirstRow.substr(begin.length)
  })
  return latestCodepushLabel
}

// Main
if (platform != "android" && platform != "ios") {
  console.log(`      Unknown platform '${platform}'.`)
  process.exit(1)
} else {
  const folderDist = `build/${platform}`
  const bundleFileName = platform == "ios" ? "main.jsbundle" : "index.android.bundle"

  console.log(`      platform .................. ${platform}`)
  console.log(`      codepushOwner ............. ${codepushOwner}`)
  console.log(`      codepushDeployment ........ ${codepushDeployment}`)
  console.log(`      appName ................... ${appName}`)
  console.log(`      bundleName ................ ${bundleName}`)
  console.log(`      binaryVersion ............. ${binaryVersion}`)
  console.log(`      sentryOrganization ........ ${sentryOrganization}`)
  console.log(`      -> folderDist ............. ${folderDist}`)
  console.log(`      -> bundleFileName ......... ${bundleFileName}`)

  outputAndExecSync(`mkdir -p ${folderDist}`)
  outputAndExecSync(`rm -rf ${folderDist}/*`)

  // 1. Create CodePush release
  let cmdCodepushRelease = `appcenter codepush release-react \
    --app ${codepushOwner}/${appName}-${platform} \
    --output-dir ${folderDist} \
    --bundle-name ${bundleFileName} \
    --target-binary-version ${binaryVersion} \
    --deployment-name ${codepushDeployment}`
  outputAndExecSync(cmdCodepushRelease)

  // 2. Get latest CodePush label
  const latestCodepushLabel = getLatestCodepushLabel({owner: codepushOwner, appName: appName, platform})
  console.log(`      -> latestCodepushLabel .... ${latestCodepushLabel}`)

  // 3. Upload Source Maps to Sentry using CodePush bundle and latest CodePush label
  let cmdUploadSourcemaps = `sentry-cli releases \
      --org=${sentryOrganization} \
      --project=${appName}-${platform} files ${bundleName}-${binaryVersion}-codepush:${latestCodepushLabel} upload-sourcemaps \
      --bundle=build/${platform}/CodePush/${bundleFileName} \
      --bundle-sourcemap=build/${platform}/CodePush/${bundleFileName}.map \
    `
  //  for verbose output, add: "--log-level=debug" as last line of cmdUploadSourcemaps
  outputAndExecSync(cmdUploadSourcemaps)
}

process.exit()
  1. Use npm run codepush:ios and npm run codepush:android to deploy.

Let me know in case something's wrong or unclear. Also, the app used in the example is one of my first apps I did with React Native and is available here: reimmund for iOS | reimmund for Android. Always happy about some support! 馃挴

Hi there, I just edited this for you. Please never post your auth token in public places like Github, Stack Overflow or the support forum. Doing so might give others access to sensitive data in your account.

Was this page helpful?
0 / 5 - 0 ratings