From aad5987a0317508562138a8454bb83dd22b8b18f Mon Sep 17 00:00:00 2001
From: Joe Haddad <timer150@gmail.com>
Date: Thu, 29 Jun 2017 00:45:45 -0400
Subject: [PATCH] Bootstrap with Yarn when available (#2673)

* Bootstrap with Yarn if we can

* Update test scripts

* Check OS and npm concurrency ability

* Windows support

* Update bootstrap.js

* Install yarn before bootstrap
---
 bootstrap.js             | 67 ++++++++++++++++++++++++++++++++++++++++
 lerna.json               |  2 +-
 package.json             |  4 +--
 tasks/e2e-installs.sh    |  8 ++---
 tasks/e2e-kitchensink.sh |  8 ++---
 tasks/e2e-simple.sh      | 12 +++----
 6 files changed, 84 insertions(+), 17 deletions(-)
 create mode 100644 bootstrap.js

diff --git a/bootstrap.js b/bootstrap.js
new file mode 100644
index 000000000..b54a1ed9f
--- /dev/null
+++ b/bootstrap.js
@@ -0,0 +1,67 @@
+'use strict';
+
+const { execSync, spawn } = require('child_process');
+const { resolve } = require('path');
+const { existsSync } = require('fs');
+const { platform } = require('os');
+
+function shouldUseYarn() {
+  try {
+    execSync('yarnpkg --version', { stdio: 'ignore' });
+    return true;
+  } catch (e) {
+    return false;
+  }
+}
+
+function shouldUseNpmConcurrently() {
+  try {
+    const versionString = execSync('npm --version');
+    const m = /^(\d+)[.]/.exec(versionString);
+    // NPM >= 5 support concurrent installs
+    return Number(m[1]) >= 5;
+  } catch (e) {
+    return false;
+  }
+}
+
+const yarn = shouldUseYarn();
+const windows = platform() === 'win32';
+const lerna = resolve(
+  __dirname,
+  'node_modules',
+  '.bin',
+  windows ? 'lerna.cmd' : 'lerna'
+);
+
+if (!existsSync(lerna)) {
+  if (yarn) {
+    console.log('Cannot find lerna. Please run `yarn --check-files`.');
+  } else {
+    console.log(
+      'Cannot find lerna. Please remove `node_modules` and run `npm install`.'
+    );
+  }
+  process.exit(1);
+}
+
+let child;
+if (yarn) {
+  // Yarn does not support concurrency
+  child = spawn(lerna, ['bootstrap', '--npm-client=yarn', '--concurrency=1'], {
+    stdio: 'inherit',
+  });
+} else {
+  let args = ['bootstrap'];
+  if (
+    // The Windows filesystem does not handle concurrency well
+    windows ||
+    // Only newer npm versions support concurrency
+    !shouldUseNpmConcurrently()
+  ) {
+    args.push('--concurrency=1');
+  }
+  child = spawn(lerna, args, { stdio: 'inherit' });
+}
+
+child.on('close', code => process.exit(code));
diff --git a/lerna.json b/lerna.json
index e2429777d..7ca916a85 100644
--- a/lerna.json
+++ b/lerna.json
@@ -1,5 +1,5 @@
 {
-  "lerna": "2.0.0-beta.38",
+  "lerna": "2.0.0-rc.5",
   "version": "independent",
   "changelog": {
     "repo": "facebookincubator/create-react-app",
diff --git a/package.json b/package.json
index 0cef9dc02..b9abb1ce8 100644
--- a/package.json
+++ b/package.json
@@ -6,7 +6,7 @@
     "create-react-app": "tasks/cra.sh",
     "e2e": "tasks/e2e-simple.sh",
     "e2e:docker": "tasks/local-test.sh",
-    "postinstall": "lerna bootstrap && cd packages/react-error-overlay/ && npm run build:prod",
+    "postinstall": "node bootstrap.js && cd packages/react-error-overlay/ && npm run build:prod",
     "publish": "tasks/release.sh",
     "start": "node packages/react-scripts/scripts/start.js",
     "test": "node packages/react-scripts/scripts/test.js --env=jsdom",
@@ -16,7 +16,7 @@
   "devDependencies": {
     "eslint": "3.19.0",
     "husky": "^0.13.2",
-    "lerna": "2.0.0-beta.38",
+    "lerna": "2.0.0-rc.5",
     "lerna-changelog": "^0.2.3",
     "lint-staged": "^3.3.1",
     "prettier": "^1.5.2"
diff --git a/tasks/e2e-installs.sh b/tasks/e2e-installs.sh
index 073fc8df6..588642632 100755
--- a/tasks/e2e-installs.sh
+++ b/tasks/e2e-installs.sh
@@ -80,7 +80,7 @@ then
   # AppVeyor uses an old version of yarn.
   # Once updated to 0.24.3 or above, the workaround can be removed
   # and replaced with `yarnpkg cache clean`
-  # Issues: 
+  # Issues:
   #    https://github.com/yarnpkg/yarn/issues/2591
   #    https://github.com/appveyor/ci/issues/1576
   #    https://github.com/facebookincubator/create-react-app/pull/2400
@@ -102,9 +102,9 @@ then
   npm cache clean || npm cache verify
 fi
 
-# Prevent lerna bootstrap, we only want top-level dependencies
+# Prevent bootstrap, we only want top-level dependencies
 cp package.json package.json.bak
-grep -v "lerna bootstrap" package.json > temp && mv temp package.json
+grep -v "postinstall" package.json > temp && mv temp package.json
 npm install
 mv package.json.bak package.json
 
@@ -116,7 +116,7 @@ then
 fi
 
 # We removed the postinstall, so do it manually
-./node_modules/.bin/lerna bootstrap --concurrency=1
+node bootstrap.js
 
 cd packages/react-error-overlay/
 npm run build:prod
diff --git a/tasks/e2e-kitchensink.sh b/tasks/e2e-kitchensink.sh
index 7f97fdc44..ebbac271e 100755
--- a/tasks/e2e-kitchensink.sh
+++ b/tasks/e2e-kitchensink.sh
@@ -72,7 +72,7 @@ then
   # AppVeyor uses an old version of yarn.
   # Once updated to 0.24.3 or above, the workaround can be removed
   # and replaced with `yarnpkg cache clean`
-  # Issues: 
+  # Issues:
   #    https://github.com/yarnpkg/yarn/issues/2591
   #    https://github.com/appveyor/ci/issues/1576
   #    https://github.com/facebookincubator/create-react-app/pull/2400
@@ -94,9 +94,9 @@ then
   npm cache clean || npm cache verify
 fi
 
-# Prevent lerna bootstrap, we only want top-level dependencies
+# Prevent bootstrap, we only want top-level dependencies
 cp package.json package.json.bak
-grep -v "lerna bootstrap" package.json > temp && mv temp package.json
+grep -v "postinstall" package.json > temp && mv temp package.json
 npm install
 mv package.json.bak package.json
 
@@ -108,7 +108,7 @@ then
 fi
 
 # We removed the postinstall, so do it manually
-./node_modules/.bin/lerna bootstrap --concurrency=1
+node bootstrap.js
 
 cd packages/react-error-overlay/
 npm run build:prod
diff --git a/tasks/e2e-simple.sh b/tasks/e2e-simple.sh
index cdcf4a63d..48d705eef 100755
--- a/tasks/e2e-simple.sh
+++ b/tasks/e2e-simple.sh
@@ -71,7 +71,7 @@ then
   # AppVeyor uses an old version of yarn.
   # Once updated to 0.24.3 or above, the workaround can be removed
   # and replaced with `yarnpkg cache clean`
-  # Issues: 
+  # Issues:
   #    https://github.com/yarnpkg/yarn/issues/2591
   #    https://github.com/appveyor/ci/issues/1576
   #    https://github.com/facebookincubator/create-react-app/pull/2400
@@ -93,9 +93,9 @@ then
   npm cache clean || npm cache verify
 fi
 
-# Prevent lerna bootstrap, we only want top-level dependencies
+# Prevent bootstrap, we only want top-level dependencies
 cp package.json package.json.bak
-grep -v "lerna bootstrap" package.json > temp && mv temp package.json
+grep -v "postinstall" package.json > temp && mv temp package.json
 npm install
 mv package.json.bak package.json
 
@@ -115,9 +115,6 @@ then
   [[ $err_output =~ You\ are\ running\ Node ]] && exit 0 || exit 1
 fi
 
-# We removed the postinstall, so do it manually here
-./node_modules/.bin/lerna bootstrap --concurrency=1
-
 if [ "$USE_YARN" = "yes" ]
 then
   # Install Yarn so that the test can use it to install packages.
@@ -125,6 +122,9 @@ then
   yarn cache clean
 fi
 
+# We removed the postinstall, so do it manually here
+node bootstrap.js
+
 # Lint own code
 ./node_modules/.bin/eslint --max-warnings 0 packages/babel-preset-react-app/
 ./node_modules/.bin/eslint --max-warnings 0 packages/create-react-app/
-- 
GitLab