From 1d650fbb4e383b20ce895dc815d07a74dc4c1b7e Mon Sep 17 00:00:00 2001 From: Lukas Holzer Date: Fri, 18 Dec 2020 14:45:06 +0000 Subject: [PATCH] feat(builtin): use npm ci as default behaviour for installing node_modules (#2328) To be more hermetic with the install of the dependencies use npm ci to install the exact version from the package-lock.json file. To update a dependency use the vendored npm binary with `bazel run @nodejs//:npm install `. Fixes #159 --- WORKSPACE | 1 + internal/bazel_integration_test/test_runner.js | 5 +++++ internal/npm_install/npm_install.bzl | 17 ++++++++++++++++- 3 files changed, 22 insertions(+), 1 deletion(-) diff --git a/WORKSPACE b/WORKSPACE index d720cf8c7f..d1dadd9d38 100644 --- a/WORKSPACE +++ b/WORKSPACE @@ -220,6 +220,7 @@ npm_install( ".json", ".proto", ], + npm_command = "install", package_json = "//:tools/fine_grained_deps_npm/package.json", package_lock_json = "//:tools/fine_grained_deps_npm/package-lock.json", symlink_node_modules = False, diff --git a/internal/bazel_integration_test/test_runner.js b/internal/bazel_integration_test/test_runner.js index 07942101e9..00824481b7 100644 --- a/internal/bazel_integration_test/test_runner.js +++ b/internal/bazel_integration_test/test_runner.js @@ -226,6 +226,11 @@ if (config.bazelrcAppend) { workspaceContents = workspaceContents.replace(/(yarn_lock[\s\S]+?,)/gm, 'frozen_lockfile = False,\n $1') + // We have to use npm install in favour of npm ci as the package-lock.json would not match the + // replaced version + workspaceContents = workspaceContents.replace( + /(package_lock_json[\s\S]+?,)/gm, 'npm_command = "install",\n $1') + if (!workspaceContents.includes(archiveFile)) { console.error( `bazel_integration_test: WORKSPACE replacement for repository ${repositoryKey} failed!`) diff --git a/internal/npm_install/npm_install.bzl b/internal/npm_install/npm_install.bzl index 323cecfe67..a2eed9e7e9 100644 --- a/internal/npm_install/npm_install.bzl +++ b/internal/npm_install/npm_install.bzl @@ -206,7 +206,11 @@ def _npm_install_impl(repository_ctx): is_windows_host = is_windows_os(repository_ctx) node = repository_ctx.path(get_node_label(repository_ctx)) npm = get_npm_label(repository_ctx) - npm_args = ["install"] + repository_ctx.attr.args + + # Set the base command (install or ci) + npm_args = [repository_ctx.attr.npm_command] + + npm_args.extend(repository_ctx.attr.args) # If symlink_node_modules is true then run the package manager # in the package.json folder; otherwise, run it in the root of @@ -303,6 +307,17 @@ npm_install = repository_rule( See npm CLI docs https://docs.npmjs.com/cli/install.html for complete list of supported arguments.""", default = [], ), + "npm_command": attr.string( + default = "ci", + doc = """The npm command to run, to install dependencies. + + See npm docs + + In particular, for "ci" it says: + > If dependencies in the package lock do not match those in package.json, npm ci will exit with an error, instead of updating the package lock. + """, + values = ["ci", "install"], + ), "package_lock_json": attr.label( mandatory = True, allow_single_file = True,