Bug 1509387 - When setting up ESLint, call npm via node so that node doesn't need to be in the path. r=ahal
☠☠ backed out by 02c470cc3f8d ☠ ☠
authorMark Banner <standard8@mozilla.com>
Mon, 26 Nov 2018 20:49:00 +0000
changeset 507428 f851c3e82c2bad0afd8a2460245c9054c908e79f
parent 507427 cb9dec83210d452c015b5608a3ea76c72ebbe777
child 507429 9f44e47ef7b33c059d076f81bac45dd7e528ce15
push id1905
push userffxbld-merge
push dateMon, 21 Jan 2019 12:33:13 +0000
treeherdermozilla-release@c2fca1944d8c [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersahal
bugs1509387
milestone65.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1509387 - When setting up ESLint, call npm via node so that node doesn't need to be in the path. r=ahal Differential Revision: https://phabricator.services.mozilla.com/D12742
python/mozbuild/mozbuild/nodeutil.py
tools/lint/eslint/setup_helper.py
--- a/python/mozbuild/mozbuild/nodeutil.py
+++ b/python/mozbuild/mozbuild/nodeutil.py
@@ -42,22 +42,32 @@ def find_node_paths():
             os.path.join(os.environ.get("ProgramFiles"), "nodejs"),
             os.path.join(os.environ.get("PROGRAMW6432"), "nodejs"),
             os.path.join(os.environ.get("PROGRAMFILES"), "nodejs")
         ]
 
     return paths
 
 
-def check_executable_version(exe):
+def check_executable_version(exe, wrap_call_with_node=True):
     """Determine the version of a Node executable by invoking it.
 
     May raise ``subprocess.CalledProcessError`` or ``ValueError`` on failure.
     """
-    out = subprocess.check_output([exe, "--version"]).lstrip('v').rstrip()
+    out = None
+    # npm may be a script, so we must call it with node.
+    if wrap_call_with_node:
+        binary, _ = find_node_executable()
+        if binary:
+            out = subprocess.check_output([binary, exe, "--version"]).lstrip('v').rstrip()
+
+    # If we can't find node, or we don't need to wrap it, fallback to calling
+    # direct.
+    if not out:
+        out = subprocess.check_output([exe, "--version"]).lstrip('v').rstrip()
     return StrictVersion(out)
 
 
 def simple_which(filename, path=None):
     # Note: On windows, npm uses ".cmd"
     exts = [".cmd", ".exe", ""] if platform.system() == "Windows" else [""]
 
     for ext in exts:
@@ -97,20 +107,20 @@ def find_node_executable(nodejs_exe=os.e
 
 def find_npm_executable(min_version=NPM_MIN_VERSION):
     """Find a Node executable from the mozbuild directory.
 
     Returns a tuple containing the the path to an executable binary and a
     version tuple. Both tuple entries will be None if a Node executable
     could not be resolved.
     """
-    return find_executable(["npm"], min_version)
+    return find_executable(["npm"], min_version, True)
 
 
-def find_executable(names, min_version):
+def find_executable(names, min_version, use_node_for_version_check=False):
     paths = find_node_paths()
 
     found_exe = None
     for name in names:
         try:
             exe = simple_which(name, paths)
         except which.WhichError:
             continue
@@ -119,16 +129,16 @@ def find_executable(names, min_version):
             continue
 
         if not found_exe:
             found_exe = exe
 
         # We always verify we can invoke the executable and its version is
         # sane.
         try:
-            version = check_executable_version(exe)
+            version = check_executable_version(exe, use_node_for_version_check)
         except (subprocess.CalledProcessError, ValueError):
             continue
 
         if version >= min_version:
             return exe, version.version
 
     return found_exe, None
--- a/tools/lint/eslint/setup_helper.py
+++ b/tools/lint/eslint/setup_helper.py
@@ -87,30 +87,34 @@ def eslint_setup(should_clobber=False):
             process.wait()
         else:
             mozfileremove(node_modules_path)
 
     npm_path, version = find_npm_executable()
     if not npm_path:
         return 1
 
+    node_path, _ = find_node_executable()
+    if not node_path:
+        return 1
+
     extra_parameters = ["--loglevel=error"]
 
     package_lock_json_path = os.path.join(get_project_root(), "package-lock.json")
     package_lock_json_tmp_path = os.path.join(tempfile.gettempdir(), "package-lock.json.tmp")
 
     # If we have an npm version newer than 5.8.0, just use 'ci', as that's much
     # simpler and does exactly what we want.
     npm_is_older_version = version < StrictVersion("5.8.0").version
 
     if npm_is_older_version:
-        cmd = [npm_path, "install"]
+        cmd = [node_path, npm_path, "install"]
         shutil.copy2(package_lock_json_path, package_lock_json_tmp_path)
     else:
-        cmd = [npm_path, "ci"]
+        cmd = [node_path, npm_path, "ci"]
 
     cmd.extend(extra_parameters)
     print("Installing eslint for mach using \"%s\"..." % (" ".join(cmd)))
     result = call_process("eslint", cmd)
 
     if npm_is_older_version:
         shutil.move(package_lock_json_tmp_path, package_lock_json_path)