Skip to content

Commit

Permalink
refactor: move yarn fetch to a separate external repo
Browse files Browse the repository at this point in the history
Previously every @node_some_platform had a yarn program in it,
which doesn't make sense since yarn is platform-independent JS.
Instead make a @Yarn repo and use that for getting our yarn binary.

Trivially allows a vendored yarn by passing the yarn attribute to
yarn_install overriding the default.

BREAKING CHANGE:
vendored_yarn attribute is removed
  • Loading branch information
alexeagle committed Jan 13, 2022
1 parent 77ab690 commit 846d351
Show file tree
Hide file tree
Showing 14 changed files with 395 additions and 318 deletions.
6 changes: 3 additions & 3 deletions .bazelci/presubmit.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ tasks:
name: ubuntu1804
platform: ubuntu1804
run_targets:
- "@node16_linux_amd64//:yarn"
- "@yarn//:yarn"
# Regression test for #1493
- "//packages/create:npm_package.pack"
- "//internal/node/test:no_deps"
Expand Down Expand Up @@ -129,7 +129,7 @@ tasks:
name: macos
platform: macos
run_targets:
- "@node16_darwin_amd64//:yarn"
- "@yarn//:yarn"
# Regression test for #1493
- "//packages/create:npm_package.pack"
- "//internal/node/test:no_deps"
Expand Down Expand Up @@ -219,7 +219,7 @@ tasks:
name: windows
platform: windows
run_targets:
- "@node16_windows_amd64//:yarn"
- "@yarn//:yarn"
- "//internal/node/test:no_deps"
- "//internal/node/test:has_deps_legacy"
- "//internal/node/test:has_deps"
Expand Down
2 changes: 1 addition & 1 deletion .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ jobs:
- *init_bazel

# Run yarn
- run: bazel run @node16_linux_amd64//:yarn
- run: bazel run @yarn//:yarn

# Save all node_modules to the cache
- save_cache:
Expand Down
12 changes: 9 additions & 3 deletions docs/Built-ins.md
Original file line number Diff line number Diff line change
Expand Up @@ -728,7 +728,7 @@ Defaults to `""`

<h4 id="npm_install-node_repository">node_repository</h4>

(*String*): The basename for nodejs toolchains.
(*String*): The basename for a nodejs toolchain to use for running npm.
Usually this is the value of the `name` attribute given to a nodejs_register_toolchains call in WORKSPACE

Defaults to `"nodejs"`
Expand Down Expand Up @@ -1182,7 +1182,7 @@ yarn_install(<a href="#yarn_install-name">name</a>, <a href="#yarn_install-args"
<a href="#yarn_install-generate_local_modules_build_files">generate_local_modules_build_files</a>, <a href="#yarn_install-included_files">included_files</a>, <a href="#yarn_install-links">links</a>, <a href="#yarn_install-manual_build_file_contents">manual_build_file_contents</a>,
<a href="#yarn_install-node_repository">node_repository</a>, <a href="#yarn_install-package_json">package_json</a>, <a href="#yarn_install-package_json_remove">package_json_remove</a>, <a href="#yarn_install-package_json_replace">package_json_replace</a>, <a href="#yarn_install-package_path">package_path</a>,
<a href="#yarn_install-patch_args">patch_args</a>, <a href="#yarn_install-patch_tool">patch_tool</a>, <a href="#yarn_install-post_install_patches">post_install_patches</a>, <a href="#yarn_install-pre_install_patches">pre_install_patches</a>, <a href="#yarn_install-quiet">quiet</a>, <a href="#yarn_install-repo_mapping">repo_mapping</a>,
<a href="#yarn_install-strict_visibility">strict_visibility</a>, <a href="#yarn_install-symlink_node_modules">symlink_node_modules</a>, <a href="#yarn_install-timeout">timeout</a>, <a href="#yarn_install-use_global_yarn_cache">use_global_yarn_cache</a>, <a href="#yarn_install-yarn_lock">yarn_lock</a>)
<a href="#yarn_install-strict_visibility">strict_visibility</a>, <a href="#yarn_install-symlink_node_modules">symlink_node_modules</a>, <a href="#yarn_install-timeout">timeout</a>, <a href="#yarn_install-use_global_yarn_cache">use_global_yarn_cache</a>, <a href="#yarn_install-yarn">yarn</a>, <a href="#yarn_install-yarn_lock">yarn_lock</a>)
</pre>

