Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Postinstall script fails when just command line tools are installed #897

Closed
rye opened this issue Aug 21, 2018 · 9 comments
Closed

Postinstall script fails when just command line tools are installed #897

rye opened this issue Aug 21, 2018 · 9 comments

Comments

@rye
Copy link
Contributor

rye commented Aug 21, 2018

Description

When I install detox on macOS with just the XCode command line tools installed, detox's postinstall script fails with the following output:

⑆ npm i -g detox
/usr/local/bin/detox -> /usr/local/lib/node_modules/detox/local-cli/detox.js

> dtrace-provider@0.8.7 install /usr/local/lib/node_modules/detox/node_modules/dtrace-provider
> node-gyp rebuild || node suppress-error.js

  ACTION binding_gyp_ndtp_target_build_ndtp .
  TOUCH Release/obj.target/ndtp.stamp

> detox@8.1.6 postinstall /usr/local/lib/node_modules/detox
> node scripts/postinstall.js

+++ dirname /usr/local/lib/node_modules/detox/scripts/build_framework.ios.sh
++ dirname /usr/local/lib/node_modules/detox/scripts
+ detoxRootPath=/usr/local/lib/node_modules/detox
++ node -p 'require('\''/usr/local/lib/node_modules/detox/package.json'\'').version'
+ detoxVersion=8.1.6
++ echo 8.1.6
++ xcodebuild -version
++ shasum
++ awk '{print $1}'
xcode-select: error: tool 'xcodebuild' requires Xcode, but active developer directory '/Library/Developer/CommandLineTools' is a command line tools instance
+ sha1=aba5c8f25bf328b40be1e29d2d653101f6ecc89d
+ detoxFrameworkDirPath=/Users/kristofer/Library/Detox/ios/aba5c8f25bf328b40be1e29d2d653101f6ecc89d
+ detoxFrameworkPath=/Users/kristofer/Library/Detox/ios/aba5c8f25bf328b40be1e29d2d653101f6ecc89d/Detox.framework
+ main
+ '[' -d /Users/kristofer/Library/Detox/ios/aba5c8f25bf328b40be1e29d2d653101f6ecc89d ']'
+ '[' '!' -d /Users/kristofer/Library/Detox/ios/aba5c8f25bf328b40be1e29d2d653101f6ecc89d/Detox.framework ']'
+ echo '/Users/kristofer/Library/Detox/ios/aba5c8f25bf328b40be1e29d2d653101f6ecc89d was found, but could not find Detox.framework inside it. This means that the Detox framework build process was interrupted.
         deleting /Users/kristofer/Library/Detox/ios/aba5c8f25bf328b40be1e29d2d653101f6ecc89d and trying to rebuild.'
/Users/kristofer/Library/Detox/ios/aba5c8f25bf328b40be1e29d2d653101f6ecc89d was found, but could not find Detox.framework inside it. This means that the Detox framework build process was interrupted.
         deleting /Users/kristofer/Library/Detox/ios/aba5c8f25bf328b40be1e29d2d653101f6ecc89d and trying to rebuild.
+ rm -rf /Users/kristofer/Library/Detox/ios/aba5c8f25bf328b40be1e29d2d653101f6ecc89d
+ prepareAndBuildFramework
+ '[' -d /usr/local/lib/node_modules/detox/ios ']'
+ detoxSourcePath=/usr/local/lib/node_modules/detox/ios_src
+ extractSources /usr/local/lib/node_modules/detox/ios_src
+ detoxSourcePath=/usr/local/lib/node_modules/detox/ios_src
+ echo 'Extracting Detox sources...'
Extracting Detox sources...
+ mkdir -p /usr/local/lib/node_modules/detox/ios_src
+ tar -xjf /usr/local/lib/node_modules/detox/Detox-ios-src.tbz -C /usr/local/lib/node_modules/detox/ios_src
+ buildFramework /usr/local/lib/node_modules/detox/ios_src
+ detoxSourcePath=/usr/local/lib/node_modules/detox/ios_src
+ echo 'Building Detox.framework from /usr/local/lib/node_modules/detox/ios_src...'
Building Detox.framework from /usr/local/lib/node_modules/detox/ios_src...
+ mkdir -p /Users/kristofer/Library/Detox/ios/aba5c8f25bf328b40be1e29d2d653101f6ecc89d
+ /usr/local/lib/node_modules/detox/scripts/build_universal_framework.sh /usr/local/lib/node_modules/detox/ios_src/Detox.xcodeproj /Users/kristofer/Library/Detox/ios/aba5c8f25bf328b40be1e29d2d653101f6ecc89d/DetoxBuild
child_process.js:621
    throw err;
    ^

Error: Command failed: /usr/local/lib/node_modules/detox/scripts/build_framework.ios.sh
    at checkExecSyncError (child_process.js:600:11)
    at Object.execFileSync (child_process.js:618:13)
    at Object.<anonymous> (/usr/local/lib/node_modules/detox/scripts/postinstall.js:2:27)
    at Module._compile (internal/modules/cjs/loader.js:689:30)
    at Object.Module._extensions..js (internal/modules/cjs/loader.js:700:10)
    at Module.load (internal/modules/cjs/loader.js:599:32)
    at tryModuleLoad (internal/modules/cjs/loader.js:538:12)
    at Function.Module._load (internal/modules/cjs/loader.js:530:3)
    at Function.Module.runMain (internal/modules/cjs/loader.js:742:12)
    at startup (internal/bootstrap/node.js:266:19)
npm ERR! code ELIFECYCLE
npm ERR! errno 1
npm ERR! detox@8.1.6 postinstall: `node scripts/postinstall.js`
npm ERR! Exit status 1
npm ERR!
npm ERR! Failed at the detox@8.1.6 postinstall script.
npm ERR! This is probably not a problem with npm. There is likely additional logging output above.

