diff --git a/docs/Built-ins.md b/docs/Built-ins.md index 99f3602a50..1235fcb808 100755 --- a/docs/Built-ins.md +++ b/docs/Built-ins.md @@ -1226,6 +1226,9 @@ See yarn CLI docs for complete list of supported arguments. Yarn 1: https://yarnpkg.com/en/docs/cli/install Yarn 2+ (Berry): https://yarnpkg.com/cli/install +Note that Yarn Berry PnP is *not* supported, follow +https://github.com/bazelbuild/rules_nodejs/issues/1599 + Defaults to `[]`

data

diff --git a/examples/vendored_node_and_yarn/package.json b/examples/vendored_node_and_yarn/package.json index f2ff9c2292..0e9e0ad29b 100644 --- a/examples/vendored_node_and_yarn/package.json +++ b/examples/vendored_node_and_yarn/package.json @@ -5,6 +5,8 @@ "jasmine": "^3.5.0" }, "scripts": { + "//": "assert that yarn version is the one we vendored", + "postinstall": "node -e \"require('assert').equal('yarn/1.10.0', process.env['npm_config_user_agent'].split(' ').find(x => x.startsWith('yarn/')))\"", "test": "bazel test ..." } } diff --git a/internal/npm_install/npm_install.bzl b/internal/npm_install/npm_install.bzl index 9471ed317a..28c8a244b2 100644 --- a/internal/npm_install/npm_install.bzl +++ b/internal/npm_install/npm_install.bzl @@ -809,6 +809,15 @@ check if yarn is being run by the `npm_install` repository rule.""", implementation = _npm_install_impl, ) +def _detect_yarn_version(rctx, yarn): + result = rctx.execute([rctx.path(yarn), "--version"]) + if result.return_code: + fail("yarn --version failed: %s (%s)" % (result.stdout, result.stderr)) + if result.stdout.startswith("1."): + return "classic" + + return "berry" + def _yarn_install_impl(repository_ctx): """Core implementation of yarn_install.""" _check_min_bazel_version("yarn_install", repository_ctx) @@ -816,43 +825,38 @@ def _yarn_install_impl(repository_ctx): is_windows_host = is_windows_os(repository_ctx) node = repository_ctx.path(get_node_label(repository_ctx)) yarn = get_yarn_label(repository_ctx) - result = repository_ctx.execute( - [repository_ctx.path(yarn), "--version"], - timeout = repository_ctx.attr.timeout, - quiet = repository_ctx.attr.quiet, - ) - if result.return_code: - fail("yarn --version failed: %s (%s)" % (result.stdout, result.stderr)) - if result.stdout.startswith("1."): - yarn_version = "classic" - else: - yarn_version = "berry" - + yarn_version = _detect_yarn_version(repository_ctx, yarn) yarn_args = [] - # Set frozen lockfile as default install to install the exact version from the yarn.lock - # file. To perform an yarn install use the vendord yarn binary with: - # `bazel run @nodejs_host//:yarn install` or `bazel run @nodejs_host//:yarn install -- -D ` - if repository_ctx.attr.frozen_lockfile: - if yarn_version == "classic": - yarn_args.append("--frozen-lockfile") - else: + # CLI arguments changed in yarn 2+ + if yarn_version == "berry": + # According to maintainers, the yarn cache is now atomic in berry, so this flag is only needed in classic. + # See https://github.com/bazelbuild/rules_nodejs/pull/3195#discussion_r780719932 + if not repository_ctx.attr.use_global_yarn_cache: + fail("""Disabling global_yarn_cache has no effect while using Yarn Berry. + Please configure it through a .yarnrc file through 'data' attribute.""") + if repository_ctx.attr.frozen_lockfile: fail("--frozen-lockfile should not be used with yarn 2+. Just pass arguments like --immutable.") - - if not repository_ctx.attr.use_global_yarn_cache: - yarn_args.extend(["--cache-folder", str(repository_ctx.path("_yarn_cache"))]) elif yarn_version == "classic": - # Multiple yarn rules cannot run simultaneously using a shared cache. - # See https://github.com/yarnpkg/yarn/issues/683 - # The --mutex option ensures only one yarn runs at a time, see - # https://yarnpkg.com/en/docs/cli#toc-concurrency-and-mutex - # The shared cache is not necessarily hermetic, but we need to cache downloaded - # artifacts somewhere, so we rely on yarn to be correct. - yarn_args.extend(["--mutex", "network"]) + # Set frozen lockfile as default install to install the exact version from the yarn.lock + # file. To perform an yarn install use the vendord yarn binary with: + # `bazel run @nodejs_host//:yarn install` or `bazel run @nodejs_host//:yarn install -- -D ` + if repository_ctx.attr.frozen_lockfile: + yarn_args.append("--frozen-lockfile") + + if repository_ctx.attr.use_global_yarn_cache: + # Multiple yarn rules cannot run simultaneously using a shared cache. + # See https://github.com/yarnpkg/yarn/issues/683 + # The --mutex option ensures only one yarn runs at a time, see + # https://yarnpkg.com/en/docs/cli#toc-concurrency-and-mutex + # The shared cache is not necessarily hermetic, but we need to cache downloaded + # artifacts somewhere, so we rely on yarn to be correct. + yarn_args.extend(["--mutex", "network"]) + else: + yarn_args.extend(["--cache-folder", str(repository_ctx.path("_yarn_cache"))]) else: - # Can't tell from documentation if Yarn Berry has any replacement for the --mutex - # flag. We'll have to assume it's safe to run concurrently. - pass + fail("yarn_version has unknown value " + yarn_version) + yarn_args.extend(repository_ctx.attr.args) # Run the package manager in the package.json folder @@ -960,6 +964,9 @@ yarn_install = repository_rule( See yarn CLI docs for complete list of supported arguments. Yarn 1: https://yarnpkg.com/en/docs/cli/install Yarn 2+ (Berry): https://yarnpkg.com/cli/install + +Note that Yarn Berry PnP is *not* supported, follow +https://github.com/bazelbuild/rules_nodejs/issues/1599 """, default = [], ),