Runs yarn install during workspace setup.
Expand Down Expand Up @@ -1415,7 +1415,7 @@ Defaults to `""`

<h4 id="yarn_install-node_repository">node_repository</h4>

(*String*): The basename for nodejs toolchains.
(*String*): The basename for a nodejs toolchain to use for running npm.
Usually this is the value of the `name` attribute given to a nodejs_register_toolchains call in WORKSPACE

Defaults to `"nodejs"`
Expand Down Expand Up @@ -1619,6 +1619,12 @@ to yarn so that the local cache is contained within the external repository.

Defaults to `True`

<h4 id="yarn_install-yarn">yarn</h4>

(*<a href="https://bazel.build/docs/build-ref.html#labels">Label</a>*): The yarn.js entry point to execute

Defaults to `@yarn//:bin/yarn`

<h4 id="yarn_install-yarn_lock">yarn_lock</h4>

(*<a href="https://bazel.build/docs/build-ref.html#labels">Label</a>, mandatory*)
Expand Down
188 changes: 112 additions & 76 deletions docs/Core.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,29 +27,28 @@ We plan to clean these up and port into `rules_nodejs` in a future major release

<pre>
node_repositories(<a href="#node_repositories-name">name</a>, <a href="#node_repositories-node_download_auth">node_download_auth</a>, <a href="#node_repositories-node_repositories">node_repositories</a>, <a href="#node_repositories-node_urls">node_urls</a>, <a href="#node_repositories-node_version">node_version</a>, <a href="#node_repositories-platform">platform</a>,
<a href="#node_repositories-repo_mapping">repo_mapping</a>, <a href="#node_repositories-use_nvmrc">use_nvmrc</a>, <a href="#node_repositories-vendored_node">vendored_node</a>, <a href="#node_repositories-vendored_yarn">vendored_yarn</a>, <a href="#node_repositories-yarn_download_auth">yarn_download_auth</a>,
<a href="#node_repositories-yarn_repositories">yarn_repositories</a>, <a href="#node_repositories-yarn_urls">yarn_urls</a>, <a href="#node_repositories-yarn_version">yarn_version</a>)
<a href="#node_repositories-repo_mapping">repo_mapping</a>, <a href="#node_repositories-use_nvmrc">use_nvmrc</a>, <a href="#node_repositories-vendored_node">vendored_node</a>)
</pre>

To be run in user's WORKSPACE to install rules_nodejs dependencies.

This rule sets up node, npm, and yarn. The versions of these tools can be specified in one of three ways
This rule sets up node, npm, and npx. The versions of these tools can be specified in one of three ways

### Simplest Usage

Specify no explicit versions. This will download and use the latest NodeJS & Yarn that were available when the
Specify no explicit versions. This will download and use the latest NodeJS that was available when the
version of rules_nodejs you're using was released.
Note that you can skip calling `node_repositories` in your WORKSPACE file - if you later try to `yarn_install` or `npm_install`,
we'll automatically select this simple usage for you.

### Forced version(s)

You can select the version of NodeJS and/or Yarn to download & use by specifying it when you call node_repositories,
You can select the version of NodeJS to download & use by specifying it when you call node_repositories,
using a value that matches a known version (see the default values)

### Using a custom version

You can pass in a custom list of NodeJS and/or Yarn repositories and URLs for node_resositories to use.
You can pass in a custom list of NodeJS repositories and URLs for node_repositories to use.

#### Custom NodeJS versions

