Open thorbenprimke opened 2 years ago
Hi @thorbenprimke, thanks for raising this one - I'm glad the plugin is working otherwise!
Could I confirm what your eas build command looks like, and which directory you are running it from? Are you hoisting the dependencies for your expo app?
Thanks!
Sure.
Commend: STAGE=production eas build --profile production --platform ios --auto-submit
I run this from the folder: /Users/thorben/projects/backstage-app/packages/expo
.
The node_modules
folder is at the project root: /Users/thorben/projects/backstage-app/
I believe the answer is yes to are you hoisting the dependencies
. It is set up as workspaces in the root package.json and all dependencies are installed at the root but defined in the expo folder's package.json.
Let me know if I can provide anything else or you want to me to test a change.
Hi @thorbenprimke - Apologies for the delay on this, could you please try the following:
Install @bugsnag/source-maps
as a dev dependency to your expo application, and add the following to the package.json
(also in the expo app):
"workspaces": {
"nohoist": [
"@bugsnag/plugin-expo-eas-sourcemaps",
"@bugsnag/source-maps"
]
}
This will prevent the dependencies being hoisted, and allow the plugin to execute the necessary binaries from the node_modules.
@gingerbenw That won't work for people running modern yarn. nohoist
only works on yarn classic (1.x
versions).
Hi @evelant! Apologies for the slow response, I needed to do some homework on this one.
nohoist works when using the node modules plugin which is required when using expo with yarn 2 and above.
we're looking to automate adding this nohoist option in our CLI shortly.
@gingerbenw Unfortunately it's not that simple.
IIRC when I went though this with yarn (it is confusing!) I found out that won't do it either. I'm pretty sure nohoist
does not work with when using nodeLinker: node-modules
. There is no way to do per-package hoisting in yarn v2+.
You first have to add nodeLinker: node-modules
which turns off "plug n' play" mode to give you a node_modules folder again. Then if you add nohoist
to your package.json it will not do anything as it's only supported in yarn v1. In v2+ the only option is install config hoisting limits.
Unfortunately with installConfig: { hoistingLimits: "" }
the only options are none
(hoist everything) dependencies
(hoist everything except direct dependencies) and workspaces
(don't hoist anything inside a workspace, treat it as if it were not a workspace).
I have no idea why the yarn team decided to remove per-package hoisting control. It makes things significantly more difficult.
Personally I've moved on to https://pnpm.io as it's far more consistent, fast, configurable, and reliable. Pnpm works well with react-native if you use @rnx-kit/metro-resolver-symlinks to work around metro's 5+ years unresolved lack of symlink support 🤦
Thanks for the useful breakdown @evelant! I think I had misunderstood what was going on in my local testing as I had hoistingLimits: "workspace" set as well as using nohoist.
I wonder whether the best thing to do would be to symlink the necessary dependencies into node_modules in a similar fashion to the expo-yarn-workspaces plugin... 🤔
@gingerbenw I think the way a lot of packages and gradle scripts are doing it now is to use node to resolve the path, such as node --print require.resolve('react-native/package.json')
although that assumes node is available on $PATH. That has the benefit of (mostly, looking at you metro) resolving files in the same way all the other tools in the stack are doing it.
After some consideration we’re going to include installConfig.hoistingLimits
on our CLI and documentation to get this functional for yarn 2+ in the short term and I will include making our source map upload compatible with hoisting for consideration on our roadmap.
Just to let you know we have released the short term changes mentioned above as of v45.1.2 (for Expo 45) and v46.0.1 (for Expo 46) and updated the documentation to match https://docs.bugsnag.com/platforms/react-native/expo/manual-setup/#eas-build
This is still a problem for us. We're using PNPM in a monorepo with a managed expo app using SDK 49, I have not been able to get this to work yet
Hi @kennethlynne,
PNPM is not something we are particularly familiar with as we don't directly support it. As a suggestion have you tried modifying hoist-pattern
or public-hoist-pattern
config settings? https://pnpm.io/npmrc#hoist-pattern.
This looks to be somewhat similar to Yarn's nohoist
option to avoid node_modules
being hoisted to the top-level of the monorepo so that it can find the bugsnag-expo-xcode.sh
script.
Hey guys, I was able to make it work on the project i am working on. In order to make it work without nohoist
, I had to make a few changes:
if [[ -f "$PODS_ROOT/../.xcode.env" ]]; then
source "$PODS_ROOT/../.xcode.env"
fi
if [[ -f "$PODS_ROOT/../.xcode.env.local" ]]; then
source "$PODS_ROOT/../.xcode.env.local"
fi
SOURCE_MAP="$TMPDIR/$(md5 -qs "$CONFIGURATION_BUILD_DIR")-main.jsbundle.map" $NODE_BINARY --print "require('path').dirname(require.resolve('@app/my-package/package.json')) + '/lib/bugsnag-expo-xcode.sh'"
3. Create a `bugsnag-expo-xcode.sh` inside the package **lib** folder. This will have the same contents as `@bugsnag/plugin-expo-eas-sourcemaps/lib/bugsnag-expo-xcode.sh`, except the call to the bugsnag-source-maps to upload a react native, which instead will call to a local script
```bash
$NODE_BINARY ../lib/bugsnag-expo-node upload-react-native "${ARGS[@]}"
The node executable is attached on the build phase script
#!/usr/bin/env node
// eslint-disable-next-line @typescript-eslint/no-var-requires const { dirname, join } = require('path');
// eslint-disable-next-line @typescript-eslint/no-var-requires require(join( dirname(require.resolve('@bugsnag/source-maps/package.json')), 'dist/bin/cli.js' )).default(process.argv);
I created two PRs to address this issue under [@bugsnag/source-maps](https://github.com/bugsnag/bugsnag-source-maps/pull/87) and [@bugsnag/expo](https://github.com/bugsnag/bugsnag-expo/pull/147)
I'm using this patch based on the open PR, which stands stale.
It's a little long as prettier also did style changes automatically - though, it does the trick.
diff --git a/lib/bugsnag-expo-xcode.sh b/lib/bugsnag-expo-xcode.sh
index 3345711939266156933d19c58cf1c3082b5b3e06..af1ef16f56fe590129b8807a5831c033b68190ea 100755
--- a/lib/bugsnag-expo-xcode.sh
+++ b/lib/bugsnag-expo-xcode.sh
@@ -60,4 +60,11 @@ if [ ! -z "$ENDPOINT" ]; then
ARGS+=("$ENDPOINT")
fi
-../node_modules/.bin/bugsnag-source-maps upload-react-native "${ARGS[@]}"
+# Make sure that node binary exists
+source `$NODE_BINARY --print "require('path').dirname(require.resolve('react-native/package.json')) + '/scripts/node-binary.sh'"`
+
+# Retrieve the expo node binary
+BUGSNAG_EXPO_NODE_BINARY=$($NODE_BINARY --print "require('path').dirname(require.resolve('@bugsnag/source-maps/bin/cli.js'))")
+
+# Start upload the source maps to bugsnag
+$BUGSNAG_EXPO_NODE_BINARY upload-react-native "${ARGS[@]}"
diff --git a/src/ios.js b/src/ios.js
index 5150364c16229665014fa26d4c298558d1ef26ad..659133f8a6a8874444841cc9185956bf0df90655 100644
--- a/src/ios.js
+++ b/src/ios.js
@@ -1,54 +1,73 @@
-const {
- withInfoPlist,
- withXcodeProject
-} = require('@expo/config-plugins')
+const { withInfoPlist, withXcodeProject } = require("@expo/config-plugins");
-const buildPhaseName = 'PBXShellScriptBuildPhase'
-const buildPhaseComment = 'Bundle React Native code and images'
+const buildPhaseName = "PBXShellScriptBuildPhase";
+const buildPhaseComment = "Bundle React Native code and images";
-function withIosPlugin (config, onPremConfig) {
+function withIosPlugin(config, onPremConfig) {
// 01. Update InfoPlist with apiKey
- config = withInfoPlist(config, config => {
- const apiKey = config?.extra?.bugsnag?.apiKey
+ config = withInfoPlist(config, (config) => {
+ const apiKey = config?.extra?.bugsnag?.apiKey;
config.modResults.bugsnag = {
- apiKey: apiKey
- }
- return config
- })
+ apiKey: apiKey,
+ };
+ return config;
+ });
- config = withXcodeProject(config, config => {
- const xcodeProject = config.modResults
+ config = withXcodeProject(config, (config) => {
+ const xcodeProject = config.modResults;
// 02. Update react native bundle phase with sourcemap filepath
- const bundleReactNativePhase = xcodeProject.pbxItemByComment(buildPhaseComment, buildPhaseName)
+ const bundleReactNativePhase = xcodeProject.pbxItemByComment(
+ buildPhaseComment,
+ buildPhaseName
+ );
- const initialScript = bundleReactNativePhase.shellScript
+ const initialScript = bundleReactNativePhase.shellScript;
- const additionalExports = '"export EXTRA_PACKAGER_ARGS=\\"--sourcemap-output $TMPDIR/$(md5 -qs \\"$CONFIGURATION_BUILD_DIR\\")-main.jsbundle.map\\"\\n'
+ const additionalExports =
+ '"export EXTRA_PACKAGER_ARGS=\\"--sourcemap-output $TMPDIR/$(md5 -qs \\"$CONFIGURATION_BUILD_DIR\\")-main.jsbundle.map\\"\\n';
if (initialScript.indexOf(additionalExports) < 0) {
- const modifiedScript = additionalExports + initialScript.substr(1)
- bundleReactNativePhase.shellScript = modifiedScript
+ const modifiedScript = additionalExports + initialScript.substr(1);
+ bundleReactNativePhase.shellScript = modifiedScript;
}
// 03. Configure the new build phase
- const uploadBuildPhaseComment = 'Upload source maps to Bugsnag'
+ const uploadBuildPhaseComment = "Upload source maps to Bugsnag";
- const uploadBuildPhase = xcodeProject.pbxItemByComment(uploadBuildPhaseComment, buildPhaseName)
+ const uploadBuildPhase = xcodeProject.pbxItemByComment(
+ uploadBuildPhaseComment,
+ buildPhaseName
+ );
if (!uploadBuildPhase) {
- const shellScript = 'SOURCE_MAP="$TMPDIR/$(md5 -qs "$CONFIGURATION_BUILD_DIR")-main.jsbundle.map" ../node_modules/@bugsnag/plugin-expo-eas-sourcemaps/lib/bugsnag-expo-xcode.sh'
+ const shellScript = `
+if [[ -f "$PODS_ROOT/../.xcode.env" ]]; then
+ source "$PODS_ROOT/../.xcode.env"
+fi
+if [[ -f "$PODS_ROOT/../.xcode.env.local" ]]; then
+ source "$PODS_ROOT/../.xcode.env.local"
+fi
+
+SOURCE_MAP="$TMPDIR/$(md5 -qs "$CONFIGURATION_BUILD_DIR")-main.jsbundle.map" \`$NODE_BINARY --print "require('path').dirname(require.resolve('@bugsnag/plugin-expo-eas-sourcemaps/package.json')) + '/lib/bugsnag-expo-xcode.sh'"\`
+ `;
- xcodeProject.addBuildPhase([], buildPhaseName, uploadBuildPhaseComment, null, {
- shellPath: '/bin/sh',
- shellScript: shellScript
- })
+ xcodeProject.addBuildPhase(
+ [],
+ buildPhaseName,
+ uploadBuildPhaseComment,
+ null,
+ {
+ shellPath: "/bin/sh",
+ shellScript: shellScript,
+ }
+ );
}
- return config
- })
+ return config;
+ });
- return config
+ return config;
}
-module.exports = { withIosPlugin }
+module.exports = { withIosPlugin };
``
Describe the bug
Add the
plugin-expo-eas-sourcemaps
config plugin to an expo project in a monorepo. It does not work due to thenode_modules
path not being what is expected in the scripts.Steps to reproduce
Environment
Example code snippet - patch packages that resolves it (but not in a dynamic manner)