Bug 1476467 - Make eslint setup use package-lock.json again and use a different method for preventing accidental changes to package-lock.json. r=ahal
authorMark Banner <standard8@mozilla.com>
Thu, 09 Aug 2018 17:22:48 +0000
changeset 485896 24337f8b8499282522e84083e4fdb821005fc340
parent 485895 f90c0cecba1973e07e5bed1d8c9faf5a48a66b16
child 485897 d7e4ce95a34e6ab71d95a1ebbc0b66e15e80faa5
push id9719
push userffxbld-merge
push dateFri, 24 Aug 2018 17:49:46 +0000
treeherdermozilla-beta@719ec98fba77 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersahal
bugs1476467
milestone63.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 1476467 - Make eslint setup use package-lock.json again and use a different method for preventing accidental changes to package-lock.json. r=ahal For npm >= 5.8.0, we use 'npm ci' which automatically only uses package-lock.json and doesn't update it. For npm < 5.8.0, we use the existing 'npm install' and take a copy of package-lock.json and replace it afterwards. MozReview-Commit-ID: EO3GdVYYNDP Differential Revision: https://phabricator.services.mozilla.com/D2829
tools/lint/eslint/setup_helper.py
--- a/tools/lint/eslint/setup_helper.py
+++ b/tools/lint/eslint/setup_helper.py
@@ -7,16 +7,18 @@
 from filecmp import dircmp
 import json
 import os
 import platform
 import re
 from mozfile.mozfile import remove as mozfileremove
 import subprocess
 import sys
+import shutil
+import tempfile
 from distutils.version import LooseVersion
 sys.path.append(os.path.join(
     os.path.dirname(__file__), "..", "..", "..", "third_party", "python", "which"))
 import which
 
 NODE_MIN_VERSION = "8.9.1"
 NPM_MIN_VERSION = "5.5.1"
 
@@ -81,29 +83,43 @@ def eslint_setup(should_clobber=False):
         node_modules_path = os.path.join(project_root, "node_modules")
         print("Clobbering node_modules...")
         if sys.platform.startswith('win') and have_winrm():
             process = subprocess.Popen(['winrm', '-rf', node_modules_path])
             process.wait()
         else:
             mozfileremove(node_modules_path)
 
-    npm_path = get_node_or_npm_path("npm")
+    npm_path, version = get_node_or_npm_path("npm")
     if not npm_path:
         return 1
 
     extra_parameters = ["--loglevel=error"]
 
-    # Install ESLint and external plugins. We pass `--no-package-lock` to avoid
-    # unexpected/unwanted npm changes to package-lock.json passing into the
-    # tree.
-    cmd = [npm_path, "install", "--no-package-lock"]
+    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 < LooseVersion("5.8.0")
+
+    if npm_is_older_version:
+        cmd = [npm_path, "install"]
+        shutil.copy2(package_lock_json_path, package_lock_json_tmp_path)
+    else:
+        cmd = [npm_path, "ci"]
+
     cmd.extend(extra_parameters)
     print("Installing eslint for mach using \"%s\"..." % (" ".join(cmd)))
-    if not call_process("eslint", cmd):
+    result = call_process("eslint", cmd)
+
+    if npm_is_older_version:
+        shutil.move(package_lock_json_tmp_path, package_lock_json_path)
+
+    if not result:
         return 1
 
     eslint_path = os.path.join(get_project_root(), "node_modules", ".bin", "eslint")
 
     print("\nESLint and approved plugins installed successfully!")
     print("\nNOTE: Your local eslint binary is at %s\n" % eslint_path)
 
     os.chdir(orig_cwd)
@@ -302,34 +318,31 @@ def get_node_or_npm_path(filename, minve
 
             for p in app_paths:
                 print("  - %s" % p)
         elif platform.system() == "Darwin":
             print("  - /usr/local/bin/{}".format(filename))
         elif platform.system() == "Linux":
             print("  - /usr/bin/{}".format(filename))
 
-        return None
-
-    if not minversion:
-        return node_or_npm_path
+        return None, None
 
     version_str = get_version(node_or_npm_path).lstrip('v')
 
     version = LooseVersion(version_str)
 
-    if version > minversion:
-        return node_or_npm_path
+    if not minversion or version > minversion:
+        return node_or_npm_path, version
 
     if filename == "npm":
         print(NPM_MACHING_VERSION_NOT_FOUND_MESSAGE % (version_str.strip(), minversion))
     else:
         print(NODE_MACHING_VERSION_NOT_FOUND_MESSAGE % (version_str.strip(), minversion))
 
-    return None
+    return None, None
 
 
 def get_version(path):
     try:
         version_str = subprocess.check_output([path, "--version"],
                                               stderr=subprocess.STDOUT)
         return version_str
     except (subprocess.CalledProcessError, OSError):