Expand Down Expand Up @@ -78,40 +77,10 @@ node_repositories(
A Mac client will try to download node from `https://mycorpproxy/mirror/node/v10.10.0/node-v10.10.0-darwin-x64.tar.gz`
and expect that file to have sha256sum `00b7a8426e076e9bf9d12ba2d571312e833fe962c70afafd10ad3682fdeeaa5e`

#### Custom Yarn versions

To specify custom Yarn versions, use the `yarn_repositories` attribute

```python
node_repositories(
yarn_repositories = {
"1.12.1": ("yarn-v1.12.1.tar.gz", "yarn-v1.12.1", "09bea8f4ec41e9079fa03093d3b2db7ac5c5331852236d63815f8df42b3ba88d"),
},
)
```

Like `node_urls`, the `yarn_urls` attribute can be used to provide a list of custom URLs to use to download yarn

```python
node_repositories(
yarn_repositories = {
"1.12.1": ("yarn-v1.12.1.tar.gz", "yarn-v1.12.1", "09bea8f4ec41e9079fa03093d3b2db7ac5c5331852236d63815f8df42b3ba88d"),
},
yarn_version = "1.12.1",
yarn_urls = [
"https://github.com/yarnpkg/yarn/releases/download/v{version}/{filename}",
],
)
```

Will download yarn from https://github.com/yarnpkg/yarn/releases/download/v1.2.1/yarn-v1.12.1.tar.gz
and expect the file to have sha256sum `09bea8f4ec41e9079fa03093d3b2db7ac5c5331852236d63815f8df42b3ba88d`.

If you don't use Yarn at all, you can skip downloading it by setting `yarn_urls = []`.

### Using a local version

To avoid downloads, you can check in vendored copies of NodeJS and/or Yarn and set vendored_node and or vendored_yarn
To avoid downloads, you can check in vendored copies of NodeJS and set vendored_node
to point to those before calling node_repositories. You can also point to a location where node is installed on your computer,
but we don't recommend this because it leads to version skew between you, your coworkers, and your Continuous Integration environment.
It also ties your build to a single platform, preventing you from cross-compiling into a Linux docker image on Mac for example.
Expand Down Expand Up @@ -189,45 +158,6 @@ If set then also set node_version to the version that of node that is vendored.

Defaults to `None`

<h4 id="node_repositories-vendored_yarn">vendored_yarn</h4>

(*<a href="https://bazel.build/docs/build-ref.html#labels">Label</a>*): the local path to a pre-installed yarn tool

Defaults to `None`

<h4 id="node_repositories-yarn_download_auth">yarn_download_auth</h4>

(*<a href="https://bazel.build/docs/skylark/lib/dict.html">Dictionary: String -> String</a>*): auth to use for all url requests
Example: {"type": "basic", "login": "<UserName>", "password": "<Password>" }

Defaults to `{}`

<h4 id="node_repositories-yarn_repositories">yarn_repositories</h4>

(*<a href="https://bazel.build/docs/skylark/lib/dict.html">Dictionary: String -> List of strings</a>*): Custom list of yarn repositories to use.

Dictionary mapping Yarn versions to their corresponding (filename, strip_prefix, sha256) tuples.

By default, if this attribute has no items, we'll use a list of all public NodeJS releases.

Defaults to `{}`

<h4 id="node_repositories-yarn_urls">yarn_urls</h4>

(*List of strings*): custom list of URLs to use to download Yarn

Each entry is a template, similar to the `node_urls` attribute, using `yarn_version` and `yarn_repositories` in the substitutions.

If this list is empty, we won't download yarn at all.

Defaults to `["https://github.com/yarnpkg/yarn/releases/download/v{version}/{filename}"]`

<h4 id="node_repositories-yarn_version">yarn_version</h4>

(*String*): the specific version of Yarn to install

Defaults to `"1.22.11"`


## node_toolchain

Expand Down Expand Up @@ -299,6 +229,112 @@ Defaults to `None`
Defaults to `""`


## yarn_repositories

**USAGE**

<pre>
yarn_repositories(<a href="#yarn_repositories-name">name</a>, <a href="#yarn_repositories-node_repository">node_repository</a>, <a href="#yarn_repositories-repo_mapping">repo_mapping</a>, <a href="#yarn_repositories-yarn_download_auth">yarn_download_auth</a>, <a href="#yarn_repositories-yarn_releases">yarn_releases</a>, <a href="#yarn_repositories-yarn_urls">yarn_urls</a>,
<a href="#yarn_repositories-yarn_version">yarn_version</a>)
</pre>

Repository rule to fetch the yarnpkg.com package manager.

Note, the recommended name is "yarn". If you choose a different name, you'll have to override the
`yarn` attribute in your `yarn_install` rule to point to your `yarn.js` file.

## Custom Yarn versions

To specify custom Yarn versions, use the `yarn_releases` attribute

```python
yarn_repositories(
yarn_releases = {
"1.12.1": ("yarn-v1.12.1.tar.gz", "yarn-v1.12.1", "09bea8f4ec41e9079fa03093d3b2db7ac5c5331852236d63815f8df42b3ba88d"),
},
)
```

Like `node_urls`, the `yarn_urls` attribute can be used to provide a list of custom URLs to use to download yarn

```python
yarn_repositories(
yarn_releases = {
"1.12.1": ("yarn-v1.12.1.tar.gz", "yarn-v1.12.1", "09bea8f4ec41e9079fa03093d3b2db7ac5c5331852236d63815f8df42b3ba88d"),
},
yarn_version = "1.12.1",
yarn_urls = [
"https://github.com/yarnpkg/yarn/releases/download/v{version}/{filename}",
],
)
```

Will download yarn from https://github.com/yarnpkg/yarn/releases/download/v1.2.1/yarn-v1.12.1.tar.gz
and expect the file to have sha256sum `09bea8f4ec41e9079fa03093d3b2db7ac5c5331852236d63815f8df42b3ba88d`.

If you don't use Yarn at all, you can skip downloading it by setting `yarn_urls = []`.

## Vendored yarn

You can vendor the `yarn.js` file into your repo. In this case, don't call `yarn_repositories` at all.
Just pass the label of your vendored file to the `yarn` attribute of `yarn_install`.


**ATTRIBUTES**


<h4 id="yarn_repositories-name">name</h4>

(*<a href="https://bazel.build/docs/build-ref.html#name">Name</a>, mandatory*): A unique name for this repository.


<h4 id="yarn_repositories-node_repository">node_repository</h4>

(*String*): The basename for a nodejs toolchain to use for running yarn.
Usually this is the value of the `name` attribute given to a nodejs_register_toolchains call in WORKSPACE

Defaults to `"nodejs"`

<h4 id="yarn_repositories-repo_mapping">repo_mapping</h4>

(*<a href="https://bazel.build/docs/skylark/lib/dict.html">Dictionary: String -> String</a>, mandatory*): A dictionary from local repository name to global repository name. This allows controls over workspace dependency resolution for dependencies of this repository.<p>For example, an entry `"@foo": "@bar"` declares that, for any time this repository depends on `@foo` (such as a dependency on `@foo//some:target`, it should actually resolve that dependency within globally-declared `@bar` (`@bar//some:target`).


<h4 id="yarn_repositories-yarn_download_auth">yarn_download_auth</h4>

(*<a href="https://bazel.build/docs/skylark/lib/dict.html">Dictionary: String -> String</a>*): auth to use for all url requests
Example: {"type": "basic", "login": "<UserName>", "password": "<Password>" }

Defaults to `{}`

<h4 id="yarn_repositories-yarn_releases">yarn_releases</h4>

(*<a href="https://bazel.build/docs/skylark/lib/dict.html">Dictionary: String -> List of strings</a>*): Custom list of yarn releases to use.

Dictionary mapping Yarn versions to their corresponding (filename, strip_prefix, sha256) tuples.

By default, if this attribute has no items, we'll use a list of all public releases which
is periodically mirrored to rules_nodejs.

Defaults to `{}`

<h4 id="yarn_repositories-yarn_urls">yarn_urls</h4>

(*List of strings*): custom list of URLs to use to download Yarn

Each entry is a template using `yarn_version` and `yarn_releases` in the substitutions.

If this list is empty, we won't download yarn at all.

Defaults to `["https://github.com/yarnpkg/yarn/releases/download/v{version}/{filename}"]`

<h4 id="yarn_repositories-yarn_version">yarn_version</h4>

(*String*): the specific version of Yarn to install

Defaults to `"1.22.11"`


## DeclarationInfo

**USAGE**
Expand Down
9 changes: 7 additions & 2 deletions docs/repositories.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ These are referenced with the `@repo//` syntax in your BUILD files.
## @nodejs_host

This repository is created by calling the `node_repositories` function in your `WORKSPACE` file.
It contains the node, npm, and yarn programs.
It contains the node, npm, and npx programs.

As always, `bazel query` is useful for learning about what targets are available.

Expand All @@ -23,7 +23,12 @@ Some ways you can use this:

- Run the Bazel-managed version of node: `bazel run @nodejs_host//:node path/to/program.js`
- Run the Bazel-managed version of npm: `bazel run @nodejs_host//:npm`
- Run the Bazel-managed version of yarn: `bazel run @nodejs_host//:yarn`

## @yarn

This repository is created by calling the `yarn_repositories` function in your `WORKSPACE` file.

- Run the Bazel-managed version of yarn: `bazel run @yarn//:yarn`

## @npm

Expand Down
6 changes: 3 additions & 3 deletions e2e/nodejs_host/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,9 @@ nodejs_test(
"@nodejs_host//:npm_bin",
"@nodejs_host//:npm_files",
"@nodejs_host//:npx_bin",
"@nodejs_host//:yarn",
"@nodejs_host//:yarn_bin",
"@nodejs_host//:yarn_files",
"@yarn",
"@yarn//:yarn_bin",
"@yarn//:yarn_files",
],
entry_point = ":index.spec.js",
)
2 changes: 1 addition & 1 deletion examples/vendored_node_and_yarn/WORKSPACE
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,6 @@ load("@build_bazel_rules_nodejs//:index.bzl", "node_repositories", "yarn_install
node_repositories(
node_version = "10.12.0",
vendored_node = "@vendored_node_10_12_0//:node-v10.12.0-linux-x64",
vendored_yarn = "@vendored_yarn_1_10_0//:yarn-v1.10.0",
)

yarn_install(
Expand All @@ -59,5 +58,6 @@ yarn_install(
],
exports_directories_only = False,
package_json = "//:package.json",
yarn = "@vendored_yarn_1_10_0//:yarn-v1.10.0/bin/yarn.js",
yarn_lock = "//:yarn.lock",
)
17 changes: 10 additions & 7 deletions internal/node/node_repositories.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ See https://docs.bazel.build/versions/main/skylark/repository_rules.html
load("@bazel_tools//tools/build_defs/repo:utils.bzl", "maybe")
load("@rules_nodejs//nodejs/private:os_name.bzl", "OS_ARCH_NAMES", "node_exists_for_os", "os_name")
load("@rules_nodejs//nodejs:repositories.bzl", "DEFAULT_NODE_VERSION", "nodejs_register_toolchains", node_repositories_rule = "node_repositories")
load("@rules_nodejs//nodejs:yarn_repositories.bzl", "yarn_repositories")
load("//internal/common:check_bazel_version.bzl", "check_bazel_version")

def node_repositories(**kwargs):
Expand All @@ -41,13 +42,15 @@ def node_repositories(**kwargs):
minimum_bazel_version = "4.0.0",
)

# buildifier: disable=print
print("""WARN: node_repositories is deprecated, please instead use:
load("@rules_nodejs//nodejs:repositories.bzl", "nodejs_register_toolchains")
nodejs_register_toolchains(name = "nodejs")
See https://github.com/bazelbuild/rules_nodejs/wiki/Migrating-to-5.0
""")
# Back-compat: allow yarn_repositories args to be provided to node_repositories
yarn_args = {}
for k, v in kwargs.items():
if k.startswith("yarn_"):
yarn_args[k] = kwargs.pop(k)
yarn_repositories(
name = "yarn",
**yarn_args
)

# This needs to be setup so toolchains can access nodejs for all different versions
node_version = kwargs.get("node_version", DEFAULT_NODE_VERSION)
Expand Down
Loading

0 comments on commit 846d351

Please sign in to comment.