Capture ios|android sourcemaps as deploy job artifacts#9641
Conversation
"Bundle React Native code and images" is the phase that generates the JS bundle using `node_modules/react-native/scripts/react-native-xcode.sh` Providing a SOURCEMAP_FILE env variable would make the script generate a `.map` at build time The file can then be accessed from App project root as `ios.jsbundle.map`
At the moment there's a big in react-native with SOURCEMAP_FILE and hermes enabled react/react-native#32497
d6378f2 to
eabc197
Compare
| "analyze-packages": "ANALYZE_BUNDLE=true webpack --config config/webpack/webpack.common.js --env.envFile=.env.production", | ||
| "check-metro-bundler-port": "node config/checkMetroBundlerPort.js" | ||
| "check-metro-bundler-port": "node config/checkMetroBundlerPort.js", | ||
| "symbolicate:android": "npx metro-symbolicate android/app/build/generated/sourcemaps/react/release/index.android.bundle.map", |
There was a problem hiding this comment.
Are these scripts used by react native automatically?
There was a problem hiding this comment.
Are these scripts used by react native automatically?
I'm not sure what do you mean - how would they be used automatically by react-native?
I've outlined sample usage in the "Details" section.
Something like this:
- Build pipeline runs and saves sourcemaps somewhere
- Firebase Crashlytics captures a crash
- Something uses crash report data to retrieve the source maps for the build (version)
- And runs
npm run symbolicate:{platform} < crashlytics.stactrace.txtwhere.stacktrace.txtare js stack traces from "Firebase Crashlytics"
There was a problem hiding this comment.
Awesome, thanks for the explanation. Sounds like a good plan
|
@roryabraham you mind being a full reviewer here as well? I'm a bit out of my understanding here and want to make sure I have a qualified set of second 👀 |
| VERSION: ${{ env.VERSION_CODE }} | ||
|
|
||
| - name: Archive Android sourcemaps | ||
| uses: actions/upload-artifact@v3 |
There was a problem hiding this comment.
Just noting here that even though we normally use SHAs for community actions instead of vX tags, I think it might be fine to make exceptions for GitHub-maintained actions in the actions/ org.
What do you think @AndrewGable ?
| "analyze-packages": "ANALYZE_BUNDLE=true webpack --config config/webpack/webpack.common.js --env.envFile=.env.production", | ||
| "check-metro-bundler-port": "node config/checkMetroBundlerPort.js" | ||
| "check-metro-bundler-port": "node config/checkMetroBundlerPort.js", | ||
| "symbolicate:android": "npx metro-symbolicate android/app/build/generated/sourcemaps/react/release/index.android.bundle.map", |
There was a problem hiding this comment.
Awesome, thanks for the explanation. Sounds like a good plan
|
npm has a |
|
npm has a |
The change is intentional - we added new scripts to |
johnmlee101
left a comment
There was a problem hiding this comment.
AFAICT it looks good on my end, will wait for the final comments/review
|
So I got an Android production build working and see the sourcemap being generated. So that's good 👍 However, using the following stacktrace copy/pasted from Firebase Crashlytics: Then running |
I had the same error, I've updated the description with
The line |
|
Cool, that worked 👍 My only other critique is that when we execute this via npm script i.e: We can workaround that by just adding the Just two things to take note of that we'll need to workaround in the next phase where we hook up decoded stacktraces with the PHP <-> Firebase integration (cc @AndrewGable): |
|
Triggered auto assignment to @PauloGasparSv ( |
|
@roryabraham looks like this was merged without passing tests. Please add a note explaining why this was done and remove the |
|
Not an emergency, tests were passing |
|
✋ This PR was not deployed to staging yet because QA is ongoing. It will be automatically deployed to staging after the next production release. |
|
@roryabraham |
|
🚀 Deployed to production by @luacmartins in version: 1.1.85-8 🚀
|


Details
Capture sourcemap files as deploy step artifacts
The artifacts can then be used in another job/workflow to decode Firebase Crashlytics stacktraces
Sample workflow
npm run symbolicate:{platform} < crashlytics.stactrace.txtto decode the stack tracesThe symbolicate command should be able to replace just the stack trace content of a text containing stack traces leaving the rest of the text intact
Storing and sharing artifacts between workflows: https://docs.github.com/en/actions/using-workflows/storing-workflow-data-as-artifacts
Fixed Issues
$ #9293
Tests
Requirements to be able to test:
Test Steps
Verify production builds are producing source map files:
npx react-native run-ios --configuration Release --device "Your Device Name"main.jsbundle.mapshould be available inside the project root -Expensify/App/main.jsbundle.mapnpx react-native run-android --variant=releaseandroid/app/build/generated/sourcemaps/react/release/index.android.bundle.mapshould be availableUse the generated source maps to symbolicate (decode) the stack traces
symbolicate:{platform}commands{platform}.stacktrace.txtfilenode_modules/react-native-onyx/lib/Onyx.jsNotes on stack traces format
Decoding would fail or be incorrect if the stack traces format does not match
The format should be
{anyText}:{lineNumber}:{colNumber}anyTextis preserved whilelineNumber:colNumberare replaced with original file and original line:columnLine numbers should start from
1(not 0)More details and examples of valid/invalid and decoded stack traces can be seen here: #9293 (comment)
Example
Minified stack trace content
Steps
android.stacktrace.txtnpm run symbolicate:android < android.stacktrace.txt > android.decoded.stacktrace.txtstack trace is decoded to
PR Review Checklist
Contributor (PR Author) Checklist
### Fixed Issuessection aboveTestssectionQA stepssectiontoggleReportand notonIconClick)src/languages/*filesSTYLE.md) were followedAvatar, I verified the components usingAvatarare working as expected)/** comment above it */displayNamepropertythisproperly so there are no scoping issues (i.e. foronClick={this.submit}the methodthis.submitshould be bound tothisin the constructor)thisare necessary to be bound (i.e. avoidthis.submit = this.submit.bind(this);ifthis.submitis never passed to a component event handler likeonClick)StyleUtils.getBackgroundAndBorderStyle(themeColors.componentBG)Avataris modified, I verified thatAvataris working as expected in all cases)PR Reviewer Checklist
### Fixed Issuessection aboveTestssectionQA stepssectiontoggleReportand notonIconClick).src/languages/*filesSTYLE.md) were followed/** comment above it */displayNamepropertythisproperly so there are no scoping issues (i.e. foronClick={this.submit}the methodthis.submitshould be bound tothisin the constructor)thisare necessary to be bound (i.e. avoidthis.submit = this.submit.bind(this);ifthis.submitis never passed to a component event handler likeonClick)StyleUtils.getBackgroundAndBorderStyle(themeColors.componentBG)Avataris modified, I verified thatAvataris working as expected in all cases)QA Steps
After this is deployed, verify that you can download the sourcemap artifacts for the
platformDeploy.ymlworkflow run in which this was deployed.No code changes
Minimal changes to ios build process - the app should still build and launch as before
Screenshots
Web
n/a
Mobile Web
n/a
Desktop
n/a
iOS
Android