[bazel] //cmd/presbmit/presubmit.go: Run "npm ci" step on CI. In https://skia-review.googlesource.com/c/buildbot/+/787329 I updated Prettier to v3.1.0. Since then, we have seen some (but not all) Housekeeper-OnDemand-Presubmit tasks fail with: npm WARN exec The following package was not found and will be installed: prettier npm ERR! code E451 npm ERR! 451 unknown - GET https://npm.skia.org/skia-infra/prettier/-/prettier-3.1.1.tgz Example: https://task-scheduler.skia.org/job/fybXDSw4BolKQ8FgX6ZP. The reason for this failure is that: - Bazel used to manage the node_modules directory for us, but this has ceased to be true since we upgraded to Bazel 6.0.0. This means we don't get a node_modules directory unless we explicitly create one, e.g. with "npm ci". - The "npx prettier" command first looks for a "prettier" package in node_modules, and if it does not find it, it tries to download the latest "prettier" version, apparently ignoring the exact version specified in //package.json and/or //package-lock.json. - "npx" fails to download "prettier" because the latest version (3.1.1) is too new, and therefore npm-audit-mirror rejects it, hence the 451 error. The solution I've found is to run "npm ci" right before "npx prettier", which ensures we have a node_modules directory. Bug: b/314813928 Change-Id: I2de92c62c82a682afd852f416330766eacfa5e9e Reviewed-on: https://skia-review.googlesource.com/c/buildbot/+/789219 Commit-Queue: Kevin Lubick <kjlubick@google.com> Reviewed-by: Kevin Lubick <kjlubick@google.com> Auto-Submit: Leandro Lovisolo <lovisolo@google.com>
diff --git a/cmd/presubmit/presubmit.go b/cmd/presubmit/presubmit.go index 579b7ec..418a88f 100644 --- a/cmd/presubmit/presubmit.go +++ b/cmd/presubmit/presubmit.go
@@ -109,6 +109,16 @@ changedFiles, _ = computeDiffFiles(ctx, branchBaseCommit) trackErrors(runGofmt(ctx, changedFiles, branchBaseCommit)) changedFiles, _ = computeDiffFiles(ctx, branchBaseCommit) + if *commit { + // When running the presubmit checks on CI, we must manually ensure that the node_modules + // directory exists because Bazel no longer manages that directory for us. Running "npm ci" + // accomplishes this. If the node_modules directory does not exist, the prettier step below + // will fail. + // + // When running the presubmit checks as part of the "git cl upload" command, it is the + // developer's responsibility to keep their node_modules directory up-to-date. + trackErrors(runNpmCi(ctx)) + } trackErrors(runPrettier(ctx, changedFiles, *repoDir, branchBaseCommit)) changedFiles, _ = computeDiffFiles(ctx, branchBaseCommit) trackErrors(runGazelle(ctx, changedFiles, deletedFiles, branchBaseCommit)) @@ -675,6 +685,18 @@ return true } +// runNpmCi runs "npm ci" to ensure that the "node_modules" directory exists. +func runNpmCi(ctx context.Context) bool { + cmd := exec.CommandContext(ctx, "bazelisk", "run", "--config=mayberemote", "//:npm", "--", "ci") + output, err := cmd.CombinedOutput() + if err != nil { + logf(ctx, "Command \"npm ci\" failed. Output:\n") + logf(ctx, string(output)) + return false + } + return true +} + // runPrettier runs prettier --write on any changed files. It returns false if // prettier returns a non-zero error code. func runPrettier(ctx context.Context, files []fileWithChanges, workspaceRoot, branchBaseCommit string) bool {