npm ERR! A complete log of this run can be found in:
npm ERR!     /Users/kristofer/.npm/_logs/2018-08-21T13_15_54_710Z-debug.log

The behavior I would expect here is an error message to indicate to me that Detox will be practically useless in my environment, not a failed postinstall. I believe that this error message is just because this condition is not checked for. Because the subprocess (xcodebuild -version) exits with status 1, this unhandled exception propagates out and results in a postinstall script failure.

Note that Line 6 of detox/scripts/build_framework.ios.sh, https://github.com/wix/detox/blob/234d611d565e4d9a75027fb57835727435f4c4e4/detox/scripts/build_framework.ios.sh#L6 does not capture the output of xcodebuild -version or handle this case; instead, it SHAsums partial output from a process which exited with code 1. In this case, xcodebuild -version outputs its error message to stderr, which is not caught by this pipe. (I would recommend using 2>&1 before the pipe to accomplish this, if that is desired.)

My idea for a "fix" for this behavior would be to check and see if xcodebuild exited with code 1, or also to redirect stderr to stdout for the purposes of guaranteeing that it makes it to the pipe which then gets sent to shasum.

Steps to Reproduce

  1. Install macOS.
  2. Enable/Install the XCode command line utils, but do not install XCode.
  3. Verify that xcodebuild -version produces an error message that XCode is not installed, and exits with code 1.
  4. Install the latest node via Homebrew.
  5. Attempt to install detox via npm i -g detox and observe the ELIFECYCLE from npm.

Detox, Node, Device, Xcode and macOS Versions

  • Detox: 8.1.6
  • React Native: 0.56.0
  • Node: 10.9.0
  • Device: MacBook Pro (Retina, 13-inch, Early 2015), 2.7 GHz Intel Core i5, 8 GB 1867 MHz DDR3
  • Xcode: [Xcode not installed]
  • macOS: 10.13.6

Device and verbose Detox logs

Not applicable.

See also StoDevX/AAO-React-Native#2842, which is my downstream tracking issue for this one.

@LeoNatan
Copy link
Contributor

Xcode is required. Detox is built on the client machine, and the iOS SDK must be present on the machine (it comes with Xcode). Indeed, it should fail postinstall as Xcode is a hard requirement.

@LeoNatan
Copy link
Contributor

Prerequisites in the getting started documentation clearly states that Xcode is required. I’m not sure what the problem is here.

@rye
Copy link
Contributor Author

rye commented Aug 21, 2018

I understand that, but my implied point was that I'd rather not have to mark detox as an optionalDependency in order to have successful package installations in my environment.

The postinstall script exits with code 1, indicating an internal error with the postinstall script, not something missing on the platform. The question in my mind is not whether Xcode should be required, (because it should be, and I'm fine with not having functionality if I don't have it) but rather whether the postinstall script should be a noop if XCode is not installed. I would argue that the postinstall script should always exit with status code 0 unless something actually went wrong.

@LeoNatan LeoNatan reopened this Aug 21, 2018
@LeoNatan
Copy link
Contributor

We’ll discuss internally. What would the expected behavior be if a user attempts to test an iOS configuration?

@rye
Copy link
Contributor Author

rye commented Aug 21, 2018

Sounds good—thanks for the reconsideration. I'd say either doing nothing, or printing an error message and doing nothing, would be behaviors I'd expect in this case. Like I say, I wouldn't expect anything to work without XCode installed.

@LeoNatan
Copy link
Contributor

@rye What does the xcode-select --print-path command print for you?

@LeoNatan
Copy link
Contributor

Fixed.
So you know, I have taken it personally that you are not willing to install Xcode, but still, what we don't do for the community. 😜

@rye
Copy link
Contributor Author

rye commented Aug 22, 2018

@LeoNatan thanks for the fix! I realize it's a bit strange for someone who does RN work to not want to install Xcode but still.

For reference,

$ xcode-select --print-path
/Library/Developer/CommandLineTools

Note that return will not work in this case (and the script thus still "fails"); better to use exit 0:

[snip]

> detox@8.2.1 postinstall /usr/local/lib/node_modules/detox
> node scripts/postinstall.js

+ xcodebuild -version
+ echo 'WARNING: Xcode is not installed on this machine. Skipping iOS framework build phase'
WARNING: Xcode is not installed on this machine. Skipping iOS framework build phase
+ return 0
/usr/local/lib/node_modules/detox/scripts/build_framework.ios.sh: line 4: return: can only `return' from a function or sourced script
child_process.js:621
    throw err;
    ^

Error: Command failed: /usr/local/lib/node_modules/detox/scripts/build_framework.ios.sh
    at checkExecSyncError (child_process.js:600:11)
    at Object.execFileSync (child_process.js:618:13)
    at Object.<anonymous> (/usr/local/lib/node_modules/detox/scripts/postinstall.js:2:27)
    at Module._compile (internal/modules/cjs/loader.js:689:30)
    at Object.Module._extensions..js (internal/modules/cjs/loader.js:700:10)
    at Module.load (internal/modules/cjs/loader.js:599:32)
    at tryModuleLoad (internal/modules/cjs/loader.js:538:12)
    at Function.Module._load (internal/modules/cjs/loader.js:530:3)
    at Function.Module.runMain (internal/modules/cjs/loader.js:742:12)
    at startup (internal/bootstrap/node.js:266:19)

[snip]

@LeoNatan
Copy link
Contributor

🤦‍♂️
Thanks

@lock lock bot locked as resolved and limited conversation to collaborators Aug 25, 2018
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants