Compare commits
20 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
65404a1883 | ||
|
|
f317a618b8 | ||
|
|
683de60603 | ||
|
|
a58028d063 | ||
|
|
626a6640f8 | ||
|
|
4f8e27cd74 | ||
|
|
31c42a8638 | ||
|
|
769b95d05b | ||
|
|
2a25cfb91a | ||
|
|
2a9bd09aa4 | ||
|
|
4b7ebb1536 | ||
| 73d4625420 | |||
|
|
b35f03872c | ||
|
|
a0bc998bd2 | ||
|
|
c446f23a35 | ||
|
|
d7a6d6b0ba | ||
|
|
81e9b93914 | ||
|
|
9cbd027e7e | ||
|
|
6b5343fdf3 | ||
|
|
9487fafe88 |
6
.github/workflows/ci.yml
vendored
6
.github/workflows/ci.yml
vendored
@@ -28,7 +28,7 @@ jobs:
|
||||
USE_BAZEL_VERSION: 9.0.0
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: bazel-contrib/setup-bazel@0.15.0
|
||||
- uses: bazel-contrib/setup-bazel@0.18.0
|
||||
with:
|
||||
bazelisk-cache: true
|
||||
repository-cache: true
|
||||
@@ -36,6 +36,8 @@ jobs:
|
||||
disk-cache: ci-${{ matrix.phase8_target }}
|
||||
cache-save: ${{ github.event_name != 'pull_request' }}
|
||||
- name: Run tests (${{ matrix.phase8_target }})
|
||||
shell: bash
|
||||
run: |
|
||||
echo "Phase 8 target: ${{ matrix.phase8_target }}"
|
||||
bazel test //tests/...
|
||||
targets="$(./tests/ci_test/phase8_ci_targets.sh "${{ matrix.phase8_target }}")"
|
||||
bazel test ${targets}
|
||||
|
||||
2
.github/workflows/pages.yml
vendored
2
.github/workflows/pages.yml
vendored
@@ -30,7 +30,7 @@ jobs:
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- uses: bazel-contrib/setup-bazel@0.15.0
|
||||
- uses: bazel-contrib/setup-bazel@0.18.0
|
||||
with:
|
||||
bazelisk-cache: true
|
||||
repository-cache: true
|
||||
|
||||
4
.gitignore
vendored
4
.gitignore
vendored
@@ -22,6 +22,6 @@ node_modules/
|
||||
|
||||
.env
|
||||
!tests/.env
|
||||
!tests/**/.env
|
||||
!examples/.env
|
||||
|
||||
.direnv
|
||||
!examples/**/.env
|
||||
|
||||
3
.gitleaksignore
Normal file
3
.gitleaksignore
Normal file
@@ -0,0 +1,3 @@
|
||||
tests/binary_test/.env:environment-file:1
|
||||
tests/script_test/.env:environment-file:1
|
||||
tests/binary_test/env_parent/.env:environment-file:1
|
||||
@@ -1 +0,0 @@
|
||||
/nix/store/qqdwqwh3dwakv119ww5hbjxlpcpf418z-pre-commit-config.json
|
||||
@@ -1 +1,9 @@
|
||||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
filegroup(
|
||||
name = "repo_runtime_files",
|
||||
srcs = [
|
||||
"BUILD.bazel",
|
||||
"MODULE.bazel",
|
||||
],
|
||||
)
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
module(
|
||||
name = "rules_bun",
|
||||
version = "0.2.2",
|
||||
version = "1.0.1",
|
||||
)
|
||||
|
||||
# Core ruleset dependencies.
|
||||
@@ -37,6 +37,13 @@ bun_install_ext.install(
|
||||
)
|
||||
use_repo(bun_install_ext, "script_test_vite_monorepo_node_modules")
|
||||
|
||||
bun_install_ext.install(
|
||||
name = "script_test_paraglide_monorepo_node_modules",
|
||||
bun_lockfile = "//tests/script_test:paraglide_monorepo/bun.lock",
|
||||
package_json = "//tests/script_test:paraglide_monorepo/package.json",
|
||||
)
|
||||
use_repo(bun_install_ext, "script_test_paraglide_monorepo_node_modules")
|
||||
|
||||
bun_install_ext.install(
|
||||
name = "examples_vite_monorepo_node_modules",
|
||||
bun_lockfile = "//examples/vite_monorepo:bun.lock",
|
||||
|
||||
81
MODULE.bazel.lock
generated
81
MODULE.bazel.lock
generated
@@ -192,8 +192,8 @@
|
||||
"moduleExtensions": {
|
||||
"//bun:extensions.bzl%bun": {
|
||||
"general": {
|
||||
"bzlTransitiveDigest": "64B4fTkEHdAlieIOkE/Wi2M/R9lMNZhFxeI1eXEFHRs=",
|
||||
"usagesDigest": "/0BcCMA6AOzLhQaRK6DquxrCfpPHJUjSUaFz4zmQrsM=",
|
||||
"bzlTransitiveDigest": "314UOH4dQIGBHGpxCwA7yzI++E2J3bjIc20m5MZhM7U=",
|
||||
"usagesDigest": "Pk8TCTd2EBKQ8R+VSF0M7sU9apLb/5tBy/dP2pjs3AU=",
|
||||
"recordedInputs": [
|
||||
"REPO_MAPPING:,bazel_tools bazel_tools"
|
||||
],
|
||||
@@ -218,6 +218,26 @@
|
||||
"build_file_content": "\nexports_files([\"bun-linux-aarch64/bun\"])\n\nfilegroup(\n name = \"bun\",\n srcs = [\"bun-linux-aarch64/bun\"],\n visibility = [\"//visibility:public\"],\n)\n"
|
||||
}
|
||||
},
|
||||
"bun_linux_x64_musl": {
|
||||
"repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_archive",
|
||||
"attributes": {
|
||||
"urls": [
|
||||
"https://github.com/oven-sh/bun/releases/download/bun-v1.3.10/bun-linux-x64-musl.zip"
|
||||
],
|
||||
"sha256": "48a6c32277d343db0148ce066336472ffd380358a4d26bb1329714742492d824",
|
||||
"build_file_content": "\nexports_files([\"bun-linux-x64-musl/bun\"])\n\nfilegroup(\n name = \"bun\",\n srcs = [\"bun-linux-x64-musl/bun\"],\n visibility = [\"//visibility:public\"],\n)\n"
|
||||
}
|
||||
},
|
||||
"bun_linux_aarch64_musl": {
|
||||
"repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_archive",
|
||||
"attributes": {
|
||||
"urls": [
|
||||
"https://github.com/oven-sh/bun/releases/download/bun-v1.3.10/bun-linux-aarch64-musl.zip"
|
||||
],
|
||||
"sha256": "d2c81365a2e529b78a42330d3a0056e8dbd7896b4a6782c8e392b6532141e34d",
|
||||
"build_file_content": "\nexports_files([\"bun-linux-aarch64-musl/bun\"])\n\nfilegroup(\n name = \"bun\",\n srcs = [\"bun-linux-aarch64-musl/bun\"],\n visibility = [\"//visibility:public\"],\n)\n"
|
||||
}
|
||||
},
|
||||
"bun_darwin_x64": {
|
||||
"repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_archive",
|
||||
"attributes": {
|
||||
@@ -247,14 +267,24 @@
|
||||
"sha256": "7a77b3e245e2e26965c93089a4a1332e8a326d3364c89fae1d1fd99cdd3cd73d",
|
||||
"build_file_content": "\nexports_files([\"bun-windows-x64/bun.exe\"])\n\nfilegroup(\n name = \"bun\",\n srcs = [\"bun-windows-x64/bun.exe\"],\n visibility = [\"//visibility:public\"],\n)\n"
|
||||
}
|
||||
},
|
||||
"bun_windows_aarch64": {
|
||||
"repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_archive",
|
||||
"attributes": {
|
||||
"urls": [
|
||||
"https://github.com/oven-sh/bun/releases/download/bun-v1.3.10/bun-windows-aarch64.zip"
|
||||
],
|
||||
"sha256": "6822f3aa7bd2be40fb94c194a1185aae1c6fade54ca4fc2efdc722e37f3257d2",
|
||||
"build_file_content": "\nexports_files([\"bun-windows-aarch64/bun.exe\"])\n\nfilegroup(\n name = \"bun\",\n srcs = [\"bun-windows-aarch64/bun.exe\"],\n visibility = [\"//visibility:public\"],\n)\n"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"//bun:extensions.bzl%bun_install": {
|
||||
"general": {
|
||||
"bzlTransitiveDigest": "64B4fTkEHdAlieIOkE/Wi2M/R9lMNZhFxeI1eXEFHRs=",
|
||||
"usagesDigest": "d+DGTyl4FpB6Ygb/R/V5knxm9bGYZKO223wMX1Q6R6w=",
|
||||
"bzlTransitiveDigest": "314UOH4dQIGBHGpxCwA7yzI++E2J3bjIc20m5MZhM7U=",
|
||||
"usagesDigest": "2qW6PUxkK7CgK8mcsgVvlIbuJS/cBBkw5mylpKlqftE=",
|
||||
"recordedInputs": [
|
||||
"REPO_MAPPING:,bazel_tools bazel_tools"
|
||||
],
|
||||
@@ -265,7 +295,14 @@
|
||||
"package_json": "@@//tests/script_test:vite_app/package.json",
|
||||
"bun_lockfile": "@@//tests/script_test:vite_app/bun.lock",
|
||||
"install_inputs": [],
|
||||
"isolated_home": true
|
||||
"isolated_home": true,
|
||||
"production": false,
|
||||
"omit": [],
|
||||
"linker": "",
|
||||
"backend": "",
|
||||
"ignore_scripts": true,
|
||||
"install_flags": [],
|
||||
"visible_repo_name": "script_test_vite_node_modules"
|
||||
}
|
||||
},
|
||||
"script_test_vite_monorepo_node_modules": {
|
||||
@@ -274,7 +311,30 @@
|
||||
"package_json": "@@//tests/script_test:vite_monorepo/package.json",
|
||||
"bun_lockfile": "@@//tests/script_test:vite_monorepo/bun.lock",
|
||||
"install_inputs": [],
|
||||
"isolated_home": true
|
||||
"isolated_home": true,
|
||||
"production": false,
|
||||
"omit": [],
|
||||
"linker": "",
|
||||
"backend": "",
|
||||
"ignore_scripts": true,
|
||||
"install_flags": [],
|
||||
"visible_repo_name": "script_test_vite_monorepo_node_modules"
|
||||
}
|
||||
},
|
||||
"script_test_paraglide_monorepo_node_modules": {
|
||||
"repoRuleId": "@@//internal:bun_install.bzl%bun_install_repository",
|
||||
"attributes": {
|
||||
"package_json": "@@//tests/script_test:paraglide_monorepo/package.json",
|
||||
"bun_lockfile": "@@//tests/script_test:paraglide_monorepo/bun.lock",
|
||||
"install_inputs": [],
|
||||
"isolated_home": true,
|
||||
"production": false,
|
||||
"omit": [],
|
||||
"linker": "",
|
||||
"backend": "",
|
||||
"ignore_scripts": true,
|
||||
"install_flags": [],
|
||||
"visible_repo_name": "script_test_paraglide_monorepo_node_modules"
|
||||
}
|
||||
},
|
||||
"examples_vite_monorepo_node_modules": {
|
||||
@@ -283,7 +343,14 @@
|
||||
"package_json": "@@//examples/vite_monorepo:package.json",
|
||||
"bun_lockfile": "@@//examples/vite_monorepo:bun.lock",
|
||||
"install_inputs": [],
|
||||
"isolated_home": true
|
||||
"isolated_home": true,
|
||||
"production": false,
|
||||
"omit": [],
|
||||
"linker": "",
|
||||
"backend": "",
|
||||
"ignore_scripts": true,
|
||||
"install_flags": [],
|
||||
"visible_repo_name": "examples_vite_monorepo_node_modules"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
104
README.md
104
README.md
@@ -1,7 +1,7 @@
|
||||
# Bun rules for [Bazel](https://bazel.build)
|
||||
|
||||
`rules_bun` provides Bazel rules for running, testing, bundling, and developing
|
||||
JavaScript and TypeScript code with Bun.
|
||||
`rules_bun` provides Bazel rules for running, testing, building, compiling,
|
||||
bundling, and developing JavaScript and TypeScript code with Bun.
|
||||
|
||||
## Repository layout
|
||||
|
||||
@@ -24,15 +24,24 @@ This repository follows the standard Bazel ruleset layout:
|
||||
|
||||
The public entrypoint for rule authors and users is `@rules_bun//bun:defs.bzl`.
|
||||
|
||||
Runtime launcher targets from `bun_binary`, `bun_script`, `bun_test`,
|
||||
`bun_dev`, and `js_run_devserver` use native platform wrappers. Windows runtime
|
||||
support is native and does not require Git Bash or MSYS.
|
||||
|
||||
## Public API
|
||||
|
||||
`rules_bun` exports these primary rules:
|
||||
|
||||
- `bun_binary`
|
||||
- `bun_build`
|
||||
- `bun_compile`
|
||||
- `bun_bundle`
|
||||
- `bun_dev`
|
||||
- `bun_script`
|
||||
- `bun_test`
|
||||
- `js_binary`
|
||||
- `js_test`
|
||||
- `js_run_devserver`
|
||||
- `js_library`
|
||||
- `ts_library`
|
||||
|
||||
@@ -43,6 +52,22 @@ Reference documentation:
|
||||
- `bun_install` extension docs: [docs/bun_install.md](docs/bun_install.md)
|
||||
- Docs index: [docs/index.md](docs/index.md)
|
||||
|
||||
## Hermeticity
|
||||
|
||||
`rules_bun` now draws a sharp line between hermetic rule surfaces and local
|
||||
workflow helpers.
|
||||
|
||||
- Hermetic build/test surfaces: `bun_build`, `bun_bundle`, `bun_compile`, `bun_test`
|
||||
- Runfiles-only executable surface: `bun_binary`
|
||||
- Reproducible but non-hermetic repository fetch surface: `bun_install`
|
||||
- Local workflow helpers: `bun_script`, `bun_dev`, `js_run_devserver`
|
||||
|
||||
Strict defaults are enabled by default:
|
||||
|
||||
- `bun_install` skips lifecycle scripts unless `ignore_scripts = False`
|
||||
- `bun_build`, `bun_bundle`, `bun_compile`, and `bun_test` require `install_mode = "disable"`
|
||||
- Runtime launchers do not inherit the host `PATH` unless `inherit_host_path = True`
|
||||
|
||||
To refresh generated rule docs:
|
||||
|
||||
```bash
|
||||
@@ -55,7 +80,7 @@ Release announcements should provide a copy-pasteable module snippet in the
|
||||
standard ruleset form:
|
||||
|
||||
```starlark
|
||||
bazel_dep(name = "rules_bun", version = "0.2.2")
|
||||
bazel_dep(name = "rules_bun", version = "1.0.1")
|
||||
```
|
||||
|
||||
Then add the Bun repositories and register the toolchains in `MODULE.bazel`:
|
||||
@@ -67,9 +92,12 @@ use_repo(
|
||||
bun_ext,
|
||||
"bun_linux_x64",
|
||||
"bun_linux_aarch64",
|
||||
"bun_linux_x64_musl",
|
||||
"bun_linux_aarch64_musl",
|
||||
"bun_darwin_x64",
|
||||
"bun_darwin_aarch64",
|
||||
"bun_windows_x64",
|
||||
"bun_windows_aarch64",
|
||||
)
|
||||
|
||||
register_toolchains(
|
||||
@@ -96,15 +124,46 @@ bun_install_ext.install(
|
||||
name = "bun_deps",
|
||||
package_json = "//:package.json",
|
||||
bun_lockfile = "//:bun.lock",
|
||||
# Optional: include extra install-time files or allow Bun to reuse the
|
||||
# host HOME/cache.
|
||||
# Optional: include extra install-time files.
|
||||
# install_inputs = ["//:.npmrc"],
|
||||
# Optional non-hermetic opt-in:
|
||||
# ignore_scripts = False,
|
||||
# isolated_home = False,
|
||||
)
|
||||
|
||||
use_repo(bun_install_ext, "bun_deps")
|
||||
```
|
||||
|
||||
## `rules_js` compatibility layer
|
||||
|
||||
`rules_bun` now exposes a Bun-backed compatibility layer for the most common
|
||||
`rules_js` entrypoints:
|
||||
|
||||
- `@rules_bun//js:defs.bzl` exports `js_binary`, `js_test`, `js_run_devserver`,
|
||||
`js_library`, `ts_library`, and `JsInfo`.
|
||||
- `@rules_bun//npm:extensions.bzl` exports `npm_translate_lock`, which creates a
|
||||
Bun-installed external repo and generates `@<repo>//:defs.bzl` with
|
||||
`npm_link_all_packages()`.
|
||||
|
||||
Example:
|
||||
|
||||
```starlark
|
||||
load("@rules_bun//js:defs.bzl", "js_binary")
|
||||
load("@npm//:defs.bzl", "npm_link_all_packages")
|
||||
|
||||
npm_link_all_packages()
|
||||
|
||||
js_binary(
|
||||
name = "app",
|
||||
entry_point = "src/main.ts",
|
||||
node_modules = ":node_modules",
|
||||
)
|
||||
```
|
||||
|
||||
This is a compatibility subset, not a full reimplementation of `rules_js`.
|
||||
Package aliases created by `npm_link_all_packages()` use sanitized target names
|
||||
such as `npm__vite` or `npm__at_types_node`.
|
||||
|
||||
## Legacy WORKSPACE usage
|
||||
|
||||
For non-Bzlmod consumers, the repository exposes a legacy setup macro in
|
||||
@@ -122,6 +181,8 @@ bun_register_toolchains()
|
||||
load(
|
||||
"@rules_bun//bun:defs.bzl",
|
||||
"bun_binary",
|
||||
"bun_build",
|
||||
"bun_compile",
|
||||
"bun_bundle",
|
||||
"bun_dev",
|
||||
"bun_script",
|
||||
@@ -158,8 +219,37 @@ bun_script(
|
||||
```
|
||||
|
||||
When `node_modules` is provided, executables from `node_modules/.bin` are added
|
||||
to `PATH`. This label typically comes from `bun_install`, which still produces a
|
||||
standard `node_modules/` directory.
|
||||
to the runtime `PATH`. The host `PATH` is not inherited unless
|
||||
`inherit_host_path = True`. This label typically comes from `bun_install`,
|
||||
which still produces a standard `node_modules/` directory.
|
||||
|
||||
### `bun_build` and `bun_compile`
|
||||
|
||||
Use `bun_build` for general-purpose `bun build` output directories and
|
||||
`bun_compile` for standalone executables built with `bun build --compile`.
|
||||
|
||||
```starlark
|
||||
load("@rules_bun//bun:defs.bzl", "bun_build", "bun_compile")
|
||||
|
||||
bun_build(
|
||||
name = "site",
|
||||
entry_points = ["src/index.html"],
|
||||
data = glob(["src/**"]),
|
||||
splitting = True,
|
||||
metafile = True,
|
||||
)
|
||||
|
||||
bun_compile(
|
||||
name = "cli",
|
||||
entry_point = "src/cli.ts",
|
||||
)
|
||||
```
|
||||
|
||||
`bun_build` exposes a directory output so Bun can emit HTML, CSS, assets, and
|
||||
split chunks. `bun_compile` produces a single executable artifact and supports
|
||||
explicit cross-compilation via `compile_executable`. When `root` is omitted,
|
||||
`bun_build` derives a stable default from the entry point parent directory so
|
||||
HTML and asset output stays inside Bazel's declared output tree.
|
||||
|
||||
### `bun_dev` for local development
|
||||
|
||||
|
||||
@@ -10,6 +10,19 @@ exports_files([
|
||||
"version.bzl",
|
||||
])
|
||||
|
||||
filegroup(
|
||||
name = "repo_runtime_files",
|
||||
srcs = [
|
||||
"BUILD.bazel",
|
||||
"defs.bzl",
|
||||
"extensions.bzl",
|
||||
"repositories.bzl",
|
||||
"toolchain.bzl",
|
||||
"version.bzl",
|
||||
],
|
||||
visibility = ["//visibility:public"],
|
||||
)
|
||||
|
||||
bzl_library(
|
||||
name = "toolchain_bzl",
|
||||
srcs = ["toolchain.bzl"],
|
||||
@@ -35,11 +48,14 @@ bzl_library(
|
||||
visibility = ["//visibility:public"],
|
||||
deps = [
|
||||
":toolchain_bzl",
|
||||
"//internal:bun_build_support_bzl",
|
||||
"//internal:bun_binary_bzl",
|
||||
"//internal:bun_compile_bzl",
|
||||
"//internal:bun_bundle_bzl",
|
||||
"//internal:bun_dev_bzl",
|
||||
"//internal:bun_script_bzl",
|
||||
"//internal:bun_test_bzl",
|
||||
"//internal:js_compat_bzl",
|
||||
"//internal:js_library_bzl",
|
||||
],
|
||||
)
|
||||
|
||||
10
bun/defs.bzl
10
bun/defs.bzl
@@ -1,21 +1,29 @@
|
||||
"""Public API surface for Bun Bazel rules."""
|
||||
load("//internal:bun_compile.bzl", _bun_build = "bun_build", _bun_compile = "bun_compile")
|
||||
load("//internal:bun_binary.bzl", _bun_binary = "bun_binary")
|
||||
load("//internal:bun_bundle.bzl", _bun_bundle = "bun_bundle")
|
||||
load("//internal:bun_dev.bzl", _bun_dev = "bun_dev")
|
||||
load("//internal:bun_script.bzl", _bun_script = "bun_script")
|
||||
load("//internal:bun_test.bzl", _bun_test = "bun_test")
|
||||
load("//internal:js_compat.bzl", _JsInfo = "JsInfo", _js_binary = "js_binary", _js_run_devserver = "js_run_devserver", _js_test = "js_test")
|
||||
load("//internal:js_library.bzl", _js_library = "js_library", _ts_library = "ts_library")
|
||||
load(":toolchain.bzl", _BunToolchainInfo = "BunToolchainInfo", _bun_toolchain = "bun_toolchain")
|
||||
|
||||
visibility("public")
|
||||
|
||||
bun_binary = _bun_binary
|
||||
bun_build = _bun_build
|
||||
bun_compile = _bun_compile
|
||||
bun_bundle = _bun_bundle
|
||||
bun_dev = _bun_dev
|
||||
bun_script = _bun_script
|
||||
bun_test = _bun_test
|
||||
js_binary = _js_binary
|
||||
js_test = _js_test
|
||||
js_run_devserver = _js_run_devserver
|
||||
js_library = _js_library
|
||||
ts_library = _ts_library
|
||||
JsInfo = _JsInfo
|
||||
BunToolchainInfo = _BunToolchainInfo
|
||||
bun_toolchain = _bun_toolchain
|
||||
|
||||
|
||||
|
||||
@@ -13,6 +13,16 @@ _BUN_ARCHIVES = {
|
||||
"asset": "bun-linux-aarch64.zip",
|
||||
"binary": "bun-linux-aarch64/bun",
|
||||
},
|
||||
"bun_linux_x64_musl": {
|
||||
"sha256": "48a6c32277d343db0148ce066336472ffd380358a4d26bb1329714742492d824",
|
||||
"asset": "bun-linux-x64-musl.zip",
|
||||
"binary": "bun-linux-x64-musl/bun",
|
||||
},
|
||||
"bun_linux_aarch64_musl": {
|
||||
"sha256": "d2c81365a2e529b78a42330d3a0056e8dbd7896b4a6782c8e392b6532141e34d",
|
||||
"asset": "bun-linux-aarch64-musl.zip",
|
||||
"binary": "bun-linux-aarch64-musl/bun",
|
||||
},
|
||||
"bun_darwin_x64": {
|
||||
"sha256": "c1d90bf6140f20e572c473065dc6b37a4b036349b5e9e4133779cc642ad94323",
|
||||
"asset": "bun-darwin-x64.zip",
|
||||
@@ -28,6 +38,11 @@ _BUN_ARCHIVES = {
|
||||
"asset": "bun-windows-x64.zip",
|
||||
"binary": "bun-windows-x64/bun.exe",
|
||||
},
|
||||
"bun_windows_aarch64": {
|
||||
"sha256": "6822f3aa7bd2be40fb94c194a1185aae1c6fade54ca4fc2efdc722e37f3257d2",
|
||||
"asset": "bun-windows-aarch64.zip",
|
||||
"binary": "bun-windows-aarch64/bun.exe",
|
||||
},
|
||||
}
|
||||
|
||||
_BUN_GITHUB_RELEASE_URL_TEMPLATE = "https://github.com/oven-sh/bun/releases/download/bun-v{}/{}"
|
||||
@@ -62,6 +77,12 @@ _install = tag_class(
|
||||
"bun_lockfile": attr.label(mandatory = True),
|
||||
"install_inputs": attr.label_list(allow_files = True),
|
||||
"isolated_home": attr.bool(default = True),
|
||||
"production": attr.bool(default = False),
|
||||
"omit": attr.string_list(),
|
||||
"linker": attr.string(),
|
||||
"backend": attr.string(),
|
||||
"ignore_scripts": attr.bool(default = True),
|
||||
"install_flags": attr.string_list(),
|
||||
},
|
||||
)
|
||||
|
||||
@@ -75,6 +96,13 @@ def _bun_install_impl(ctx):
|
||||
bun_lockfile = install.bun_lockfile,
|
||||
install_inputs = install.install_inputs,
|
||||
isolated_home = install.isolated_home,
|
||||
production = install.production,
|
||||
omit = install.omit,
|
||||
linker = install.linker,
|
||||
backend = install.backend,
|
||||
ignore_scripts = install.ignore_scripts,
|
||||
install_flags = install.install_flags,
|
||||
visible_repo_name = install.name,
|
||||
)
|
||||
|
||||
|
||||
|
||||
@@ -12,6 +12,16 @@ _BUN_ARCHIVES = {
|
||||
"asset": "bun-linux-aarch64.zip",
|
||||
"binary": "bun-linux-aarch64/bun",
|
||||
},
|
||||
"bun_linux_x64_musl": {
|
||||
"sha256": "48a6c32277d343db0148ce066336472ffd380358a4d26bb1329714742492d824",
|
||||
"asset": "bun-linux-x64-musl.zip",
|
||||
"binary": "bun-linux-x64-musl/bun",
|
||||
},
|
||||
"bun_linux_aarch64_musl": {
|
||||
"sha256": "d2c81365a2e529b78a42330d3a0056e8dbd7896b4a6782c8e392b6532141e34d",
|
||||
"asset": "bun-linux-aarch64-musl.zip",
|
||||
"binary": "bun-linux-aarch64-musl/bun",
|
||||
},
|
||||
"bun_darwin_x64": {
|
||||
"sha256": "c1d90bf6140f20e572c473065dc6b37a4b036349b5e9e4133779cc642ad94323",
|
||||
"asset": "bun-darwin-x64.zip",
|
||||
@@ -27,6 +37,11 @@ _BUN_ARCHIVES = {
|
||||
"asset": "bun-windows-x64.zip",
|
||||
"binary": "bun-windows-x64/bun.exe",
|
||||
},
|
||||
"bun_windows_aarch64": {
|
||||
"sha256": "6822f3aa7bd2be40fb94c194a1185aae1c6fade54ca4fc2efdc722e37f3257d2",
|
||||
"asset": "bun-windows-aarch64.zip",
|
||||
"binary": "bun-windows-aarch64/bun.exe",
|
||||
},
|
||||
}
|
||||
|
||||
_BUN_GITHUB_RELEASE_URL_TEMPLATE = "https://github.com/oven-sh/bun/releases/download/bun-v{}/{}"
|
||||
|
||||
@@ -8,13 +8,17 @@ stardoc(
|
||||
input = "//bun:defs.bzl",
|
||||
symbol_names = [
|
||||
"bun_binary",
|
||||
"bun_build",
|
||||
"bun_compile",
|
||||
"bun_bundle",
|
||||
"bun_dev",
|
||||
"bun_script",
|
||||
"bun_test",
|
||||
"js_binary",
|
||||
"js_run_devserver",
|
||||
"js_test",
|
||||
"js_library",
|
||||
"ts_library",
|
||||
],
|
||||
deps = ["//bun:defs_bzl"],
|
||||
target_compatible_with = ["@platforms//os:linux"],
|
||||
)
|
||||
|
||||
@@ -14,11 +14,27 @@ Unlike the build rules in [rules.md](rules.md), `bun_install` is not loaded from
|
||||
- runs `bun install --frozen-lockfile`
|
||||
- uses your checked-in `package.json` and `bun.lock` or `bun.lockb`
|
||||
- creates an external Bazel repository exposing `:node_modules`
|
||||
- generates `:defs.bzl` with `npm_link_all_packages()` and `package_target_name()`
|
||||
- keeps dependency installation under Bun rather than npm
|
||||
|
||||
The generated repository can then be passed to rules such as `bun_script`,
|
||||
`bun_binary`, `bun_bundle`, and `bun_test`.
|
||||
|
||||
## Hermeticity
|
||||
|
||||
`bun_install` is a repository convenience rule, not a hermetic build action.
|
||||
It is intended to be reproducible from a checked-in lockfile and pinned Bun
|
||||
toolchain, but it still performs dependency fetching as part of repository
|
||||
materialization.
|
||||
|
||||
Strict defaults now favor reproducibility:
|
||||
|
||||
- `isolated_home = True`
|
||||
- `ignore_scripts = True`
|
||||
|
||||
Set `ignore_scripts = False` only when you explicitly want lifecycle scripts to
|
||||
run during repository creation.
|
||||
|
||||
## Usage
|
||||
|
||||
```starlark
|
||||
@@ -28,6 +44,8 @@ bun_install_ext.install(
|
||||
name = "bun_deps",
|
||||
package_json = "//:package.json",
|
||||
bun_lockfile = "//:bun.lock",
|
||||
production = True,
|
||||
omit = ["peer"],
|
||||
)
|
||||
|
||||
use_repo(bun_install_ext, "bun_deps")
|
||||
@@ -112,6 +130,48 @@ repository root.
|
||||
- `False`: lets Bun use the host `HOME`, which can improve repeated-install
|
||||
performance when Bun's cache is home-scoped
|
||||
|
||||
### `production`
|
||||
|
||||
Optional boolean controlling whether Bun installs only production dependencies.
|
||||
|
||||
Example:
|
||||
|
||||
```starlark
|
||||
production = True
|
||||
```
|
||||
|
||||
### `omit`
|
||||
|
||||
Optional list of dependency groups to omit, forwarded as repeated
|
||||
`--omit` flags. Common values are `dev`, `optional`, and `peer`.
|
||||
|
||||
### `linker`
|
||||
|
||||
Optional Bun linker strategy, forwarded as `--linker`.
|
||||
|
||||
Common values:
|
||||
|
||||
- `isolated`
|
||||
- `hoisted`
|
||||
|
||||
### `backend`
|
||||
|
||||
Optional Bun install backend, forwarded as `--backend`.
|
||||
|
||||
Examples include `hardlink`, `symlink`, and `copyfile`.
|
||||
|
||||
### `ignore_scripts`
|
||||
|
||||
Optional boolean controlling whether Bun skips lifecycle scripts in the project
|
||||
manifest.
|
||||
|
||||
- `True` (default): skips lifecycle scripts for stricter, more reproducible installs
|
||||
- `False`: allows lifecycle scripts to run during repository creation
|
||||
|
||||
### `install_flags`
|
||||
|
||||
Optional list of additional raw flags forwarded to `bun install`.
|
||||
|
||||
## Notes
|
||||
|
||||
- `bun_install` runs Bun, not npm.
|
||||
@@ -122,3 +182,5 @@ repository root.
|
||||
`package.json`.
|
||||
- Additional `install_inputs` must be files under the same package root as the
|
||||
selected `package_json`.
|
||||
- `bun_install` does not make the install step remotely hermetic; it makes the
|
||||
generated repository stricter and more reproducible by default.
|
||||
|
||||
@@ -17,6 +17,13 @@ Supporting material lives in:
|
||||
- [docs/rules.md](rules.md) for generated build rule reference
|
||||
- [docs/bun_install.md](bun_install.md) for `bun_install` extension docs
|
||||
|
||||
## Hermeticity
|
||||
|
||||
- Hermetic rule surfaces: `bun_build`, `bun_bundle`, `bun_compile`, `bun_test`
|
||||
- Runfiles-only executable surface: `bun_binary`
|
||||
- Reproducible but non-hermetic repository surface: `bun_install`
|
||||
- Local workflow helpers: `bun_script`, `bun_dev`, `js_run_devserver`
|
||||
|
||||
## Rule reference
|
||||
|
||||
- [rules.md](rules.md)
|
||||
@@ -36,9 +43,12 @@ use_repo(
|
||||
bun_ext,
|
||||
"bun_linux_x64",
|
||||
"bun_linux_aarch64",
|
||||
"bun_linux_x64_musl",
|
||||
"bun_linux_aarch64_musl",
|
||||
"bun_darwin_x64",
|
||||
"bun_darwin_aarch64",
|
||||
"bun_windows_x64",
|
||||
"bun_windows_aarch64",
|
||||
)
|
||||
|
||||
register_toolchains(
|
||||
@@ -79,6 +89,12 @@ bun_script(
|
||||
`bun_script` runs from the package directory by default and adds
|
||||
`node_modules/.bin` to `PATH`.
|
||||
|
||||
## Build and compile
|
||||
|
||||
Use `bun_build` when Bun may emit a directory of outputs such as HTML, CSS,
|
||||
chunks, and static assets. Use `bun_compile` for standalone executables created
|
||||
with `bun build --compile`.
|
||||
|
||||
## Regeneration
|
||||
|
||||
The rule reference is generated from the public Starlark symbols in
|
||||
|
||||
513
docs/rules.md
513
docs/rules.md
@@ -1,88 +1,499 @@
|
||||
# rules_bun rule reference
|
||||
<!-- Generated with Stardoc: http://skydoc.bazel.build -->
|
||||
|
||||
This file documents the public rules exported from `@rules_bun//bun:defs.bzl`.
|
||||
Public API surface for Bun Bazel rules.
|
||||
|
||||
## Hermeticity And Determinism
|
||||
|
||||
- Hermetic rule surfaces: `bun_build`, `bun_bundle`, `bun_compile`, `bun_test`
|
||||
- Runfiles-only executable surface: `bun_binary`
|
||||
- Reproducible but non-hermetic repository surface: `bun_install`
|
||||
- Local workflow helpers: `bun_script`, `bun_dev`, `js_run_devserver`
|
||||
|
||||
Strict defaults:
|
||||
|
||||
- `bun_build`, `bun_bundle`, `bun_compile`, and `bun_test` require `install_mode = "disable"`
|
||||
- Runtime launchers do not inherit the host `PATH` unless `inherit_host_path = True`
|
||||
|
||||
<a id="bun_binary"></a>
|
||||
|
||||
## bun_binary
|
||||
|
||||
Runs a JS/TS entry point with Bun as an executable target (`bazel run`).
|
||||
<pre>
|
||||
load("@rules_bun//bun:defs.bzl", "bun_binary")
|
||||
|
||||
Attributes:
|
||||
bun_binary(<a href="#bun_binary-name">name</a>, <a href="#bun_binary-deps">deps</a>, <a href="#bun_binary-data">data</a>, <a href="#bun_binary-conditions">conditions</a>, <a href="#bun_binary-entry_point">entry_point</a>, <a href="#bun_binary-env_files">env_files</a>, <a href="#bun_binary-install_mode">install_mode</a>, <a href="#bun_binary-no_env_file">no_env_file</a>,
|
||||
<a href="#bun_binary-node_modules">node_modules</a>, <a href="#bun_binary-preload">preload</a>, <a href="#bun_binary-run_flags">run_flags</a>, <a href="#bun_binary-smol">smol</a>, <a href="#bun_binary-working_dir">working_dir</a>)
|
||||
</pre>
|
||||
|
||||
- `entry_point` (label, required): path to the main JS/TS file to execute.
|
||||
- `node_modules` (label, optional): package files from a `node_modules` tree, typically produced by `bun_install`, made available in runfiles.
|
||||
- `data` (label_list, optional): additional runtime files.
|
||||
- `working_dir` (string, default: `"workspace"`, values: `"workspace" | "entry_point"`): runtime working directory.
|
||||
Runs a JS/TS entry point with Bun as an executable target.
|
||||
|
||||
## bun_dev
|
||||
Use this rule for non-test scripts and CLIs that should run via `bazel run`.
|
||||
|
||||
Runs a JS/TS entry point in Bun development watch mode (`bazel run`).
|
||||
**ATTRIBUTES**
|
||||
|
||||
Attributes:
|
||||
|
||||
- `entry_point` (label, required): path to the main JS/TS file.
|
||||
- `watch_mode` (string, default: `"watch"`, values: `"watch" | "hot"`): Bun live-reload mode.
|
||||
- `restart_on` (label_list, optional): files that trigger full process restart when changed.
|
||||
- `node_modules` (label, optional): package files from a `node_modules` tree, typically produced by `bun_install`, made available in runfiles.
|
||||
- `data` (label_list, optional): additional runtime files for dev process.
|
||||
- `working_dir` (string, default: `"workspace"`, values: `"workspace" | "entry_point"`): runtime working directory.
|
||||
| Name | Description | Type | Mandatory | Default |
|
||||
| :------------- | :------------- | :------------- | :------------- | :------------- |
|
||||
| <a id="bun_binary-name"></a>name | A unique name for this target. | <a href="https://bazel.build/concepts/labels#target-names">Name</a> | required | |
|
||||
| <a id="bun_binary-deps"></a>deps | Library dependencies required by the program. | <a href="https://bazel.build/concepts/labels">List of labels</a> | optional | `[]` |
|
||||
| <a id="bun_binary-data"></a>data | Additional runtime files required by the program. | <a href="https://bazel.build/concepts/labels">List of labels</a> | optional | `[]` |
|
||||
| <a id="bun_binary-conditions"></a>conditions | Custom package resolve conditions passed to Bun. | List of strings | optional | `[]` |
|
||||
| <a id="bun_binary-entry_point"></a>entry_point | Path to the main JS/TS file to execute. | <a href="https://bazel.build/concepts/labels">Label</a> | required | |
|
||||
| <a id="bun_binary-env_files"></a>env_files | Additional environment files loaded with `--env-file`. | <a href="https://bazel.build/concepts/labels">List of labels</a> | optional | `[]` |
|
||||
| <a id="bun_binary-install_mode"></a>install_mode | Whether Bun may auto-install missing packages at runtime. Non-`disable` values are runtime opt-ins and are not hermetic. | String | optional | `"disable"` |
|
||||
| <a id="bun_binary-inherit_host_path"></a>inherit_host_path | If true, appends the host PATH after staged `node_modules/.bin` entries at runtime. | Boolean | optional | `False` |
|
||||
| <a id="bun_binary-no_env_file"></a>no_env_file | If true, disables Bun's automatic `.env` loading. | Boolean | optional | `False` |
|
||||
| <a id="bun_binary-node_modules"></a>node_modules | Optional label providing package files from a `node_modules` tree, typically produced by `bun_install`, in runfiles. | <a href="https://bazel.build/concepts/labels">Label</a> | optional | `None` |
|
||||
| <a id="bun_binary-preload"></a>preload | Modules to preload with `--preload` before running the entry point. | <a href="https://bazel.build/concepts/labels">List of labels</a> | optional | `[]` |
|
||||
| <a id="bun_binary-run_flags"></a>run_flags | Additional raw flags forwarded to `bun run` before the entry point. | List of strings | optional | `[]` |
|
||||
| <a id="bun_binary-smol"></a>smol | If true, enables Bun's lower-memory runtime mode. | Boolean | optional | `False` |
|
||||
| <a id="bun_binary-working_dir"></a>working_dir | Working directory at runtime: `workspace` root or nearest `entry_point` ancestor containing `.env`/`package.json`. | String | optional | `"workspace"` |
|
||||
|
||||
## bun_script
|
||||
|
||||
Runs a named `package.json` script with Bun as an executable target (`bazel run`).
|
||||
<a id="bun_build"></a>
|
||||
|
||||
Recommended for package-script based tools such as Vite (`dev`, `build`, `preview`).
|
||||
When `node_modules` is provided, executables from `node_modules/.bin` are added
|
||||
to `PATH`, so scripts like `vite` work without wrapper scripts.
|
||||
## bun_build
|
||||
|
||||
Attributes:
|
||||
<pre>
|
||||
load("@rules_bun//bun:defs.bzl", "bun_build")
|
||||
|
||||
- `script` (string, required): package script name passed to `bun run <script>`.
|
||||
- `package_json` (label, required): `package.json` file containing the named script.
|
||||
- `node_modules` (label, optional): package files from a `node_modules` tree, typically produced by `bun_install`, made available in runfiles.
|
||||
- `data` (label_list, optional): additional runtime files for the script.
|
||||
- `working_dir` (string, default: `"package"`, values: `"workspace" | "package"`): runtime working directory. The default is a good fit for Vite and similar package-script based tools.
|
||||
bun_build(<a href="#bun_build-name">name</a>, <a href="#bun_build-deps">deps</a>, <a href="#bun_build-data">data</a>, <a href="#bun_build-asset_naming">asset_naming</a>, <a href="#bun_build-banner">banner</a>, <a href="#bun_build-build_flags">build_flags</a>, <a href="#bun_build-chunk_naming">chunk_naming</a>, <a href="#bun_build-conditions">conditions</a>,
|
||||
<a href="#bun_build-css_chunking">css_chunking</a>, <a href="#bun_build-define">define</a>, <a href="#bun_build-drop">drop</a>, <a href="#bun_build-emit_dce_annotations">emit_dce_annotations</a>, <a href="#bun_build-entry_naming">entry_naming</a>, <a href="#bun_build-entry_points">entry_points</a>, <a href="#bun_build-env">env</a>, <a href="#bun_build-external">external</a>,
|
||||
<a href="#bun_build-feature">feature</a>, <a href="#bun_build-footer">footer</a>, <a href="#bun_build-format">format</a>, <a href="#bun_build-install_mode">install_mode</a>, <a href="#bun_build-jsx_factory">jsx_factory</a>, <a href="#bun_build-jsx_fragment">jsx_fragment</a>, <a href="#bun_build-jsx_import_source">jsx_import_source</a>,
|
||||
<a href="#bun_build-jsx_runtime">jsx_runtime</a>, <a href="#bun_build-jsx_side_effects">jsx_side_effects</a>, <a href="#bun_build-keep_names">keep_names</a>, <a href="#bun_build-loader">loader</a>, <a href="#bun_build-metafile">metafile</a>, <a href="#bun_build-metafile_md">metafile_md</a>, <a href="#bun_build-minify">minify</a>,
|
||||
<a href="#bun_build-minify_identifiers">minify_identifiers</a>, <a href="#bun_build-minify_syntax">minify_syntax</a>, <a href="#bun_build-minify_whitespace">minify_whitespace</a>, <a href="#bun_build-no_bundle">no_bundle</a>, <a href="#bun_build-node_modules">node_modules</a>, <a href="#bun_build-packages">packages</a>,
|
||||
<a href="#bun_build-production">production</a>, <a href="#bun_build-public_path">public_path</a>, <a href="#bun_build-react_fast_refresh">react_fast_refresh</a>, <a href="#bun_build-root">root</a>, <a href="#bun_build-sourcemap">sourcemap</a>, <a href="#bun_build-splitting">splitting</a>, <a href="#bun_build-target">target</a>)
|
||||
</pre>
|
||||
|
||||
Builds one or more entry points with `bun build`.
|
||||
|
||||
The rule emits a directory artifact so Bun can materialize multi-file output
|
||||
graphs such as HTML, CSS, assets, and split chunks. Optional metafile outputs
|
||||
may be requested with `metafile` and `metafile_md`.
|
||||
|
||||
**ATTRIBUTES**
|
||||
|
||||
|
||||
| Name | Description | Type | Mandatory | Default |
|
||||
| :------------- | :------------- | :------------- | :------------- | :------------- |
|
||||
| <a id="bun_build-name"></a>name | A unique name for this target. | <a href="https://bazel.build/concepts/labels#target-names">Name</a> | required | |
|
||||
| <a id="bun_build-deps"></a>deps | Source/library dependencies that provide transitive inputs. | <a href="https://bazel.build/concepts/labels">List of labels</a> | optional | `[]` |
|
||||
| <a id="bun_build-data"></a>data | Additional non-source files needed during building. | <a href="https://bazel.build/concepts/labels">List of labels</a> | optional | `[]` |
|
||||
| <a id="bun_build-asset_naming"></a>asset_naming | Optional asset naming template. | String | optional | `""` |
|
||||
| <a id="bun_build-banner"></a>banner | Optional bundle banner text. | String | optional | `""` |
|
||||
| <a id="bun_build-build_flags"></a>build_flags | Additional raw flags forwarded to `bun build`. | List of strings | optional | `[]` |
|
||||
| <a id="bun_build-chunk_naming"></a>chunk_naming | Optional chunk naming template. | String | optional | `""` |
|
||||
| <a id="bun_build-conditions"></a>conditions | Custom resolve conditions passed to Bun. | List of strings | optional | `[]` |
|
||||
| <a id="bun_build-css_chunking"></a>css_chunking | If true, Bun chunks CSS across multiple entry points. | Boolean | optional | `False` |
|
||||
| <a id="bun_build-define"></a>define | Repeated `--define` values such as `process.env.NODE_ENV:"production"`. | List of strings | optional | `[]` |
|
||||
| <a id="bun_build-drop"></a>drop | Repeated `--drop` values, for example `console`. | List of strings | optional | `[]` |
|
||||
| <a id="bun_build-emit_dce_annotations"></a>emit_dce_annotations | If true, re-emits DCE annotations in the bundle. | Boolean | optional | `False` |
|
||||
| <a id="bun_build-entry_naming"></a>entry_naming | Optional entry naming template. | String | optional | `""` |
|
||||
| <a id="bun_build-entry_points"></a>entry_points | Entry files to build, including JS/TS or HTML entry points. | <a href="https://bazel.build/concepts/labels">List of labels</a> | required | |
|
||||
| <a id="bun_build-env"></a>env | Inline environment variable behavior passed to `--env`. | String | optional | `""` |
|
||||
| <a id="bun_build-external"></a>external | Modules treated as externals (not bundled). | List of strings | optional | `[]` |
|
||||
| <a id="bun_build-feature"></a>feature | Repeated `--feature` values for dead-code elimination. | List of strings | optional | `[]` |
|
||||
| <a id="bun_build-footer"></a>footer | Optional bundle footer text. | String | optional | `""` |
|
||||
| <a id="bun_build-format"></a>format | Output module format. | String | optional | `"esm"` |
|
||||
| <a id="bun_build-install_mode"></a>install_mode | Whether Bun may auto-install missing packages while executing the build. Hermetic builds require `\"disable\"`, and other values are rejected. | String | optional | `"disable"` |
|
||||
| <a id="bun_build-jsx_factory"></a>jsx_factory | Optional JSX factory override. | String | optional | `""` |
|
||||
| <a id="bun_build-jsx_fragment"></a>jsx_fragment | Optional JSX fragment override. | String | optional | `""` |
|
||||
| <a id="bun_build-jsx_import_source"></a>jsx_import_source | Optional JSX import source override. | String | optional | `""` |
|
||||
| <a id="bun_build-jsx_runtime"></a>jsx_runtime | Optional JSX runtime override. | String | optional | `""` |
|
||||
| <a id="bun_build-jsx_side_effects"></a>jsx_side_effects | If true, treats JSX as having side effects. | Boolean | optional | `False` |
|
||||
| <a id="bun_build-keep_names"></a>keep_names | If true, preserves function and class names when minifying. | Boolean | optional | `False` |
|
||||
| <a id="bun_build-loader"></a>loader | Repeated `--loader` values such as `.svg:file`. | List of strings | optional | `[]` |
|
||||
| <a id="bun_build-metafile"></a>metafile | If true, emits Bun's JSON metafile alongside the output directory. | Boolean | optional | `False` |
|
||||
| <a id="bun_build-metafile_md"></a>metafile_md | If true, emits Bun's markdown metafile alongside the output directory. | Boolean | optional | `False` |
|
||||
| <a id="bun_build-minify"></a>minify | If true, enables all Bun minification passes. | Boolean | optional | `False` |
|
||||
| <a id="bun_build-minify_identifiers"></a>minify_identifiers | If true, minifies identifiers only. | Boolean | optional | `False` |
|
||||
| <a id="bun_build-minify_syntax"></a>minify_syntax | If true, minifies syntax only. | Boolean | optional | `False` |
|
||||
| <a id="bun_build-minify_whitespace"></a>minify_whitespace | If true, minifies whitespace only. | Boolean | optional | `False` |
|
||||
| <a id="bun_build-no_bundle"></a>no_bundle | If true, transpiles without bundling. | Boolean | optional | `False` |
|
||||
| <a id="bun_build-node_modules"></a>node_modules | Optional label providing package files from a `node_modules` tree, typically produced by `bun_install`, for package resolution. | <a href="https://bazel.build/concepts/labels">Label</a> | optional | `None` |
|
||||
| <a id="bun_build-packages"></a>packages | Whether packages stay bundled or are treated as external. | String | optional | `"bundle"` |
|
||||
| <a id="bun_build-production"></a>production | If true, sets `NODE_ENV=production` and enables Bun production mode. | Boolean | optional | `False` |
|
||||
| <a id="bun_build-public_path"></a>public_path | Optional public path prefix for emitted imports. | String | optional | `""` |
|
||||
| <a id="bun_build-react_fast_refresh"></a>react_fast_refresh | If true, enables Bun's React fast refresh transform. | Boolean | optional | `False` |
|
||||
| <a id="bun_build-root"></a>root | Optional root directory for multiple entry points. When omitted, `bun_build` derives one from the entry point parent directories to keep emitted files inside the declared output tree. | String | optional | `""` |
|
||||
| <a id="bun_build-sourcemap"></a>sourcemap | Sourcemap emission mode. | String | optional | `"none"` |
|
||||
| <a id="bun_build-splitting"></a>splitting | If true, enables code splitting. | Boolean | optional | `False` |
|
||||
| <a id="bun_build-target"></a>target | Bun build target environment. | String | optional | `"browser"` |
|
||||
|
||||
|
||||
<a id="bun_bundle"></a>
|
||||
|
||||
## bun_bundle
|
||||
|
||||
Bundles one or more JS/TS entry points with Bun build.
|
||||
<pre>
|
||||
load("@rules_bun//bun:defs.bzl", "bun_bundle")
|
||||
|
||||
Attributes:
|
||||
bun_bundle(<a href="#bun_bundle-name">name</a>, <a href="#bun_bundle-deps">deps</a>, <a href="#bun_bundle-data">data</a>, <a href="#bun_bundle-build_flags">build_flags</a>, <a href="#bun_bundle-entry_points">entry_points</a>, <a href="#bun_bundle-external">external</a>, <a href="#bun_bundle-format">format</a>, <a href="#bun_bundle-install_mode">install_mode</a>, <a href="#bun_bundle-minify">minify</a>,
|
||||
<a href="#bun_bundle-node_modules">node_modules</a>, <a href="#bun_bundle-sourcemap">sourcemap</a>, <a href="#bun_bundle-target">target</a>)
|
||||
</pre>
|
||||
|
||||
- `entry_points` (label_list, required): entry files to bundle.
|
||||
- `node_modules` (label, optional): package files from a `node_modules` tree, typically produced by `bun_install`, used for package resolution.
|
||||
- `deps` (label_list, optional): source/library dependencies for transitive inputs.
|
||||
- `data` (label_list, optional): additional non-source files needed during bundling.
|
||||
- `target` (string, default: `"browser"`, values: `"browser" | "node" | "bun"`): Bun build target.
|
||||
- `format` (string, default: `"esm"`, values: `"esm" | "cjs" | "iife"`): module format.
|
||||
- `minify` (bool, default: `False`): minifies bundle output.
|
||||
- `sourcemap` (bool, default: `False`): emits source maps.
|
||||
- `external` (string_list, optional): package names treated as external (not bundled).
|
||||
Bundles one or more JS/TS entry points using Bun build.
|
||||
|
||||
Each entry point produces one output JavaScript artifact.
|
||||
|
||||
**ATTRIBUTES**
|
||||
|
||||
|
||||
| Name | Description | Type | Mandatory | Default |
|
||||
| :------------- | :------------- | :------------- | :------------- | :------------- |
|
||||
| <a id="bun_bundle-name"></a>name | A unique name for this target. | <a href="https://bazel.build/concepts/labels#target-names">Name</a> | required | |
|
||||
| <a id="bun_bundle-deps"></a>deps | Source/library dependencies that provide transitive inputs. | <a href="https://bazel.build/concepts/labels">List of labels</a> | optional | `[]` |
|
||||
| <a id="bun_bundle-data"></a>data | Additional non-source files needed during bundling. | <a href="https://bazel.build/concepts/labels">List of labels</a> | optional | `[]` |
|
||||
| <a id="bun_bundle-build_flags"></a>build_flags | Additional raw flags forwarded to `bun build`. | List of strings | optional | `[]` |
|
||||
| <a id="bun_bundle-entry_points"></a>entry_points | Entry files to bundle. | <a href="https://bazel.build/concepts/labels">List of labels</a> | required | |
|
||||
| <a id="bun_bundle-external"></a>external | Package names to treat as externals (not bundled). | List of strings | optional | `[]` |
|
||||
| <a id="bun_bundle-format"></a>format | Output module format. | String | optional | `"esm"` |
|
||||
| <a id="bun_bundle-install_mode"></a>install_mode | Whether Bun may auto-install missing packages during bundling. Hermetic bundles require `\"disable\"`, and other values are rejected. | String | optional | `"disable"` |
|
||||
| <a id="bun_bundle-minify"></a>minify | If true, minifies bundle output. | Boolean | optional | `False` |
|
||||
| <a id="bun_bundle-node_modules"></a>node_modules | Optional label providing package files from a `node_modules` tree, typically produced by `bun_install`, for package resolution. | <a href="https://bazel.build/concepts/labels">Label</a> | optional | `None` |
|
||||
| <a id="bun_bundle-sourcemap"></a>sourcemap | If true, emits source maps. | Boolean | optional | `False` |
|
||||
| <a id="bun_bundle-target"></a>target | Bun build target environment. | String | optional | `"browser"` |
|
||||
|
||||
|
||||
<a id="bun_compile"></a>
|
||||
|
||||
## bun_compile
|
||||
|
||||
<pre>
|
||||
load("@rules_bun//bun:defs.bzl", "bun_compile")
|
||||
|
||||
bun_compile(<a href="#bun_compile-name">name</a>, <a href="#bun_compile-deps">deps</a>, <a href="#bun_compile-data">data</a>, <a href="#bun_compile-asset_naming">asset_naming</a>, <a href="#bun_compile-banner">banner</a>, <a href="#bun_compile-build_flags">build_flags</a>, <a href="#bun_compile-bytecode">bytecode</a>, <a href="#bun_compile-chunk_naming">chunk_naming</a>,
|
||||
<a href="#bun_compile-compile_autoload_bunfig">compile_autoload_bunfig</a>, <a href="#bun_compile-compile_autoload_dotenv">compile_autoload_dotenv</a>, <a href="#bun_compile-compile_autoload_package_json">compile_autoload_package_json</a>,
|
||||
<a href="#bun_compile-compile_autoload_tsconfig">compile_autoload_tsconfig</a>, <a href="#bun_compile-compile_exec_argv">compile_exec_argv</a>, <a href="#bun_compile-compile_executable">compile_executable</a>, <a href="#bun_compile-conditions">conditions</a>,
|
||||
<a href="#bun_compile-css_chunking">css_chunking</a>, <a href="#bun_compile-define">define</a>, <a href="#bun_compile-drop">drop</a>, <a href="#bun_compile-emit_dce_annotations">emit_dce_annotations</a>, <a href="#bun_compile-entry_naming">entry_naming</a>, <a href="#bun_compile-entry_point">entry_point</a>, <a href="#bun_compile-env">env</a>,
|
||||
<a href="#bun_compile-external">external</a>, <a href="#bun_compile-feature">feature</a>, <a href="#bun_compile-footer">footer</a>, <a href="#bun_compile-format">format</a>, <a href="#bun_compile-install_mode">install_mode</a>, <a href="#bun_compile-jsx_factory">jsx_factory</a>, <a href="#bun_compile-jsx_fragment">jsx_fragment</a>,
|
||||
<a href="#bun_compile-jsx_import_source">jsx_import_source</a>, <a href="#bun_compile-jsx_runtime">jsx_runtime</a>, <a href="#bun_compile-jsx_side_effects">jsx_side_effects</a>, <a href="#bun_compile-keep_names">keep_names</a>, <a href="#bun_compile-loader">loader</a>, <a href="#bun_compile-minify">minify</a>,
|
||||
<a href="#bun_compile-minify_identifiers">minify_identifiers</a>, <a href="#bun_compile-minify_syntax">minify_syntax</a>, <a href="#bun_compile-minify_whitespace">minify_whitespace</a>, <a href="#bun_compile-no_bundle">no_bundle</a>, <a href="#bun_compile-node_modules">node_modules</a>, <a href="#bun_compile-packages">packages</a>,
|
||||
<a href="#bun_compile-production">production</a>, <a href="#bun_compile-public_path">public_path</a>, <a href="#bun_compile-react_fast_refresh">react_fast_refresh</a>, <a href="#bun_compile-root">root</a>, <a href="#bun_compile-sourcemap">sourcemap</a>, <a href="#bun_compile-splitting">splitting</a>, <a href="#bun_compile-target">target</a>,
|
||||
<a href="#bun_compile-windows_copyright">windows_copyright</a>, <a href="#bun_compile-windows_description">windows_description</a>, <a href="#bun_compile-windows_hide_console">windows_hide_console</a>, <a href="#bun_compile-windows_icon">windows_icon</a>,
|
||||
<a href="#bun_compile-windows_publisher">windows_publisher</a>, <a href="#bun_compile-windows_title">windows_title</a>, <a href="#bun_compile-windows_version">windows_version</a>)
|
||||
</pre>
|
||||
|
||||
Compiles a Bun program into a standalone executable with `bun build --compile`.
|
||||
|
||||
**ATTRIBUTES**
|
||||
|
||||
|
||||
| Name | Description | Type | Mandatory | Default |
|
||||
| :------------- | :------------- | :------------- | :------------- | :------------- |
|
||||
| <a id="bun_compile-name"></a>name | A unique name for this target. | <a href="https://bazel.build/concepts/labels#target-names">Name</a> | required | |
|
||||
| <a id="bun_compile-deps"></a>deps | Source/library dependencies that provide transitive inputs. | <a href="https://bazel.build/concepts/labels">List of labels</a> | optional | `[]` |
|
||||
| <a id="bun_compile-data"></a>data | Additional non-source files needed during building. | <a href="https://bazel.build/concepts/labels">List of labels</a> | optional | `[]` |
|
||||
| <a id="bun_compile-asset_naming"></a>asset_naming | Optional asset naming template. | String | optional | `""` |
|
||||
| <a id="bun_compile-banner"></a>banner | Optional bundle banner text. | String | optional | `""` |
|
||||
| <a id="bun_compile-build_flags"></a>build_flags | Additional raw flags forwarded to `bun build`. | List of strings | optional | `[]` |
|
||||
| <a id="bun_compile-bytecode"></a>bytecode | If true, enables Bun bytecode caching in the compiled executable. | Boolean | optional | `False` |
|
||||
| <a id="bun_compile-chunk_naming"></a>chunk_naming | Optional chunk naming template. | String | optional | `""` |
|
||||
| <a id="bun_compile-compile_autoload_bunfig"></a>compile_autoload_bunfig | Whether the compiled executable auto-loads `bunfig.toml` at runtime. | Boolean | optional | `True` |
|
||||
| <a id="bun_compile-compile_autoload_dotenv"></a>compile_autoload_dotenv | Whether the compiled executable auto-loads `.env` files at runtime. | Boolean | optional | `True` |
|
||||
| <a id="bun_compile-compile_autoload_package_json"></a>compile_autoload_package_json | Whether the compiled executable auto-loads `package.json` at runtime. | Boolean | optional | `False` |
|
||||
| <a id="bun_compile-compile_autoload_tsconfig"></a>compile_autoload_tsconfig | Whether the compiled executable auto-loads `tsconfig.json` at runtime. | Boolean | optional | `False` |
|
||||
| <a id="bun_compile-compile_exec_argv"></a>compile_exec_argv | Repeated `--compile-exec-argv` values prepended to the executable's `execArgv`. | List of strings | optional | `[]` |
|
||||
| <a id="bun_compile-compile_executable"></a>compile_executable | Optional Bun executable used for cross-compilation via `--compile-executable-path`. | <a href="https://bazel.build/concepts/labels">Label</a> | optional | `None` |
|
||||
| <a id="bun_compile-conditions"></a>conditions | Custom resolve conditions passed to Bun. | List of strings | optional | `[]` |
|
||||
| <a id="bun_compile-css_chunking"></a>css_chunking | If true, Bun chunks CSS across multiple entry points. | Boolean | optional | `False` |
|
||||
| <a id="bun_compile-define"></a>define | Repeated `--define` values such as `process.env.NODE_ENV:"production"`. | List of strings | optional | `[]` |
|
||||
| <a id="bun_compile-drop"></a>drop | Repeated `--drop` values, for example `console`. | List of strings | optional | `[]` |
|
||||
| <a id="bun_compile-emit_dce_annotations"></a>emit_dce_annotations | If true, re-emits DCE annotations in the bundle. | Boolean | optional | `False` |
|
||||
| <a id="bun_compile-entry_naming"></a>entry_naming | Optional entry naming template. | String | optional | `""` |
|
||||
| <a id="bun_compile-entry_point"></a>entry_point | Entry file to compile into an executable. | <a href="https://bazel.build/concepts/labels">Label</a> | required | |
|
||||
| <a id="bun_compile-env"></a>env | Inline environment variable behavior passed to `--env`. | String | optional | `""` |
|
||||
| <a id="bun_compile-external"></a>external | Modules treated as externals (not bundled). | List of strings | optional | `[]` |
|
||||
| <a id="bun_compile-feature"></a>feature | Repeated `--feature` values for dead-code elimination. | List of strings | optional | `[]` |
|
||||
| <a id="bun_compile-footer"></a>footer | Optional bundle footer text. | String | optional | `""` |
|
||||
| <a id="bun_compile-format"></a>format | Output module format. | String | optional | `"esm"` |
|
||||
| <a id="bun_compile-install_mode"></a>install_mode | Whether Bun may auto-install missing packages while executing the build. Hermetic compile actions require `\"disable\"`, and other values are rejected. | String | optional | `"disable"` |
|
||||
| <a id="bun_compile-jsx_factory"></a>jsx_factory | Optional JSX factory override. | String | optional | `""` |
|
||||
| <a id="bun_compile-jsx_fragment"></a>jsx_fragment | Optional JSX fragment override. | String | optional | `""` |
|
||||
| <a id="bun_compile-jsx_import_source"></a>jsx_import_source | Optional JSX import source override. | String | optional | `""` |
|
||||
| <a id="bun_compile-jsx_runtime"></a>jsx_runtime | Optional JSX runtime override. | String | optional | `""` |
|
||||
| <a id="bun_compile-jsx_side_effects"></a>jsx_side_effects | If true, treats JSX as having side effects. | Boolean | optional | `False` |
|
||||
| <a id="bun_compile-keep_names"></a>keep_names | If true, preserves function and class names when minifying. | Boolean | optional | `False` |
|
||||
| <a id="bun_compile-loader"></a>loader | Repeated `--loader` values such as `.svg:file`. | List of strings | optional | `[]` |
|
||||
| <a id="bun_compile-minify"></a>minify | If true, enables all Bun minification passes. | Boolean | optional | `False` |
|
||||
| <a id="bun_compile-minify_identifiers"></a>minify_identifiers | If true, minifies identifiers only. | Boolean | optional | `False` |
|
||||
| <a id="bun_compile-minify_syntax"></a>minify_syntax | If true, minifies syntax only. | Boolean | optional | `False` |
|
||||
| <a id="bun_compile-minify_whitespace"></a>minify_whitespace | If true, minifies whitespace only. | Boolean | optional | `False` |
|
||||
| <a id="bun_compile-no_bundle"></a>no_bundle | If true, transpiles without bundling. | Boolean | optional | `False` |
|
||||
| <a id="bun_compile-node_modules"></a>node_modules | Optional label providing package files from a `node_modules` tree, typically produced by `bun_install`, for package resolution. | <a href="https://bazel.build/concepts/labels">Label</a> | optional | `None` |
|
||||
| <a id="bun_compile-packages"></a>packages | Whether packages stay bundled or are treated as external. | String | optional | `"bundle"` |
|
||||
| <a id="bun_compile-production"></a>production | If true, sets `NODE_ENV=production` and enables Bun production mode. | Boolean | optional | `False` |
|
||||
| <a id="bun_compile-public_path"></a>public_path | Optional public path prefix for emitted imports. | String | optional | `""` |
|
||||
| <a id="bun_compile-react_fast_refresh"></a>react_fast_refresh | If true, enables Bun's React fast refresh transform. | Boolean | optional | `False` |
|
||||
| <a id="bun_compile-root"></a>root | Optional root directory for multiple entry points. | String | optional | `""` |
|
||||
| <a id="bun_compile-sourcemap"></a>sourcemap | Sourcemap emission mode. | String | optional | `"none"` |
|
||||
| <a id="bun_compile-splitting"></a>splitting | If true, enables code splitting. | Boolean | optional | `False` |
|
||||
| <a id="bun_compile-target"></a>target | Bun build target environment for the compiled executable. | String | optional | `"bun"` |
|
||||
| <a id="bun_compile-windows_copyright"></a>windows_copyright | Optional Windows copyright metadata. | String | optional | `""` |
|
||||
| <a id="bun_compile-windows_description"></a>windows_description | Optional Windows description metadata. | String | optional | `""` |
|
||||
| <a id="bun_compile-windows_hide_console"></a>windows_hide_console | When targeting Windows, hides the console window for GUI-style executables. | Boolean | optional | `False` |
|
||||
| <a id="bun_compile-windows_icon"></a>windows_icon | Optional Windows icon path passed directly to Bun. | String | optional | `""` |
|
||||
| <a id="bun_compile-windows_publisher"></a>windows_publisher | Optional Windows publisher metadata. | String | optional | `""` |
|
||||
| <a id="bun_compile-windows_title"></a>windows_title | Optional Windows executable title. | String | optional | `""` |
|
||||
| <a id="bun_compile-windows_version"></a>windows_version | Optional Windows version metadata. | String | optional | `""` |
|
||||
|
||||
|
||||
<a id="bun_dev"></a>
|
||||
|
||||
## bun_dev
|
||||
|
||||
<pre>
|
||||
load("@rules_bun//bun:defs.bzl", "bun_dev")
|
||||
|
||||
bun_dev(<a href="#bun_dev-name">name</a>, <a href="#bun_dev-data">data</a>, <a href="#bun_dev-conditions">conditions</a>, <a href="#bun_dev-entry_point">entry_point</a>, <a href="#bun_dev-env_files">env_files</a>, <a href="#bun_dev-install_mode">install_mode</a>, <a href="#bun_dev-no_clear_screen">no_clear_screen</a>, <a href="#bun_dev-no_env_file">no_env_file</a>,
|
||||
<a href="#bun_dev-node_modules">node_modules</a>, <a href="#bun_dev-preload">preload</a>, <a href="#bun_dev-restart_on">restart_on</a>, <a href="#bun_dev-run_flags">run_flags</a>, <a href="#bun_dev-smol">smol</a>, <a href="#bun_dev-watch_mode">watch_mode</a>, <a href="#bun_dev-working_dir">working_dir</a>)
|
||||
</pre>
|
||||
|
||||
Runs a JS/TS entry point in Bun development watch mode.
|
||||
|
||||
This rule is intended for local dev loops (`bazel run`) and supports Bun
|
||||
watch/HMR plus optional full restarts on selected file changes.
|
||||
|
||||
**ATTRIBUTES**
|
||||
|
||||
|
||||
| Name | Description | Type | Mandatory | Default |
|
||||
| :------------- | :------------- | :------------- | :------------- | :------------- |
|
||||
| <a id="bun_dev-name"></a>name | A unique name for this target. | <a href="https://bazel.build/concepts/labels#target-names">Name</a> | required | |
|
||||
| <a id="bun_dev-data"></a>data | Additional runtime files required by the dev process. | <a href="https://bazel.build/concepts/labels">List of labels</a> | optional | `[]` |
|
||||
| <a id="bun_dev-conditions"></a>conditions | Custom package resolve conditions passed to Bun. | List of strings | optional | `[]` |
|
||||
| <a id="bun_dev-entry_point"></a>entry_point | Path to the main JS/TS file to execute in dev mode. | <a href="https://bazel.build/concepts/labels">Label</a> | required | |
|
||||
| <a id="bun_dev-env_files"></a>env_files | Additional environment files loaded with `--env-file`. | <a href="https://bazel.build/concepts/labels">List of labels</a> | optional | `[]` |
|
||||
| <a id="bun_dev-install_mode"></a>install_mode | Whether Bun may auto-install missing packages in dev mode. This is a local workflow helper, not a hermetic execution surface. | String | optional | `"disable"` |
|
||||
| <a id="bun_dev-inherit_host_path"></a>inherit_host_path | If true, appends the host PATH after staged `node_modules/.bin` entries at runtime. | Boolean | optional | `False` |
|
||||
| <a id="bun_dev-no_clear_screen"></a>no_clear_screen | If true, disables terminal clearing on Bun reloads. | Boolean | optional | `False` |
|
||||
| <a id="bun_dev-no_env_file"></a>no_env_file | If true, disables Bun's automatic `.env` loading. | Boolean | optional | `False` |
|
||||
| <a id="bun_dev-node_modules"></a>node_modules | Optional label providing package files from a `node_modules` tree, typically produced by `bun_install`, in runfiles. | <a href="https://bazel.build/concepts/labels">Label</a> | optional | `None` |
|
||||
| <a id="bun_dev-preload"></a>preload | Modules to preload with `--preload` before running the entry point. | <a href="https://bazel.build/concepts/labels">List of labels</a> | optional | `[]` |
|
||||
| <a id="bun_dev-restart_on"></a>restart_on | Files that trigger a full Bun process restart when they change. | <a href="https://bazel.build/concepts/labels">List of labels</a> | optional | `[]` |
|
||||
| <a id="bun_dev-run_flags"></a>run_flags | Additional raw flags forwarded to `bun run` before the entry point. | List of strings | optional | `[]` |
|
||||
| <a id="bun_dev-smol"></a>smol | If true, enables Bun's lower-memory runtime mode. | Boolean | optional | `False` |
|
||||
| <a id="bun_dev-watch_mode"></a>watch_mode | Bun live-reload mode: `watch` (default) or `hot`. | String | optional | `"watch"` |
|
||||
| <a id="bun_dev-working_dir"></a>working_dir | Working directory at runtime: `workspace` root or nearest `entry_point` ancestor containing `.env`/`package.json`. | String | optional | `"workspace"` |
|
||||
|
||||
|
||||
<a id="bun_script"></a>
|
||||
|
||||
## bun_script
|
||||
|
||||
<pre>
|
||||
load("@rules_bun//bun:defs.bzl", "bun_script")
|
||||
|
||||
bun_script(<a href="#bun_script-name">name</a>, <a href="#bun_script-data">data</a>, <a href="#bun_script-conditions">conditions</a>, <a href="#bun_script-env_files">env_files</a>, <a href="#bun_script-execution_mode">execution_mode</a>, <a href="#bun_script-filters">filters</a>, <a href="#bun_script-install_mode">install_mode</a>, <a href="#bun_script-no_env_file">no_env_file</a>,
|
||||
<a href="#bun_script-no_exit_on_error">no_exit_on_error</a>, <a href="#bun_script-node_modules">node_modules</a>, <a href="#bun_script-package_json">package_json</a>, <a href="#bun_script-preload">preload</a>, <a href="#bun_script-run_flags">run_flags</a>, <a href="#bun_script-script">script</a>, <a href="#bun_script-shell">shell</a>, <a href="#bun_script-silent">silent</a>,
|
||||
<a href="#bun_script-smol">smol</a>, <a href="#bun_script-working_dir">working_dir</a>, <a href="#bun_script-workspaces">workspaces</a>)
|
||||
</pre>
|
||||
|
||||
Runs a named `package.json` script with Bun as an executable target.
|
||||
|
||||
Use this rule to expose existing package scripts such as `dev`, `build`, or
|
||||
`check` via `bazel run` without adding wrapper shell scripts. This is a good fit
|
||||
for Vite-style workflows, where scripts like `vite dev` or `vite build` are
|
||||
declared in `package.json` and expect to run from the package directory with
|
||||
`node_modules/.bin` available on `PATH`.
|
||||
|
||||
**ATTRIBUTES**
|
||||
|
||||
|
||||
| Name | Description | Type | Mandatory | Default |
|
||||
| :------------- | :------------- | :------------- | :------------- | :------------- |
|
||||
| <a id="bun_script-name"></a>name | A unique name for this target. | <a href="https://bazel.build/concepts/labels#target-names">Name</a> | required | |
|
||||
| <a id="bun_script-data"></a>data | Additional runtime files required by the script. | <a href="https://bazel.build/concepts/labels">List of labels</a> | optional | `[]` |
|
||||
| <a id="bun_script-conditions"></a>conditions | Custom package resolve conditions passed to Bun. | List of strings | optional | `[]` |
|
||||
| <a id="bun_script-env_files"></a>env_files | Additional environment files loaded with `--env-file`. | <a href="https://bazel.build/concepts/labels">List of labels</a> | optional | `[]` |
|
||||
| <a id="bun_script-execution_mode"></a>execution_mode | How Bun should execute matching workspace scripts. | String | optional | `"single"` |
|
||||
| <a id="bun_script-filters"></a>filters | Workspace package filters passed via repeated `--filter` flags. | List of strings | optional | `[]` |
|
||||
| <a id="bun_script-install_mode"></a>install_mode | Whether Bun may auto-install missing packages while running the script. This is a local workflow helper, not a hermetic execution surface. | String | optional | `"disable"` |
|
||||
| <a id="bun_script-inherit_host_path"></a>inherit_host_path | If true, appends the host PATH after staged `node_modules/.bin` entries at runtime. | Boolean | optional | `False` |
|
||||
| <a id="bun_script-no_env_file"></a>no_env_file | If true, disables Bun's automatic `.env` loading. | Boolean | optional | `False` |
|
||||
| <a id="bun_script-no_exit_on_error"></a>no_exit_on_error | If true, Bun keeps running other workspace scripts when one fails. | Boolean | optional | `False` |
|
||||
| <a id="bun_script-node_modules"></a>node_modules | Optional label providing package files from a `node_modules` tree, typically produced by `bun_install`, in runfiles. Executables from `node_modules/.bin` are added to `PATH`, which is useful for scripts such as `vite`. | <a href="https://bazel.build/concepts/labels">Label</a> | optional | `None` |
|
||||
| <a id="bun_script-package_json"></a>package_json | Label of the `package.json` file containing the named script. | <a href="https://bazel.build/concepts/labels">Label</a> | required | |
|
||||
| <a id="bun_script-preload"></a>preload | Modules to preload with `--preload` before running the script. | <a href="https://bazel.build/concepts/labels">List of labels</a> | optional | `[]` |
|
||||
| <a id="bun_script-run_flags"></a>run_flags | Additional raw flags forwarded to `bun run` before the script name. | List of strings | optional | `[]` |
|
||||
| <a id="bun_script-script"></a>script | Name of the `package.json` script to execute via `bun run <script>`. | String | required | |
|
||||
| <a id="bun_script-shell"></a>shell | Optional shell implementation for package scripts. | String | optional | `""` |
|
||||
| <a id="bun_script-silent"></a>silent | If true, suppresses Bun's command echo for package scripts. | Boolean | optional | `False` |
|
||||
| <a id="bun_script-smol"></a>smol | If true, enables Bun's lower-memory runtime mode. | Boolean | optional | `False` |
|
||||
| <a id="bun_script-working_dir"></a>working_dir | Working directory at runtime: Bazel runfiles `workspace` root or the directory containing `package.json`. The default `package` mode matches tools such as Vite that resolve config and assets relative to the package directory. | String | optional | `"package"` |
|
||||
| <a id="bun_script-workspaces"></a>workspaces | If true, runs the script in all workspace packages. | Boolean | optional | `False` |
|
||||
|
||||
|
||||
<a id="bun_test"></a>
|
||||
|
||||
## bun_test
|
||||
|
||||
Runs Bun tests as a Bazel test target (`bazel test`).
|
||||
<pre>
|
||||
load("@rules_bun//bun:defs.bzl", "bun_test")
|
||||
|
||||
Attributes:
|
||||
bun_test(<a href="#bun_test-name">name</a>, <a href="#bun_test-deps">deps</a>, <a href="#bun_test-srcs">srcs</a>, <a href="#bun_test-data">data</a>, <a href="#bun_test-bail">bail</a>, <a href="#bun_test-concurrent">concurrent</a>, <a href="#bun_test-coverage">coverage</a>, <a href="#bun_test-coverage_reporters">coverage_reporters</a>, <a href="#bun_test-env_files">env_files</a>,
|
||||
<a href="#bun_test-install_mode">install_mode</a>, <a href="#bun_test-max_concurrency">max_concurrency</a>, <a href="#bun_test-no_env_file">no_env_file</a>, <a href="#bun_test-node_modules">node_modules</a>, <a href="#bun_test-only">only</a>, <a href="#bun_test-pass_with_no_tests">pass_with_no_tests</a>, <a href="#bun_test-preload">preload</a>,
|
||||
<a href="#bun_test-randomize">randomize</a>, <a href="#bun_test-reporter">reporter</a>, <a href="#bun_test-rerun_each">rerun_each</a>, <a href="#bun_test-retry">retry</a>, <a href="#bun_test-seed">seed</a>, <a href="#bun_test-smol">smol</a>, <a href="#bun_test-test_flags">test_flags</a>, <a href="#bun_test-timeout_ms">timeout_ms</a>, <a href="#bun_test-todo">todo</a>,
|
||||
<a href="#bun_test-update_snapshots">update_snapshots</a>)
|
||||
</pre>
|
||||
|
||||
- `srcs` (label_list, required): test source files passed to `bun test`.
|
||||
- `node_modules` (label, optional): package files from a `node_modules` tree, typically produced by `bun_install`, made available in runfiles.
|
||||
- `deps` (label_list, optional): library dependencies required by tests.
|
||||
- `data` (label_list, optional): additional runtime files needed by tests.
|
||||
Runs Bun tests as a Bazel test target.
|
||||
|
||||
Supports Bazel test filtering (`--test_filter`) and coverage integration.
|
||||
|
||||
**ATTRIBUTES**
|
||||
|
||||
|
||||
| Name | Description | Type | Mandatory | Default |
|
||||
| :------------- | :------------- | :------------- | :------------- | :------------- |
|
||||
| <a id="bun_test-name"></a>name | A unique name for this target. | <a href="https://bazel.build/concepts/labels#target-names">Name</a> | required | |
|
||||
| <a id="bun_test-deps"></a>deps | Library dependencies required by test sources. | <a href="https://bazel.build/concepts/labels">List of labels</a> | optional | `[]` |
|
||||
| <a id="bun_test-srcs"></a>srcs | Test source files passed to `bun test`. | <a href="https://bazel.build/concepts/labels">List of labels</a> | required | |
|
||||
| <a id="bun_test-data"></a>data | Additional runtime files needed by tests. | <a href="https://bazel.build/concepts/labels">List of labels</a> | optional | `[]` |
|
||||
| <a id="bun_test-bail"></a>bail | Optional failure count after which Bun exits the test run. | Integer | optional | `0` |
|
||||
| <a id="bun_test-concurrent"></a>concurrent | If true, treats all tests as concurrent tests. | Boolean | optional | `False` |
|
||||
| <a id="bun_test-coverage"></a>coverage | If true, always enables Bun coverage output. | Boolean | optional | `False` |
|
||||
| <a id="bun_test-coverage_reporters"></a>coverage_reporters | Repeated Bun coverage reporters such as `text` or `lcov`. | List of strings | optional | `[]` |
|
||||
| <a id="bun_test-env_files"></a>env_files | Additional environment files loaded with `--env-file`. | <a href="https://bazel.build/concepts/labels">List of labels</a> | optional | `[]` |
|
||||
| <a id="bun_test-install_mode"></a>install_mode | Whether Bun may auto-install missing packages while testing. Hermetic tests require `\"disable\"`, and other values are rejected. | String | optional | `"disable"` |
|
||||
| <a id="bun_test-inherit_host_path"></a>inherit_host_path | If true, appends the host PATH after staged `node_modules/.bin` entries at runtime. | Boolean | optional | `False` |
|
||||
| <a id="bun_test-max_concurrency"></a>max_concurrency | Optional maximum number of concurrent tests. | Integer | optional | `0` |
|
||||
| <a id="bun_test-no_env_file"></a>no_env_file | If true, disables Bun's automatic `.env` loading. | Boolean | optional | `False` |
|
||||
| <a id="bun_test-node_modules"></a>node_modules | Optional label providing package files from a `node_modules` tree, typically produced by `bun_install`, in runfiles. | <a href="https://bazel.build/concepts/labels">Label</a> | optional | `None` |
|
||||
| <a id="bun_test-only"></a>only | If true, runs only tests marked with `test.only()` or `describe.only()`. | Boolean | optional | `False` |
|
||||
| <a id="bun_test-pass_with_no_tests"></a>pass_with_no_tests | If true, exits successfully when no tests are found. | Boolean | optional | `False` |
|
||||
| <a id="bun_test-preload"></a>preload | Modules to preload with `--preload` before running tests. | <a href="https://bazel.build/concepts/labels">List of labels</a> | optional | `[]` |
|
||||
| <a id="bun_test-randomize"></a>randomize | If true, runs tests in random order. | Boolean | optional | `False` |
|
||||
| <a id="bun_test-reporter"></a>reporter | Test reporter format. | String | optional | `"console"` |
|
||||
| <a id="bun_test-rerun_each"></a>rerun_each | Optional number of times to rerun each test file. | Integer | optional | `0` |
|
||||
| <a id="bun_test-retry"></a>retry | Optional default retry count for all tests. | Integer | optional | `0` |
|
||||
| <a id="bun_test-seed"></a>seed | Optional randomization seed. | Integer | optional | `0` |
|
||||
| <a id="bun_test-smol"></a>smol | If true, enables Bun's lower-memory runtime mode. | Boolean | optional | `False` |
|
||||
| <a id="bun_test-test_flags"></a>test_flags | Additional raw flags forwarded to `bun test` before the test source list. | List of strings | optional | `[]` |
|
||||
| <a id="bun_test-timeout_ms"></a>timeout_ms | Optional per-test timeout in milliseconds. | Integer | optional | `0` |
|
||||
| <a id="bun_test-todo"></a>todo | If true, includes tests marked with `test.todo()`. | Boolean | optional | `False` |
|
||||
| <a id="bun_test-update_snapshots"></a>update_snapshots | If true, updates Bun snapshot files. | Boolean | optional | `False` |
|
||||
|
||||
|
||||
<a id="js_library"></a>
|
||||
|
||||
## js_library
|
||||
|
||||
<pre>
|
||||
load("@rules_bun//bun:defs.bzl", "js_library")
|
||||
|
||||
js_library(<a href="#js_library-name">name</a>, <a href="#js_library-deps">deps</a>, <a href="#js_library-srcs">srcs</a>, <a href="#js_library-data">data</a>, <a href="#js_library-types">types</a>)
|
||||
</pre>
|
||||
|
||||
Aggregates JavaScript sources and transitive Bun source dependencies.
|
||||
|
||||
Attributes:
|
||||
**ATTRIBUTES**
|
||||
|
||||
- `srcs` (label_list, optional): `.js`, `.jsx`, `.mjs`, `.cjs` files.
|
||||
- `deps` (label_list, optional): dependent source libraries.
|
||||
|
||||
| Name | Description | Type | Mandatory | Default |
|
||||
| :------------- | :------------- | :------------- | :------------- | :------------- |
|
||||
| <a id="js_library-name"></a>name | A unique name for this target. | <a href="https://bazel.build/concepts/labels#target-names">Name</a> | required | |
|
||||
| <a id="js_library-deps"></a>deps | Other Bun source libraries to include transitively. | <a href="https://bazel.build/concepts/labels">List of labels</a> | optional | `[]` |
|
||||
| <a id="js_library-srcs"></a>srcs | JavaScript source files in this library. | <a href="https://bazel.build/concepts/labels">List of labels</a> | optional | `[]` |
|
||||
| <a id="js_library-data"></a>data | Optional runtime files propagated to dependents. | <a href="https://bazel.build/concepts/labels">List of labels</a> | optional | `[]` |
|
||||
| <a id="js_library-types"></a>types | Optional declaration files associated with this library. | <a href="https://bazel.build/concepts/labels">List of labels</a> | optional | `[]` |
|
||||
|
||||
|
||||
<a id="js_run_devserver"></a>
|
||||
|
||||
## js_run_devserver
|
||||
|
||||
<pre>
|
||||
load("@rules_bun//bun:defs.bzl", "js_run_devserver")
|
||||
|
||||
js_run_devserver(<a href="#js_run_devserver-name">name</a>, <a href="#js_run_devserver-deps">deps</a>, <a href="#js_run_devserver-data">data</a>, <a href="#js_run_devserver-node_modules">node_modules</a>, <a href="#js_run_devserver-package_dir_hint">package_dir_hint</a>, <a href="#js_run_devserver-package_json">package_json</a>, <a href="#js_run_devserver-tool">tool</a>, <a href="#js_run_devserver-working_dir">working_dir</a>)
|
||||
</pre>
|
||||
|
||||
Runs an executable target from a staged JS workspace.
|
||||
|
||||
This is a Bun-backed compatibility adapter for `rules_js`-style devserver
|
||||
targets. It stages the same runtime workspace as the Bun rules, then executes
|
||||
the provided tool with any default arguments.
|
||||
|
||||
**ATTRIBUTES**
|
||||
|
||||
|
||||
| Name | Description | Type | Mandatory | Default |
|
||||
| :------------- | :------------- | :------------- | :------------- | :------------- |
|
||||
| <a id="js_run_devserver-name"></a>name | A unique name for this target. | <a href="https://bazel.build/concepts/labels#target-names">Name</a> | required | |
|
||||
| <a id="js_run_devserver-deps"></a>deps | Library dependencies required by the dev server. | <a href="https://bazel.build/concepts/labels">List of labels</a> | optional | `[]` |
|
||||
| <a id="js_run_devserver-data"></a>data | Additional runtime files required by the dev server. | <a href="https://bazel.build/concepts/labels">List of labels</a> | optional | `[]` |
|
||||
| <a id="js_run_devserver-node_modules"></a>node_modules | Optional label providing package files from a node_modules tree, typically produced by bun_install or npm_translate_lock, in runfiles. | <a href="https://bazel.build/concepts/labels">Label</a> | optional | `None` |
|
||||
| <a id="js_run_devserver-package_dir_hint"></a>package_dir_hint | Optional package-relative directory hint when package_json is not supplied. | String | optional | `"."` |
|
||||
| <a id="js_run_devserver-package_json"></a>package_json | Optional package.json used to resolve the package working directory. | <a href="https://bazel.build/concepts/labels">Label</a> | optional | `None` |
|
||||
| <a id="js_run_devserver-tool"></a>tool | Executable target to launch as the dev server. | <a href="https://bazel.build/concepts/labels">Label</a> | required | |
|
||||
| <a id="js_run_devserver-inherit_host_path"></a>inherit_host_path | If true, appends the host PATH after staged `node_modules/.bin` entries at runtime. | Boolean | optional | `False` |
|
||||
| <a id="js_run_devserver-working_dir"></a>working_dir | Working directory at runtime: Bazel runfiles workspace root or the resolved package directory. | String | optional | `"workspace"` |
|
||||
|
||||
|
||||
<a id="ts_library"></a>
|
||||
|
||||
## ts_library
|
||||
|
||||
<pre>
|
||||
load("@rules_bun//bun:defs.bzl", "ts_library")
|
||||
|
||||
ts_library(<a href="#ts_library-name">name</a>, <a href="#ts_library-deps">deps</a>, <a href="#ts_library-srcs">srcs</a>, <a href="#ts_library-data">data</a>, <a href="#ts_library-types">types</a>)
|
||||
</pre>
|
||||
|
||||
Aggregates TypeScript sources and transitive Bun source dependencies.
|
||||
|
||||
Attributes:
|
||||
**ATTRIBUTES**
|
||||
|
||||
- `srcs` (label_list, optional): `.ts`, `.tsx` files.
|
||||
- `deps` (label_list, optional): dependent source libraries.
|
||||
|
||||
| Name | Description | Type | Mandatory | Default |
|
||||
| :------------- | :------------- | :------------- | :------------- | :------------- |
|
||||
| <a id="ts_library-name"></a>name | A unique name for this target. | <a href="https://bazel.build/concepts/labels#target-names">Name</a> | required | |
|
||||
| <a id="ts_library-deps"></a>deps | Other Bun source libraries to include transitively. | <a href="https://bazel.build/concepts/labels">List of labels</a> | optional | `[]` |
|
||||
| <a id="ts_library-srcs"></a>srcs | TypeScript source files in this library. | <a href="https://bazel.build/concepts/labels">List of labels</a> | optional | `[]` |
|
||||
| <a id="ts_library-data"></a>data | Optional runtime files propagated to dependents. | <a href="https://bazel.build/concepts/labels">List of labels</a> | optional | `[]` |
|
||||
| <a id="ts_library-types"></a>types | Optional declaration files associated with this library. | <a href="https://bazel.build/concepts/labels">List of labels</a> | optional | `[]` |
|
||||
|
||||
|
||||
<a id="js_binary"></a>
|
||||
|
||||
## js_binary
|
||||
|
||||
<pre>
|
||||
load("@rules_bun//bun:defs.bzl", "js_binary")
|
||||
|
||||
js_binary(<a href="#js_binary-name">name</a>, <a href="#js_binary-kwargs">**kwargs</a>)
|
||||
</pre>
|
||||
|
||||
|
||||
|
||||
**PARAMETERS**
|
||||
|
||||
|
||||
| Name | Description | Default Value |
|
||||
| :------------- | :------------- | :------------- |
|
||||
| <a id="js_binary-name"></a>name | <p align="center"> - </p> | none |
|
||||
| <a id="js_binary-kwargs"></a>kwargs | <p align="center"> - </p> | none |
|
||||
|
||||
|
||||
<a id="js_test"></a>
|
||||
|
||||
## js_test
|
||||
|
||||
<pre>
|
||||
load("@rules_bun//bun:defs.bzl", "js_test")
|
||||
|
||||
js_test(<a href="#js_test-name">name</a>, <a href="#js_test-entry_point">entry_point</a>, <a href="#js_test-srcs">srcs</a>, <a href="#js_test-kwargs">**kwargs</a>)
|
||||
</pre>
|
||||
|
||||
|
||||
|
||||
**PARAMETERS**
|
||||
|
||||
|
||||
| Name | Description | Default Value |
|
||||
| :------------- | :------------- | :------------- |
|
||||
| <a id="js_test-name"></a>name | <p align="center"> - </p> | none |
|
||||
| <a id="js_test-entry_point"></a>entry_point | <p align="center"> - </p> | `None` |
|
||||
| <a id="js_test-srcs"></a>srcs | <p align="center"> - </p> | `None` |
|
||||
| <a id="js_test-kwargs"></a>kwargs | <p align="center"> - </p> | none |
|
||||
|
||||
@@ -11,3 +11,11 @@ bun_dev(
|
||||
name = "web_dev",
|
||||
entry_point = "main.ts",
|
||||
)
|
||||
|
||||
bun_dev(
|
||||
name = "web_dev_hot_restart",
|
||||
entry_point = "main.ts",
|
||||
no_clear_screen = True,
|
||||
restart_on = ["README.md"],
|
||||
watch_mode = "hot",
|
||||
)
|
||||
|
||||
@@ -9,3 +9,12 @@ bazel run //examples/basic:web_dev
|
||||
```
|
||||
|
||||
This starts Bun in watch mode for `main.ts`.
|
||||
|
||||
For the hot-reload launcher variant:
|
||||
|
||||
```bash
|
||||
bazel run //examples/basic:web_dev_hot_restart
|
||||
```
|
||||
|
||||
This starts Bun with `watch_mode = "hot"`, disables screen clearing, and wires
|
||||
`README.md` through `restart_on` to exercise the custom restart launcher path.
|
||||
|
||||
80
flake.lock
generated
80
flake.lock
generated
@@ -1,28 +1,5 @@
|
||||
{
|
||||
"nodes": {
|
||||
"devshell-lib": {
|
||||
"inputs": {
|
||||
"git-hooks": "git-hooks",
|
||||
"nixpkgs": [
|
||||
"nixpkgs"
|
||||
],
|
||||
"treefmt-nix": "treefmt-nix"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1772815059,
|
||||
"narHash": "sha256-9Mn8t/a7b43omtmKRsF0HmFpCkNpTsvYEq0y85KLL5s=",
|
||||
"ref": "v2.0.1",
|
||||
"rev": "80cc529de7060e079d89a69d8daaf0347b53d8f9",
|
||||
"revCount": 43,
|
||||
"type": "git",
|
||||
"url": "https://git.dgren.dev/eric/nix-flake-lib"
|
||||
},
|
||||
"original": {
|
||||
"ref": "v2.0.1",
|
||||
"type": "git",
|
||||
"url": "https://git.dgren.dev/eric/nix-flake-lib"
|
||||
}
|
||||
},
|
||||
"flake-compat": {
|
||||
"flake": false,
|
||||
"locked": {
|
||||
@@ -43,7 +20,7 @@
|
||||
"inputs": {
|
||||
"flake-compat": "flake-compat",
|
||||
"gitignore": "gitignore",
|
||||
"nixpkgs": "nixpkgs"
|
||||
"nixpkgs": "nixpkgs_2"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1772024342,
|
||||
@@ -62,7 +39,7 @@
|
||||
"gitignore": {
|
||||
"inputs": {
|
||||
"nixpkgs": [
|
||||
"devshell-lib",
|
||||
"repo-lib",
|
||||
"git-hooks",
|
||||
"nixpkgs"
|
||||
]
|
||||
@@ -82,6 +59,22 @@
|
||||
}
|
||||
},
|
||||
"nixpkgs": {
|
||||
"locked": {
|
||||
"lastModified": 1772542754,
|
||||
"narHash": "sha256-WGV2hy+VIeQsYXpsLjdr4GvHv5eECMISX1zKLTedhdg=",
|
||||
"owner": "nixos",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "8c809a146a140c5c8806f13399592dbcb1bb5dc4",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "nixos",
|
||||
"ref": "nixos-unstable",
|
||||
"repo": "nixpkgs",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"nixpkgs_2": {
|
||||
"locked": {
|
||||
"lastModified": 1770073757,
|
||||
"narHash": "sha256-Vy+G+F+3E/Tl+GMNgiHl9Pah2DgShmIUBJXmbiQPHbI=",
|
||||
@@ -97,7 +90,7 @@
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"nixpkgs_2": {
|
||||
"nixpkgs_3": {
|
||||
"locked": {
|
||||
"lastModified": 1770107345,
|
||||
"narHash": "sha256-tbS0Ebx2PiA1FRW8mt8oejR0qMXmziJmPaU1d4kYY9g=",
|
||||
@@ -113,31 +106,38 @@
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"nixpkgs_3": {
|
||||
"repo-lib": {
|
||||
"inputs": {
|
||||
"git-hooks": "git-hooks",
|
||||
"nixpkgs": [
|
||||
"nixpkgs"
|
||||
],
|
||||
"treefmt-nix": "treefmt-nix"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1772542754,
|
||||
"narHash": "sha256-WGV2hy+VIeQsYXpsLjdr4GvHv5eECMISX1zKLTedhdg=",
|
||||
"owner": "nixos",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "8c809a146a140c5c8806f13399592dbcb1bb5dc4",
|
||||
"type": "github"
|
||||
"lastModified": 1772866275,
|
||||
"narHash": "sha256-lsJrFIbq6OO5wUC648VnvOmJm3qgJrlEugbdjeZsP34=",
|
||||
"ref": "refs/tags/v3.0.0",
|
||||
"rev": "96d2d190466dddcb9e652c38b70152f09b9fcb05",
|
||||
"revCount": 50,
|
||||
"type": "git",
|
||||
"url": "https://git.dgren.dev/eric/nix-flake-lib"
|
||||
},
|
||||
"original": {
|
||||
"owner": "nixos",
|
||||
"ref": "nixos-unstable",
|
||||
"repo": "nixpkgs",
|
||||
"type": "github"
|
||||
"ref": "refs/tags/v3.0.0",
|
||||
"type": "git",
|
||||
"url": "https://git.dgren.dev/eric/nix-flake-lib"
|
||||
}
|
||||
},
|
||||
"root": {
|
||||
"inputs": {
|
||||
"devshell-lib": "devshell-lib",
|
||||
"nixpkgs": "nixpkgs_3"
|
||||
"nixpkgs": "nixpkgs",
|
||||
"repo-lib": "repo-lib"
|
||||
}
|
||||
},
|
||||
"treefmt-nix": {
|
||||
"inputs": {
|
||||
"nixpkgs": "nixpkgs_2"
|
||||
"nixpkgs": "nixpkgs_3"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1770228511,
|
||||
|
||||
205
flake.nix
205
flake.nix
@@ -3,143 +3,50 @@
|
||||
|
||||
inputs = {
|
||||
nixpkgs.url = "github:nixos/nixpkgs?ref=nixos-unstable";
|
||||
devshell-lib.url = "git+https://git.dgren.dev/eric/nix-flake-lib?ref=v2.0.1";
|
||||
devshell-lib.inputs.nixpkgs.follows = "nixpkgs";
|
||||
repo-lib.url = "git+https://git.dgren.dev/eric/nix-flake-lib?ref=refs/tags/v3.0.0";
|
||||
repo-lib.inputs.nixpkgs.follows = "nixpkgs";
|
||||
};
|
||||
|
||||
outputs =
|
||||
{
|
||||
self,
|
||||
nixpkgs,
|
||||
devshell-lib,
|
||||
repo-lib,
|
||||
...
|
||||
}:
|
||||
let
|
||||
supportedSystems = [
|
||||
"x86_64-linux"
|
||||
"aarch64-linux"
|
||||
"x86_64-darwin"
|
||||
"aarch64-darwin"
|
||||
];
|
||||
forAllSystems = nixpkgs.lib.genAttrs supportedSystems;
|
||||
bazelVersion = "9.0.0";
|
||||
in
|
||||
{
|
||||
devShells = forAllSystems (
|
||||
system:
|
||||
let
|
||||
pkgs = import nixpkgs { inherit system; };
|
||||
bazel9 = pkgs.writeShellScriptBin "bazel" ''
|
||||
export USE_BAZEL_VERSION="''${USE_BAZEL_VERSION:-9.0.0}"
|
||||
exec ${pkgs.bazelisk}/bin/bazelisk "$@"
|
||||
'';
|
||||
env = devshell-lib.lib.mkDevShell {
|
||||
inherit system;
|
||||
repo-lib.lib.mkRepo {
|
||||
inherit self nixpkgs;
|
||||
src = ./.;
|
||||
|
||||
extraPackages = with pkgs; [
|
||||
go
|
||||
gopls
|
||||
gotools
|
||||
bun
|
||||
bazel9
|
||||
bazel-buildtools
|
||||
self.packages.${system}.release
|
||||
];
|
||||
config = {
|
||||
shell.extraShellText = ''
|
||||
export USE_BAZEL_VERSION="''${USE_BAZEL_VERSION:-${bazelVersion}}"
|
||||
export BUN_INSTALL="''${BUN_INSTALL:-$HOME/.bun}"
|
||||
export PATH="$BUN_INSTALL/bin:$PATH"
|
||||
'';
|
||||
|
||||
features = {
|
||||
oxfmt = false;
|
||||
};
|
||||
formatting = {
|
||||
programs.shfmt.enable = true;
|
||||
settings.shfmt.options = [
|
||||
"-i"
|
||||
"2"
|
||||
"-s"
|
||||
"-w"
|
||||
];
|
||||
};
|
||||
|
||||
formatters = {
|
||||
shfmt.enable = true;
|
||||
};
|
||||
|
||||
formatterSettings = {
|
||||
shfmt.options = [
|
||||
"-i"
|
||||
"2"
|
||||
"-s"
|
||||
"-w"
|
||||
];
|
||||
};
|
||||
|
||||
additionalHooks = {
|
||||
tests = {
|
||||
enable = true;
|
||||
entry = ''
|
||||
${pkgs.bash}/bin/bash -ec 'bazel test //tests/... --test_output=errors && tests/install_test/workspace_parity.sh "$(command -v bun)"'
|
||||
'';
|
||||
pass_filenames = false;
|
||||
stages = [ "pre-push" ];
|
||||
};
|
||||
};
|
||||
|
||||
tools = [
|
||||
{
|
||||
name = "Bun";
|
||||
bin = "${pkgs.bun}/bin/bun";
|
||||
versionCmd = "--version";
|
||||
color = "YELLOW";
|
||||
}
|
||||
{
|
||||
name = "Go";
|
||||
bin = "${pkgs.go}/bin/go";
|
||||
versionCmd = "version";
|
||||
color = "CYAN";
|
||||
}
|
||||
{
|
||||
name = "Bazel";
|
||||
bin = "${bazel9}/bin/bazel";
|
||||
versionCmd = "--version";
|
||||
color = "GREEN";
|
||||
}
|
||||
];
|
||||
|
||||
extraShellHook = ''
|
||||
export USE_BAZEL_VERSION="''${USE_BAZEL_VERSION:-9.0.0}"
|
||||
export BUN_INSTALL="''${BUN_INSTALL:-$HOME/.bun}"
|
||||
export PATH="$BUN_INSTALL/bin:$PATH"
|
||||
'';
|
||||
};
|
||||
in
|
||||
{
|
||||
default = env.shell;
|
||||
}
|
||||
);
|
||||
|
||||
checks = forAllSystems (
|
||||
system:
|
||||
let
|
||||
env = devshell-lib.lib.mkDevShell { inherit system; };
|
||||
in
|
||||
{
|
||||
inherit (env) pre-commit-check;
|
||||
}
|
||||
);
|
||||
|
||||
formatter = forAllSystems (system: (devshell-lib.lib.mkDevShell { inherit system; }).formatter);
|
||||
|
||||
# Optional: release command (`release`)
|
||||
#
|
||||
# The release script always updates VERSION first, then:
|
||||
# 1) runs release steps in order (file writes and scripts)
|
||||
# 2) runs postVersion hook
|
||||
# 3) formats, stages, commits, tags, and pushes
|
||||
#
|
||||
# Runtime env vars available in release.run/postVersion:
|
||||
# BASE_VERSION, CHANNEL, PRERELEASE_NUM, FULL_VERSION, FULL_TAG
|
||||
#
|
||||
packages = forAllSystems (system: {
|
||||
release = devshell-lib.lib.mkRelease {
|
||||
inherit system;
|
||||
|
||||
release = [
|
||||
release = {
|
||||
steps = [
|
||||
{
|
||||
run = ''
|
||||
run.script = ''
|
||||
sed -E -i 's#^([[:space:]]*version[[:space:]]*=[[:space:]]*")[^"]*(",)$#\1'"$FULL_VERSION"'\2#' "$ROOT_DIR/MODULE.bazel"
|
||||
'';
|
||||
}
|
||||
{
|
||||
run = ''
|
||||
run.script = ''
|
||||
README="$ROOT_DIR/README.md"
|
||||
TMP="$README.tmp"
|
||||
|
||||
@@ -168,14 +75,70 @@
|
||||
' "$README" > "$TMP" && mv "$TMP" "$README"
|
||||
'';
|
||||
}
|
||||
{
|
||||
run.script = ''
|
||||
bazel cquery //tests/... >/dev/null
|
||||
'';
|
||||
}
|
||||
];
|
||||
|
||||
postVersion = ''
|
||||
echo "Released $FULL_TAG"
|
||||
'';
|
||||
};
|
||||
});
|
||||
};
|
||||
|
||||
perSystem =
|
||||
{
|
||||
pkgs,
|
||||
system,
|
||||
...
|
||||
}:
|
||||
let
|
||||
bazel9 = pkgs.writeShellScriptBin "bazel" ''
|
||||
export USE_BAZEL_VERSION="''${USE_BAZEL_VERSION:-${bazelVersion}}"
|
||||
exec ${pkgs.bazelisk}/bin/bazelisk "$@"
|
||||
'';
|
||||
in
|
||||
{
|
||||
tools = [
|
||||
(repo-lib.lib.tools.fromPackage {
|
||||
name = "Bun";
|
||||
package = pkgs.bun;
|
||||
version.args = [ "--version" ];
|
||||
banner.color = "YELLOW";
|
||||
})
|
||||
(repo-lib.lib.tools.fromPackage {
|
||||
name = "Go";
|
||||
package = pkgs.go;
|
||||
version.args = [ "version" ];
|
||||
banner.color = "CYAN";
|
||||
})
|
||||
(repo-lib.lib.tools.fromPackage {
|
||||
name = "Bazel";
|
||||
package = bazel9;
|
||||
version.args = [ "--version" ];
|
||||
banner.color = "GREEN";
|
||||
})
|
||||
];
|
||||
|
||||
shell.packages = [
|
||||
pkgs.gopls
|
||||
pkgs.gotools
|
||||
pkgs.bazel-buildtools
|
||||
self.packages.${system}.release
|
||||
];
|
||||
|
||||
checks.tests = {
|
||||
command = "bazel test //tests/...";
|
||||
stage = "pre-push";
|
||||
passFilenames = false;
|
||||
runtimeInputs = [
|
||||
bazel9
|
||||
pkgs.bun
|
||||
pkgs.go
|
||||
];
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -3,29 +3,95 @@ load("@bazel_skylib//:bzl_library.bzl", "bzl_library")
|
||||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
exports_files([
|
||||
"bun_build_support.bzl",
|
||||
"bun_binary.bzl",
|
||||
"bun_command.bzl",
|
||||
"bun_compile.bzl",
|
||||
"bun_bundle.bzl",
|
||||
"bun_dev.bzl",
|
||||
"bun_install.bzl",
|
||||
"bun_script.bzl",
|
||||
"bun_test.bzl",
|
||||
"js_compat.bzl",
|
||||
"js_library.bzl",
|
||||
"js_run_devserver.bzl",
|
||||
"runtime_launcher.bzl",
|
||||
"runtime_launcher.js",
|
||||
"workspace.bzl",
|
||||
])
|
||||
|
||||
filegroup(
|
||||
name = "repo_runtime_files",
|
||||
srcs = [
|
||||
"BUILD.bazel",
|
||||
"bun_binary.bzl",
|
||||
"bun_build_support.bzl",
|
||||
"bun_bundle.bzl",
|
||||
"bun_command.bzl",
|
||||
"bun_compile.bzl",
|
||||
"bun_dev.bzl",
|
||||
"bun_install.bzl",
|
||||
"bun_script.bzl",
|
||||
"bun_test.bzl",
|
||||
"js_compat.bzl",
|
||||
"js_library.bzl",
|
||||
"js_run_devserver.bzl",
|
||||
"runtime_launcher.bzl",
|
||||
"runtime_launcher.js",
|
||||
"workspace.bzl",
|
||||
],
|
||||
visibility = ["//visibility:public"],
|
||||
)
|
||||
|
||||
bzl_library(
|
||||
name = "bun_command_bzl",
|
||||
srcs = ["bun_command.bzl"],
|
||||
)
|
||||
|
||||
bzl_library(
|
||||
name = "bun_build_support_bzl",
|
||||
srcs = ["bun_build_support.bzl"],
|
||||
deps = [
|
||||
":bun_command_bzl",
|
||||
":js_library_bzl",
|
||||
],
|
||||
)
|
||||
|
||||
bzl_library(
|
||||
name = "bun_binary_bzl",
|
||||
srcs = ["bun_binary.bzl"],
|
||||
deps = [
|
||||
":bun_command_bzl",
|
||||
":js_library_bzl",
|
||||
":runtime_launcher_bzl",
|
||||
":workspace_bzl",
|
||||
],
|
||||
)
|
||||
|
||||
bzl_library(
|
||||
name = "bun_compile_bzl",
|
||||
srcs = ["bun_compile.bzl"],
|
||||
deps = [
|
||||
":bun_build_support_bzl",
|
||||
],
|
||||
)
|
||||
|
||||
bzl_library(
|
||||
name = "bun_bundle_bzl",
|
||||
srcs = ["bun_bundle.bzl"],
|
||||
deps = [":js_library_bzl"],
|
||||
deps = [
|
||||
":bun_build_support_bzl",
|
||||
],
|
||||
)
|
||||
|
||||
bzl_library(
|
||||
name = "bun_dev_bzl",
|
||||
srcs = ["bun_dev.bzl"],
|
||||
deps = [
|
||||
":bun_command_bzl",
|
||||
":runtime_launcher_bzl",
|
||||
":workspace_bzl",
|
||||
],
|
||||
)
|
||||
|
||||
bzl_library(
|
||||
@@ -36,15 +102,56 @@ bzl_library(
|
||||
bzl_library(
|
||||
name = "bun_script_bzl",
|
||||
srcs = ["bun_script.bzl"],
|
||||
deps = [
|
||||
":bun_command_bzl",
|
||||
":runtime_launcher_bzl",
|
||||
":workspace_bzl",
|
||||
],
|
||||
)
|
||||
|
||||
bzl_library(
|
||||
name = "bun_test_bzl",
|
||||
srcs = ["bun_test.bzl"],
|
||||
deps = [":js_library_bzl"],
|
||||
deps = [
|
||||
":bun_command_bzl",
|
||||
":js_library_bzl",
|
||||
":runtime_launcher_bzl",
|
||||
":workspace_bzl",
|
||||
],
|
||||
)
|
||||
|
||||
bzl_library(
|
||||
name = "js_compat_bzl",
|
||||
srcs = ["js_compat.bzl"],
|
||||
deps = [
|
||||
":bun_binary_bzl",
|
||||
":bun_test_bzl",
|
||||
":js_library_bzl",
|
||||
":js_run_devserver_bzl",
|
||||
],
|
||||
)
|
||||
|
||||
bzl_library(
|
||||
name = "js_library_bzl",
|
||||
srcs = ["js_library.bzl"],
|
||||
)
|
||||
|
||||
bzl_library(
|
||||
name = "js_run_devserver_bzl",
|
||||
srcs = ["js_run_devserver.bzl"],
|
||||
deps = [
|
||||
":js_library_bzl",
|
||||
":runtime_launcher_bzl",
|
||||
":workspace_bzl",
|
||||
],
|
||||
)
|
||||
|
||||
bzl_library(
|
||||
name = "runtime_launcher_bzl",
|
||||
srcs = ["runtime_launcher.bzl"],
|
||||
)
|
||||
|
||||
bzl_library(
|
||||
name = "workspace_bzl",
|
||||
srcs = ["workspace.bzl"],
|
||||
)
|
||||
|
||||
@@ -1,70 +1,122 @@
|
||||
"""Rule for running JS/TS scripts with Bun."""
|
||||
|
||||
load("//internal:bun_command.bzl", "append_flag", "append_flag_values", "append_install_mode", "append_raw_flags")
|
||||
load("//internal:js_library.bzl", "collect_js_runfiles")
|
||||
load("//internal:runtime_launcher.bzl", "declare_runtime_wrapper", "runfiles_path", "runtime_launcher_attrs", "write_launcher_spec")
|
||||
load("//internal:workspace.bzl", "create_bun_workspace_info", "workspace_runfiles")
|
||||
|
||||
def _bun_binary_impl(ctx):
|
||||
toolchain = ctx.toolchains["//bun:toolchain_type"]
|
||||
bun_bin = toolchain.bun.bun_bin
|
||||
entry_point = ctx.file.entry_point
|
||||
|
||||
launcher = ctx.actions.declare_file(ctx.label.name)
|
||||
ctx.actions.write(
|
||||
output = launcher,
|
||||
is_executable = True,
|
||||
content = """#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
runfiles_dir="${{RUNFILES_DIR:-$0.runfiles}}"
|
||||
workspace_root="${{runfiles_dir}}/_main"
|
||||
bun_bin="${{runfiles_dir}}/_main/{bun_short_path}"
|
||||
entry_point="${{runfiles_dir}}/_main/{entry_short_path}"
|
||||
|
||||
resolve_entrypoint_workdir() {{
|
||||
local dir
|
||||
dir="$(dirname "${{entry_point}}")"
|
||||
while [[ "${{dir}}" == "${{workspace_root}}"* ]]; do
|
||||
if [[ -f "${{dir}}/.env" || -f "${{dir}}/package.json" ]]; then
|
||||
echo "${{dir}}"
|
||||
return 0
|
||||
fi
|
||||
if [[ "${{dir}}" == "${{workspace_root}}" ]]; then
|
||||
break
|
||||
fi
|
||||
dir="$(dirname "${{dir}}")"
|
||||
done
|
||||
echo "$(dirname "${{entry_point}}")"
|
||||
}}
|
||||
|
||||
working_dir="{working_dir}"
|
||||
if [[ "${{working_dir}}" == "entry_point" ]]; then
|
||||
cd "$(resolve_entrypoint_workdir)"
|
||||
else
|
||||
cd "${{workspace_root}}"
|
||||
fi
|
||||
|
||||
exec "${{bun_bin}}" --bun run "${{entry_point}}" "$@"
|
||||
""".format(
|
||||
bun_short_path = bun_bin.short_path,
|
||||
entry_short_path = entry_point.short_path,
|
||||
working_dir = ctx.attr.working_dir,
|
||||
),
|
||||
dep_runfiles = [collect_js_runfiles(dep) for dep in ctx.attr.deps]
|
||||
workspace_info = create_bun_workspace_info(
|
||||
ctx,
|
||||
extra_files = ctx.files.data + ctx.files.preload + ctx.files.env_files + [bun_bin],
|
||||
primary_file = entry_point,
|
||||
)
|
||||
|
||||
transitive_files = []
|
||||
if ctx.attr.node_modules:
|
||||
transitive_files.append(ctx.attr.node_modules[DefaultInfo].files)
|
||||
argv = ["--bun", "run"]
|
||||
append_install_mode(argv, ctx.attr.install_mode)
|
||||
append_flag(argv, "--no-env-file", ctx.attr.no_env_file)
|
||||
append_flag(argv, "--smol", ctx.attr.smol)
|
||||
append_flag_values(argv, "--conditions", ctx.attr.conditions)
|
||||
append_raw_flags(argv, ctx.attr.run_flags)
|
||||
|
||||
runfiles = ctx.runfiles(
|
||||
files = [bun_bin, entry_point] + ctx.files.data,
|
||||
transitive_files = depset(transitive = transitive_files),
|
||||
)
|
||||
spec_file = write_launcher_spec(ctx, {
|
||||
"version": 1,
|
||||
"kind": "bun_run",
|
||||
"bun_short_path": runfiles_path(bun_bin),
|
||||
"primary_source_short_path": runfiles_path(entry_point),
|
||||
"package_json_short_path": "",
|
||||
"install_metadata_short_path": runfiles_path(workspace_info.install_metadata_file) if workspace_info.install_metadata_file else "",
|
||||
"install_repo_runfiles_path": workspace_info.install_repo_runfiles_path,
|
||||
"node_modules_roots": workspace_info.node_modules_roots,
|
||||
"package_dir_hint": workspace_info.package_dir_hint,
|
||||
"working_dir_mode": ctx.attr.working_dir,
|
||||
"inherit_host_path": ctx.attr.inherit_host_path,
|
||||
"argv": argv,
|
||||
"args": ctx.attr.args,
|
||||
"passthrough_args": True,
|
||||
"tool_short_path": "",
|
||||
"restart_on": [],
|
||||
"watch_mode": "",
|
||||
"reporter": "",
|
||||
"coverage": False,
|
||||
"coverage_reporters": [],
|
||||
"preload_short_paths": [runfiles_path(file) for file in ctx.files.preload],
|
||||
"env_file_short_paths": [runfiles_path(file) for file in ctx.files.env_files],
|
||||
"test_short_paths": [],
|
||||
})
|
||||
launcher = declare_runtime_wrapper(ctx, bun_bin, spec_file)
|
||||
|
||||
return [
|
||||
workspace_info,
|
||||
DefaultInfo(
|
||||
executable = launcher,
|
||||
runfiles = runfiles,
|
||||
executable = launcher.executable,
|
||||
runfiles = workspace_runfiles(
|
||||
ctx,
|
||||
workspace_info,
|
||||
direct_files = [launcher.executable, launcher.runner, spec_file],
|
||||
transitive_files = dep_runfiles,
|
||||
),
|
||||
),
|
||||
]
|
||||
|
||||
_BUN_BINARY_ATTRS = runtime_launcher_attrs()
|
||||
_BUN_BINARY_ATTRS.update({
|
||||
"entry_point": attr.label(
|
||||
mandatory = True,
|
||||
allow_single_file = [".js", ".ts", ".jsx", ".tsx", ".mjs", ".cjs"],
|
||||
doc = "Path to the main JS/TS file to execute.",
|
||||
),
|
||||
"node_modules": attr.label(
|
||||
doc = "Optional label providing package files from a `node_modules` tree, typically produced by `bun_install`, in runfiles.",
|
||||
),
|
||||
"data": attr.label_list(
|
||||
allow_files = True,
|
||||
doc = "Additional runtime files required by the program.",
|
||||
),
|
||||
"deps": attr.label_list(
|
||||
doc = "Library dependencies required by the program.",
|
||||
),
|
||||
"preload": attr.label_list(
|
||||
allow_files = True,
|
||||
doc = "Modules to preload with `--preload` before running the entry point.",
|
||||
),
|
||||
"env_files": attr.label_list(
|
||||
allow_files = True,
|
||||
doc = "Additional environment files loaded with `--env-file`.",
|
||||
),
|
||||
"no_env_file": attr.bool(
|
||||
default = False,
|
||||
doc = "If true, disables Bun's automatic `.env` loading.",
|
||||
),
|
||||
"smol": attr.bool(
|
||||
default = False,
|
||||
doc = "If true, enables Bun's lower-memory runtime mode.",
|
||||
),
|
||||
"conditions": attr.string_list(
|
||||
doc = "Custom package resolve conditions passed to Bun.",
|
||||
),
|
||||
"install_mode": attr.string(
|
||||
default = "disable",
|
||||
values = ["disable", "auto", "fallback", "force"],
|
||||
doc = "Whether Bun may auto-install missing packages at runtime.",
|
||||
),
|
||||
"run_flags": attr.string_list(
|
||||
doc = "Additional raw flags forwarded to `bun run` before the entry point.",
|
||||
),
|
||||
"working_dir": attr.string(
|
||||
default = "workspace",
|
||||
values = ["workspace", "entry_point"],
|
||||
doc = "Working directory at runtime: `workspace` root or nearest `entry_point` ancestor containing `.env`/`package.json`.",
|
||||
),
|
||||
"inherit_host_path": attr.bool(
|
||||
default = False,
|
||||
doc = "If true, appends the host PATH after staged node_modules/.bin entries at runtime.",
|
||||
),
|
||||
})
|
||||
|
||||
bun_binary = rule(
|
||||
implementation = _bun_binary_impl,
|
||||
@@ -72,25 +124,7 @@ bun_binary = rule(
|
||||
|
||||
Use this rule for non-test scripts and CLIs that should run via `bazel run`.
|
||||
""",
|
||||
attrs = {
|
||||
"entry_point": attr.label(
|
||||
mandatory = True,
|
||||
allow_single_file = [".js", ".ts", ".jsx", ".tsx", ".mjs", ".cjs"],
|
||||
doc = "Path to the main JS/TS file to execute.",
|
||||
),
|
||||
"node_modules": attr.label(
|
||||
doc = "Optional label providing package files from a `node_modules` tree, typically produced by `bun_install`, in runfiles.",
|
||||
),
|
||||
"data": attr.label_list(
|
||||
allow_files = True,
|
||||
doc = "Additional runtime files required by the program.",
|
||||
),
|
||||
"working_dir": attr.string(
|
||||
default = "workspace",
|
||||
values = ["workspace", "entry_point"],
|
||||
doc = "Working directory at runtime: `workspace` root or nearest `entry_point` ancestor containing `.env`/`package.json`.",
|
||||
),
|
||||
},
|
||||
attrs = _BUN_BINARY_ATTRS,
|
||||
executable = True,
|
||||
toolchains = ["//bun:toolchain_type"],
|
||||
)
|
||||
|
||||
208
internal/bun_build_support.bzl
Normal file
208
internal/bun_build_support.bzl
Normal file
@@ -0,0 +1,208 @@
|
||||
"""Shared helpers for Bun build- and compile-style rules."""
|
||||
|
||||
load("//internal:bun_command.bzl", "add_flag", "add_flag_value", "add_flag_values", "add_install_mode", "add_raw_flags")
|
||||
load("//internal:js_library.bzl", "collect_js_sources")
|
||||
|
||||
_STAGED_BUILD_RUNNER = """import { spawnSync } from "node:child_process";
|
||||
import { cpSync, mkdirSync, mkdtempSync, readFileSync, rmSync } from "node:fs";
|
||||
import { tmpdir } from "node:os";
|
||||
import { dirname, resolve } from "node:path";
|
||||
|
||||
const [, , manifestPath, ...buildArgs] = process.argv;
|
||||
const execroot = process.cwd();
|
||||
const stageDir = mkdtempSync(resolve(tmpdir(), "rules_bun_build-"));
|
||||
|
||||
function rewriteArgPath(flag, value) {
|
||||
return `${flag}=${resolve(execroot, value)}`;
|
||||
}
|
||||
|
||||
try {
|
||||
for (const relpath of readFileSync(manifestPath, "utf8").split(/\\r?\\n/)) {
|
||||
if (!relpath) {
|
||||
continue;
|
||||
}
|
||||
const src = resolve(execroot, relpath);
|
||||
const dest = resolve(stageDir, relpath);
|
||||
mkdirSync(dirname(dest), { recursive: true });
|
||||
cpSync(src, dest, { dereference: true, force: true, recursive: true });
|
||||
}
|
||||
|
||||
const forwardedArgs = [];
|
||||
for (let index = 0; index < buildArgs.length; index += 1) {
|
||||
const arg = buildArgs[index];
|
||||
if ((arg === "--outdir" || arg === "--outfile") && index + 1 < buildArgs.length) {
|
||||
forwardedArgs.push(arg, resolve(execroot, buildArgs[index + 1]));
|
||||
index += 1;
|
||||
continue;
|
||||
}
|
||||
if (arg.startsWith("--metafile=")) {
|
||||
forwardedArgs.push(rewriteArgPath("--metafile", arg.slice("--metafile=".length)));
|
||||
continue;
|
||||
}
|
||||
if (arg.startsWith("--metafile-md=")) {
|
||||
forwardedArgs.push(rewriteArgPath("--metafile-md", arg.slice("--metafile-md=".length)));
|
||||
continue;
|
||||
}
|
||||
forwardedArgs.push(arg);
|
||||
}
|
||||
|
||||
const result = spawnSync(process.execPath, forwardedArgs, {
|
||||
cwd: stageDir,
|
||||
stdio: "inherit",
|
||||
});
|
||||
if (result.error) {
|
||||
throw result.error;
|
||||
}
|
||||
process.exit(typeof result.status === "number" ? result.status : 1);
|
||||
} finally {
|
||||
rmSync(stageDir, { recursive: true, force: true });
|
||||
}
|
||||
"""
|
||||
|
||||
def sort_files_by_short_path(files):
|
||||
files_by_path = {}
|
||||
short_paths = []
|
||||
for file in files:
|
||||
files_by_path[file.short_path] = file
|
||||
short_paths.append(file.short_path)
|
||||
return [files_by_path[short_path] for short_path in sorted(short_paths)]
|
||||
|
||||
def validate_hermetic_install_mode(attr, rule_name):
|
||||
if getattr(attr, "install_mode", "disable") != "disable":
|
||||
fail("{} requires install_mode = \"disable\" for hermetic execution".format(rule_name))
|
||||
|
||||
def infer_entry_point_root(entries):
|
||||
if not entries:
|
||||
return None
|
||||
|
||||
common_segments = entries[0].path.split("/")[:-1]
|
||||
for entry in entries[1:]:
|
||||
entry_segments = entry.path.split("/")[:-1]
|
||||
common_length = min(len(common_segments), len(entry_segments))
|
||||
idx = common_length
|
||||
for segment_idx in range(common_length):
|
||||
if common_segments[segment_idx] != entry_segments[segment_idx]:
|
||||
idx = segment_idx
|
||||
break
|
||||
common_segments = common_segments[:idx]
|
||||
|
||||
if not common_segments:
|
||||
return "."
|
||||
|
||||
return "/".join(common_segments)
|
||||
|
||||
def bun_build_transitive_inputs(ctx):
|
||||
transitive_inputs = []
|
||||
if getattr(ctx.attr, "node_modules", None):
|
||||
transitive_inputs.append(ctx.attr.node_modules[DefaultInfo].files)
|
||||
for dep in getattr(ctx.attr, "deps", []):
|
||||
transitive_inputs.append(collect_js_sources(dep))
|
||||
return transitive_inputs
|
||||
|
||||
def add_bun_build_common_flags(args, attr, metafile = None, metafile_md = None, root = None):
|
||||
build_root = root
|
||||
if build_root == None:
|
||||
build_root = getattr(attr, "root", None)
|
||||
|
||||
add_install_mode(args, getattr(attr, "install_mode", "disable"))
|
||||
add_flag_value(args, "--target", getattr(attr, "target", None))
|
||||
add_flag_value(args, "--format", getattr(attr, "format", None))
|
||||
add_flag(args, "--production", getattr(attr, "production", False))
|
||||
add_flag(args, "--splitting", getattr(attr, "splitting", False))
|
||||
add_flag_value(args, "--root", build_root)
|
||||
|
||||
sourcemap = getattr(attr, "sourcemap", None)
|
||||
if sourcemap == True:
|
||||
args.add("--sourcemap")
|
||||
elif sourcemap and sourcemap != "none":
|
||||
add_flag_value(args, "--sourcemap", sourcemap)
|
||||
|
||||
add_flag_value(args, "--banner", getattr(attr, "banner", None))
|
||||
add_flag_value(args, "--footer", getattr(attr, "footer", None))
|
||||
add_flag_value(args, "--public-path", getattr(attr, "public_path", None))
|
||||
add_flag_value(args, "--packages", getattr(attr, "packages", None))
|
||||
add_flag_values(args, "--external", getattr(attr, "external", []))
|
||||
add_flag_value(args, "--entry-naming", getattr(attr, "entry_naming", None))
|
||||
add_flag_value(args, "--chunk-naming", getattr(attr, "chunk_naming", None))
|
||||
add_flag_value(args, "--asset-naming", getattr(attr, "asset_naming", None))
|
||||
add_flag(args, "--minify", getattr(attr, "minify", False))
|
||||
add_flag(args, "--minify-syntax", getattr(attr, "minify_syntax", False))
|
||||
add_flag(args, "--minify-whitespace", getattr(attr, "minify_whitespace", False))
|
||||
add_flag(args, "--minify-identifiers", getattr(attr, "minify_identifiers", False))
|
||||
add_flag(args, "--keep-names", getattr(attr, "keep_names", False))
|
||||
add_flag(args, "--css-chunking", getattr(attr, "css_chunking", False))
|
||||
add_flag_values(args, "--conditions", getattr(attr, "conditions", []))
|
||||
add_flag_value(args, "--env", getattr(attr, "env", None))
|
||||
add_flag_values(args, "--define", getattr(attr, "define", []))
|
||||
add_flag_values(args, "--drop", getattr(attr, "drop", []))
|
||||
add_flag_values(args, "--feature", getattr(attr, "feature", []))
|
||||
add_flag_values(args, "--loader", getattr(attr, "loader", []))
|
||||
add_flag_value(args, "--jsx-factory", getattr(attr, "jsx_factory", None))
|
||||
add_flag_value(args, "--jsx-fragment", getattr(attr, "jsx_fragment", None))
|
||||
add_flag_value(args, "--jsx-import-source", getattr(attr, "jsx_import_source", None))
|
||||
add_flag_value(args, "--jsx-runtime", getattr(attr, "jsx_runtime", None))
|
||||
add_flag(args, "--jsx-side-effects", getattr(attr, "jsx_side_effects", False))
|
||||
add_flag(args, "--react-fast-refresh", getattr(attr, "react_fast_refresh", False))
|
||||
add_flag(args, "--emit-dce-annotations", getattr(attr, "emit_dce_annotations", False))
|
||||
add_flag(args, "--no-bundle", getattr(attr, "no_bundle", False))
|
||||
if metafile:
|
||||
args.add("--metafile=%s" % metafile.path)
|
||||
if metafile_md:
|
||||
args.add("--metafile-md=%s" % metafile_md.path)
|
||||
add_raw_flags(args, getattr(attr, "build_flags", []))
|
||||
|
||||
def add_bun_compile_flags(args, attr, compile_executable = None):
|
||||
add_flag(args, "--compile", True)
|
||||
add_flag(args, "--bytecode", getattr(attr, "bytecode", False))
|
||||
add_flag_values(args, "--compile-exec-argv", getattr(attr, "compile_exec_argv", []))
|
||||
if getattr(attr, "compile_autoload_dotenv", True):
|
||||
args.add("--compile-autoload-dotenv")
|
||||
else:
|
||||
args.add("--no-compile-autoload-dotenv")
|
||||
if getattr(attr, "compile_autoload_bunfig", True):
|
||||
args.add("--compile-autoload-bunfig")
|
||||
else:
|
||||
args.add("--no-compile-autoload-bunfig")
|
||||
if getattr(attr, "compile_autoload_tsconfig", False):
|
||||
args.add("--compile-autoload-tsconfig")
|
||||
else:
|
||||
args.add("--no-compile-autoload-tsconfig")
|
||||
if getattr(attr, "compile_autoload_package_json", False):
|
||||
args.add("--compile-autoload-package-json")
|
||||
else:
|
||||
args.add("--no-compile-autoload-package-json")
|
||||
if compile_executable:
|
||||
add_flag_value(args, "--compile-executable-path", compile_executable.path)
|
||||
add_flag(args, "--windows-hide-console", getattr(attr, "windows_hide_console", False))
|
||||
add_flag_value(args, "--windows-icon", getattr(attr, "windows_icon", None))
|
||||
add_flag_value(args, "--windows-title", getattr(attr, "windows_title", None))
|
||||
add_flag_value(args, "--windows-publisher", getattr(attr, "windows_publisher", None))
|
||||
add_flag_value(args, "--windows-version", getattr(attr, "windows_version", None))
|
||||
add_flag_value(args, "--windows-description", getattr(attr, "windows_description", None))
|
||||
add_flag_value(args, "--windows-copyright", getattr(attr, "windows_copyright", None))
|
||||
|
||||
def declare_staged_bun_build_action(ctx, bun_bin, build_args, build_inputs, outputs, mnemonic, progress_message, name_suffix):
|
||||
sorted_inputs = sort_files_by_short_path(build_inputs.to_list())
|
||||
input_manifest = ctx.actions.declare_file(ctx.label.name + name_suffix + ".inputs")
|
||||
runner = ctx.actions.declare_file(ctx.label.name + name_suffix + "_runner.js")
|
||||
|
||||
ctx.actions.write(
|
||||
output = input_manifest,
|
||||
content = "".join([file.path + "\n" for file in sorted_inputs]),
|
||||
)
|
||||
ctx.actions.write(
|
||||
output = runner,
|
||||
content = _STAGED_BUILD_RUNNER,
|
||||
)
|
||||
|
||||
ctx.actions.run(
|
||||
executable = bun_bin,
|
||||
arguments = ["--bun", runner.path, input_manifest.path, build_args],
|
||||
inputs = depset(
|
||||
direct = [input_manifest, runner],
|
||||
transitive = [build_inputs],
|
||||
),
|
||||
outputs = outputs,
|
||||
mnemonic = mnemonic,
|
||||
progress_message = progress_message,
|
||||
)
|
||||
@@ -1,59 +1,53 @@
|
||||
"""Rule for bundling JS/TS sources with Bun."""
|
||||
|
||||
load("//internal:js_library.bzl", "BunSourcesInfo")
|
||||
load("//internal:bun_build_support.bzl", "add_bun_build_common_flags", "bun_build_transitive_inputs", "declare_staged_bun_build_action", "sort_files_by_short_path", "validate_hermetic_install_mode")
|
||||
|
||||
|
||||
def _output_name(target_name, entry):
|
||||
stem = entry.basename.rsplit(".", 1)[0]
|
||||
return "{}__{}.js".format(target_name, stem)
|
||||
stem = entry.short_path.rsplit(".", 1)[0]
|
||||
sanitized = stem.replace("\\", "_").replace("/", "_").replace("-", "_").replace(".", "_").replace("@", "at_")
|
||||
sanitized = sanitized.replace("__", "_").replace("__", "_").replace("__", "_")
|
||||
sanitized = sanitized.strip("_")
|
||||
if not sanitized:
|
||||
sanitized = entry.basename.rsplit(".", 1)[0]
|
||||
return "{}__{}.js".format(target_name, sanitized)
|
||||
|
||||
|
||||
def _bun_bundle_impl(ctx):
|
||||
validate_hermetic_install_mode(ctx.attr, "bun_bundle")
|
||||
|
||||
toolchain = ctx.toolchains["//bun:toolchain_type"]
|
||||
bun_bin = toolchain.bun.bun_bin
|
||||
entry_points = sort_files_by_short_path(ctx.files.entry_points)
|
||||
data_files = sort_files_by_short_path(ctx.files.data)
|
||||
|
||||
transitive_inputs = []
|
||||
if ctx.attr.node_modules:
|
||||
transitive_inputs.append(ctx.attr.node_modules[DefaultInfo].files)
|
||||
for dep in ctx.attr.deps:
|
||||
if BunSourcesInfo in dep:
|
||||
transitive_inputs.append(dep[BunSourcesInfo].transitive_sources)
|
||||
else:
|
||||
transitive_inputs.append(dep[DefaultInfo].files)
|
||||
transitive_inputs = bun_build_transitive_inputs(ctx)
|
||||
|
||||
outputs = []
|
||||
for entry in ctx.files.entry_points:
|
||||
for entry in entry_points:
|
||||
output = ctx.actions.declare_file(_output_name(ctx.label.name, entry))
|
||||
outputs.append(output)
|
||||
|
||||
args = ctx.actions.args()
|
||||
args.add("--bun")
|
||||
args.add("build")
|
||||
args.add(entry.path)
|
||||
add_bun_build_common_flags(args, ctx.attr)
|
||||
args.add("--outfile")
|
||||
args.add(output.path)
|
||||
args.add("--target")
|
||||
args.add(ctx.attr.target)
|
||||
args.add("--format")
|
||||
args.add(ctx.attr.format)
|
||||
if ctx.attr.minify:
|
||||
args.add("--minify")
|
||||
if ctx.attr.sourcemap:
|
||||
args.add("--sourcemap")
|
||||
for package in ctx.attr.external:
|
||||
args.add("--external")
|
||||
args.add(package)
|
||||
args.add(entry.path)
|
||||
|
||||
ctx.actions.run(
|
||||
executable = bun_bin,
|
||||
arguments = [args],
|
||||
inputs = depset(
|
||||
direct = [entry] + ctx.files.data,
|
||||
declare_staged_bun_build_action(
|
||||
ctx,
|
||||
bun_bin,
|
||||
args,
|
||||
depset(
|
||||
direct = [entry] + data_files,
|
||||
transitive = transitive_inputs,
|
||||
),
|
||||
outputs = [output],
|
||||
mnemonic = "BunBundle",
|
||||
progress_message = "Bundling {} with Bun".format(entry.short_path),
|
||||
name_suffix = "_bundle_{}".format(output.basename.rsplit(".", 1)[0]),
|
||||
)
|
||||
|
||||
return [DefaultInfo(files = depset(outputs))]
|
||||
@@ -81,6 +75,11 @@ Each entry point produces one output JavaScript artifact.
|
||||
allow_files = True,
|
||||
doc = "Additional non-source files needed during bundling.",
|
||||
),
|
||||
"install_mode": attr.string(
|
||||
default = "disable",
|
||||
values = ["disable", "auto", "fallback", "force"],
|
||||
doc = "Whether Bun may auto-install missing packages during bundling. Hermetic bundle actions require `disable`; other values are rejected.",
|
||||
),
|
||||
"target": attr.string(
|
||||
default = "browser",
|
||||
values = ["browser", "node", "bun"],
|
||||
@@ -102,6 +101,9 @@ Each entry point produces one output JavaScript artifact.
|
||||
"external": attr.string_list(
|
||||
doc = "Package names to treat as externals (not bundled).",
|
||||
),
|
||||
"build_flags": attr.string_list(
|
||||
doc = "Additional raw flags forwarded to `bun build`.",
|
||||
),
|
||||
},
|
||||
toolchains = ["//bun:toolchain_type"],
|
||||
)
|
||||
|
||||
113
internal/bun_command.bzl
Normal file
113
internal/bun_command.bzl
Normal file
@@ -0,0 +1,113 @@
|
||||
"""Shared Bun CLI flag builders for rules and launchers."""
|
||||
|
||||
def shell_quote(value):
|
||||
return "'" + str(value).replace("'", "'\"'\"'") + "'"
|
||||
|
||||
def _runfiles_workspace(file):
|
||||
workspace_name = file.owner.workspace_name
|
||||
if workspace_name:
|
||||
return workspace_name
|
||||
return "_main"
|
||||
|
||||
def runfiles_path_expr(file):
|
||||
return '"${runfiles_dir}/%s/%s"' % (_runfiles_workspace(file), file.short_path)
|
||||
|
||||
def render_shell_array(name, values):
|
||||
rendered = [shell_quote(value) for value in values]
|
||||
return "%s=(%s)" % (name, " ".join(rendered))
|
||||
|
||||
def append_shell_arg(lines, name, value):
|
||||
lines.append("%s+=(%s)" % (name, shell_quote(value)))
|
||||
|
||||
def append_shell_expr(lines, name, expr):
|
||||
lines.append("%s+=(%s)" % (name, expr))
|
||||
|
||||
def append_shell_flag(lines, name, flag, enabled):
|
||||
if enabled:
|
||||
append_shell_arg(lines, name, flag)
|
||||
|
||||
def append_shell_flag_value(lines, name, flag, value):
|
||||
if value == None:
|
||||
return
|
||||
if type(value) == type("") and not value:
|
||||
return
|
||||
append_shell_arg(lines, name, flag)
|
||||
append_shell_arg(lines, name, value)
|
||||
|
||||
def append_shell_flag_values(lines, name, flag, values):
|
||||
for value in values:
|
||||
append_shell_flag_value(lines, name, flag, value)
|
||||
|
||||
def append_shell_flag_files(lines, name, flag, files):
|
||||
for file in files:
|
||||
append_shell_arg(lines, name, flag)
|
||||
append_shell_expr(lines, name, runfiles_path_expr(file))
|
||||
|
||||
def append_shell_raw_flags(lines, name, values):
|
||||
for value in values:
|
||||
append_shell_arg(lines, name, value)
|
||||
|
||||
def append_shell_install_mode(lines, name, install_mode):
|
||||
if install_mode == "disable":
|
||||
append_shell_arg(lines, name, "--no-install")
|
||||
elif install_mode in ["fallback", "force"]:
|
||||
append_shell_flag_value(lines, name, "--install", install_mode)
|
||||
|
||||
def add_flag(args, flag, enabled):
|
||||
if enabled:
|
||||
args.add(flag)
|
||||
|
||||
def add_flag_value(args, flag, value):
|
||||
if value == None:
|
||||
return
|
||||
if type(value) == type("") and not value:
|
||||
return
|
||||
args.add(flag)
|
||||
args.add(value)
|
||||
|
||||
def add_flag_values(args, flag, values):
|
||||
for value in values:
|
||||
add_flag_value(args, flag, value)
|
||||
|
||||
def add_flag_files(args, flag, files):
|
||||
for file in files:
|
||||
args.add(flag)
|
||||
args.add(file.path)
|
||||
|
||||
def add_raw_flags(args, values):
|
||||
args.add_all(values)
|
||||
|
||||
def add_install_mode(args, install_mode):
|
||||
if install_mode == "disable":
|
||||
args.add("--no-install")
|
||||
elif install_mode in ["fallback", "force"]:
|
||||
add_flag_value(args, "--install", install_mode)
|
||||
|
||||
def append_arg(values, value):
|
||||
values.append(str(value))
|
||||
|
||||
def append_flag(values, flag, enabled):
|
||||
if enabled:
|
||||
append_arg(values, flag)
|
||||
|
||||
def append_flag_value(values, flag, value):
|
||||
if value == None:
|
||||
return
|
||||
if type(value) == type("") and not value:
|
||||
return
|
||||
append_arg(values, flag)
|
||||
append_arg(values, value)
|
||||
|
||||
def append_flag_values(values, flag, items):
|
||||
for item in items:
|
||||
append_flag_value(values, flag, item)
|
||||
|
||||
def append_raw_flags(values, items):
|
||||
for item in items:
|
||||
append_arg(values, item)
|
||||
|
||||
def append_install_mode(values, install_mode):
|
||||
if install_mode == "disable":
|
||||
append_arg(values, "--no-install")
|
||||
elif install_mode in ["fallback", "force"]:
|
||||
append_flag_value(values, "--install", install_mode)
|
||||
335
internal/bun_compile.bzl
Normal file
335
internal/bun_compile.bzl
Normal file
@@ -0,0 +1,335 @@
|
||||
"""Rules for Bun build outputs and standalone executables."""
|
||||
|
||||
load("//internal:bun_build_support.bzl", "add_bun_build_common_flags", "add_bun_compile_flags", "bun_build_transitive_inputs", "declare_staged_bun_build_action", "infer_entry_point_root", "sort_files_by_short_path", "validate_hermetic_install_mode")
|
||||
|
||||
def _bun_build_impl(ctx):
|
||||
validate_hermetic_install_mode(ctx.attr, "bun_build")
|
||||
|
||||
toolchain = ctx.toolchains["//bun:toolchain_type"]
|
||||
bun_bin = toolchain.bun.bun_bin
|
||||
entry_points = sort_files_by_short_path(ctx.files.entry_points)
|
||||
data_files = sort_files_by_short_path(ctx.files.data)
|
||||
output_dir = ctx.actions.declare_directory(ctx.label.name)
|
||||
metafile = None
|
||||
if ctx.attr.metafile:
|
||||
metafile = ctx.actions.declare_file(ctx.label.name + ".meta.json")
|
||||
metafile_md = None
|
||||
if ctx.attr.metafile_md:
|
||||
metafile_md = ctx.actions.declare_file(ctx.label.name + ".meta.md")
|
||||
build_root = ctx.attr.root
|
||||
if not build_root:
|
||||
build_root = infer_entry_point_root(entry_points)
|
||||
transitive_inputs = bun_build_transitive_inputs(ctx)
|
||||
build_inputs = depset(
|
||||
direct = entry_points + data_files,
|
||||
transitive = transitive_inputs,
|
||||
)
|
||||
|
||||
build_args = ctx.actions.args()
|
||||
build_args.add("--bun")
|
||||
build_args.add("build")
|
||||
add_bun_build_common_flags(build_args, ctx.attr, metafile = metafile, metafile_md = metafile_md, root = build_root)
|
||||
build_args.add("--outdir")
|
||||
build_args.add(output_dir.path)
|
||||
build_args.add_all(entry_points)
|
||||
|
||||
outputs = [output_dir]
|
||||
if metafile:
|
||||
outputs.append(metafile)
|
||||
if metafile_md:
|
||||
outputs.append(metafile_md)
|
||||
|
||||
declare_staged_bun_build_action(
|
||||
ctx,
|
||||
bun_bin,
|
||||
build_args,
|
||||
build_inputs,
|
||||
outputs = outputs,
|
||||
mnemonic = "BunBuild",
|
||||
progress_message = "Building {} with Bun".format(ctx.label.name),
|
||||
name_suffix = "_build",
|
||||
)
|
||||
|
||||
return [DefaultInfo(files = depset(outputs))]
|
||||
|
||||
def _bun_compile_impl(ctx):
|
||||
validate_hermetic_install_mode(ctx.attr, "bun_compile")
|
||||
|
||||
toolchain = ctx.toolchains["//bun:toolchain_type"]
|
||||
bun_bin = toolchain.bun.bun_bin
|
||||
output = ctx.actions.declare_file(ctx.label.name)
|
||||
compile_executable = ctx.file.compile_executable
|
||||
data_files = sort_files_by_short_path(ctx.files.data)
|
||||
|
||||
args = ctx.actions.args()
|
||||
args.add("--bun")
|
||||
args.add("build")
|
||||
add_bun_build_common_flags(args, ctx.attr)
|
||||
add_bun_compile_flags(args, ctx.attr, compile_executable = compile_executable)
|
||||
args.add("--outfile")
|
||||
args.add(output.path)
|
||||
args.add(ctx.file.entry_point.path)
|
||||
|
||||
direct_inputs = [ctx.file.entry_point] + data_files
|
||||
if compile_executable:
|
||||
direct_inputs.append(compile_executable)
|
||||
|
||||
declare_staged_bun_build_action(
|
||||
ctx,
|
||||
bun_bin,
|
||||
args,
|
||||
depset(
|
||||
direct = direct_inputs,
|
||||
transitive = bun_build_transitive_inputs(ctx),
|
||||
),
|
||||
outputs = [output],
|
||||
mnemonic = "BunCompile",
|
||||
progress_message = "Compiling {} with Bun".format(ctx.file.entry_point.short_path),
|
||||
name_suffix = "_compile",
|
||||
)
|
||||
|
||||
return [
|
||||
DefaultInfo(
|
||||
executable = output,
|
||||
files = depset([output]),
|
||||
),
|
||||
]
|
||||
|
||||
_COMMON_BUILD_ATTRS = {
|
||||
"node_modules": attr.label(
|
||||
doc = "Optional label providing package files from a `node_modules` tree, typically produced by `bun_install`, for package resolution.",
|
||||
),
|
||||
"deps": attr.label_list(
|
||||
doc = "Source/library dependencies that provide transitive inputs.",
|
||||
),
|
||||
"data": attr.label_list(
|
||||
allow_files = True,
|
||||
doc = "Additional non-source files needed during building.",
|
||||
),
|
||||
"install_mode": attr.string(
|
||||
default = "disable",
|
||||
values = ["disable", "auto", "fallback", "force"],
|
||||
doc = "Whether Bun may auto-install missing packages while executing the build. Hermetic build actions require `disable`; other values are rejected.",
|
||||
),
|
||||
"target": attr.string(
|
||||
default = "browser",
|
||||
values = ["browser", "node", "bun"],
|
||||
doc = "Bun build target environment.",
|
||||
),
|
||||
"format": attr.string(
|
||||
default = "esm",
|
||||
values = ["esm", "cjs", "iife"],
|
||||
doc = "Output module format.",
|
||||
),
|
||||
"production": attr.bool(
|
||||
default = False,
|
||||
doc = "If true, sets `NODE_ENV=production` and enables Bun production mode.",
|
||||
),
|
||||
"splitting": attr.bool(
|
||||
default = False,
|
||||
doc = "If true, enables code splitting.",
|
||||
),
|
||||
"root": attr.string(
|
||||
doc = "Optional root directory for multiple entry points.",
|
||||
),
|
||||
"sourcemap": attr.string(
|
||||
default = "none",
|
||||
values = ["none", "linked", "inline", "external"],
|
||||
doc = "Sourcemap emission mode.",
|
||||
),
|
||||
"banner": attr.string(
|
||||
doc = "Optional bundle banner text.",
|
||||
),
|
||||
"footer": attr.string(
|
||||
doc = "Optional bundle footer text.",
|
||||
),
|
||||
"public_path": attr.string(
|
||||
doc = "Optional public path prefix for emitted imports.",
|
||||
),
|
||||
"packages": attr.string(
|
||||
default = "bundle",
|
||||
values = ["bundle", "external"],
|
||||
doc = "Whether packages stay bundled or are treated as external.",
|
||||
),
|
||||
"external": attr.string_list(
|
||||
doc = "Modules treated as externals (not bundled).",
|
||||
),
|
||||
"entry_naming": attr.string(
|
||||
doc = "Optional entry naming template.",
|
||||
),
|
||||
"chunk_naming": attr.string(
|
||||
doc = "Optional chunk naming template.",
|
||||
),
|
||||
"asset_naming": attr.string(
|
||||
doc = "Optional asset naming template.",
|
||||
),
|
||||
"minify": attr.bool(
|
||||
default = False,
|
||||
doc = "If true, enables all Bun minification passes.",
|
||||
),
|
||||
"minify_syntax": attr.bool(
|
||||
default = False,
|
||||
doc = "If true, minifies syntax only.",
|
||||
),
|
||||
"minify_whitespace": attr.bool(
|
||||
default = False,
|
||||
doc = "If true, minifies whitespace only.",
|
||||
),
|
||||
"minify_identifiers": attr.bool(
|
||||
default = False,
|
||||
doc = "If true, minifies identifiers only.",
|
||||
),
|
||||
"keep_names": attr.bool(
|
||||
default = False,
|
||||
doc = "If true, preserves function and class names when minifying.",
|
||||
),
|
||||
"css_chunking": attr.bool(
|
||||
default = False,
|
||||
doc = "If true, Bun chunks CSS across multiple entry points.",
|
||||
),
|
||||
"conditions": attr.string_list(
|
||||
doc = "Custom resolve conditions passed to Bun.",
|
||||
),
|
||||
"env": attr.string(
|
||||
doc = "Inline environment variable behavior passed to `--env`.",
|
||||
),
|
||||
"define": attr.string_list(
|
||||
doc = "Repeated `--define` values such as `process.env.NODE_ENV:\"production\"`.",
|
||||
),
|
||||
"drop": attr.string_list(
|
||||
doc = "Repeated `--drop` values, for example `console`.",
|
||||
),
|
||||
"feature": attr.string_list(
|
||||
doc = "Repeated `--feature` values for dead-code elimination.",
|
||||
),
|
||||
"loader": attr.string_list(
|
||||
doc = "Repeated `--loader` values such as `.svg:file`.",
|
||||
),
|
||||
"jsx_factory": attr.string(
|
||||
doc = "Optional JSX factory override.",
|
||||
),
|
||||
"jsx_fragment": attr.string(
|
||||
doc = "Optional JSX fragment override.",
|
||||
),
|
||||
"jsx_import_source": attr.string(
|
||||
doc = "Optional JSX import source override.",
|
||||
),
|
||||
"jsx_runtime": attr.string(
|
||||
values = ["", "automatic", "classic"],
|
||||
default = "",
|
||||
doc = "Optional JSX runtime override.",
|
||||
),
|
||||
"jsx_side_effects": attr.bool(
|
||||
default = False,
|
||||
doc = "If true, treats JSX as having side effects.",
|
||||
),
|
||||
"react_fast_refresh": attr.bool(
|
||||
default = False,
|
||||
doc = "If true, enables Bun's React fast refresh transform.",
|
||||
),
|
||||
"emit_dce_annotations": attr.bool(
|
||||
default = False,
|
||||
doc = "If true, re-emits DCE annotations in the bundle.",
|
||||
),
|
||||
"no_bundle": attr.bool(
|
||||
default = False,
|
||||
doc = "If true, transpiles without bundling.",
|
||||
),
|
||||
"build_flags": attr.string_list(
|
||||
doc = "Additional raw flags forwarded to `bun build`.",
|
||||
),
|
||||
}
|
||||
|
||||
bun_build = rule(
|
||||
implementation = _bun_build_impl,
|
||||
doc = """Builds one or more entry points with `bun build`.
|
||||
|
||||
The rule emits a directory artifact so Bun can materialize multi-file output
|
||||
graphs such as HTML, CSS, assets, and split chunks. Optional metafile outputs
|
||||
may be requested with `metafile` and `metafile_md`.
|
||||
""",
|
||||
attrs = dict(_COMMON_BUILD_ATTRS, **{
|
||||
"entry_points": attr.label_list(
|
||||
mandatory = True,
|
||||
allow_files = True,
|
||||
doc = "Entry files to build, including JS/TS or HTML entry points.",
|
||||
),
|
||||
"metafile": attr.bool(
|
||||
default = False,
|
||||
doc = "If true, emits Bun's JSON metafile alongside the output directory.",
|
||||
),
|
||||
"metafile_md": attr.bool(
|
||||
default = False,
|
||||
doc = "If true, emits Bun's markdown metafile alongside the output directory.",
|
||||
),
|
||||
}),
|
||||
toolchains = ["//bun:toolchain_type"],
|
||||
)
|
||||
|
||||
bun_compile = rule(
|
||||
implementation = _bun_compile_impl,
|
||||
doc = """Compiles a Bun program into a standalone executable with `bun build --compile`.""",
|
||||
attrs = dict(_COMMON_BUILD_ATTRS, **{
|
||||
"target": attr.string(
|
||||
default = "bun",
|
||||
values = ["browser", "node", "bun"],
|
||||
doc = "Bun build target environment for the compiled executable.",
|
||||
),
|
||||
"entry_point": attr.label(
|
||||
mandatory = True,
|
||||
allow_single_file = True,
|
||||
doc = "Entry file to compile into an executable.",
|
||||
),
|
||||
"bytecode": attr.bool(
|
||||
default = False,
|
||||
doc = "If true, enables Bun bytecode caching in the compiled executable.",
|
||||
),
|
||||
"compile_exec_argv": attr.string_list(
|
||||
doc = "Repeated `--compile-exec-argv` values prepended to the executable's `execArgv`.",
|
||||
),
|
||||
"compile_executable": attr.label(
|
||||
allow_single_file = True,
|
||||
doc = "Optional Bun executable used for cross-compilation via `--compile-executable-path`.",
|
||||
),
|
||||
"compile_autoload_dotenv": attr.bool(
|
||||
default = True,
|
||||
doc = "Whether the compiled executable auto-loads `.env` files at runtime.",
|
||||
),
|
||||
"compile_autoload_bunfig": attr.bool(
|
||||
default = True,
|
||||
doc = "Whether the compiled executable auto-loads `bunfig.toml` at runtime.",
|
||||
),
|
||||
"compile_autoload_tsconfig": attr.bool(
|
||||
default = False,
|
||||
doc = "Whether the compiled executable auto-loads `tsconfig.json` at runtime.",
|
||||
),
|
||||
"compile_autoload_package_json": attr.bool(
|
||||
default = False,
|
||||
doc = "Whether the compiled executable auto-loads `package.json` at runtime.",
|
||||
),
|
||||
"windows_hide_console": attr.bool(
|
||||
default = False,
|
||||
doc = "When targeting Windows, hides the console window for GUI-style executables.",
|
||||
),
|
||||
"windows_icon": attr.string(
|
||||
doc = "Optional Windows icon path passed directly to Bun.",
|
||||
),
|
||||
"windows_title": attr.string(
|
||||
doc = "Optional Windows executable title.",
|
||||
),
|
||||
"windows_publisher": attr.string(
|
||||
doc = "Optional Windows publisher metadata.",
|
||||
),
|
||||
"windows_version": attr.string(
|
||||
doc = "Optional Windows version metadata.",
|
||||
),
|
||||
"windows_description": attr.string(
|
||||
doc = "Optional Windows description metadata.",
|
||||
),
|
||||
"windows_copyright": attr.string(
|
||||
doc = "Optional Windows copyright metadata.",
|
||||
),
|
||||
}),
|
||||
executable = True,
|
||||
toolchains = ["//bun:toolchain_type"],
|
||||
)
|
||||
@@ -1,186 +1,140 @@
|
||||
"""Rule for running JS/TS scripts with Bun in watch mode for development."""
|
||||
|
||||
load("//internal:bun_command.bzl", "append_flag", "append_flag_values", "append_install_mode", "append_raw_flags")
|
||||
load("//internal:runtime_launcher.bzl", "declare_runtime_wrapper", "runfiles_path", "runtime_launcher_attrs", "write_launcher_spec")
|
||||
load("//internal:workspace.bzl", "create_bun_workspace_info", "workspace_runfiles")
|
||||
|
||||
def _bun_dev_impl(ctx):
|
||||
toolchain = ctx.toolchains["//bun:toolchain_type"]
|
||||
bun_bin = toolchain.bun.bun_bin
|
||||
entry_point = ctx.file.entry_point
|
||||
|
||||
restart_watch_paths = "\n".join([path.short_path for path in ctx.files.restart_on])
|
||||
|
||||
launcher = ctx.actions.declare_file(ctx.label.name)
|
||||
ctx.actions.write(
|
||||
output = launcher,
|
||||
is_executable = True,
|
||||
content = """#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
runfiles_dir="${{RUNFILES_DIR:-$0.runfiles}}"
|
||||
workspace_root="${{runfiles_dir}}/_main"
|
||||
bun_bin="${{runfiles_dir}}/_main/{bun_short_path}"
|
||||
entry_point="${{runfiles_dir}}/_main/{entry_short_path}"
|
||||
|
||||
resolve_entrypoint_workdir() {{
|
||||
local dir
|
||||
dir="$(dirname "${{entry_point}}")"
|
||||
while [[ "${{dir}}" == "${{workspace_root}}"* ]]; do
|
||||
if [[ -f "${{dir}}/.env" || -f "${{dir}}/package.json" ]]; then
|
||||
echo "${{dir}}"
|
||||
return 0
|
||||
fi
|
||||
if [[ "${{dir}}" == "${{workspace_root}}" ]]; then
|
||||
break
|
||||
fi
|
||||
dir="$(dirname "${{dir}}")"
|
||||
done
|
||||
echo "$(dirname "${{entry_point}}")"
|
||||
}}
|
||||
|
||||
working_dir="{working_dir}"
|
||||
if [[ "${{working_dir}}" == "entry_point" ]]; then
|
||||
cd "$(resolve_entrypoint_workdir)"
|
||||
else
|
||||
cd "${{workspace_root}}"
|
||||
fi
|
||||
|
||||
watch_mode="{watch_mode}"
|
||||
if [[ "${{watch_mode}}" == "hot" ]]; then
|
||||
dev_flag="--hot"
|
||||
else
|
||||
dev_flag="--watch"
|
||||
fi
|
||||
|
||||
run_dev() {{
|
||||
exec "${{bun_bin}}" --bun "${{dev_flag}}" run "${{entry_point}}" "$@"
|
||||
}}
|
||||
|
||||
if [[ {restart_count} -eq 0 ]]; then
|
||||
run_dev "$@"
|
||||
fi
|
||||
|
||||
readarray -t restart_paths <<'EOF_RESTART_PATHS'
|
||||
{restart_watch_paths}
|
||||
EOF_RESTART_PATHS
|
||||
|
||||
file_mtime() {{
|
||||
local p="$1"
|
||||
if stat -f '%m' "${{p}}" >/dev/null 2>&1; then
|
||||
stat -f '%m' "${{p}}"
|
||||
return 0
|
||||
fi
|
||||
stat -c '%Y' "${{p}}"
|
||||
}}
|
||||
|
||||
declare -A mtimes
|
||||
for rel in "${{restart_paths[@]}}"; do
|
||||
path="${{runfiles_dir}}/_main/${{rel}}"
|
||||
if [[ -e "${{path}}" ]]; then
|
||||
mtimes["${{rel}}"]="$(file_mtime "${{path}}")"
|
||||
else
|
||||
mtimes["${{rel}}"]="missing"
|
||||
fi
|
||||
done
|
||||
|
||||
child_pid=""
|
||||
restart_child() {{
|
||||
if [[ -n "${{child_pid}}" ]] && kill -0 "${{child_pid}}" 2>/dev/null; then
|
||||
kill "${{child_pid}}"
|
||||
wait "${{child_pid}}" || true
|
||||
fi
|
||||
"${{bun_bin}}" --bun "${{dev_flag}}" run "${{entry_point}}" "$@" &
|
||||
child_pid=$!
|
||||
}}
|
||||
|
||||
cleanup() {{
|
||||
if [[ -n "${{child_pid}}" ]] && kill -0 "${{child_pid}}" 2>/dev/null; then
|
||||
kill "${{child_pid}}"
|
||||
wait "${{child_pid}}" || true
|
||||
fi
|
||||
}}
|
||||
|
||||
trap cleanup EXIT INT TERM
|
||||
|
||||
restart_child "$@"
|
||||
|
||||
while true; do
|
||||
sleep 1
|
||||
changed=0
|
||||
for rel in "${{restart_paths[@]}}"; do
|
||||
path="${{runfiles_dir}}/_main/${{rel}}"
|
||||
if [[ -e "${{path}}" ]]; then
|
||||
current="$(file_mtime "${{path}}")"
|
||||
else
|
||||
current="missing"
|
||||
fi
|
||||
if [[ "${{current}}" != "${{mtimes[${{rel}}]}}" ]]; then
|
||||
mtimes["${{rel}}"]="${{current}}"
|
||||
changed=1
|
||||
fi
|
||||
done
|
||||
if [[ "${{changed}}" -eq 1 ]]; then
|
||||
restart_child "$@"
|
||||
fi
|
||||
done
|
||||
""".format(
|
||||
bun_short_path = bun_bin.short_path,
|
||||
entry_short_path = entry_point.short_path,
|
||||
watch_mode = ctx.attr.watch_mode,
|
||||
working_dir = ctx.attr.working_dir,
|
||||
restart_count = len(ctx.files.restart_on),
|
||||
restart_watch_paths = restart_watch_paths,
|
||||
),
|
||||
workspace_info = create_bun_workspace_info(
|
||||
ctx,
|
||||
extra_files = ctx.files.data + ctx.files.restart_on + ctx.files.preload + ctx.files.env_files + [bun_bin],
|
||||
primary_file = entry_point,
|
||||
)
|
||||
|
||||
transitive_files = []
|
||||
if ctx.attr.node_modules:
|
||||
transitive_files.append(ctx.attr.node_modules[DefaultInfo].files)
|
||||
argv = ["--bun", "run"]
|
||||
append_install_mode(argv, ctx.attr.install_mode)
|
||||
append_flag(argv, "--no-env-file", ctx.attr.no_env_file)
|
||||
append_flag(argv, "--smol", ctx.attr.smol)
|
||||
append_flag_values(argv, "--conditions", ctx.attr.conditions)
|
||||
append_flag(argv, "--no-clear-screen", ctx.attr.no_clear_screen)
|
||||
append_raw_flags(argv, ctx.attr.run_flags)
|
||||
|
||||
runfiles = ctx.runfiles(
|
||||
files = [bun_bin, entry_point] + ctx.files.data + ctx.files.restart_on,
|
||||
transitive_files = depset(transitive = transitive_files),
|
||||
)
|
||||
spec_file = write_launcher_spec(ctx, {
|
||||
"version": 1,
|
||||
"kind": "bun_run",
|
||||
"bun_short_path": runfiles_path(bun_bin),
|
||||
"primary_source_short_path": runfiles_path(entry_point),
|
||||
"package_json_short_path": "",
|
||||
"install_metadata_short_path": runfiles_path(workspace_info.install_metadata_file) if workspace_info.install_metadata_file else "",
|
||||
"install_repo_runfiles_path": workspace_info.install_repo_runfiles_path,
|
||||
"node_modules_roots": workspace_info.node_modules_roots,
|
||||
"package_dir_hint": workspace_info.package_dir_hint,
|
||||
"working_dir_mode": ctx.attr.working_dir,
|
||||
"inherit_host_path": ctx.attr.inherit_host_path,
|
||||
"argv": argv,
|
||||
"args": ctx.attr.args,
|
||||
"passthrough_args": True,
|
||||
"tool_short_path": "",
|
||||
"restart_on": [runfiles_path(file) for file in ctx.files.restart_on],
|
||||
"watch_mode": ctx.attr.watch_mode,
|
||||
"reporter": "",
|
||||
"coverage": False,
|
||||
"coverage_reporters": [],
|
||||
"preload_short_paths": [runfiles_path(file) for file in ctx.files.preload],
|
||||
"env_file_short_paths": [runfiles_path(file) for file in ctx.files.env_files],
|
||||
"test_short_paths": [],
|
||||
})
|
||||
launcher = declare_runtime_wrapper(ctx, bun_bin, spec_file)
|
||||
|
||||
return [
|
||||
workspace_info,
|
||||
DefaultInfo(
|
||||
executable = launcher,
|
||||
runfiles = runfiles,
|
||||
executable = launcher.executable,
|
||||
runfiles = workspace_runfiles(
|
||||
ctx,
|
||||
workspace_info,
|
||||
direct_files = [launcher.executable, launcher.runner, spec_file],
|
||||
),
|
||||
),
|
||||
]
|
||||
|
||||
_BUN_DEV_ATTRS = runtime_launcher_attrs()
|
||||
_BUN_DEV_ATTRS.update({
|
||||
"entry_point": attr.label(
|
||||
mandatory = True,
|
||||
allow_single_file = [".js", ".ts", ".jsx", ".tsx", ".mjs", ".cjs"],
|
||||
doc = "Path to the main JS/TS file to execute in dev mode.",
|
||||
),
|
||||
"watch_mode": attr.string(
|
||||
default = "watch",
|
||||
values = ["watch", "hot"],
|
||||
doc = "Bun live-reload mode: `watch` (default) or `hot`.",
|
||||
),
|
||||
"restart_on": attr.label_list(
|
||||
allow_files = True,
|
||||
doc = "Files that trigger a full Bun process restart when they change.",
|
||||
),
|
||||
"node_modules": attr.label(
|
||||
doc = "Optional label providing package files from a `node_modules` tree, typically produced by `bun_install`, in runfiles.",
|
||||
),
|
||||
"data": attr.label_list(
|
||||
allow_files = True,
|
||||
doc = "Additional runtime files required by the dev process.",
|
||||
),
|
||||
"preload": attr.label_list(
|
||||
allow_files = True,
|
||||
doc = "Modules to preload with `--preload` before running the entry point.",
|
||||
),
|
||||
"env_files": attr.label_list(
|
||||
allow_files = True,
|
||||
doc = "Additional environment files loaded with `--env-file`.",
|
||||
),
|
||||
"no_env_file": attr.bool(
|
||||
default = False,
|
||||
doc = "If true, disables Bun's automatic `.env` loading.",
|
||||
),
|
||||
"smol": attr.bool(
|
||||
default = False,
|
||||
doc = "If true, enables Bun's lower-memory runtime mode.",
|
||||
),
|
||||
"conditions": attr.string_list(
|
||||
doc = "Custom package resolve conditions passed to Bun.",
|
||||
),
|
||||
"install_mode": attr.string(
|
||||
default = "disable",
|
||||
values = ["disable", "auto", "fallback", "force"],
|
||||
doc = "Whether Bun may auto-install missing packages in dev mode.",
|
||||
),
|
||||
"no_clear_screen": attr.bool(
|
||||
default = False,
|
||||
doc = "If true, disables terminal clearing on Bun reloads.",
|
||||
),
|
||||
"run_flags": attr.string_list(
|
||||
doc = "Additional raw flags forwarded to `bun run` before the entry point.",
|
||||
),
|
||||
"working_dir": attr.string(
|
||||
default = "workspace",
|
||||
values = ["workspace", "entry_point"],
|
||||
doc = "Working directory at runtime: `workspace` root or nearest `entry_point` ancestor containing `.env`/`package.json`.",
|
||||
),
|
||||
"inherit_host_path": attr.bool(
|
||||
default = False,
|
||||
doc = "If true, appends the host PATH after staged node_modules/.bin entries at runtime.",
|
||||
),
|
||||
})
|
||||
|
||||
bun_dev = rule(
|
||||
implementation = _bun_dev_impl,
|
||||
doc = """Runs a JS/TS entry point in Bun development watch mode.
|
||||
|
||||
This rule is intended for local dev loops (`bazel run`) and supports Bun
|
||||
watch/HMR plus optional full restarts on selected file changes.
|
||||
watch/HMR plus optional full restarts on selected file changes. It is a local
|
||||
workflow helper rather than a hermetic build rule.
|
||||
""",
|
||||
attrs = {
|
||||
"entry_point": attr.label(
|
||||
mandatory = True,
|
||||
allow_single_file = [".js", ".ts", ".jsx", ".tsx", ".mjs", ".cjs"],
|
||||
doc = "Path to the main JS/TS file to execute in dev mode.",
|
||||
),
|
||||
"watch_mode": attr.string(
|
||||
default = "watch",
|
||||
values = ["watch", "hot"],
|
||||
doc = "Bun live-reload mode: `watch` (default) or `hot`.",
|
||||
),
|
||||
"restart_on": attr.label_list(
|
||||
allow_files = True,
|
||||
doc = "Files that trigger a full Bun process restart when they change.",
|
||||
),
|
||||
"node_modules": attr.label(
|
||||
doc = "Optional label providing package files from a `node_modules` tree, typically produced by `bun_install`, in runfiles.",
|
||||
),
|
||||
"data": attr.label_list(
|
||||
allow_files = True,
|
||||
doc = "Additional runtime files required by the dev process.",
|
||||
),
|
||||
"working_dir": attr.string(
|
||||
default = "workspace",
|
||||
values = ["workspace", "entry_point"],
|
||||
doc = "Working directory at runtime: `workspace` root or nearest `entry_point` ancestor containing `.env`/`package.json`.",
|
||||
),
|
||||
},
|
||||
attrs = _BUN_DEV_ATTRS,
|
||||
executable = True,
|
||||
toolchains = ["//bun:toolchain_type"],
|
||||
)
|
||||
|
||||
@@ -6,6 +6,13 @@ _DEFAULT_INSTALL_INPUTS = [
|
||||
"bunfig.toml",
|
||||
]
|
||||
|
||||
_MANIFEST_DEP_FIELDS = [
|
||||
"dependencies",
|
||||
"devDependencies",
|
||||
"optionalDependencies",
|
||||
"peerDependencies",
|
||||
]
|
||||
|
||||
def _normalize_path(path):
|
||||
normalized = path.replace("\\", "/")
|
||||
if normalized.endswith("/") and normalized != "/":
|
||||
@@ -96,10 +103,82 @@ def _workspace_patterns(repository_ctx, package_json):
|
||||
|
||||
return patterns
|
||||
|
||||
def _validate_catalog_shape(field, value):
|
||||
if value == None:
|
||||
return
|
||||
|
||||
if type(value) != type({}):
|
||||
fail("bun_install: `{}` must be an object".format(field))
|
||||
|
||||
if field not in ["catalogs", "workspaces.catalogs"]:
|
||||
return
|
||||
|
||||
for name, catalog in value.items():
|
||||
if type(name) != type(""):
|
||||
fail("bun_install: `catalogs` keys must be strings, got {}".format(type(name)))
|
||||
if type(catalog) != type({}):
|
||||
fail("bun_install: `catalogs.{}` must be an object".format(name))
|
||||
|
||||
def _copy_json_value(value):
|
||||
return json.decode(json.encode(value))
|
||||
|
||||
def _package_target_name(package_name):
|
||||
sanitized = package_name
|
||||
sanitized = sanitized.replace("@", "at_")
|
||||
sanitized = sanitized.replace("/", "_")
|
||||
sanitized = sanitized.replace("-", "_")
|
||||
sanitized = sanitized.replace(".", "_")
|
||||
sanitized = sanitized.replace("__", "_").replace("__", "_").replace("__", "_")
|
||||
sanitized = sanitized.strip("_")
|
||||
if not sanitized:
|
||||
sanitized = "package"
|
||||
return "npm__" + sanitized
|
||||
|
||||
def _manifest_dependency_names(manifest):
|
||||
names = {}
|
||||
for field in _MANIFEST_DEP_FIELDS:
|
||||
dependencies = manifest.get(field)
|
||||
if dependencies == None:
|
||||
continue
|
||||
if type(dependencies) != type({}):
|
||||
fail("bun_install: `{}` must be an object when present".format(field))
|
||||
for name in dependencies.keys():
|
||||
names[name] = True
|
||||
return names
|
||||
|
||||
def _normalized_root_manifest(repository_ctx, package_json):
|
||||
manifest = json.decode(repository_ctx.read(package_json))
|
||||
workspaces = manifest.get("workspaces")
|
||||
|
||||
for field in ["catalog", "catalogs"]:
|
||||
manifest_value = manifest.get(field)
|
||||
_validate_catalog_shape(field, manifest_value)
|
||||
|
||||
if type(workspaces) != type({}):
|
||||
continue
|
||||
|
||||
workspace_value = workspaces.get(field)
|
||||
_validate_catalog_shape("workspaces.{}".format(field), workspace_value)
|
||||
|
||||
if workspace_value == None:
|
||||
continue
|
||||
|
||||
if manifest_value == None:
|
||||
manifest[field] = _copy_json_value(workspace_value)
|
||||
continue
|
||||
|
||||
if manifest_value != workspace_value:
|
||||
fail(
|
||||
"bun_install: `{}` conflicts with `workspaces.{}`; use one source of truth or keep both values identical".format(field, field),
|
||||
)
|
||||
|
||||
return json.encode(manifest)
|
||||
|
||||
def _materialize_workspace_packages(repository_ctx, package_json):
|
||||
package_root = package_json.dirname
|
||||
package_root_str = str(package_root)
|
||||
written = {}
|
||||
workspace_packages = {}
|
||||
|
||||
for pattern in _workspace_patterns(repository_ctx, package_json):
|
||||
segments = pattern.split("/")
|
||||
@@ -121,6 +200,21 @@ def _materialize_workspace_packages(repository_ctx, package_json):
|
||||
repository_ctx.read(workspace_package_json),
|
||||
)
|
||||
written[relative_dir] = True
|
||||
manifest = json.decode(repository_ctx.read(workspace_package_json))
|
||||
package_name = manifest.get("name")
|
||||
workspace_packages[relative_dir] = package_name if type(package_name) == type("") else ""
|
||||
|
||||
package_dirs = sorted(workspace_packages.keys())
|
||||
package_names_by_dir = {}
|
||||
for package_dir in package_dirs:
|
||||
package_name = workspace_packages[package_dir]
|
||||
if package_name:
|
||||
package_names_by_dir[package_dir] = package_name
|
||||
return struct(
|
||||
package_dirs = package_dirs,
|
||||
package_names_by_dir = package_names_by_dir,
|
||||
package_names = [workspace_packages[package_dir] for package_dir in package_dirs if workspace_packages[package_dir]],
|
||||
)
|
||||
|
||||
def _materialize_install_inputs(repository_ctx, package_json):
|
||||
package_root = package_json.dirname
|
||||
@@ -171,6 +265,68 @@ def _select_bun_binary(repository_ctx):
|
||||
|
||||
fail("Unsupported host platform: os={}, arch={}".format(repository_ctx.os.name, repository_ctx.os.arch))
|
||||
|
||||
def _render_package_targets_file(package_names):
|
||||
lines = ["NPM_PACKAGE_TARGETS = {"]
|
||||
for package_name in package_names:
|
||||
lines.append(' "{}": "{}",'.format(package_name, _package_target_name(package_name)))
|
||||
lines.extend([
|
||||
"}",
|
||||
"",
|
||||
])
|
||||
return "\n".join(lines)
|
||||
|
||||
def _render_repo_defs_bzl(repo_name):
|
||||
return """load(":packages.bzl", "NPM_PACKAGE_TARGETS")
|
||||
|
||||
def package_target_name(package_name):
|
||||
return NPM_PACKAGE_TARGETS.get(package_name)
|
||||
|
||||
def npm_link_all_packages(name = "node_modules", imported_links = []):
|
||||
if not native.existing_rule(name):
|
||||
native.alias(
|
||||
name = name,
|
||||
actual = "@{repo_name}//:node_modules",
|
||||
)
|
||||
|
||||
requested = {{}}
|
||||
for package_name in imported_links:
|
||||
requested[package_name] = True
|
||||
|
||||
for package_name, target_name in NPM_PACKAGE_TARGETS.items():
|
||||
if imported_links and package_name not in requested:
|
||||
continue
|
||||
if native.existing_rule(target_name):
|
||||
continue
|
||||
native.alias(
|
||||
name = target_name,
|
||||
actual = "@{repo_name}//:%s" % target_name,
|
||||
)
|
||||
""".format(repo_name = repo_name)
|
||||
|
||||
def _render_repo_build(package_names):
|
||||
lines = [
|
||||
'exports_files(["defs.bzl", "packages.bzl"])',
|
||||
"",
|
||||
"filegroup(",
|
||||
' name = "node_modules",',
|
||||
' srcs = glob(["**/node_modules/**"], allow_empty = False),',
|
||||
' visibility = ["//visibility:public"],',
|
||||
")",
|
||||
"",
|
||||
]
|
||||
|
||||
for package_name in package_names:
|
||||
lines.extend([
|
||||
"filegroup(",
|
||||
' name = "{}",'.format(_package_target_name(package_name)),
|
||||
' srcs = glob(["node_modules/{}/**"], allow_empty = True),'.format(package_name),
|
||||
' visibility = ["//visibility:public"],',
|
||||
")",
|
||||
"",
|
||||
])
|
||||
|
||||
return "\n".join(lines)
|
||||
|
||||
def _bun_install_repository_impl(repository_ctx):
|
||||
package_json = repository_ctx.path(repository_ctx.attr.package_json)
|
||||
bun_lockfile = repository_ctx.path(repository_ctx.attr.bun_lockfile)
|
||||
@@ -183,16 +339,28 @@ def _bun_install_repository_impl(repository_ctx):
|
||||
|
||||
bun_bin = _select_bun_binary(repository_ctx)
|
||||
lockfile_name = bun_lockfile.basename
|
||||
root_manifest = json.decode(repository_ctx.read(package_json))
|
||||
|
||||
if lockfile_name not in ["bun.lock", "bun.lockb"]:
|
||||
lockfile_name = "bun.lock"
|
||||
|
||||
repository_ctx.file("package.json", repository_ctx.read(package_json))
|
||||
repository_ctx.file("package.json", _normalized_root_manifest(repository_ctx, package_json))
|
||||
repository_ctx.symlink(bun_lockfile, lockfile_name)
|
||||
_materialize_install_inputs(repository_ctx, package_json)
|
||||
_materialize_workspace_packages(repository_ctx, package_json)
|
||||
workspace_packages = _materialize_workspace_packages(repository_ctx, package_json)
|
||||
|
||||
install_args = [str(bun_bin), "--bun", "install", "--frozen-lockfile", "--no-progress"]
|
||||
if repository_ctx.attr.production:
|
||||
install_args.append("--production")
|
||||
for omit in repository_ctx.attr.omit:
|
||||
install_args.extend(["--omit", omit])
|
||||
if repository_ctx.attr.linker:
|
||||
install_args.extend(["--linker", repository_ctx.attr.linker])
|
||||
if repository_ctx.attr.backend:
|
||||
install_args.extend(["--backend", repository_ctx.attr.backend])
|
||||
if repository_ctx.attr.ignore_scripts:
|
||||
install_args.append("--ignore-scripts")
|
||||
install_args.extend(repository_ctx.attr.install_flags)
|
||||
if repository_ctx.attr.isolated_home:
|
||||
result = repository_ctx.execute(
|
||||
install_args,
|
||||
@@ -216,15 +384,28 @@ stderr:
|
||||
""".format(result.stdout, result.stderr))
|
||||
|
||||
repository_ctx.file(
|
||||
"BUILD.bazel",
|
||||
"""filegroup(
|
||||
name = "node_modules",
|
||||
srcs = glob(["**/node_modules/**"], allow_empty = False),
|
||||
visibility = ["//visibility:public"],
|
||||
)
|
||||
""",
|
||||
"node_modules/.rules_bun/install.json",
|
||||
json.encode({
|
||||
"bun_lockfile": lockfile_name,
|
||||
"install_root_rel_dir": ".",
|
||||
"package_json": "package.json",
|
||||
"workspace_package_dirs": workspace_packages.package_dirs,
|
||||
"workspace_package_names_by_dir": workspace_packages.package_names_by_dir,
|
||||
}) + "\n",
|
||||
)
|
||||
|
||||
package_names = {}
|
||||
for package_name in _manifest_dependency_names(root_manifest).keys():
|
||||
package_names[package_name] = True
|
||||
for package_name in workspace_packages.package_names:
|
||||
package_names[package_name] = True
|
||||
|
||||
sorted_package_names = sorted(package_names.keys())
|
||||
visible_repo_name = repository_ctx.attr.visible_repo_name or repository_ctx.name
|
||||
repository_ctx.file("packages.bzl", _render_package_targets_file(sorted_package_names))
|
||||
repository_ctx.file("defs.bzl", _render_repo_defs_bzl(visible_repo_name))
|
||||
repository_ctx.file("BUILD.bazel", _render_repo_build(sorted_package_names))
|
||||
|
||||
bun_install_repository = repository_rule(
|
||||
implementation = _bun_install_repository_impl,
|
||||
attrs = {
|
||||
@@ -232,6 +413,13 @@ bun_install_repository = repository_rule(
|
||||
"bun_lockfile": attr.label(mandatory = True, allow_single_file = True),
|
||||
"install_inputs": attr.label_list(allow_files = True),
|
||||
"isolated_home": attr.bool(default = True),
|
||||
"production": attr.bool(default = False),
|
||||
"omit": attr.string_list(),
|
||||
"linker": attr.string(),
|
||||
"backend": attr.string(),
|
||||
"ignore_scripts": attr.bool(default = True),
|
||||
"install_flags": attr.string_list(),
|
||||
"visible_repo_name": attr.string(),
|
||||
"bun_linux_x64": attr.label(default = "@bun_linux_x64//:bun-linux-x64/bun", allow_single_file = True),
|
||||
"bun_linux_aarch64": attr.label(default = "@bun_linux_aarch64//:bun-linux-aarch64/bun", allow_single_file = True),
|
||||
"bun_darwin_x64": attr.label(default = "@bun_darwin_x64//:bun-darwin-x64/bun", allow_single_file = True),
|
||||
@@ -240,7 +428,18 @@ bun_install_repository = repository_rule(
|
||||
},
|
||||
)
|
||||
|
||||
def bun_install(name, package_json, bun_lockfile, install_inputs = [], isolated_home = True):
|
||||
def bun_install(
|
||||
name,
|
||||
package_json,
|
||||
bun_lockfile,
|
||||
install_inputs = [],
|
||||
isolated_home = True,
|
||||
production = False,
|
||||
omit = [],
|
||||
linker = "",
|
||||
backend = "",
|
||||
ignore_scripts = True,
|
||||
install_flags = []):
|
||||
"""Create an external repository containing installed node_modules.
|
||||
|
||||
Args:
|
||||
@@ -251,6 +450,12 @@ def bun_install(name, package_json, bun_lockfile, install_inputs = [], isolated_
|
||||
into the install context, such as patch files or auth/config files.
|
||||
isolated_home: Whether to run Bun with HOME set to the generated
|
||||
repository root for a more isolated install context.
|
||||
production: Whether to omit devDependencies during install.
|
||||
omit: Optional Bun dependency groups to omit, such as `dev` or `peer`.
|
||||
linker: Optional Bun linker strategy, such as `isolated` or `hoisted`.
|
||||
backend: Optional Bun install backend, such as `hardlink` or `copyfile`.
|
||||
ignore_scripts: Whether to skip lifecycle scripts in the project manifest.
|
||||
install_flags: Additional raw flags forwarded to `bun install`.
|
||||
|
||||
Usage (WORKSPACE):
|
||||
bun_install(
|
||||
@@ -266,4 +471,11 @@ def bun_install(name, package_json, bun_lockfile, install_inputs = [], isolated_
|
||||
bun_lockfile = bun_lockfile,
|
||||
install_inputs = install_inputs,
|
||||
isolated_home = isolated_home,
|
||||
production = production,
|
||||
omit = omit,
|
||||
linker = linker,
|
||||
backend = backend,
|
||||
ignore_scripts = ignore_scripts,
|
||||
install_flags = install_flags,
|
||||
visible_repo_name = name,
|
||||
)
|
||||
|
||||
@@ -1,185 +1,156 @@
|
||||
"""Rule for running package.json scripts with Bun."""
|
||||
|
||||
|
||||
def _shell_quote(value):
|
||||
return "'" + value.replace("'", "'\"'\"'") + "'"
|
||||
|
||||
load("//internal:bun_command.bzl", "append_flag", "append_flag_value", "append_flag_values", "append_install_mode", "append_raw_flags")
|
||||
load("//internal:runtime_launcher.bzl", "declare_runtime_wrapper", "runfiles_path", "runtime_launcher_attrs", "write_launcher_spec")
|
||||
load("//internal:workspace.bzl", "create_bun_workspace_info", "workspace_runfiles")
|
||||
|
||||
def _bun_script_impl(ctx):
|
||||
toolchain = ctx.toolchains["//bun:toolchain_type"]
|
||||
bun_bin = toolchain.bun.bun_bin
|
||||
package_json = ctx.file.package_json
|
||||
|
||||
launcher = ctx.actions.declare_file(ctx.label.name)
|
||||
ctx.actions.write(
|
||||
output = launcher,
|
||||
is_executable = True,
|
||||
content = """#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
runfiles_dir="${{RUNFILES_DIR:-$0.runfiles}}"
|
||||
workspace_root="${{runfiles_dir}}/_main"
|
||||
workspace_root="$(cd "${{workspace_root}}" && pwd -P)"
|
||||
bun_bin="${{runfiles_dir}}/_main/{bun_short_path}"
|
||||
package_json="${{runfiles_dir}}/_main/{package_json_short_path}"
|
||||
package_dir="$(cd "$(dirname "${{package_json}}")" && pwd -P)"
|
||||
package_rel_dir="{package_rel_dir}"
|
||||
|
||||
select_primary_node_modules() {{
|
||||
local selected=""
|
||||
local fallback=""
|
||||
while IFS= read -r node_modules_dir; do
|
||||
if [[ -z "${{fallback}}" ]]; then
|
||||
fallback="${{node_modules_dir}}"
|
||||
fi
|
||||
|
||||
if [[ ! -d "${{node_modules_dir}}/.bun" ]]; then
|
||||
continue
|
||||
fi
|
||||
|
||||
if [[ "${{node_modules_dir}}" != *"/runfiles/_main/"* ]]; then
|
||||
selected="${{node_modules_dir}}"
|
||||
break
|
||||
fi
|
||||
|
||||
if [[ -z "${{selected}}" ]]; then
|
||||
selected="${{node_modules_dir}}"
|
||||
fi
|
||||
done < <(find -L "${{runfiles_dir}}" -type d -name node_modules 2>/dev/null | sort)
|
||||
|
||||
if [[ -n "${{selected}}" ]]; then
|
||||
echo "${{selected}}"
|
||||
else
|
||||
echo "${{fallback}}"
|
||||
fi
|
||||
}}
|
||||
|
||||
primary_node_modules="$(select_primary_node_modules)"
|
||||
|
||||
runtime_workspace="$(mktemp -d)"
|
||||
cleanup_runtime_workspace() {{
|
||||
rm -rf "${{runtime_workspace}}"
|
||||
}}
|
||||
trap cleanup_runtime_workspace EXIT
|
||||
|
||||
runtime_package_dir="${{runtime_workspace}}/${{package_rel_dir}}"
|
||||
mkdir -p "${{runtime_package_dir}}"
|
||||
cp -RL "${{package_dir}}/." "${{runtime_package_dir}}/"
|
||||
|
||||
install_repo_root=""
|
||||
if [[ -n "${{primary_node_modules}}" ]]; then
|
||||
install_repo_root="$(dirname "${{primary_node_modules}}")"
|
||||
ln -s "${{primary_node_modules}}" "${{runtime_workspace}}/node_modules"
|
||||
fi
|
||||
|
||||
find_node_modules() {{
|
||||
local dir="$1"
|
||||
local root="$2"
|
||||
|
||||
while [[ "$dir" == "$root"* ]]; do
|
||||
if [[ -d "$dir/node_modules" ]]; then
|
||||
echo "$dir/node_modules"
|
||||
return 0
|
||||
fi
|
||||
|
||||
if [[ "$dir" == "$root" ]]; then
|
||||
break
|
||||
fi
|
||||
|
||||
dir="$(dirname "$dir")"
|
||||
done
|
||||
|
||||
return 1
|
||||
}}
|
||||
|
||||
find_install_repo_node_modules() {{
|
||||
local repo_root="$1"
|
||||
local rel_dir="$2"
|
||||
local candidate="${{rel_dir}}"
|
||||
|
||||
while [[ -n "${{candidate}}" ]]; do
|
||||
if [[ -d "${{repo_root}}/${{candidate}}/node_modules" ]]; then
|
||||
echo "${{repo_root}}/${{candidate}}/node_modules"
|
||||
return 0
|
||||
fi
|
||||
|
||||
if [[ "${{candidate}}" != */* ]]; then
|
||||
break
|
||||
fi
|
||||
|
||||
candidate="${{candidate#*/}}"
|
||||
done
|
||||
|
||||
if [[ -d "${{repo_root}}/node_modules" ]]; then
|
||||
echo "${{repo_root}}/node_modules"
|
||||
return 0
|
||||
fi
|
||||
|
||||
return 1
|
||||
}}
|
||||
|
||||
resolved_install_node_modules=""
|
||||
if [[ -n "${{install_repo_root}}" ]]; then
|
||||
resolved_install_node_modules="$(find_install_repo_node_modules "${{install_repo_root}}" "${{package_rel_dir}}" || true)"
|
||||
fi
|
||||
|
||||
if [[ -n "${{resolved_install_node_modules}}" ]]; then
|
||||
rm -rf "${{runtime_package_dir}}/node_modules"
|
||||
ln -s "${{resolved_install_node_modules}}" "${{runtime_package_dir}}/node_modules"
|
||||
else
|
||||
resolved_node_modules="$(find_node_modules "${{runtime_package_dir}}" "${{runtime_workspace}}" || true)"
|
||||
if [[ -n "${{resolved_node_modules}}" && "${{resolved_node_modules}}" != "${{runtime_package_dir}}/node_modules" ]]; then
|
||||
rm -rf "${{runtime_package_dir}}/node_modules"
|
||||
ln -s "${{resolved_node_modules}}" "${{runtime_package_dir}}/node_modules"
|
||||
fi
|
||||
fi
|
||||
|
||||
path_entries=()
|
||||
if [[ -d "${{runtime_package_dir}}/node_modules/.bin" ]]; then
|
||||
path_entries+=("${{runtime_package_dir}}/node_modules/.bin")
|
||||
fi
|
||||
|
||||
if [[ -d "${{runtime_workspace}}/node_modules/.bin" && "${{runtime_workspace}}/node_modules/.bin" != "${{runtime_package_dir}}/node_modules/.bin" ]]; then
|
||||
path_entries+=("${{runtime_workspace}}/node_modules/.bin")
|
||||
fi
|
||||
|
||||
if [[ ${{#path_entries[@]}} -gt 0 ]]; then
|
||||
export PATH="$(IFS=:; echo "${{path_entries[*]}}"):${{PATH}}"
|
||||
fi
|
||||
|
||||
working_dir="{working_dir}"
|
||||
if [[ "${{working_dir}}" == "package" ]]; then
|
||||
cd "${{runtime_package_dir}}"
|
||||
else
|
||||
cd "${{runtime_workspace}}"
|
||||
fi
|
||||
|
||||
exec "${{bun_bin}}" --bun run {script} "$@"
|
||||
""".format(
|
||||
bun_short_path = bun_bin.short_path,
|
||||
package_json_short_path = package_json.short_path,
|
||||
package_rel_dir = package_json.dirname,
|
||||
working_dir = ctx.attr.working_dir,
|
||||
script = _shell_quote(ctx.attr.script),
|
||||
),
|
||||
workspace_info = create_bun_workspace_info(
|
||||
ctx,
|
||||
extra_files = ctx.files.data + ctx.files.preload + ctx.files.env_files + [bun_bin],
|
||||
package_dir_hint = package_json.dirname or ".",
|
||||
package_json = package_json,
|
||||
primary_file = package_json,
|
||||
)
|
||||
|
||||
transitive_files = []
|
||||
if ctx.attr.node_modules:
|
||||
transitive_files.append(ctx.attr.node_modules[DefaultInfo].files)
|
||||
argv = ["--bun", "run"]
|
||||
append_install_mode(argv, ctx.attr.install_mode)
|
||||
append_flag(argv, "--no-env-file", ctx.attr.no_env_file)
|
||||
append_flag(argv, "--smol", ctx.attr.smol)
|
||||
append_flag_values(argv, "--conditions", ctx.attr.conditions)
|
||||
append_flag(argv, "--workspaces", ctx.attr.workspaces)
|
||||
append_flag_values(argv, "--filter", ctx.attr.filters)
|
||||
if ctx.attr.execution_mode == "parallel":
|
||||
append_flag(argv, "--parallel", True)
|
||||
elif ctx.attr.execution_mode == "sequential":
|
||||
append_flag(argv, "--sequential", True)
|
||||
append_flag(argv, "--no-exit-on-error", ctx.attr.no_exit_on_error)
|
||||
append_flag_value(argv, "--shell", ctx.attr.shell)
|
||||
append_flag(argv, "--silent", ctx.attr.silent)
|
||||
append_raw_flags(argv, ctx.attr.run_flags)
|
||||
|
||||
runfiles = ctx.runfiles(
|
||||
files = [bun_bin, package_json] + ctx.files.data,
|
||||
transitive_files = depset(transitive = transitive_files),
|
||||
)
|
||||
spec_file = write_launcher_spec(ctx, {
|
||||
"version": 1,
|
||||
"kind": "bun_run",
|
||||
"bun_short_path": runfiles_path(bun_bin),
|
||||
"primary_source_short_path": "",
|
||||
"package_json_short_path": runfiles_path(package_json),
|
||||
"install_metadata_short_path": runfiles_path(workspace_info.install_metadata_file) if workspace_info.install_metadata_file else "",
|
||||
"install_repo_runfiles_path": workspace_info.install_repo_runfiles_path,
|
||||
"node_modules_roots": workspace_info.node_modules_roots,
|
||||
"package_dir_hint": package_json.dirname or ".",
|
||||
"working_dir_mode": ctx.attr.working_dir,
|
||||
"inherit_host_path": ctx.attr.inherit_host_path,
|
||||
"argv": argv,
|
||||
"args": [ctx.attr.script] + ctx.attr.args,
|
||||
"passthrough_args": True,
|
||||
"tool_short_path": "",
|
||||
"restart_on": [],
|
||||
"watch_mode": "",
|
||||
"reporter": "",
|
||||
"coverage": False,
|
||||
"coverage_reporters": [],
|
||||
"preload_short_paths": [runfiles_path(file) for file in ctx.files.preload],
|
||||
"env_file_short_paths": [runfiles_path(file) for file in ctx.files.env_files],
|
||||
"test_short_paths": [],
|
||||
})
|
||||
launcher = declare_runtime_wrapper(ctx, bun_bin, spec_file)
|
||||
|
||||
return [
|
||||
workspace_info,
|
||||
DefaultInfo(
|
||||
executable = launcher,
|
||||
runfiles = runfiles,
|
||||
executable = launcher.executable,
|
||||
runfiles = workspace_runfiles(
|
||||
ctx,
|
||||
workspace_info,
|
||||
direct_files = [launcher.executable, launcher.runner, spec_file],
|
||||
),
|
||||
),
|
||||
]
|
||||
|
||||
_BUN_SCRIPT_ATTRS = runtime_launcher_attrs()
|
||||
_BUN_SCRIPT_ATTRS.update({
|
||||
"script": attr.string(
|
||||
mandatory = True,
|
||||
doc = "Name of the `package.json` script to execute via `bun run <script>`.",
|
||||
),
|
||||
"package_json": attr.label(
|
||||
mandatory = True,
|
||||
allow_single_file = True,
|
||||
doc = "Label of the `package.json` file containing the named script.",
|
||||
),
|
||||
"node_modules": attr.label(
|
||||
doc = "Optional label providing package files from a `node_modules` tree, typically produced by `bun_install`, in runfiles. Executables from `node_modules/.bin` are added to `PATH`, which is useful for scripts such as `vite`.",
|
||||
),
|
||||
"data": attr.label_list(
|
||||
allow_files = True,
|
||||
doc = "Additional runtime files required by the script.",
|
||||
),
|
||||
"preload": attr.label_list(
|
||||
allow_files = True,
|
||||
doc = "Modules to preload with `--preload` before running the script.",
|
||||
),
|
||||
"env_files": attr.label_list(
|
||||
allow_files = True,
|
||||
doc = "Additional environment files loaded with `--env-file`.",
|
||||
),
|
||||
"no_env_file": attr.bool(
|
||||
default = False,
|
||||
doc = "If true, disables Bun's automatic `.env` loading.",
|
||||
),
|
||||
"smol": attr.bool(
|
||||
default = False,
|
||||
doc = "If true, enables Bun's lower-memory runtime mode.",
|
||||
),
|
||||
"conditions": attr.string_list(
|
||||
doc = "Custom package resolve conditions passed to Bun.",
|
||||
),
|
||||
"install_mode": attr.string(
|
||||
default = "disable",
|
||||
values = ["disable", "auto", "fallback", "force"],
|
||||
doc = "Whether Bun may auto-install missing packages while running the script.",
|
||||
),
|
||||
"filters": attr.string_list(
|
||||
doc = "Workspace package filters passed via repeated `--filter` flags.",
|
||||
),
|
||||
"workspaces": attr.bool(
|
||||
default = False,
|
||||
doc = "If true, runs the script in all workspace packages.",
|
||||
),
|
||||
"execution_mode": attr.string(
|
||||
default = "single",
|
||||
values = ["single", "parallel", "sequential"],
|
||||
doc = "How Bun should execute matching workspace scripts.",
|
||||
),
|
||||
"no_exit_on_error": attr.bool(
|
||||
default = False,
|
||||
doc = "If true, Bun keeps running other workspace scripts when one fails.",
|
||||
),
|
||||
"shell": attr.string(
|
||||
default = "",
|
||||
values = ["", "bun", "system"],
|
||||
doc = "Optional shell implementation for package scripts.",
|
||||
),
|
||||
"silent": attr.bool(
|
||||
default = False,
|
||||
doc = "If true, suppresses Bun's command echo for package scripts.",
|
||||
),
|
||||
"run_flags": attr.string_list(
|
||||
doc = "Additional raw flags forwarded to `bun run` before the script name.",
|
||||
),
|
||||
"working_dir": attr.string(
|
||||
default = "package",
|
||||
values = ["workspace", "package"],
|
||||
doc = "Working directory at runtime: Bazel runfiles `workspace` root or the directory containing `package.json`. The default `package` mode matches tools such as Vite that resolve config and assets relative to the package directory.",
|
||||
),
|
||||
"inherit_host_path": attr.bool(
|
||||
default = False,
|
||||
doc = "If true, appends the host PATH after staged node_modules/.bin entries at runtime.",
|
||||
),
|
||||
})
|
||||
|
||||
bun_script = rule(
|
||||
implementation = _bun_script_impl,
|
||||
@@ -188,32 +159,10 @@ bun_script = rule(
|
||||
Use this rule to expose existing package scripts such as `dev`, `build`, or
|
||||
`check` via `bazel run` without adding wrapper shell scripts. This is a good fit
|
||||
for Vite-style workflows, where scripts like `vite dev` or `vite build` are
|
||||
declared in `package.json` and expect to run from the package directory with
|
||||
`node_modules/.bin` available on `PATH`.
|
||||
declared in `package.json` and expect to run from the package directory. This
|
||||
is a local workflow helper rather than a hermetic build rule.
|
||||
""",
|
||||
attrs = {
|
||||
"script": attr.string(
|
||||
mandatory = True,
|
||||
doc = "Name of the `package.json` script to execute via `bun run <script>`.",
|
||||
),
|
||||
"package_json": attr.label(
|
||||
mandatory = True,
|
||||
allow_single_file = True,
|
||||
doc = "Label of the `package.json` file containing the named script.",
|
||||
),
|
||||
"node_modules": attr.label(
|
||||
doc = "Optional label providing package files from a `node_modules` tree, typically produced by `bun_install`, in runfiles. Executables from `node_modules/.bin` are added to `PATH`, which is useful for scripts such as `vite`.",
|
||||
),
|
||||
"data": attr.label_list(
|
||||
allow_files = True,
|
||||
doc = "Additional runtime files required by the script.",
|
||||
),
|
||||
"working_dir": attr.string(
|
||||
default = "package",
|
||||
values = ["workspace", "package"],
|
||||
doc = "Working directory at runtime: Bazel runfiles `workspace` root or the directory containing `package.json`. The default `package` mode matches tools such as Vite that resolve config and assets relative to the package directory.",
|
||||
),
|
||||
},
|
||||
attrs = _BUN_SCRIPT_ATTRS,
|
||||
executable = True,
|
||||
toolchains = ["//bun:toolchain_type"],
|
||||
)
|
||||
)
|
||||
|
||||
@@ -1,89 +1,198 @@
|
||||
"""Rule for running test suites with Bun."""
|
||||
|
||||
load("//internal:js_library.bzl", "BunSourcesInfo")
|
||||
|
||||
|
||||
def _shell_quote(value):
|
||||
return "'" + value.replace("'", "'\"'\"'") + "'"
|
||||
|
||||
load("//internal:bun_command.bzl", "append_flag", "append_flag_value", "append_install_mode", "append_raw_flags")
|
||||
load("//internal:js_library.bzl", "collect_js_runfiles")
|
||||
load("//internal:runtime_launcher.bzl", "declare_runtime_wrapper", "runfiles_path", "runtime_launcher_attrs", "write_launcher_spec")
|
||||
load("//internal:workspace.bzl", "create_bun_workspace_info", "workspace_runfiles")
|
||||
|
||||
def _bun_test_impl(ctx):
|
||||
if ctx.attr.install_mode != "disable":
|
||||
fail("bun_test requires install_mode = \"disable\" for hermetic test execution")
|
||||
|
||||
toolchain = ctx.toolchains["//bun:toolchain_type"]
|
||||
bun_bin = toolchain.bun.bun_bin
|
||||
|
||||
src_args = " ".join([_shell_quote(src.short_path) for src in ctx.files.srcs])
|
||||
launcher = ctx.actions.declare_file(ctx.label.name)
|
||||
ctx.actions.write(
|
||||
output = launcher,
|
||||
is_executable = True,
|
||||
content = """#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
runfiles_dir="${{RUNFILES_DIR:-$0.runfiles}}"
|
||||
bun_bin="${{runfiles_dir}}/_main/{bun_short_path}"
|
||||
cd "${{runfiles_dir}}/_main"
|
||||
|
||||
if [[ -n "${{TESTBRIDGE_TEST_ONLY:-}}" && -n "${{COVERAGE_DIR:-}}" ]]; then
|
||||
exec "${{bun_bin}}" --bun test {src_args} --test-name-pattern "${{TESTBRIDGE_TEST_ONLY}}" --coverage "$@"
|
||||
fi
|
||||
if [[ -n "${{TESTBRIDGE_TEST_ONLY:-}}" ]]; then
|
||||
exec "${{bun_bin}}" --bun test {src_args} --test-name-pattern "${{TESTBRIDGE_TEST_ONLY}}" "$@"
|
||||
fi
|
||||
if [[ -n "${{COVERAGE_DIR:-}}" ]]; then
|
||||
exec "${{bun_bin}}" --bun test {src_args} --coverage "$@"
|
||||
fi
|
||||
exec "${{bun_bin}}" --bun test {src_args} "$@"
|
||||
""".format(
|
||||
bun_short_path = bun_bin.short_path,
|
||||
src_args = src_args,
|
||||
),
|
||||
primary_file = ctx.files.srcs[0]
|
||||
dep_runfiles = [collect_js_runfiles(dep) for dep in ctx.attr.deps]
|
||||
workspace_info = create_bun_workspace_info(
|
||||
ctx,
|
||||
extra_files = ctx.files.srcs + ctx.files.data + ctx.files.preload + ctx.files.env_files + [bun_bin],
|
||||
primary_file = primary_file,
|
||||
)
|
||||
|
||||
transitive_files = []
|
||||
if ctx.attr.node_modules:
|
||||
transitive_files.append(ctx.attr.node_modules[DefaultInfo].files)
|
||||
for dep in ctx.attr.deps:
|
||||
if BunSourcesInfo in dep:
|
||||
transitive_files.append(dep[BunSourcesInfo].transitive_sources)
|
||||
else:
|
||||
transitive_files.append(dep[DefaultInfo].files)
|
||||
argv = ["--bun", "test"]
|
||||
append_install_mode(argv, ctx.attr.install_mode)
|
||||
append_flag(argv, "--no-env-file", ctx.attr.no_env_file)
|
||||
append_flag(argv, "--smol", ctx.attr.smol)
|
||||
append_flag_value(argv, "--timeout", str(ctx.attr.timeout_ms) if ctx.attr.timeout_ms > 0 else None)
|
||||
append_flag(argv, "--update-snapshots", ctx.attr.update_snapshots)
|
||||
append_flag_value(argv, "--rerun-each", str(ctx.attr.rerun_each) if ctx.attr.rerun_each > 0 else None)
|
||||
append_flag_value(argv, "--retry", str(ctx.attr.retry) if ctx.attr.retry > 0 else None)
|
||||
append_flag(argv, "--todo", ctx.attr.todo)
|
||||
append_flag(argv, "--only", ctx.attr.only)
|
||||
append_flag(argv, "--pass-with-no-tests", ctx.attr.pass_with_no_tests)
|
||||
append_flag(argv, "--concurrent", ctx.attr.concurrent)
|
||||
append_flag(argv, "--randomize", ctx.attr.randomize)
|
||||
append_flag_value(argv, "--seed", str(ctx.attr.seed) if ctx.attr.seed > 0 else None)
|
||||
append_flag_value(argv, "--bail", str(ctx.attr.bail) if ctx.attr.bail > 0 else None)
|
||||
append_flag_value(argv, "--max-concurrency", str(ctx.attr.max_concurrency) if ctx.attr.max_concurrency > 0 else None)
|
||||
append_raw_flags(argv, ctx.attr.test_flags)
|
||||
|
||||
runfiles = ctx.runfiles(
|
||||
files = [bun_bin] + ctx.files.srcs + ctx.files.data,
|
||||
transitive_files = depset(transitive = transitive_files),
|
||||
)
|
||||
spec_file = write_launcher_spec(ctx, {
|
||||
"version": 1,
|
||||
"kind": "bun_test",
|
||||
"bun_short_path": runfiles_path(bun_bin),
|
||||
"primary_source_short_path": runfiles_path(primary_file),
|
||||
"package_json_short_path": "",
|
||||
"install_metadata_short_path": runfiles_path(workspace_info.install_metadata_file) if workspace_info.install_metadata_file else "",
|
||||
"install_repo_runfiles_path": workspace_info.install_repo_runfiles_path,
|
||||
"node_modules_roots": workspace_info.node_modules_roots,
|
||||
"package_dir_hint": workspace_info.package_dir_hint,
|
||||
"working_dir_mode": "workspace",
|
||||
"inherit_host_path": ctx.attr.inherit_host_path,
|
||||
"argv": argv,
|
||||
"args": ctx.attr.args,
|
||||
"passthrough_args": True,
|
||||
"tool_short_path": "",
|
||||
"restart_on": [],
|
||||
"watch_mode": "",
|
||||
"reporter": ctx.attr.reporter,
|
||||
"coverage": ctx.attr.coverage,
|
||||
"coverage_reporters": ctx.attr.coverage_reporters,
|
||||
"preload_short_paths": [runfiles_path(file) for file in ctx.files.preload],
|
||||
"env_file_short_paths": [runfiles_path(file) for file in ctx.files.env_files],
|
||||
"test_short_paths": [runfiles_path(file) for file in ctx.files.srcs],
|
||||
})
|
||||
launcher = declare_runtime_wrapper(ctx, bun_bin, spec_file)
|
||||
|
||||
return [
|
||||
workspace_info,
|
||||
DefaultInfo(
|
||||
executable = launcher,
|
||||
runfiles = runfiles,
|
||||
executable = launcher.executable,
|
||||
runfiles = workspace_runfiles(
|
||||
ctx,
|
||||
workspace_info,
|
||||
direct_files = [launcher.executable, launcher.runner, spec_file],
|
||||
transitive_files = dep_runfiles,
|
||||
),
|
||||
),
|
||||
]
|
||||
|
||||
_BUN_TEST_ATTRS = runtime_launcher_attrs()
|
||||
_BUN_TEST_ATTRS.update({
|
||||
"srcs": attr.label_list(
|
||||
mandatory = True,
|
||||
allow_files = [".js", ".ts", ".jsx", ".tsx", ".mjs", ".cjs"],
|
||||
doc = "Test source files passed to `bun test`.",
|
||||
),
|
||||
"node_modules": attr.label(
|
||||
doc = "Optional label providing package files from a `node_modules` tree, typically produced by `bun_install`, in runfiles.",
|
||||
),
|
||||
"deps": attr.label_list(
|
||||
doc = "Library dependencies required by test sources.",
|
||||
),
|
||||
"data": attr.label_list(
|
||||
allow_files = True,
|
||||
doc = "Additional runtime files needed by tests.",
|
||||
),
|
||||
"preload": attr.label_list(
|
||||
allow_files = True,
|
||||
doc = "Modules to preload with `--preload` before running tests.",
|
||||
),
|
||||
"env_files": attr.label_list(
|
||||
allow_files = True,
|
||||
doc = "Additional environment files loaded with `--env-file`.",
|
||||
),
|
||||
"no_env_file": attr.bool(
|
||||
default = False,
|
||||
doc = "If true, disables Bun's automatic `.env` loading.",
|
||||
),
|
||||
"smol": attr.bool(
|
||||
default = False,
|
||||
doc = "If true, enables Bun's lower-memory runtime mode.",
|
||||
),
|
||||
"install_mode": attr.string(
|
||||
default = "disable",
|
||||
values = ["disable", "auto", "fallback", "force"],
|
||||
doc = "Whether Bun may auto-install missing packages while testing.",
|
||||
),
|
||||
"timeout_ms": attr.int(
|
||||
default = 0,
|
||||
doc = "Optional per-test timeout in milliseconds.",
|
||||
),
|
||||
"update_snapshots": attr.bool(
|
||||
default = False,
|
||||
doc = "If true, updates Bun snapshot files.",
|
||||
),
|
||||
"rerun_each": attr.int(
|
||||
default = 0,
|
||||
doc = "Optional number of times to rerun each test file.",
|
||||
),
|
||||
"retry": attr.int(
|
||||
default = 0,
|
||||
doc = "Optional default retry count for all tests.",
|
||||
),
|
||||
"todo": attr.bool(
|
||||
default = False,
|
||||
doc = "If true, includes tests marked with `test.todo()`.",
|
||||
),
|
||||
"only": attr.bool(
|
||||
default = False,
|
||||
doc = "If true, runs only tests marked with `test.only()` or `describe.only()`.",
|
||||
),
|
||||
"pass_with_no_tests": attr.bool(
|
||||
default = False,
|
||||
doc = "If true, exits successfully when no tests are found.",
|
||||
),
|
||||
"concurrent": attr.bool(
|
||||
default = False,
|
||||
doc = "If true, treats all tests as concurrent tests.",
|
||||
),
|
||||
"randomize": attr.bool(
|
||||
default = False,
|
||||
doc = "If true, runs tests in random order.",
|
||||
),
|
||||
"seed": attr.int(
|
||||
default = 0,
|
||||
doc = "Optional randomization seed.",
|
||||
),
|
||||
"bail": attr.int(
|
||||
default = 0,
|
||||
doc = "Optional failure count after which Bun exits the test run.",
|
||||
),
|
||||
"reporter": attr.string(
|
||||
default = "console",
|
||||
values = ["console", "dots", "junit"],
|
||||
doc = "Test reporter format.",
|
||||
),
|
||||
"max_concurrency": attr.int(
|
||||
default = 0,
|
||||
doc = "Optional maximum number of concurrent tests.",
|
||||
),
|
||||
"coverage": attr.bool(
|
||||
default = False,
|
||||
doc = "If true, always enables Bun coverage output.",
|
||||
),
|
||||
"coverage_reporters": attr.string_list(
|
||||
doc = "Repeated Bun coverage reporters such as `text` or `lcov`.",
|
||||
),
|
||||
"test_flags": attr.string_list(
|
||||
doc = "Additional raw flags forwarded to `bun test` before the test source list.",
|
||||
),
|
||||
"inherit_host_path": attr.bool(
|
||||
default = False,
|
||||
doc = "If true, appends the host PATH after staged node_modules/.bin entries at runtime.",
|
||||
),
|
||||
})
|
||||
|
||||
bun_test = rule(
|
||||
implementation = _bun_test_impl,
|
||||
doc = """Runs Bun tests as a Bazel test target.
|
||||
|
||||
Supports Bazel test filtering (`--test_filter`) and coverage integration.
|
||||
Supports Bazel test filtering (`--test_filter`) and coverage integration. Tests
|
||||
run with strict install-mode semantics and do not inherit the host PATH unless
|
||||
explicitly requested.
|
||||
""",
|
||||
attrs = {
|
||||
"srcs": attr.label_list(
|
||||
mandatory = True,
|
||||
allow_files = [".js", ".ts", ".jsx", ".tsx", ".mjs", ".cjs"],
|
||||
doc = "Test source files passed to `bun test`.",
|
||||
),
|
||||
"node_modules": attr.label(
|
||||
doc = "Optional label providing package files from a `node_modules` tree, typically produced by `bun_install`, in runfiles.",
|
||||
),
|
||||
"deps": attr.label_list(
|
||||
doc = "Library dependencies required by test sources.",
|
||||
),
|
||||
"data": attr.label_list(
|
||||
allow_files = True,
|
||||
doc = "Additional runtime files needed by tests.",
|
||||
),
|
||||
},
|
||||
attrs = _BUN_TEST_ATTRS,
|
||||
test = True,
|
||||
toolchains = ["//bun:toolchain_type"],
|
||||
)
|
||||
|
||||
29
internal/js_compat.bzl
Normal file
29
internal/js_compat.bzl
Normal file
@@ -0,0 +1,29 @@
|
||||
"""rules_js-style compatibility exports backed by Bun."""
|
||||
|
||||
load("//internal:bun_binary.bzl", _bun_binary = "bun_binary")
|
||||
load("//internal:bun_test.bzl", _bun_test = "bun_test")
|
||||
load("//internal:js_library.bzl", _JsInfo = "JsInfo", _js_library = "js_library", _ts_library = "ts_library")
|
||||
load("//internal:js_run_devserver.bzl", _js_run_devserver = "js_run_devserver")
|
||||
|
||||
JsInfo = _JsInfo
|
||||
js_library = _js_library
|
||||
ts_library = _ts_library
|
||||
js_run_devserver = _js_run_devserver
|
||||
|
||||
def js_binary(name, **kwargs):
|
||||
_bun_binary(name = name, **kwargs)
|
||||
|
||||
def js_test(name, entry_point = None, srcs = None, **kwargs):
|
||||
if entry_point != None:
|
||||
if srcs != None:
|
||||
fail("js_test accepts either `entry_point` or `srcs`, but not both")
|
||||
srcs = [entry_point]
|
||||
|
||||
if srcs == None:
|
||||
fail("js_test requires `entry_point` or `srcs`")
|
||||
|
||||
_bun_test(
|
||||
name = name,
|
||||
srcs = srcs,
|
||||
**kwargs
|
||||
)
|
||||
@@ -1,23 +1,74 @@
|
||||
"""Lightweight JS/TS source grouping rules."""
|
||||
|
||||
JsInfo = provider(
|
||||
doc = "Provides transitive JavaScript/TypeScript metadata for Bun and JS compatibility rules.",
|
||||
fields = {
|
||||
"sources": "Direct source files owned by this target.",
|
||||
"transitive_sources": "Transitive source files from this target and its deps.",
|
||||
"types": "Direct type files owned by this target.",
|
||||
"transitive_types": "Transitive type files from this target and its deps.",
|
||||
"data_files": "Direct runtime data files owned by this target.",
|
||||
"transitive_runfiles": "Transitive runtime files from this target and its deps.",
|
||||
},
|
||||
)
|
||||
|
||||
BunSourcesInfo = provider(
|
||||
"Provides transitive sources for Bun libraries.",
|
||||
fields = ["transitive_sources"],
|
||||
)
|
||||
|
||||
def collect_js_sources(dep):
|
||||
if JsInfo in dep:
|
||||
return dep[JsInfo].transitive_sources
|
||||
if BunSourcesInfo in dep:
|
||||
return dep[BunSourcesInfo].transitive_sources
|
||||
return dep[DefaultInfo].files
|
||||
|
||||
def collect_js_runfiles(dep):
|
||||
if JsInfo in dep:
|
||||
return dep[JsInfo].transitive_runfiles
|
||||
if BunSourcesInfo in dep:
|
||||
return dep[BunSourcesInfo].transitive_sources
|
||||
return dep[DefaultInfo].files
|
||||
|
||||
def _bun_library_impl(ctx):
|
||||
transitive_sources = [
|
||||
dep[BunSourcesInfo].transitive_sources
|
||||
transitive_sources = [collect_js_sources(dep) for dep in ctx.attr.deps]
|
||||
transitive_types = [
|
||||
dep[JsInfo].transitive_types
|
||||
for dep in ctx.attr.deps
|
||||
if BunSourcesInfo in dep
|
||||
if JsInfo in dep
|
||||
]
|
||||
transitive_runfiles = [collect_js_runfiles(dep) for dep in ctx.attr.deps]
|
||||
|
||||
all_sources = depset(
|
||||
direct = ctx.files.srcs,
|
||||
transitive = transitive_sources,
|
||||
)
|
||||
all_types = depset(
|
||||
direct = ctx.files.types,
|
||||
transitive = transitive_types,
|
||||
)
|
||||
all_runfiles = depset(
|
||||
direct = ctx.files.srcs + ctx.files.types + ctx.files.data,
|
||||
transitive = transitive_runfiles,
|
||||
)
|
||||
default_files = depset(
|
||||
direct = ctx.files.srcs + ctx.files.types + ctx.files.data,
|
||||
transitive = transitive_sources + transitive_types + transitive_runfiles,
|
||||
)
|
||||
|
||||
js_info = JsInfo(
|
||||
sources = depset(ctx.files.srcs),
|
||||
transitive_sources = all_sources,
|
||||
types = depset(ctx.files.types),
|
||||
transitive_types = all_types,
|
||||
data_files = depset(ctx.files.data),
|
||||
transitive_runfiles = all_runfiles,
|
||||
)
|
||||
return [
|
||||
js_info,
|
||||
BunSourcesInfo(transitive_sources = all_sources),
|
||||
DefaultInfo(files = all_sources),
|
||||
DefaultInfo(files = default_files),
|
||||
]
|
||||
|
||||
js_library = rule(
|
||||
@@ -28,6 +79,14 @@ js_library = rule(
|
||||
allow_files = [".js", ".jsx", ".mjs", ".cjs"],
|
||||
doc = "JavaScript source files in this library.",
|
||||
),
|
||||
"types": attr.label_list(
|
||||
allow_files = [".d.ts"],
|
||||
doc = "Optional declaration files associated with this library.",
|
||||
),
|
||||
"data": attr.label_list(
|
||||
allow_files = True,
|
||||
doc = "Optional runtime files propagated to dependents.",
|
||||
),
|
||||
"deps": attr.label_list(
|
||||
doc = "Other Bun source libraries to include transitively.",
|
||||
),
|
||||
@@ -42,6 +101,14 @@ ts_library = rule(
|
||||
allow_files = [".ts", ".tsx"],
|
||||
doc = "TypeScript source files in this library.",
|
||||
),
|
||||
"types": attr.label_list(
|
||||
allow_files = [".d.ts"],
|
||||
doc = "Optional declaration files associated with this library.",
|
||||
),
|
||||
"data": attr.label_list(
|
||||
allow_files = True,
|
||||
doc = "Optional runtime files propagated to dependents.",
|
||||
),
|
||||
"deps": attr.label_list(
|
||||
doc = "Other Bun source libraries to include transitively.",
|
||||
),
|
||||
|
||||
111
internal/js_run_devserver.bzl
Normal file
111
internal/js_run_devserver.bzl
Normal file
@@ -0,0 +1,111 @@
|
||||
"""Compatibility rule for running an executable target as a dev server."""
|
||||
|
||||
load("//internal:js_library.bzl", "collect_js_runfiles")
|
||||
load("//internal:runtime_launcher.bzl", "declare_runtime_wrapper", "runfiles_path", "runtime_launcher_attrs", "write_launcher_spec")
|
||||
load("//internal:workspace.bzl", "create_bun_workspace_info", "workspace_runfiles")
|
||||
|
||||
def _js_run_devserver_impl(ctx):
|
||||
toolchain = ctx.toolchains["//bun:toolchain_type"]
|
||||
bun_bin = toolchain.bun.bun_bin
|
||||
package_json = ctx.file.package_json
|
||||
dep_runfiles = [collect_js_runfiles(dep) for dep in ctx.attr.deps]
|
||||
tool_default_info = ctx.attr.tool[DefaultInfo]
|
||||
|
||||
workspace_info = create_bun_workspace_info(
|
||||
ctx,
|
||||
primary_file = package_json or tool_default_info.files_to_run.executable,
|
||||
package_json = package_json,
|
||||
package_dir_hint = ctx.attr.package_dir_hint,
|
||||
extra_files = ctx.files.data + [bun_bin, tool_default_info.files_to_run.executable],
|
||||
)
|
||||
|
||||
spec_file = write_launcher_spec(ctx, {
|
||||
"version": 1,
|
||||
"kind": "tool_exec",
|
||||
"bun_short_path": runfiles_path(bun_bin),
|
||||
"primary_source_short_path": runfiles_path(package_json) if package_json else runfiles_path(tool_default_info.files_to_run.executable),
|
||||
"package_json_short_path": runfiles_path(package_json) if package_json else "",
|
||||
"install_metadata_short_path": runfiles_path(workspace_info.install_metadata_file) if workspace_info.install_metadata_file else "",
|
||||
"install_repo_runfiles_path": workspace_info.install_repo_runfiles_path,
|
||||
"node_modules_roots": workspace_info.node_modules_roots,
|
||||
"package_dir_hint": ctx.attr.package_dir_hint,
|
||||
"working_dir_mode": ctx.attr.working_dir,
|
||||
"inherit_host_path": ctx.attr.inherit_host_path,
|
||||
"argv": [],
|
||||
"args": ctx.attr.args,
|
||||
"passthrough_args": True,
|
||||
"tool_short_path": runfiles_path(tool_default_info.files_to_run.executable),
|
||||
"restart_on": [],
|
||||
"watch_mode": "",
|
||||
"reporter": "",
|
||||
"coverage": False,
|
||||
"coverage_reporters": [],
|
||||
"preload_short_paths": [],
|
||||
"env_file_short_paths": [],
|
||||
"test_short_paths": [],
|
||||
})
|
||||
launcher = declare_runtime_wrapper(ctx, bun_bin, spec_file)
|
||||
|
||||
return [
|
||||
workspace_info,
|
||||
DefaultInfo(
|
||||
executable = launcher.executable,
|
||||
runfiles = workspace_runfiles(
|
||||
ctx,
|
||||
workspace_info,
|
||||
direct_files = [launcher.executable, launcher.runner, spec_file, tool_default_info.files_to_run.executable],
|
||||
transitive_files = dep_runfiles,
|
||||
).merge(tool_default_info.default_runfiles),
|
||||
),
|
||||
]
|
||||
|
||||
_JS_RUN_DEVSERVER_ATTRS = runtime_launcher_attrs()
|
||||
_JS_RUN_DEVSERVER_ATTRS.update({
|
||||
"tool": attr.label(
|
||||
mandatory = True,
|
||||
executable = True,
|
||||
cfg = "target",
|
||||
doc = "Executable target to launch as the dev server.",
|
||||
),
|
||||
"package_json": attr.label(
|
||||
allow_single_file = True,
|
||||
doc = "Optional package.json used to resolve the package working directory.",
|
||||
),
|
||||
"package_dir_hint": attr.string(
|
||||
default = ".",
|
||||
doc = "Optional package-relative directory hint when package_json is not supplied.",
|
||||
),
|
||||
"node_modules": attr.label(
|
||||
doc = "Optional label providing package files from a node_modules tree, typically produced by bun_install or npm_translate_lock, in runfiles.",
|
||||
),
|
||||
"deps": attr.label_list(
|
||||
doc = "Library dependencies required by the dev server.",
|
||||
),
|
||||
"data": attr.label_list(
|
||||
allow_files = True,
|
||||
doc = "Additional runtime files required by the dev server.",
|
||||
),
|
||||
"working_dir": attr.string(
|
||||
default = "workspace",
|
||||
values = ["workspace", "package"],
|
||||
doc = "Working directory at runtime: Bazel runfiles workspace root or the resolved package directory.",
|
||||
),
|
||||
"inherit_host_path": attr.bool(
|
||||
default = False,
|
||||
doc = "If true, appends the host PATH after staged node_modules/.bin entries at runtime.",
|
||||
),
|
||||
})
|
||||
|
||||
js_run_devserver = rule(
|
||||
implementation = _js_run_devserver_impl,
|
||||
doc = """Runs an executable target from a staged JS workspace.
|
||||
|
||||
This is a Bun-backed compatibility adapter for `rules_js`-style devserver
|
||||
targets. It stages the same runtime workspace as the Bun rules, then executes
|
||||
the provided tool with any default arguments. It is intended for local
|
||||
development workflows rather than hermetic build execution.
|
||||
""",
|
||||
attrs = _JS_RUN_DEVSERVER_ATTRS,
|
||||
executable = True,
|
||||
toolchains = ["//bun:toolchain_type"],
|
||||
)
|
||||
173
internal/runtime_launcher.bzl
Normal file
173
internal/runtime_launcher.bzl
Normal file
@@ -0,0 +1,173 @@
|
||||
"""Shared launcher spec and OS-native wrapper helpers for runtime rules."""
|
||||
|
||||
_RUNTIME_LAUNCHER = Label("//internal:runtime_launcher.js")
|
||||
_WINDOWS_CONSTRAINT = Label("@platforms//os:windows")
|
||||
|
||||
_POSIX_WRAPPER_TEMPLATE = """#!/bin/sh
|
||||
set -eu
|
||||
|
||||
self="$0"
|
||||
runfiles_dir="${RUNFILES_DIR:-}"
|
||||
manifest="${RUNFILES_MANIFEST_FILE:-}"
|
||||
|
||||
if [ -n "${runfiles_dir}" ] && [ -d "${runfiles_dir}" ]; then
|
||||
:
|
||||
elif [ -n "${manifest}" ] && [ -f "${manifest}" ]; then
|
||||
:
|
||||
elif [ -d "${self}.runfiles" ]; then
|
||||
runfiles_dir="${self}.runfiles"
|
||||
elif [ -f "${self}.runfiles_manifest" ]; then
|
||||
manifest="${self}.runfiles_manifest"
|
||||
elif [ -f "${self}.exe.runfiles_manifest" ]; then
|
||||
manifest="${self}.exe.runfiles_manifest"
|
||||
else
|
||||
echo "rules_bun: unable to locate runfiles for ${self}" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
rlocation() {
|
||||
path="$1"
|
||||
if [ -n "${runfiles_dir}" ]; then
|
||||
printf '%s\\n' "${runfiles_dir}/${path}"
|
||||
return 0
|
||||
fi
|
||||
|
||||
result=""
|
||||
while IFS= read -r line; do
|
||||
case "${line}" in
|
||||
"${path} "*)
|
||||
result="${line#${path} }"
|
||||
break
|
||||
;;
|
||||
esac
|
||||
done < "${manifest}"
|
||||
if [ -z "${result}" ]; then
|
||||
echo "rules_bun: missing runfile ${path}" >&2
|
||||
exit 1
|
||||
fi
|
||||
printf '%s\\n' "${result}"
|
||||
}
|
||||
|
||||
bun_bin="$(rlocation "__BUN_RUNFILES_PATH__")"
|
||||
runner="$(rlocation "__RUNNER_RUNFILES_PATH__")"
|
||||
spec="$(rlocation "__SPEC_RUNFILES_PATH__")"
|
||||
|
||||
export RULES_BUN_LAUNCHER_PATH="${self}"
|
||||
if [ -n "${runfiles_dir}" ]; then
|
||||
export RULES_BUN_RUNFILES_DIR="${runfiles_dir}"
|
||||
fi
|
||||
if [ -n "${manifest}" ]; then
|
||||
export RULES_BUN_RUNFILES_MANIFEST="${manifest}"
|
||||
fi
|
||||
|
||||
exec "${bun_bin}" --bun "${runner}" "${spec}" "$@"
|
||||
"""
|
||||
|
||||
_CMD_WRAPPER_TEMPLATE = """@echo off
|
||||
setlocal
|
||||
|
||||
set "SELF=%~f0"
|
||||
set "RUNFILES_DIR_VALUE=%RUNFILES_DIR%"
|
||||
set "RUNFILES_MANIFEST_VALUE=%RUNFILES_MANIFEST_FILE%"
|
||||
|
||||
if defined RUNFILES_DIR_VALUE if exist "%RUNFILES_DIR_VALUE%" goto have_runfiles
|
||||
if defined RUNFILES_MANIFEST_VALUE if exist "%RUNFILES_MANIFEST_VALUE%" goto have_runfiles
|
||||
if exist "%SELF%.runfiles" (
|
||||
set "RUNFILES_DIR_VALUE=%SELF%.runfiles"
|
||||
goto have_runfiles
|
||||
)
|
||||
if exist "%SELF%.runfiles_manifest" (
|
||||
set "RUNFILES_MANIFEST_VALUE=%SELF%.runfiles_manifest"
|
||||
goto have_runfiles
|
||||
)
|
||||
if exist "%~dpn0.runfiles_manifest" (
|
||||
set "RUNFILES_MANIFEST_VALUE=%~dpn0.runfiles_manifest"
|
||||
goto have_runfiles
|
||||
)
|
||||
|
||||
echo rules_bun: unable to locate runfiles for "%SELF%" 1>&2
|
||||
exit /b 1
|
||||
|
||||
:have_runfiles
|
||||
call :rlocation "__BUN_RUNFILES_PATH__" BUN_BIN || exit /b 1
|
||||
call :rlocation "__RUNNER_RUNFILES_PATH__" RUNNER || exit /b 1
|
||||
call :rlocation "__SPEC_RUNFILES_PATH__" SPEC || exit /b 1
|
||||
|
||||
set "RULES_BUN_LAUNCHER_PATH=%SELF%"
|
||||
if defined RUNFILES_DIR_VALUE (
|
||||
set "RULES_BUN_RUNFILES_DIR=%RUNFILES_DIR_VALUE%"
|
||||
) else (
|
||||
set "RULES_BUN_RUNFILES_DIR="
|
||||
)
|
||||
if defined RUNFILES_MANIFEST_VALUE (
|
||||
set "RULES_BUN_RUNFILES_MANIFEST=%RUNFILES_MANIFEST_VALUE%"
|
||||
) else (
|
||||
set "RULES_BUN_RUNFILES_MANIFEST="
|
||||
)
|
||||
|
||||
"%BUN_BIN%" --bun "%RUNNER%" "%SPEC%" %*
|
||||
exit /b %ERRORLEVEL%
|
||||
|
||||
:rlocation
|
||||
set "LOOKUP=%~1"
|
||||
set "OUTPUT_VAR=%~2"
|
||||
if defined RUNFILES_DIR_VALUE (
|
||||
set "%OUTPUT_VAR%=%RUNFILES_DIR_VALUE%\\%LOOKUP:/=\\%"
|
||||
exit /b 0
|
||||
)
|
||||
for /f "tokens=1,* delims= " %%A in ('findstr /b /c:"%LOOKUP% " "%RUNFILES_MANIFEST_VALUE%"') do (
|
||||
set "%OUTPUT_VAR%=%%B"
|
||||
exit /b 0
|
||||
)
|
||||
echo rules_bun: missing runfile %LOOKUP% 1>&2
|
||||
exit /b 1
|
||||
"""
|
||||
|
||||
def runfiles_path(file):
|
||||
workspace_name = file.owner.workspace_name
|
||||
if workspace_name:
|
||||
return "{}/{}".format(workspace_name, file.short_path)
|
||||
return "_main/{}".format(file.short_path)
|
||||
|
||||
def runtime_launcher_attrs():
|
||||
return {
|
||||
"_runtime_launcher": attr.label(
|
||||
default = _RUNTIME_LAUNCHER,
|
||||
allow_single_file = True,
|
||||
),
|
||||
"_windows_constraint": attr.label(
|
||||
default = _WINDOWS_CONSTRAINT,
|
||||
),
|
||||
}
|
||||
|
||||
def is_windows_target(ctx):
|
||||
return ctx.target_platform_has_constraint(ctx.attr._windows_constraint[platform_common.ConstraintValueInfo])
|
||||
|
||||
def write_launcher_spec(ctx, spec):
|
||||
spec_file = ctx.actions.declare_file(ctx.label.name + ".launcher.json")
|
||||
ctx.actions.write(
|
||||
output = spec_file,
|
||||
content = json.encode(spec) + "\n",
|
||||
)
|
||||
return spec_file
|
||||
|
||||
def declare_runtime_wrapper(ctx, bun_bin, spec_file):
|
||||
runner = ctx.file._runtime_launcher
|
||||
wrapper = ctx.actions.declare_file(ctx.label.name + (".cmd" if is_windows_target(ctx) else ""))
|
||||
content = _CMD_WRAPPER_TEMPLATE if is_windows_target(ctx) else _POSIX_WRAPPER_TEMPLATE
|
||||
content = content.replace("__BUN_RUNFILES_PATH__", runfiles_path(bun_bin)).replace(
|
||||
"__RUNNER_RUNFILES_PATH__",
|
||||
runfiles_path(runner),
|
||||
).replace(
|
||||
"__SPEC_RUNFILES_PATH__",
|
||||
runfiles_path(spec_file),
|
||||
)
|
||||
ctx.actions.write(
|
||||
output = wrapper,
|
||||
content = content,
|
||||
is_executable = True,
|
||||
)
|
||||
return struct(
|
||||
executable = wrapper,
|
||||
runner = runner,
|
||||
)
|
||||
1199
internal/runtime_launcher.js
Normal file
1199
internal/runtime_launcher.js
Normal file
File diff suppressed because it is too large
Load Diff
113
internal/workspace.bzl
Normal file
113
internal/workspace.bzl
Normal file
@@ -0,0 +1,113 @@
|
||||
"""Shared Bun workspace metadata helpers."""
|
||||
|
||||
BunWorkspaceInfo = provider(
|
||||
doc = "Workspace/runtime metadata shared by Bun rules and adapters.",
|
||||
fields = {
|
||||
"install_metadata_file": "Optional install metadata file from bun_install.",
|
||||
"install_repo_runfiles_path": "Runfiles root for the node_modules repository when present.",
|
||||
"metadata_file": "Rule-local metadata file describing the staged workspace inputs.",
|
||||
"node_modules_files": "Depset of node_modules files from bun_install.",
|
||||
"node_modules_roots": "Sorted repo-relative node_modules roots available in runfiles.",
|
||||
"package_dir_hint": "Package-relative directory when known at analysis time.",
|
||||
"package_json": "Package manifest file when explicitly provided.",
|
||||
"primary_file": "Primary source file used to resolve the runtime package context.",
|
||||
"runtime_files": "Depset of runtime files required to stage the workspace.",
|
||||
},
|
||||
)
|
||||
|
||||
def find_install_metadata_file(files):
|
||||
for file in files:
|
||||
if file.short_path.endswith("node_modules/.rules_bun/install.json"):
|
||||
return file
|
||||
return None
|
||||
|
||||
def _runfiles_workspace(file):
|
||||
workspace_name = file.owner.workspace_name
|
||||
if workspace_name:
|
||||
return workspace_name
|
||||
return "_main"
|
||||
|
||||
def _repo_relative_short_path(file):
|
||||
short_path = file.short_path.replace("\\", "/")
|
||||
workspace_name = _runfiles_workspace(file)
|
||||
external_prefix = "../{}/".format(workspace_name)
|
||||
if short_path.startswith(external_prefix):
|
||||
return short_path[len(external_prefix):]
|
||||
if short_path == "../{}".format(workspace_name):
|
||||
return "."
|
||||
return short_path
|
||||
|
||||
def resolve_node_modules_roots(files):
|
||||
roots = {}
|
||||
marker = "/node_modules/"
|
||||
for file in files:
|
||||
short_path = _repo_relative_short_path(file)
|
||||
if short_path == "node_modules" or short_path.startswith("node_modules/"):
|
||||
roots["node_modules"] = True
|
||||
|
||||
marker_index = short_path.find(marker)
|
||||
if marker_index >= 0:
|
||||
roots[short_path[:marker_index + len("/node_modules")]] = True
|
||||
|
||||
return sorted(roots.keys())
|
||||
|
||||
def create_bun_workspace_info(ctx, primary_file = None, package_json = None, package_dir_hint = ".", extra_files = None):
|
||||
direct_runtime_files = []
|
||||
if primary_file:
|
||||
direct_runtime_files.append(primary_file)
|
||||
if package_json and package_json != primary_file:
|
||||
direct_runtime_files.append(package_json)
|
||||
direct_runtime_files.extend(extra_files or [])
|
||||
|
||||
node_modules_files = depset()
|
||||
install_metadata_file = None
|
||||
install_repo_runfiles_path = ""
|
||||
node_modules_roots = []
|
||||
if getattr(ctx.attr, "node_modules", None):
|
||||
node_modules_files = ctx.attr.node_modules[DefaultInfo].files
|
||||
node_modules_file_list = node_modules_files.to_list()
|
||||
install_metadata_file = find_install_metadata_file(node_modules_file_list)
|
||||
node_modules_roots = resolve_node_modules_roots(node_modules_file_list)
|
||||
if install_metadata_file:
|
||||
install_repo_runfiles_path = _runfiles_workspace(install_metadata_file)
|
||||
elif node_modules_file_list:
|
||||
install_repo_runfiles_path = _runfiles_workspace(node_modules_file_list[0])
|
||||
|
||||
metadata_file = ctx.actions.declare_file(ctx.label.name + ".bun_workspace.json")
|
||||
ctx.actions.write(
|
||||
output = metadata_file,
|
||||
content = json.encode({
|
||||
"install_metadata": install_metadata_file.short_path if install_metadata_file else "",
|
||||
"install_repo_runfiles_path": install_repo_runfiles_path,
|
||||
"node_modules_roots": node_modules_roots,
|
||||
"package_dir_hint": package_dir_hint or ".",
|
||||
"package_json": package_json.short_path if package_json else "",
|
||||
"primary_file": primary_file.short_path if primary_file else "",
|
||||
}) + "\n",
|
||||
)
|
||||
direct_runtime_files.append(metadata_file)
|
||||
|
||||
runtime_files = depset(
|
||||
direct = direct_runtime_files,
|
||||
transitive = [node_modules_files],
|
||||
)
|
||||
|
||||
return BunWorkspaceInfo(
|
||||
install_metadata_file = install_metadata_file,
|
||||
install_repo_runfiles_path = install_repo_runfiles_path,
|
||||
metadata_file = metadata_file,
|
||||
node_modules_files = node_modules_files,
|
||||
node_modules_roots = node_modules_roots,
|
||||
package_dir_hint = package_dir_hint or ".",
|
||||
package_json = package_json,
|
||||
primary_file = primary_file,
|
||||
runtime_files = runtime_files,
|
||||
)
|
||||
|
||||
def workspace_runfiles(ctx, workspace_info, direct_files = None, transitive_files = None):
|
||||
return ctx.runfiles(
|
||||
files = direct_files or [],
|
||||
transitive_files = depset(
|
||||
transitive = [workspace_info.runtime_files] + (transitive_files or []),
|
||||
),
|
||||
)
|
||||
21
js/BUILD.bazel
Normal file
21
js/BUILD.bazel
Normal file
@@ -0,0 +1,21 @@
|
||||
load("@bazel_skylib//:bzl_library.bzl", "bzl_library")
|
||||
|
||||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
exports_files(["defs.bzl"])
|
||||
|
||||
filegroup(
|
||||
name = "repo_runtime_files",
|
||||
srcs = [
|
||||
"BUILD.bazel",
|
||||
"defs.bzl",
|
||||
],
|
||||
visibility = ["//visibility:public"],
|
||||
)
|
||||
|
||||
bzl_library(
|
||||
name = "defs_bzl",
|
||||
srcs = ["defs.bzl"],
|
||||
visibility = ["//visibility:public"],
|
||||
deps = ["//internal:js_compat_bzl"],
|
||||
)
|
||||
12
js/defs.bzl
Normal file
12
js/defs.bzl
Normal file
@@ -0,0 +1,12 @@
|
||||
"""rules_js-style public API backed by Bun."""
|
||||
|
||||
load("//internal:js_compat.bzl", _JsInfo = "JsInfo", _js_binary = "js_binary", _js_library = "js_library", _js_run_devserver = "js_run_devserver", _js_test = "js_test", _ts_library = "ts_library")
|
||||
|
||||
visibility("public")
|
||||
|
||||
JsInfo = _JsInfo
|
||||
js_binary = _js_binary
|
||||
js_test = _js_test
|
||||
js_run_devserver = _js_run_devserver
|
||||
js_library = _js_library
|
||||
ts_library = _ts_library
|
||||
32
npm/BUILD.bazel
Normal file
32
npm/BUILD.bazel
Normal file
@@ -0,0 +1,32 @@
|
||||
load("@bazel_skylib//:bzl_library.bzl", "bzl_library")
|
||||
|
||||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
exports_files([
|
||||
"extensions.bzl",
|
||||
"repositories.bzl",
|
||||
])
|
||||
|
||||
filegroup(
|
||||
name = "repo_runtime_files",
|
||||
srcs = [
|
||||
"BUILD.bazel",
|
||||
"extensions.bzl",
|
||||
"repositories.bzl",
|
||||
],
|
||||
visibility = ["//visibility:public"],
|
||||
)
|
||||
|
||||
bzl_library(
|
||||
name = "extensions_bzl",
|
||||
srcs = ["extensions.bzl"],
|
||||
visibility = ["//visibility:public"],
|
||||
deps = ["//internal:bun_install_bzl"],
|
||||
)
|
||||
|
||||
bzl_library(
|
||||
name = "repositories_bzl",
|
||||
srcs = ["repositories.bzl"],
|
||||
visibility = ["//visibility:public"],
|
||||
deps = ["//internal:bun_install_bzl"],
|
||||
)
|
||||
28
npm/extensions.bzl
Normal file
28
npm/extensions.bzl
Normal file
@@ -0,0 +1,28 @@
|
||||
load("//internal:bun_install.bzl", "bun_install_repository")
|
||||
|
||||
_translate = tag_class(
|
||||
attrs = {
|
||||
"name": attr.string(mandatory = True),
|
||||
"package_json": attr.label(mandatory = True),
|
||||
"lockfile": attr.label(mandatory = True),
|
||||
"install_inputs": attr.label_list(allow_files = True),
|
||||
"isolated_home": attr.bool(default = True),
|
||||
},
|
||||
)
|
||||
|
||||
def _npm_translate_lock_impl(ctx):
|
||||
for mod in ctx.modules:
|
||||
for install in mod.tags.translate:
|
||||
bun_install_repository(
|
||||
name = install.name,
|
||||
package_json = install.package_json,
|
||||
bun_lockfile = install.lockfile,
|
||||
install_inputs = install.install_inputs,
|
||||
isolated_home = install.isolated_home,
|
||||
visible_repo_name = install.name,
|
||||
)
|
||||
|
||||
npm_translate_lock = module_extension(
|
||||
implementation = _npm_translate_lock_impl,
|
||||
tag_classes = {"translate": _translate},
|
||||
)
|
||||
11
npm/repositories.bzl
Normal file
11
npm/repositories.bzl
Normal file
@@ -0,0 +1,11 @@
|
||||
load("//internal:bun_install.bzl", "bun_install_repository")
|
||||
|
||||
def npm_translate_lock(name, package_json, lockfile, install_inputs = [], isolated_home = True):
|
||||
bun_install_repository(
|
||||
name = name,
|
||||
package_json = package_json,
|
||||
bun_lockfile = lockfile,
|
||||
install_inputs = install_inputs,
|
||||
isolated_home = isolated_home,
|
||||
visible_repo_name = name,
|
||||
)
|
||||
@@ -1 +1,3 @@
|
||||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
exports_files(["nested_bazel_test.sh"])
|
||||
|
||||
1
tests/binary_test/.env
Normal file
1
tests/binary_test/.env
Normal file
@@ -0,0 +1 @@
|
||||
BUN_ENV_CWD_TEST=from-dotenv
|
||||
@@ -1,5 +1,5 @@
|
||||
load("//bun:defs.bzl", "bun_binary")
|
||||
load("@rules_shell//shell:sh_test.bzl", "sh_test")
|
||||
load("//bun:defs.bzl", "bun_binary")
|
||||
|
||||
bun_binary(
|
||||
name = "hello_js_bin",
|
||||
@@ -8,8 +8,12 @@ bun_binary(
|
||||
|
||||
sh_test(
|
||||
name = "bun_binary_js_test",
|
||||
size = "small",
|
||||
srcs = ["run_binary.sh"],
|
||||
args = ["$(location :hello_js_bin)", "hello-js"],
|
||||
args = [
|
||||
"$(location :hello_js_bin)",
|
||||
"hello-js",
|
||||
],
|
||||
data = [":hello_js_bin"],
|
||||
)
|
||||
|
||||
@@ -20,19 +24,24 @@ bun_binary(
|
||||
|
||||
sh_test(
|
||||
name = "bun_binary_ts_test",
|
||||
size = "small",
|
||||
srcs = ["run_binary.sh"],
|
||||
args = ["$(location :hello_ts_bin)", "hello-ts"],
|
||||
args = [
|
||||
"$(location :hello_ts_bin)",
|
||||
"hello-ts",
|
||||
],
|
||||
data = [":hello_ts_bin"],
|
||||
)
|
||||
|
||||
bun_binary(
|
||||
name = "hello_js_with_data_bin",
|
||||
entry_point = "hello.js",
|
||||
data = ["payload.txt"],
|
||||
entry_point = "hello.js",
|
||||
)
|
||||
|
||||
sh_test(
|
||||
name = "bun_binary_data_test",
|
||||
size = "small",
|
||||
srcs = ["verify_data_shape.sh"],
|
||||
args = [
|
||||
"$(location //internal:bun_binary.bzl)",
|
||||
@@ -46,13 +55,14 @@ sh_test(
|
||||
|
||||
bun_binary(
|
||||
name = "env_cwd_bin",
|
||||
entry_point = "env.ts",
|
||||
data = [".env"],
|
||||
entry_point = "env.ts",
|
||||
working_dir = "entry_point",
|
||||
)
|
||||
|
||||
sh_test(
|
||||
name = "bun_binary_env_cwd_test",
|
||||
size = "small",
|
||||
srcs = ["run_env_binary.sh"],
|
||||
args = ["$(location :env_cwd_bin)"],
|
||||
data = [":env_cwd_bin"],
|
||||
@@ -60,14 +70,94 @@ sh_test(
|
||||
|
||||
bun_binary(
|
||||
name = "env_parent_cwd_bin",
|
||||
entry_point = "env_parent/src/main.ts",
|
||||
data = ["env_parent/.env"],
|
||||
entry_point = "env_parent/src/main.ts",
|
||||
working_dir = "entry_point",
|
||||
)
|
||||
|
||||
sh_test(
|
||||
name = "bun_binary_env_parent_cwd_test",
|
||||
size = "small",
|
||||
srcs = ["run_parent_env_binary.sh"],
|
||||
args = ["$(location :env_parent_cwd_bin)"],
|
||||
data = [":env_parent_cwd_bin"],
|
||||
)
|
||||
|
||||
bun_binary(
|
||||
name = "runtime_flag_bin",
|
||||
args = [
|
||||
"one",
|
||||
"two",
|
||||
],
|
||||
entry_point = "flag_probe.ts",
|
||||
env_files = ["runtime.env"],
|
||||
preload = ["preload.ts"],
|
||||
)
|
||||
|
||||
sh_test(
|
||||
name = "bun_binary_runtime_flags_test",
|
||||
size = "small",
|
||||
srcs = ["run_flag_binary.sh"],
|
||||
args = ["$(location :runtime_flag_bin)"],
|
||||
data = [":runtime_flag_bin"],
|
||||
)
|
||||
|
||||
sh_test(
|
||||
name = "bun_binary_runtime_flags_shape_test",
|
||||
size = "small",
|
||||
srcs = ["verify_runtime_flags_shape.sh"],
|
||||
args = ["$(location :runtime_flag_bin)"],
|
||||
data = [":runtime_flag_bin"],
|
||||
)
|
||||
|
||||
bun_binary(
|
||||
name = "configured_launcher_bin",
|
||||
conditions = [
|
||||
"browser",
|
||||
"development",
|
||||
],
|
||||
entry_point = "hello.ts",
|
||||
inherit_host_path = True,
|
||||
install_mode = "force",
|
||||
node_modules = "@script_test_vite_node_modules//:node_modules",
|
||||
run_flags = [
|
||||
"--hot",
|
||||
"--console-depth",
|
||||
"4",
|
||||
],
|
||||
smol = True,
|
||||
visibility = ["//tests/ci_test:__pkg__"],
|
||||
)
|
||||
|
||||
sh_test(
|
||||
name = "bun_binary_configured_launcher_shape_test",
|
||||
size = "small",
|
||||
srcs = ["verify_configured_launcher_shape.sh"],
|
||||
args = ["$(location :configured_launcher_bin)"],
|
||||
data = [":configured_launcher_bin"],
|
||||
)
|
||||
|
||||
bun_binary(
|
||||
name = "path_default_bin",
|
||||
entry_point = "path_probe.ts",
|
||||
)
|
||||
|
||||
bun_binary(
|
||||
name = "path_inherit_bin",
|
||||
entry_point = "path_probe.ts",
|
||||
inherit_host_path = True,
|
||||
)
|
||||
|
||||
sh_test(
|
||||
name = "bun_binary_host_path_test",
|
||||
size = "small",
|
||||
srcs = ["run_path_binary.sh"],
|
||||
args = [
|
||||
"$(location :path_default_bin)",
|
||||
"$(location :path_inherit_bin)",
|
||||
],
|
||||
data = [
|
||||
":path_default_bin",
|
||||
":path_inherit_bin",
|
||||
],
|
||||
)
|
||||
|
||||
1
tests/binary_test/env_parent/.env
Normal file
1
tests/binary_test/env_parent/.env
Normal file
@@ -0,0 +1 @@
|
||||
BUN_ENV_PARENT_TEST=from-parent-dotenv
|
||||
7
tests/binary_test/flag_probe.ts
Normal file
7
tests/binary_test/flag_probe.ts
Normal file
@@ -0,0 +1,7 @@
|
||||
const state = globalThis as typeof globalThis & { __rules_bun_preloaded?: string };
|
||||
|
||||
console.log(JSON.stringify({
|
||||
preloaded: state.__rules_bun_preloaded ?? null,
|
||||
env: process.env.RUNTIME_FLAG_TEST ?? null,
|
||||
argv: process.argv.slice(2),
|
||||
}));
|
||||
5
tests/binary_test/path_probe.ts
Normal file
5
tests/binary_test/path_probe.ts
Normal file
@@ -0,0 +1,5 @@
|
||||
const pathValue = process.env.PATH ?? "";
|
||||
|
||||
console.log(JSON.stringify({
|
||||
hasHostSentinel: pathValue.includes("rules_bun_host_path_sentinel"),
|
||||
}));
|
||||
1
tests/binary_test/preload.ts
Normal file
1
tests/binary_test/preload.ts
Normal file
@@ -0,0 +1 @@
|
||||
(globalThis as typeof globalThis & { __rules_bun_preloaded?: string }).__rules_bun_preloaded = "yes";
|
||||
@@ -3,9 +3,25 @@ set -euo pipefail
|
||||
|
||||
binary="$1"
|
||||
expected="$2"
|
||||
output="$(${binary})"
|
||||
|
||||
if [[ "${output}" != "${expected}" ]]; then
|
||||
run_launcher() {
|
||||
local launcher="$1"
|
||||
shift
|
||||
if [[ ${launcher} == *.cmd ]]; then
|
||||
local command
|
||||
printf -v command '"%s"' "${launcher}"
|
||||
for arg in "$@"; do
|
||||
printf -v command '%s "%s"' "${command}" "${arg}"
|
||||
done
|
||||
cmd.exe /c "${command}" | tr -d '\r'
|
||||
return 0
|
||||
fi
|
||||
"${launcher}" "$@"
|
||||
}
|
||||
|
||||
output="$(run_launcher "${binary}")"
|
||||
|
||||
if [[ ${output} != "${expected}" ]]; then
|
||||
echo "Unexpected output from ${binary}: ${output}" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
@@ -2,7 +2,23 @@
|
||||
set -euo pipefail
|
||||
|
||||
binary="$1"
|
||||
output="$(${binary})"
|
||||
|
||||
run_launcher() {
|
||||
local launcher="$1"
|
||||
shift
|
||||
if [[ ${launcher} == *.cmd ]]; then
|
||||
local command
|
||||
printf -v command '"%s"' "${launcher}"
|
||||
for arg in "$@"; do
|
||||
printf -v command '%s "%s"' "${command}" "${arg}"
|
||||
done
|
||||
cmd.exe /c "${command}" | tr -d '\r'
|
||||
return 0
|
||||
fi
|
||||
"${launcher}" "$@"
|
||||
}
|
||||
|
||||
output="$(run_launcher "${binary}")"
|
||||
|
||||
if [[ ${output} != "from-dotenv" ]]; then
|
||||
echo "Expected .env value from entry-point directory, got: ${output}" >&2
|
||||
|
||||
28
tests/binary_test/run_flag_binary.sh
Executable file
28
tests/binary_test/run_flag_binary.sh
Executable file
@@ -0,0 +1,28 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
binary="$1"
|
||||
|
||||
run_launcher() {
|
||||
local launcher="$1"
|
||||
shift
|
||||
if [[ ${launcher} == *.cmd ]]; then
|
||||
local command
|
||||
printf -v command '"%s"' "${launcher}"
|
||||
for arg in "$@"; do
|
||||
printf -v command '%s "%s"' "${command}" "${arg}"
|
||||
done
|
||||
cmd.exe /c "${command}" | tr -d '\r'
|
||||
return 0
|
||||
fi
|
||||
"${launcher}" "$@"
|
||||
}
|
||||
|
||||
output="$(run_launcher "${binary}")"
|
||||
|
||||
expected='{"preloaded":"yes","env":"from-env-file","argv":["one","two"]}'
|
||||
|
||||
if [[ ${output} != "${expected}" ]]; then
|
||||
echo "Unexpected output from ${binary}: ${output}" >&2
|
||||
exit 1
|
||||
fi
|
||||
@@ -2,7 +2,23 @@
|
||||
set -euo pipefail
|
||||
|
||||
binary="$1"
|
||||
output="$(${binary})"
|
||||
|
||||
run_launcher() {
|
||||
local launcher="$1"
|
||||
shift
|
||||
if [[ ${launcher} == *.cmd ]]; then
|
||||
local command
|
||||
printf -v command '"%s"' "${launcher}"
|
||||
for arg in "$@"; do
|
||||
printf -v command '%s "%s"' "${command}" "${arg}"
|
||||
done
|
||||
cmd.exe /c "${command}" | tr -d '\r'
|
||||
return 0
|
||||
fi
|
||||
"${launcher}" "$@"
|
||||
}
|
||||
|
||||
output="$(run_launcher "${binary}")"
|
||||
|
||||
if [[ ${output} != "from-parent-dotenv" ]]; then
|
||||
echo "Expected .env value from parent directory, got: ${output}" >&2
|
||||
|
||||
33
tests/binary_test/run_path_binary.sh
Executable file
33
tests/binary_test/run_path_binary.sh
Executable file
@@ -0,0 +1,33 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
default_binary="$1"
|
||||
inherit_binary="$2"
|
||||
|
||||
run_launcher() {
|
||||
local launcher="$1"
|
||||
shift
|
||||
if [[ ${launcher} == *.cmd ]]; then
|
||||
local command
|
||||
printf -v command '"%s"' "${launcher}"
|
||||
for arg in "$@"; do
|
||||
printf -v command '%s "%s"' "${command}" "${arg}"
|
||||
done
|
||||
env PATH="rules_bun_host_path_sentinel:${PATH:-}" cmd.exe /c "${command}" | tr -d '\r'
|
||||
return 0
|
||||
fi
|
||||
env PATH="rules_bun_host_path_sentinel:${PATH:-}" "${launcher}" "$@"
|
||||
}
|
||||
|
||||
default_output="$(run_launcher "${default_binary}")"
|
||||
inherit_output="$(run_launcher "${inherit_binary}")"
|
||||
|
||||
if [[ ${default_output} != '{"hasHostSentinel":false}' ]]; then
|
||||
echo "Expected default launcher to hide host PATH, got: ${default_output}" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [[ ${inherit_output} != '{"hasHostSentinel":true}' ]]; then
|
||||
echo "Expected inherit_host_path launcher to preserve host PATH, got: ${inherit_output}" >&2
|
||||
exit 1
|
||||
fi
|
||||
1
tests/binary_test/runtime.env
Normal file
1
tests/binary_test/runtime.env
Normal file
@@ -0,0 +1 @@
|
||||
RUNTIME_FLAG_TEST=from-env-file
|
||||
23
tests/binary_test/verify_configured_launcher_shape.sh
Executable file
23
tests/binary_test/verify_configured_launcher_shape.sh
Executable file
@@ -0,0 +1,23 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
launcher="$1"
|
||||
|
||||
python3 - "${launcher}" <<'PY'
|
||||
import json
|
||||
import pathlib
|
||||
import sys
|
||||
|
||||
path = pathlib.Path(sys.argv[1])
|
||||
if path.suffix.lower() == ".cmd":
|
||||
path = pathlib.Path(str(path)[:-4])
|
||||
spec = json.loads(pathlib.Path(f"{path}.launcher.json").read_text())
|
||||
argv = spec["argv"]
|
||||
|
||||
assert spec["install_metadata_short_path"].endswith("node_modules/.rules_bun/install.json"), spec
|
||||
assert spec["inherit_host_path"] is True, spec
|
||||
assert spec["node_modules_roots"], spec
|
||||
assert all(not root.startswith("../") for root in spec["node_modules_roots"]), spec
|
||||
for value in ["--smol", "--conditions", "browser", "development", "--install", "force", "--hot", "--console-depth", "4"]:
|
||||
assert value in argv, (value, spec)
|
||||
PY
|
||||
@@ -4,6 +4,6 @@ set -euo pipefail
|
||||
rule_file="$1"
|
||||
build_file="$2"
|
||||
|
||||
grep -Eq 'files = \[bun_bin, entry_point\] \+ ctx\.files\.data' "${rule_file}"
|
||||
grep -Eq 'extra_files = ctx\.files\.data \+ ctx\.files\.preload \+ ctx\.files\.env_files \+ \[bun_bin\]' "${rule_file}"
|
||||
grep -Eq 'name = "hello_js_with_data_bin"' "${build_file}"
|
||||
grep -Eq 'data = \["payload\.txt"\]' "${build_file}"
|
||||
|
||||
20
tests/binary_test/verify_runtime_flags_shape.sh
Executable file
20
tests/binary_test/verify_runtime_flags_shape.sh
Executable file
@@ -0,0 +1,20 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
launcher="$1"
|
||||
|
||||
python3 - "${launcher}" <<'PY'
|
||||
import json
|
||||
import pathlib
|
||||
import sys
|
||||
|
||||
path = pathlib.Path(sys.argv[1])
|
||||
if path.suffix.lower() == ".cmd":
|
||||
path = pathlib.Path(str(path)[:-4])
|
||||
spec = json.loads(pathlib.Path(f"{path}.launcher.json").read_text())
|
||||
|
||||
assert "--no-install" in spec["argv"], spec
|
||||
assert spec["inherit_host_path"] is False, spec
|
||||
assert spec["preload_short_paths"] and spec["preload_short_paths"][0].endswith("tests/binary_test/preload.ts"), spec
|
||||
assert spec["env_file_short_paths"] and spec["env_file_short_paths"][0].endswith("tests/binary_test/runtime.env"), spec
|
||||
PY
|
||||
@@ -3,16 +3,62 @@ load("//bun:defs.bzl", "bun_test")
|
||||
|
||||
bun_test(
|
||||
name = "passing_suite",
|
||||
size = "small",
|
||||
srcs = ["passing.test.ts"],
|
||||
)
|
||||
|
||||
bun_test(
|
||||
name = "failing_suite",
|
||||
size = "small",
|
||||
srcs = ["failing.test.ts"],
|
||||
)
|
||||
|
||||
bun_test(
|
||||
name = "configured_suite",
|
||||
size = "small",
|
||||
srcs = ["passing.test.ts"],
|
||||
bail = 1,
|
||||
concurrent = True,
|
||||
coverage = True,
|
||||
coverage_reporters = ["lcov"],
|
||||
env_files = ["test.env"],
|
||||
max_concurrency = 4,
|
||||
no_env_file = True,
|
||||
preload = ["preload.ts"],
|
||||
randomize = True,
|
||||
reporter = "junit",
|
||||
rerun_each = 2,
|
||||
seed = 7,
|
||||
test_flags = ["--only-failures"],
|
||||
timeout_ms = 250,
|
||||
update_snapshots = True,
|
||||
visibility = ["//tests/ci_test:__pkg__"],
|
||||
)
|
||||
|
||||
bun_test(
|
||||
name = "configured_retry_suite",
|
||||
size = "small",
|
||||
srcs = ["passing.test.ts"],
|
||||
retry = 3,
|
||||
)
|
||||
|
||||
sh_test(
|
||||
name = "bun_test_configured_suite_shape_test",
|
||||
size = "small",
|
||||
srcs = ["configured_suite_shape.sh"],
|
||||
args = [
|
||||
"$(location :configured_suite)",
|
||||
"$(location :configured_retry_suite)",
|
||||
],
|
||||
data = [
|
||||
":configured_retry_suite",
|
||||
":configured_suite",
|
||||
],
|
||||
)
|
||||
|
||||
sh_test(
|
||||
name = "bun_test_failing_suite_test",
|
||||
size = "small",
|
||||
srcs = ["failing_suite_shape.sh"],
|
||||
args = ["$(location //tests/bun_test_test:BUILD.bazel)"],
|
||||
data = ["//tests/bun_test_test:BUILD.bazel"],
|
||||
@@ -20,21 +66,24 @@ sh_test(
|
||||
|
||||
sh_test(
|
||||
name = "bun_test_cache_hit_test",
|
||||
size = "small",
|
||||
srcs = ["cache_hit_shape.sh"],
|
||||
args = ["$(location //internal:bun_test.bzl)"],
|
||||
data = ["//internal:bun_test.bzl"],
|
||||
args = ["$(location :passing_suite)"],
|
||||
data = [":passing_suite"],
|
||||
)
|
||||
|
||||
sh_test(
|
||||
name = "bun_test_cache_miss_test",
|
||||
size = "small",
|
||||
srcs = ["cache_miss_shape.sh"],
|
||||
args = ["$(location //internal:bun_test.bzl)"],
|
||||
data = ["//internal:bun_test.bzl"],
|
||||
args = ["$(location :configured_suite)"],
|
||||
data = [":configured_suite"],
|
||||
)
|
||||
|
||||
sh_test(
|
||||
name = "bun_test_junit_output_test",
|
||||
size = "small",
|
||||
srcs = ["junit_shape.sh"],
|
||||
args = ["$(location //internal:bun_test.bzl)"],
|
||||
data = ["//internal:bun_test.bzl"],
|
||||
args = ["$(location :configured_suite)"],
|
||||
data = [":configured_suite"],
|
||||
)
|
||||
|
||||
@@ -1,8 +1,19 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
rule_file="$1"
|
||||
launcher="$1"
|
||||
|
||||
grep -Fq 'set -euo pipefail' "${rule_file}"
|
||||
grep -Fq 'src_args = " ".join([_shell_quote(src.short_path) for src in ctx.files.srcs])' "${rule_file}"
|
||||
grep -Fq 'exec "${{bun_bin}}" --bun test {src_args} "$@"' "${rule_file}"
|
||||
python3 - "${launcher}" <<'PY'
|
||||
import json
|
||||
import pathlib
|
||||
import sys
|
||||
|
||||
path = pathlib.Path(sys.argv[1])
|
||||
if path.suffix.lower() == ".cmd":
|
||||
path = pathlib.Path(str(path)[:-4])
|
||||
spec = json.loads(pathlib.Path(f"{path}.launcher.json").read_text())
|
||||
|
||||
assert spec["kind"] == "bun_test", spec
|
||||
assert spec["argv"][:2] == ["--bun", "test"], spec
|
||||
assert spec["test_short_paths"], spec
|
||||
PY
|
||||
|
||||
@@ -1,7 +1,20 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
rule_file="$1"
|
||||
launcher="$1"
|
||||
|
||||
grep -Eq 'files = \[bun_bin\] \+ ctx\.files\.srcs \+ ctx\.files\.data' "${rule_file}"
|
||||
grep -Eq '"srcs": attr\.label_list\(' "${rule_file}"
|
||||
python3 - "${launcher}" <<'PY'
|
||||
import json
|
||||
import pathlib
|
||||
import sys
|
||||
|
||||
path = pathlib.Path(sys.argv[1])
|
||||
if path.suffix.lower() == ".cmd":
|
||||
path = pathlib.Path(str(path)[:-4])
|
||||
spec = json.loads(pathlib.Path(f"{path}.launcher.json").read_text())
|
||||
|
||||
assert spec["coverage"] is True, spec
|
||||
assert spec["preload_short_paths"], spec
|
||||
assert spec["env_file_short_paths"], spec
|
||||
assert spec["test_short_paths"], spec
|
||||
PY
|
||||
|
||||
42
tests/bun_test_test/configured_suite_shape.sh
Executable file
42
tests/bun_test_test/configured_suite_shape.sh
Executable file
@@ -0,0 +1,42 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
launcher="$1"
|
||||
retry_launcher="$2"
|
||||
|
||||
python3 - "${launcher}" "${retry_launcher}" <<'PY'
|
||||
import json
|
||||
import pathlib
|
||||
import sys
|
||||
|
||||
def read_spec(launcher: str):
|
||||
path = pathlib.Path(launcher)
|
||||
if path.suffix.lower() == ".cmd":
|
||||
path = pathlib.Path(str(path)[:-4])
|
||||
return json.loads(pathlib.Path(f"{path}.launcher.json").read_text())
|
||||
|
||||
launcher_spec = read_spec(sys.argv[1])
|
||||
retry_spec = read_spec(sys.argv[2])
|
||||
|
||||
for value in [
|
||||
"--no-install",
|
||||
"--no-env-file",
|
||||
"--timeout",
|
||||
"--update-snapshots",
|
||||
"--rerun-each",
|
||||
"--concurrent",
|
||||
"--randomize",
|
||||
"--seed",
|
||||
"--bail",
|
||||
"--max-concurrency",
|
||||
]:
|
||||
assert value in launcher_spec["argv"], (value, launcher_spec)
|
||||
|
||||
assert launcher_spec["preload_short_paths"], launcher_spec
|
||||
assert launcher_spec["env_file_short_paths"], launcher_spec
|
||||
assert launcher_spec["reporter"] == "junit", launcher_spec
|
||||
assert launcher_spec["coverage"] is True, launcher_spec
|
||||
assert launcher_spec["coverage_reporters"] == ["lcov"], launcher_spec
|
||||
assert "--retry" in retry_spec["argv"], retry_spec
|
||||
assert "3" in retry_spec["argv"], retry_spec
|
||||
PY
|
||||
@@ -1,7 +1,17 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
rule_file="$1"
|
||||
launcher="$1"
|
||||
|
||||
grep -Fq 'exec "${{bun_bin}}" --bun test {src_args} --test-name-pattern "${{TESTBRIDGE_TEST_ONLY}}" "$@"' "${rule_file}"
|
||||
grep -Fq 'if [[ -n "${{TESTBRIDGE_TEST_ONLY:-}}" ]]' "${rule_file}"
|
||||
python3 - "${launcher}" <<'PY'
|
||||
import json
|
||||
import pathlib
|
||||
import sys
|
||||
|
||||
path = pathlib.Path(sys.argv[1])
|
||||
if path.suffix.lower() == ".cmd":
|
||||
path = pathlib.Path(str(path)[:-4])
|
||||
spec = json.loads(pathlib.Path(f"{path}.launcher.json").read_text())
|
||||
|
||||
assert spec["reporter"] == "junit", spec
|
||||
PY
|
||||
|
||||
1
tests/bun_test_test/preload.ts
Normal file
1
tests/bun_test_test/preload.ts
Normal file
@@ -0,0 +1 @@
|
||||
(globalThis as typeof globalThis & { __rules_bun_test_preloaded?: boolean }).__rules_bun_test_preloaded = true;
|
||||
1
tests/bun_test_test/test.env
Normal file
1
tests/bun_test_test/test.env
Normal file
@@ -0,0 +1 @@
|
||||
TEST_FROM_ENV=1
|
||||
@@ -1,5 +1,5 @@
|
||||
load("//bun:defs.bzl", "bun_bundle")
|
||||
load("@rules_shell//shell:sh_test.bzl", "sh_test")
|
||||
load("//bun:defs.bzl", "bun_build", "bun_bundle", "bun_compile")
|
||||
|
||||
bun_bundle(
|
||||
name = "simple_bundle",
|
||||
@@ -18,8 +18,132 @@ bun_bundle(
|
||||
external = ["left-pad"],
|
||||
)
|
||||
|
||||
bun_bundle(
|
||||
name = "collision_bundle",
|
||||
entry_points = [
|
||||
"collision_case/a/main.ts",
|
||||
"collision_case/b/main.ts",
|
||||
],
|
||||
)
|
||||
|
||||
bun_build(
|
||||
name = "site_build",
|
||||
data = [
|
||||
"site/main.ts",
|
||||
"site/styles.css",
|
||||
],
|
||||
entry_points = ["site/index.html"],
|
||||
splitting = True,
|
||||
)
|
||||
|
||||
bun_build(
|
||||
name = "site_build_with_meta",
|
||||
data = [
|
||||
"site/main.ts",
|
||||
"site/styles.css",
|
||||
],
|
||||
entry_points = ["site/index.html"],
|
||||
metafile = True,
|
||||
metafile_md = True,
|
||||
)
|
||||
|
||||
bun_build(
|
||||
name = "advanced_site_build",
|
||||
asset_naming = "assets/[name]-[hash].[ext]",
|
||||
banner = "/* bundle banner */",
|
||||
build_flags = [
|
||||
"--app",
|
||||
"--server-components",
|
||||
],
|
||||
chunk_naming = "chunks/[name]-[hash].[ext]",
|
||||
conditions = [
|
||||
"browser",
|
||||
"custom",
|
||||
],
|
||||
css_chunking = True,
|
||||
data = [
|
||||
"site/main.ts",
|
||||
"site/styles.css",
|
||||
],
|
||||
define = [
|
||||
"process.env.NODE_ENV:\"production\"",
|
||||
"__DEV__:false",
|
||||
],
|
||||
drop = [
|
||||
"console",
|
||||
"debugger",
|
||||
],
|
||||
emit_dce_annotations = True,
|
||||
entry_naming = "entries/[name]-[hash].[ext]",
|
||||
entry_points = ["site/index.html"],
|
||||
env = "PUBLIC_*",
|
||||
external = [
|
||||
"left-pad",
|
||||
"react",
|
||||
],
|
||||
feature = [
|
||||
"react_fast_refresh",
|
||||
"server_components",
|
||||
],
|
||||
footer = "// bundle footer",
|
||||
format = "cjs",
|
||||
jsx_factory = "h",
|
||||
jsx_fragment = "Fragment",
|
||||
jsx_import_source = "preact",
|
||||
jsx_runtime = "automatic",
|
||||
jsx_side_effects = True,
|
||||
keep_names = True,
|
||||
loader = [
|
||||
".svg:file",
|
||||
".txt:text",
|
||||
],
|
||||
minify = True,
|
||||
minify_identifiers = True,
|
||||
minify_syntax = True,
|
||||
minify_whitespace = True,
|
||||
no_bundle = True,
|
||||
packages = "external",
|
||||
production = True,
|
||||
public_path = "/static/",
|
||||
react_fast_refresh = True,
|
||||
root = "tests/bundle_test/site",
|
||||
sourcemap = "linked",
|
||||
splitting = True,
|
||||
tags = ["manual"],
|
||||
target = "node",
|
||||
)
|
||||
|
||||
bun_compile(
|
||||
name = "compiled_cli",
|
||||
entry_point = "cli.ts",
|
||||
)
|
||||
|
||||
bun_compile(
|
||||
name = "compiled_cli_with_flags",
|
||||
bytecode = True,
|
||||
compile_autoload_bunfig = False,
|
||||
compile_autoload_dotenv = False,
|
||||
compile_autoload_package_json = True,
|
||||
compile_autoload_tsconfig = True,
|
||||
compile_exec_argv = [
|
||||
"--smol",
|
||||
"--inspect-wait",
|
||||
],
|
||||
compile_executable = "fake_cross_bun.bin",
|
||||
entry_point = "cli.ts",
|
||||
tags = ["manual"],
|
||||
windows_copyright = "(c) rules_bun",
|
||||
windows_description = "compile flag coverage",
|
||||
windows_hide_console = True,
|
||||
windows_icon = "branding/icon.ico",
|
||||
windows_publisher = "rules_bun",
|
||||
windows_title = "Rules Bun Test App",
|
||||
windows_version = "1.2.3.4",
|
||||
)
|
||||
|
||||
sh_test(
|
||||
name = "bundle_output_test",
|
||||
size = "small",
|
||||
srcs = ["verify_bundle.sh"],
|
||||
args = ["$(location :simple_bundle)"],
|
||||
data = [":simple_bundle"],
|
||||
@@ -27,19 +151,21 @@ sh_test(
|
||||
|
||||
sh_test(
|
||||
name = "bundle_minify_test",
|
||||
size = "small",
|
||||
srcs = ["verify_minify.sh"],
|
||||
args = [
|
||||
"$(location :simple_bundle)",
|
||||
"$(location :minified_bundle)",
|
||||
],
|
||||
data = [
|
||||
":simple_bundle",
|
||||
":minified_bundle",
|
||||
":simple_bundle",
|
||||
],
|
||||
)
|
||||
|
||||
sh_test(
|
||||
name = "bundle_hermetic_digest_test",
|
||||
size = "small",
|
||||
srcs = ["verify_hermetic_shape.sh"],
|
||||
args = ["$(location //internal:bun_bundle.bzl)"],
|
||||
data = ["//internal:bun_bundle.bzl"],
|
||||
@@ -47,6 +173,7 @@ sh_test(
|
||||
|
||||
sh_test(
|
||||
name = "bundle_external_exclusion_test",
|
||||
size = "small",
|
||||
srcs = ["verify_external_shape.sh"],
|
||||
args = [
|
||||
"$(location //internal:bun_bundle.bzl)",
|
||||
@@ -57,3 +184,72 @@ sh_test(
|
||||
"//tests/bundle_test:BUILD.bazel",
|
||||
],
|
||||
)
|
||||
|
||||
sh_test(
|
||||
name = "bundle_collision_output_test",
|
||||
size = "small",
|
||||
srcs = ["verify_collision_outputs.sh"],
|
||||
args = ["$(locations :collision_bundle)"],
|
||||
data = [":collision_bundle"],
|
||||
)
|
||||
|
||||
sh_test(
|
||||
name = "bundle_sourcemap_shape_test",
|
||||
size = "small",
|
||||
srcs = ["verify_sourcemap_shape.sh"],
|
||||
tags = ["exclusive"],
|
||||
data = [
|
||||
"BUILD.bazel",
|
||||
"//:repo_runtime_files",
|
||||
"//bun:repo_runtime_files",
|
||||
"//internal:repo_runtime_files",
|
||||
"//tests:nested_bazel_test.sh",
|
||||
"//tests/bundle_test/sourcemap_case:BUILD.bazel",
|
||||
"//tests/bundle_test/sourcemap_case:entry.ts",
|
||||
],
|
||||
env_inherit = ["PATH"],
|
||||
)
|
||||
|
||||
sh_test(
|
||||
name = "bun_build_site_output_test",
|
||||
size = "small",
|
||||
srcs = ["verify_site_build.sh"],
|
||||
args = ["$(location :site_build)"],
|
||||
data = [":site_build"],
|
||||
)
|
||||
|
||||
sh_test(
|
||||
name = "bun_build_site_meta_test",
|
||||
size = "small",
|
||||
srcs = ["verify_site_build_meta.sh"],
|
||||
args = ["$(locations :site_build_with_meta)"],
|
||||
data = [":site_build_with_meta"],
|
||||
)
|
||||
|
||||
sh_test(
|
||||
name = "bun_compile_output_test",
|
||||
size = "small",
|
||||
srcs = ["run_compiled_binary.sh"],
|
||||
args = ["$(location :compiled_cli)"],
|
||||
data = [":compiled_cli"],
|
||||
)
|
||||
|
||||
sh_test(
|
||||
name = "bun_build_compile_flag_shape_test",
|
||||
size = "small",
|
||||
srcs = ["verify_flag_aquery.sh"],
|
||||
tags = ["exclusive"],
|
||||
data = [
|
||||
"BUILD.bazel",
|
||||
"cli.ts",
|
||||
"fake_cross_bun.bin",
|
||||
"site/index.html",
|
||||
"site/main.ts",
|
||||
"site/styles.css",
|
||||
"//:repo_runtime_files",
|
||||
"//bun:repo_runtime_files",
|
||||
"//internal:repo_runtime_files",
|
||||
"//tests:nested_bazel_test.sh",
|
||||
],
|
||||
env_inherit = ["PATH"],
|
||||
)
|
||||
|
||||
1
tests/bundle_test/cli.ts
Normal file
1
tests/bundle_test/cli.ts
Normal file
@@ -0,0 +1 @@
|
||||
console.log("compiled-cli");
|
||||
1
tests/bundle_test/collision_case/a/main.ts
Normal file
1
tests/bundle_test/collision_case/a/main.ts
Normal file
@@ -0,0 +1 @@
|
||||
console.log("a");
|
||||
1
tests/bundle_test/collision_case/b/main.ts
Normal file
1
tests/bundle_test/collision_case/b/main.ts
Normal file
@@ -0,0 +1 @@
|
||||
console.log("b");
|
||||
1
tests/bundle_test/fake_cross_bun.bin
Normal file
1
tests/bundle_test/fake_cross_bun.bin
Normal file
@@ -0,0 +1 @@
|
||||
placeholder
|
||||
11
tests/bundle_test/out.js
Normal file
11
tests/bundle_test/out.js
Normal file
@@ -0,0 +1,11 @@
|
||||
// tests/bundle_test/main.ts
|
||||
function greet(name) {
|
||||
return `Hello ${name}`;
|
||||
}
|
||||
console.log(greet("bundle"));
|
||||
export {
|
||||
greet
|
||||
};
|
||||
|
||||
//# debugId=A86FEBA7FCC390B664756E2164756E21
|
||||
//# sourceMappingURL=out.js.map
|
||||
10
tests/bundle_test/out.js.map
Normal file
10
tests/bundle_test/out.js.map
Normal file
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"version": 3,
|
||||
"sources": ["tests/bundle_test/main.ts"],
|
||||
"sourcesContent": [
|
||||
"export function greet(name: string): string {\n return `Hello ${name}`;\n}\n\nconsole.log(greet(\"bundle\"));\n"
|
||||
],
|
||||
"mappings": ";AAAO,SAAS,KAAK,CAAC,MAAsB;AAAA,EAC1C,OAAO,SAAS;AAAA;AAGlB,QAAQ,IAAI,MAAM,QAAQ,CAAC;",
|
||||
"debugId": "A86FEBA7FCC390B664756E2164756E21",
|
||||
"names": []
|
||||
}
|
||||
10
tests/bundle_test/run_compiled_binary.sh
Executable file
10
tests/bundle_test/run_compiled_binary.sh
Executable file
@@ -0,0 +1,10 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
binary="$1"
|
||||
output="$(${binary})"
|
||||
|
||||
if [[ ${output} != "compiled-cli" ]]; then
|
||||
echo "Unexpected output from compiled binary ${binary}: ${output}" >&2
|
||||
exit 1
|
||||
fi
|
||||
12
tests/bundle_test/site/index.html
Normal file
12
tests/bundle_test/site/index.html
Normal file
@@ -0,0 +1,12 @@
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>rules_bun site build</title>
|
||||
<link rel="stylesheet" href="./styles.css">
|
||||
</head>
|
||||
<body>
|
||||
<div id="app">rules_bun</div>
|
||||
<script type="module" src="./main.ts"></script>
|
||||
</body>
|
||||
</html>
|
||||
1
tests/bundle_test/site/main.ts
Normal file
1
tests/bundle_test/site/main.ts
Normal file
@@ -0,0 +1 @@
|
||||
document.getElementById("app")?.setAttribute("data-built", "yes");
|
||||
4
tests/bundle_test/site/styles.css
Normal file
4
tests/bundle_test/site/styles.css
Normal file
@@ -0,0 +1,4 @@
|
||||
body {
|
||||
background: #f5efe2;
|
||||
color: #1f1b14;
|
||||
}
|
||||
11
tests/bundle_test/sourcemap_bundle__main.js
Normal file
11
tests/bundle_test/sourcemap_bundle__main.js
Normal file
@@ -0,0 +1,11 @@
|
||||
// ../../../../../../../Projects/rules_bun/tests/bundle_test/main.ts
|
||||
function greet(name) {
|
||||
return `Hello ${name}`;
|
||||
}
|
||||
console.log(greet("bundle"));
|
||||
export {
|
||||
greet
|
||||
};
|
||||
|
||||
//# debugId=D8717FECBBDCEC7764756E2164756E21
|
||||
//# sourceMappingURL=sourcemap_bundle__main.js.map
|
||||
10
tests/bundle_test/sourcemap_bundle__main.js.map
Normal file
10
tests/bundle_test/sourcemap_bundle__main.js.map
Normal file
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"version": 3,
|
||||
"sources": ["../../../../../../../Projects/rules_bun/tests/bundle_test/main.ts"],
|
||||
"sourcesContent": [
|
||||
"export function greet(name: string): string {\n return `Hello ${name}`;\n}\n\nconsole.log(greet(\"bundle\"));\n"
|
||||
],
|
||||
"mappings": ";AAAO,SAAS,KAAK,CAAC,MAAsB;AAAA,EAC1C,OAAO,SAAS;AAAA;AAGlB,QAAQ,IAAI,MAAM,QAAQ,CAAC;",
|
||||
"debugId": "D8717FECBBDCEC7764756E2164756E21",
|
||||
"names": []
|
||||
}
|
||||
13
tests/bundle_test/sourcemap_case/BUILD.bazel
Normal file
13
tests/bundle_test/sourcemap_case/BUILD.bazel
Normal file
@@ -0,0 +1,13 @@
|
||||
load("//bun:defs.bzl", "bun_bundle")
|
||||
|
||||
exports_files([
|
||||
"BUILD.bazel",
|
||||
"entry.ts",
|
||||
])
|
||||
|
||||
bun_bundle(
|
||||
name = "sourcemap_bundle",
|
||||
tags = ["manual"],
|
||||
entry_points = ["entry.ts"],
|
||||
sourcemap = True,
|
||||
)
|
||||
3
tests/bundle_test/sourcemap_case/entry.ts
Normal file
3
tests/bundle_test/sourcemap_case/entry.ts
Normal file
@@ -0,0 +1,3 @@
|
||||
const message: string = "sourcemap coverage";
|
||||
|
||||
console.log(message);
|
||||
@@ -3,12 +3,12 @@ set -euo pipefail
|
||||
|
||||
bundle="$1"
|
||||
|
||||
if [[ ! -f "${bundle}" ]]; then
|
||||
if [[ ! -f ${bundle} ]]; then
|
||||
echo "Bundle output not found: ${bundle}" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [[ ! -s "${bundle}" ]]; then
|
||||
if [[ ! -s ${bundle} ]]; then
|
||||
echo "Bundle output is empty: ${bundle}" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
25
tests/bundle_test/verify_collision_outputs.sh
Executable file
25
tests/bundle_test/verify_collision_outputs.sh
Executable file
@@ -0,0 +1,25 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
first_output="$1"
|
||||
second_output="$2"
|
||||
|
||||
if [[ ${first_output} == "${second_output}" ]]; then
|
||||
echo "Expected distinct bundle outputs for same-basename entry points" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [[ ! -f ${first_output} || ! -f ${second_output} ]]; then
|
||||
echo "Expected both bundle outputs to exist" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [[ ${first_output} != *"collision_bundle__tests_bundle_test_collision_case_a_main.js" ]]; then
|
||||
echo "Unexpected first output path: ${first_output}" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [[ ${second_output} != *"collision_bundle__tests_bundle_test_collision_case_b_main.js" ]]; then
|
||||
echo "Unexpected second output path: ${second_output}" >&2
|
||||
exit 1
|
||||
fi
|
||||
@@ -4,7 +4,7 @@ set -euo pipefail
|
||||
rule_file="$1"
|
||||
build_file="$2"
|
||||
|
||||
grep -Eq 'for package in ctx\.attr\.external:' "${rule_file}"
|
||||
grep -Eq 'args\.add\("--external"\)' "${rule_file}"
|
||||
grep -Eq 'add_bun_build_common_flags\(args, ctx\.attr\)' "${rule_file}"
|
||||
grep -Eq '"external": attr\.string_list\(' "${rule_file}"
|
||||
grep -Eq 'name = "external_bundle"' "${build_file}"
|
||||
grep -Eq 'external = \["left-pad"\]' "${build_file}"
|
||||
|
||||
172
tests/bundle_test/verify_flag_aquery.sh
Executable file
172
tests/bundle_test/verify_flag_aquery.sh
Executable file
@@ -0,0 +1,172 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
script_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd -P)"
|
||||
# shellcheck source=../nested_bazel_test.sh
|
||||
source "${script_dir}/../nested_bazel_test.sh"
|
||||
setup_nested_bazel_cmd
|
||||
|
||||
find_workspace_root() {
|
||||
local candidate
|
||||
local module_path
|
||||
local search_dir
|
||||
|
||||
for candidate in \
|
||||
"${TEST_SRCDIR:-}/${TEST_WORKSPACE:-}" \
|
||||
"${TEST_SRCDIR:-}/_main"; do
|
||||
if [[ -n ${candidate} && -f "${candidate}/MODULE.bazel" ]]; then
|
||||
printf '%s\n' "${candidate}"
|
||||
return 0
|
||||
fi
|
||||
done
|
||||
|
||||
if [[ -n ${TEST_SRCDIR:-} ]]; then
|
||||
module_path="$(find "${TEST_SRCDIR}" -maxdepth 3 -name MODULE.bazel -print -quit 2>/dev/null || true)"
|
||||
if [[ -n ${module_path} ]]; then
|
||||
dirname "${module_path}"
|
||||
return 0
|
||||
fi
|
||||
fi
|
||||
|
||||
search_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd -P)"
|
||||
candidate="$(cd "${search_dir}/../.." && pwd -P)"
|
||||
if [[ -f "${candidate}/MODULE.bazel" ]]; then
|
||||
printf '%s\n' "${candidate}"
|
||||
return 0
|
||||
fi
|
||||
|
||||
echo "Unable to locate rules_bun workspace root" >&2
|
||||
exit 1
|
||||
}
|
||||
|
||||
rules_bun_root="$(find_workspace_root)"
|
||||
|
||||
cleanup() {
|
||||
local status="$1"
|
||||
trap - EXIT
|
||||
shutdown_nested_bazel_workspace "${rules_bun_root}"
|
||||
exit "${status}"
|
||||
}
|
||||
trap 'cleanup $?' EXIT
|
||||
|
||||
run_aquery() {
|
||||
local mnemonic="$1"
|
||||
local target="$2"
|
||||
|
||||
(
|
||||
cd "${rules_bun_root}" &&
|
||||
"${bazel_cmd[@]}" aquery "mnemonic(\"${mnemonic}\", ${target})" --output=textproto
|
||||
)
|
||||
}
|
||||
|
||||
expect_line() {
|
||||
local output="$1"
|
||||
local expected="$2"
|
||||
|
||||
if ! grep -Fq -- "${expected}" <<<"${output}"; then
|
||||
echo "Expected aquery output to contain: ${expected}" >&2
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
build_output="$(run_aquery "BunBuild" "//tests/bundle_test:advanced_site_build")"
|
||||
|
||||
for expected in \
|
||||
'arguments: "--target"' \
|
||||
'arguments: "node"' \
|
||||
'arguments: "--format"' \
|
||||
'arguments: "cjs"' \
|
||||
'arguments: "--production"' \
|
||||
'arguments: "--splitting"' \
|
||||
'arguments: "--root"' \
|
||||
'arguments: "tests/bundle_test/site"' \
|
||||
'arguments: "--sourcemap"' \
|
||||
'arguments: "linked"' \
|
||||
'arguments: "--banner"' \
|
||||
'arguments: "/* bundle banner */"' \
|
||||
'arguments: "--footer"' \
|
||||
'arguments: "// bundle footer"' \
|
||||
'arguments: "--public-path"' \
|
||||
'arguments: "/static/"' \
|
||||
'arguments: "--packages"' \
|
||||
'arguments: "external"' \
|
||||
'arguments: "left-pad"' \
|
||||
'arguments: "react"' \
|
||||
'arguments: "--entry-naming"' \
|
||||
'arguments: "entries/[name]-[hash].[ext]"' \
|
||||
'arguments: "--chunk-naming"' \
|
||||
'arguments: "chunks/[name]-[hash].[ext]"' \
|
||||
'arguments: "--asset-naming"' \
|
||||
'arguments: "assets/[name]-[hash].[ext]"' \
|
||||
'arguments: "--minify"' \
|
||||
'arguments: "--minify-syntax"' \
|
||||
'arguments: "--minify-whitespace"' \
|
||||
'arguments: "--minify-identifiers"' \
|
||||
'arguments: "--keep-names"' \
|
||||
'arguments: "--css-chunking"' \
|
||||
'arguments: "--conditions"' \
|
||||
'arguments: "browser"' \
|
||||
'arguments: "custom"' \
|
||||
'arguments: "--env"' \
|
||||
'arguments: "PUBLIC_*"' \
|
||||
'arguments: "process.env.NODE_ENV:\"production\""' \
|
||||
'arguments: "__DEV__:false"' \
|
||||
'arguments: "console"' \
|
||||
'arguments: "debugger"' \
|
||||
'arguments: "react_fast_refresh"' \
|
||||
'arguments: "server_components"' \
|
||||
'arguments: ".svg:file"' \
|
||||
'arguments: ".txt:text"' \
|
||||
'arguments: "--jsx-factory"' \
|
||||
'arguments: "h"' \
|
||||
'arguments: "--jsx-fragment"' \
|
||||
'arguments: "Fragment"' \
|
||||
'arguments: "--jsx-import-source"' \
|
||||
'arguments: "preact"' \
|
||||
'arguments: "--jsx-runtime"' \
|
||||
'arguments: "automatic"' \
|
||||
'arguments: "--jsx-side-effects"' \
|
||||
'arguments: "--react-fast-refresh"' \
|
||||
'arguments: "--emit-dce-annotations"' \
|
||||
'arguments: "--no-bundle"' \
|
||||
'arguments: "--app"' \
|
||||
'arguments: "--server-components"'; do
|
||||
expect_line "${build_output}" "${expected}"
|
||||
done
|
||||
|
||||
default_root_output="$(run_aquery "BunBuild" "//tests/bundle_test:site_build_with_meta")"
|
||||
|
||||
for expected in \
|
||||
'arguments: "--root"' \
|
||||
'arguments: "tests/bundle_test/site"'; do
|
||||
expect_line "${default_root_output}" "${expected}"
|
||||
done
|
||||
|
||||
compile_output="$(run_aquery "BunCompile" "//tests/bundle_test:compiled_cli_with_flags")"
|
||||
|
||||
for expected in \
|
||||
'arguments: "--bytecode"' \
|
||||
'arguments: "--compile-exec-argv"' \
|
||||
'arguments: "--smol"' \
|
||||
'arguments: "--inspect-wait"' \
|
||||
'arguments: "--no-compile-autoload-dotenv"' \
|
||||
'arguments: "--no-compile-autoload-bunfig"' \
|
||||
'arguments: "--compile-autoload-tsconfig"' \
|
||||
'arguments: "--compile-autoload-package-json"' \
|
||||
'arguments: "--compile-executable-path"' \
|
||||
'arguments: "tests/bundle_test/fake_cross_bun.bin"' \
|
||||
'arguments: "--windows-hide-console"' \
|
||||
'arguments: "--windows-icon"' \
|
||||
'arguments: "branding/icon.ico"' \
|
||||
'arguments: "--windows-title"' \
|
||||
'arguments: "Rules Bun Test App"' \
|
||||
'arguments: "--windows-publisher"' \
|
||||
'arguments: "rules_bun"' \
|
||||
'arguments: "--windows-version"' \
|
||||
'arguments: "1.2.3.4"' \
|
||||
'arguments: "--windows-description"' \
|
||||
'arguments: "compile flag coverage"' \
|
||||
'arguments: "--windows-copyright"' \
|
||||
'arguments: "(c) rules_bun"'; do
|
||||
expect_line "${compile_output}" "${expected}"
|
||||
done
|
||||
@@ -4,6 +4,6 @@ set -euo pipefail
|
||||
rule_file="$1"
|
||||
|
||||
grep -Fq 'def _output_name(target_name, entry):' "${rule_file}"
|
||||
grep -Fq 'return "{}__{}.js".format(target_name, stem)' "${rule_file}"
|
||||
grep -Fq 'inputs = depset(' "${rule_file}"
|
||||
grep -Fq 'direct = [entry] + ctx.files.data' "${rule_file}"
|
||||
grep -Fq 'stem = entry.short_path.rsplit(".", 1)[0]' "${rule_file}"
|
||||
grep -Fq 'validate_hermetic_install_mode(ctx.attr, "bun_bundle")' "${rule_file}"
|
||||
grep -Fq 'declare_staged_bun_build_action(' "${rule_file}"
|
||||
|
||||
@@ -4,10 +4,10 @@ set -euo pipefail
|
||||
bundle="$1"
|
||||
minified="$2"
|
||||
|
||||
bundle_size="$(wc -c < "${bundle}")"
|
||||
minified_size="$(wc -c < "${minified}")"
|
||||
bundle_size="$(wc -c <"${bundle}")"
|
||||
minified_size="$(wc -c <"${minified}")"
|
||||
|
||||
if (( minified_size >= bundle_size )); then
|
||||
if ((minified_size >= bundle_size)); then
|
||||
echo "Expected minified bundle (${minified_size}) to be smaller than regular bundle (${bundle_size})" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
14
tests/bundle_test/verify_site_build.sh
Executable file
14
tests/bundle_test/verify_site_build.sh
Executable file
@@ -0,0 +1,14 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
output_dir="$1"
|
||||
|
||||
if [[ ! -d ${output_dir} ]]; then
|
||||
echo "Expected output directory: ${output_dir}" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if ! find -L "${output_dir}" -type f \( -name '*.js' -o -name '*.css' \) | grep -q .; then
|
||||
echo "Expected Bun build assets in ${output_dir}" >&2
|
||||
exit 1
|
||||
fi
|
||||
29
tests/bundle_test/verify_site_build_meta.sh
Executable file
29
tests/bundle_test/verify_site_build_meta.sh
Executable file
@@ -0,0 +1,29 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
output_dir=""
|
||||
meta_json=""
|
||||
meta_md=""
|
||||
|
||||
for path in "$@"; do
|
||||
case "${path}" in
|
||||
*.meta.json) meta_json="${path}" ;;
|
||||
*.meta.md) meta_md="${path}" ;;
|
||||
*) output_dir="${path}" ;;
|
||||
esac
|
||||
done
|
||||
|
||||
if [[ ! -d ${output_dir} ]]; then
|
||||
echo "Expected directory output, got: ${output_dir}" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [[ ! -f ${meta_json} ]]; then
|
||||
echo "Expected JSON metafile output" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [[ ! -f ${meta_md} ]]; then
|
||||
echo "Expected markdown metafile output" >&2
|
||||
exit 1
|
||||
fi
|
||||
64
tests/bundle_test/verify_sourcemap_shape.sh
Executable file
64
tests/bundle_test/verify_sourcemap_shape.sh
Executable file
@@ -0,0 +1,64 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
script_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd -P)"
|
||||
# shellcheck source=../nested_bazel_test.sh
|
||||
source "${script_dir}/../nested_bazel_test.sh"
|
||||
setup_nested_bazel_cmd
|
||||
|
||||
find_workspace_root() {
|
||||
local candidate
|
||||
local module_path
|
||||
local search_dir
|
||||
|
||||
for candidate in \
|
||||
"${TEST_SRCDIR:-}/${TEST_WORKSPACE:-}" \
|
||||
"${TEST_SRCDIR:-}/_main"; do
|
||||
if [[ -n ${candidate} && -f "${candidate}/MODULE.bazel" ]]; then
|
||||
printf '%s\n' "${candidate}"
|
||||
return 0
|
||||
fi
|
||||
done
|
||||
|
||||
if [[ -n ${TEST_SRCDIR:-} ]]; then
|
||||
module_path="$(find "${TEST_SRCDIR}" -maxdepth 3 -name MODULE.bazel -print -quit 2>/dev/null || true)"
|
||||
if [[ -n ${module_path} ]]; then
|
||||
dirname "${module_path}"
|
||||
return 0
|
||||
fi
|
||||
fi
|
||||
|
||||
search_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd -P)"
|
||||
candidate="$(cd "${search_dir}/../.." && pwd -P)"
|
||||
if [[ -f "${candidate}/MODULE.bazel" ]]; then
|
||||
printf '%s\n' "${candidate}"
|
||||
return 0
|
||||
fi
|
||||
|
||||
echo "Unable to locate rules_bun workspace root" >&2
|
||||
exit 1
|
||||
}
|
||||
|
||||
rules_bun_root="$(find_workspace_root)"
|
||||
|
||||
cleanup() {
|
||||
local status="$1"
|
||||
trap - EXIT
|
||||
shutdown_nested_bazel_workspace "${rules_bun_root}"
|
||||
exit "${status}"
|
||||
}
|
||||
trap 'cleanup $?' EXIT
|
||||
|
||||
bundle_output="$(
|
||||
cd "${rules_bun_root}" &&
|
||||
"${bazel_cmd[@]}" aquery 'mnemonic("BunBundle", //tests/bundle_test/sourcemap_case:sourcemap_bundle)' --output=textproto
|
||||
)"
|
||||
|
||||
count="$(grep -Fc 'arguments: "--sourcemap"' <<<"${bundle_output}")"
|
||||
if [[ ${count} != "1" ]]; then
|
||||
echo "Expected bun_bundle(sourcemap = True) to emit exactly one --sourcemap flag, got ${count}" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
grep -Fq 'arguments: "--outfile"' <<<"${bundle_output}"
|
||||
grep -Fq 'arguments: "tests/bundle_test/sourcemap_case/entry.ts"' <<<"${bundle_output}"
|
||||
@@ -2,7 +2,34 @@ load("@rules_shell//shell:sh_test.bzl", "sh_test")
|
||||
|
||||
sh_test(
|
||||
name = "phase8_ci_matrix_shape_test",
|
||||
size = "small",
|
||||
srcs = ["phase8_ci_matrix_shape_test.sh"],
|
||||
args = ["$(location //.github/workflows:ci.yml)"],
|
||||
data = ["//.github/workflows:ci.yml"],
|
||||
)
|
||||
|
||||
sh_test(
|
||||
name = "phase8_ci_targets_test",
|
||||
size = "small",
|
||||
srcs = ["phase8_ci_targets_test.sh"],
|
||||
args = ["$(location :phase8_ci_targets.sh)"],
|
||||
data = [":phase8_ci_targets.sh"],
|
||||
)
|
||||
|
||||
sh_test(
|
||||
name = "native_wrapper_shape_test",
|
||||
size = "small",
|
||||
srcs = ["verify_native_wrapper_shape.sh"],
|
||||
args = [
|
||||
"$(location //tests/binary_test:configured_launcher_bin)",
|
||||
"$(location //tests/script_test:workspace_flagged_script)",
|
||||
"$(location //tests/js_compat_test:compat_devserver)",
|
||||
"$(location //tests/bun_test_test:configured_suite)",
|
||||
],
|
||||
data = [
|
||||
"//tests/binary_test:configured_launcher_bin",
|
||||
"//tests/bun_test_test:configured_suite",
|
||||
"//tests/js_compat_test:compat_devserver",
|
||||
"//tests/script_test:workspace_flagged_script",
|
||||
],
|
||||
)
|
||||
|
||||
@@ -22,6 +22,17 @@ check_pattern 'os:[[:space:]]+ubuntu-latest' "missing ubuntu matrix entry"
|
||||
check_pattern 'phase8_target:[[:space:]]+linux-x64' "missing linux-x64 matrix target"
|
||||
check_pattern 'os:[[:space:]]+macos-14' "missing macos matrix entry"
|
||||
check_pattern 'phase8_target:[[:space:]]+darwin-arm64' "missing darwin-arm64 matrix target"
|
||||
check_pattern 'os:[[:space:]]+windows-latest' "missing windows matrix entry"
|
||||
check_pattern 'phase8_target:[[:space:]]+windows' "missing windows matrix target"
|
||||
|
||||
has_windows_os=0
|
||||
has_windows_target=0
|
||||
if grep -Eq 'os:[[:space:]]+windows-latest' "${workflow_file}"; then
|
||||
has_windows_os=1
|
||||
fi
|
||||
if grep -Eq 'phase8_target:[[:space:]]+windows' "${workflow_file}"; then
|
||||
has_windows_target=1
|
||||
fi
|
||||
if [[ ${has_windows_os} -ne ${has_windows_target} ]]; then
|
||||
echo "Error: windows matrix entry and windows phase8 target must be added or removed together" >&2
|
||||
exit 1
|
||||
fi
|
||||
echo "CI matrix shape checks passed"
|
||||
|
||||
27
tests/ci_test/phase8_ci_targets.sh
Executable file
27
tests/ci_test/phase8_ci_targets.sh
Executable file
@@ -0,0 +1,27 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
phase8_target="${1:-}"
|
||||
if [[ -z ${phase8_target} ]]; then
|
||||
echo "Error: phase8 target required as first argument" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
case "${phase8_target}" in
|
||||
linux-x64 | darwin-arm64)
|
||||
printf '%s\n' "//tests/..."
|
||||
;;
|
||||
windows)
|
||||
printf '%s\n' \
|
||||
"//tests/binary_test/..." \
|
||||
"//tests/bun_test_test/..." \
|
||||
"//tests/ci_test/..." \
|
||||
"//tests/js_compat_test/..." \
|
||||
"//tests/script_test/..." \
|
||||
"//tests/toolchain_test/..."
|
||||
;;
|
||||
*)
|
||||
echo "Error: unsupported phase8 target: ${phase8_target}" >&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
44
tests/ci_test/phase8_ci_targets_test.sh
Executable file
44
tests/ci_test/phase8_ci_targets_test.sh
Executable file
@@ -0,0 +1,44 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
resolver="${1:-}"
|
||||
if [[ -z ${resolver} ]]; then
|
||||
echo "Error: resolver path required as first argument" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
linux_targets="$("${resolver}" linux-x64)"
|
||||
if [[ ${linux_targets} != "//tests/..." ]]; then
|
||||
echo "Error: linux-x64 should resolve to //tests/..." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
darwin_targets="$("${resolver}" darwin-arm64)"
|
||||
if [[ ${darwin_targets} != "//tests/..." ]]; then
|
||||
echo "Error: darwin-arm64 should resolve to //tests/..." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
windows_targets="$("${resolver}" windows)"
|
||||
expected_windows_targets="$(
|
||||
cat <<'EOF'
|
||||
//tests/binary_test/...
|
||||
//tests/bun_test_test/...
|
||||
//tests/ci_test/...
|
||||
//tests/js_compat_test/...
|
||||
//tests/script_test/...
|
||||
//tests/toolchain_test/...
|
||||
EOF
|
||||
)"
|
||||
if [[ ${windows_targets} != "${expected_windows_targets}" ]]; then
|
||||
echo "Error: unexpected windows targets" >&2
|
||||
printf 'Expected:\n%s\nActual:\n%s\n' "${expected_windows_targets}" "${windows_targets}" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if "${resolver}" unsupported >/dev/null 2>&1; then
|
||||
echo "Error: unsupported phase8 target should fail" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "Phase 8 CI targets resolve correctly"
|
||||
17
tests/ci_test/verify_native_wrapper_shape.sh
Executable file
17
tests/ci_test/verify_native_wrapper_shape.sh
Executable file
@@ -0,0 +1,17 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
python3 - "$@" <<'PY'
|
||||
import pathlib
|
||||
import sys
|
||||
|
||||
windows = sys.platform.startswith("win")
|
||||
|
||||
for launcher in sys.argv[1:]:
|
||||
suffix = pathlib.Path(launcher).suffix.lower()
|
||||
if windows:
|
||||
if suffix != ".cmd":
|
||||
raise SystemExit(f"expected .cmd launcher on Windows: {launcher}")
|
||||
elif suffix == ".sh":
|
||||
raise SystemExit(f"unexpected .sh launcher executable: {launcher}")
|
||||
PY
|
||||
@@ -2,7 +2,16 @@ load("@rules_shell//shell:sh_test.bzl", "sh_test")
|
||||
|
||||
sh_test(
|
||||
name = "bun_install_extension_shape_test",
|
||||
size = "small",
|
||||
srcs = ["extension_shape_test.sh"],
|
||||
args = ["$(location //bun:extensions.bzl)"],
|
||||
data = ["//bun:extensions.bzl"],
|
||||
)
|
||||
|
||||
sh_test(
|
||||
name = "npm_translate_lock_extension_shape_test",
|
||||
size = "small",
|
||||
srcs = ["npm_extension_shape_test.sh"],
|
||||
args = ["$(location //npm:extensions.bzl)"],
|
||||
data = ["//npm:extensions.bzl"],
|
||||
)
|
||||
|
||||
@@ -10,3 +10,4 @@ grep -Eq '"package_json":[[:space:]]*attr\.label\(mandatory[[:space:]]*=[[:space
|
||||
grep -Eq '"bun_lockfile":[[:space:]]*attr\.label\(mandatory[[:space:]]*=[[:space:]]*True\)' "${extension_file}"
|
||||
grep -Eq '"install_inputs":[[:space:]]*attr\.label_list\(allow_files[[:space:]]*=[[:space:]]*True\)' "${extension_file}"
|
||||
grep -Eq '"isolated_home":[[:space:]]*attr\.bool\(default[[:space:]]*=[[:space:]]*True\)' "${extension_file}"
|
||||
grep -Eq '"ignore_scripts":[[:space:]]*attr\.bool\(default[[:space:]]*=[[:space:]]*True\)' "${extension_file}"
|
||||
|
||||
10
tests/install_extension_test/npm_extension_shape_test.sh
Executable file
10
tests/install_extension_test/npm_extension_shape_test.sh
Executable file
@@ -0,0 +1,10 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
extension_file="$1"
|
||||
|
||||
grep -Eq 'npm_translate_lock[[:space:]]*=[[:space:]]*module_extension\(' "${extension_file}"
|
||||
grep -Eq 'tag_classes[[:space:]]*=[[:space:]]*\{"translate":[[:space:]]*_translate\}' "${extension_file}"
|
||||
grep -Eq '"name":[[:space:]]*attr\.string\(mandatory[[:space:]]*=[[:space:]]*True\)' "${extension_file}"
|
||||
grep -Eq '"package_json":[[:space:]]*attr\.label\(mandatory[[:space:]]*=[[:space:]]*True\)' "${extension_file}"
|
||||
grep -Eq '"lockfile":[[:space:]]*attr\.label\(mandatory[[:space:]]*=[[:space:]]*True\)' "${extension_file}"
|
||||
@@ -32,14 +32,24 @@ config_setting(
|
||||
],
|
||||
)
|
||||
|
||||
config_setting(
|
||||
name = "windows_x86_64",
|
||||
constraint_values = [
|
||||
"@platforms//os:windows",
|
||||
"@platforms//cpu:x86_64",
|
||||
],
|
||||
)
|
||||
|
||||
sh_test(
|
||||
name = "bun_install_clean_install_test",
|
||||
size = "small",
|
||||
srcs = ["clean_install.sh"],
|
||||
args = select({
|
||||
":linux_x86_64": ["$(location @bun_linux_x64//:bun)"],
|
||||
":linux_aarch64": ["$(location @bun_linux_aarch64//:bun)"],
|
||||
":darwin_x86_64": ["$(location @bun_darwin_x64//:bun)"],
|
||||
":darwin_aarch64": ["$(location @bun_darwin_aarch64//:bun)"],
|
||||
":windows_x86_64": ["$(location @bun_windows_x64//:bun)"],
|
||||
"//conditions:default": ["$(location @bun_linux_x64//:bun)"],
|
||||
}),
|
||||
data = select({
|
||||
@@ -47,18 +57,21 @@ sh_test(
|
||||
":linux_aarch64": ["@bun_linux_aarch64//:bun"],
|
||||
":darwin_x86_64": ["@bun_darwin_x64//:bun"],
|
||||
":darwin_aarch64": ["@bun_darwin_aarch64//:bun"],
|
||||
":windows_x86_64": ["@bun_windows_x64//:bun"],
|
||||
"//conditions:default": ["@bun_linux_x64//:bun"],
|
||||
}),
|
||||
)
|
||||
|
||||
sh_test(
|
||||
name = "bun_install_stale_lockfile_test",
|
||||
size = "small",
|
||||
srcs = ["stale_lockfile.sh"],
|
||||
args = select({
|
||||
":linux_x86_64": ["$(location @bun_linux_x64//:bun)"],
|
||||
":linux_aarch64": ["$(location @bun_linux_aarch64//:bun)"],
|
||||
":darwin_x86_64": ["$(location @bun_darwin_x64//:bun)"],
|
||||
":darwin_aarch64": ["$(location @bun_darwin_aarch64//:bun)"],
|
||||
":windows_x86_64": ["$(location @bun_windows_x64//:bun)"],
|
||||
"//conditions:default": ["$(location @bun_linux_x64//:bun)"],
|
||||
}),
|
||||
data = select({
|
||||
@@ -66,12 +79,14 @@ sh_test(
|
||||
":linux_aarch64": ["@bun_linux_aarch64//:bun"],
|
||||
":darwin_x86_64": ["@bun_darwin_x64//:bun"],
|
||||
":darwin_aarch64": ["@bun_darwin_aarch64//:bun"],
|
||||
":windows_x86_64": ["@bun_windows_x64//:bun"],
|
||||
"//conditions:default": ["@bun_linux_x64//:bun"],
|
||||
}),
|
||||
)
|
||||
|
||||
sh_test(
|
||||
name = "bun_install_determinism_test",
|
||||
size = "small",
|
||||
srcs = ["determinism.sh"],
|
||||
args = ["$(location //internal:bun_install.bzl)"],
|
||||
data = ["//internal:bun_install.bzl"],
|
||||
@@ -79,6 +94,7 @@ sh_test(
|
||||
|
||||
sh_test(
|
||||
name = "bun_install_environment_shape_test",
|
||||
size = "small",
|
||||
srcs = ["environment_shape.sh"],
|
||||
args = ["$(location //internal:bun_install.bzl)"],
|
||||
data = ["//internal:bun_install.bzl"],
|
||||
@@ -86,12 +102,14 @@ sh_test(
|
||||
|
||||
sh_test(
|
||||
name = "bun_install_workspaces_test",
|
||||
size = "small",
|
||||
srcs = ["workspaces.sh"],
|
||||
args = select({
|
||||
":linux_x86_64": ["$(location @bun_linux_x64//:bun)"],
|
||||
":linux_aarch64": ["$(location @bun_linux_aarch64//:bun)"],
|
||||
":darwin_x86_64": ["$(location @bun_darwin_x64//:bun)"],
|
||||
":darwin_aarch64": ["$(location @bun_darwin_aarch64//:bun)"],
|
||||
":windows_x86_64": ["$(location @bun_windows_x64//:bun)"],
|
||||
"//conditions:default": ["$(location @bun_linux_x64//:bun)"],
|
||||
}),
|
||||
data = select({
|
||||
@@ -99,6 +117,124 @@ sh_test(
|
||||
":linux_aarch64": ["@bun_linux_aarch64//:bun"],
|
||||
":darwin_x86_64": ["@bun_darwin_x64//:bun"],
|
||||
":darwin_aarch64": ["@bun_darwin_aarch64//:bun"],
|
||||
":windows_x86_64": ["@bun_windows_x64//:bun"],
|
||||
"//conditions:default": ["@bun_linux_x64//:bun"],
|
||||
}),
|
||||
)
|
||||
|
||||
sh_test(
|
||||
name = "bun_install_workspaces_catalog_test",
|
||||
size = "small",
|
||||
srcs = ["workspaces_catalog.sh"],
|
||||
args = select({
|
||||
":linux_x86_64": ["$(location @bun_linux_x64//:bun)"],
|
||||
":linux_aarch64": ["$(location @bun_linux_aarch64//:bun)"],
|
||||
":darwin_x86_64": ["$(location @bun_darwin_x64//:bun)"],
|
||||
":darwin_aarch64": ["$(location @bun_darwin_aarch64//:bun)"],
|
||||
":windows_x86_64": ["$(location @bun_windows_x64//:bun)"],
|
||||
"//conditions:default": ["$(location @bun_linux_x64//:bun)"],
|
||||
}),
|
||||
data = select({
|
||||
":linux_x86_64": ["@bun_linux_x64//:bun"],
|
||||
":linux_aarch64": ["@bun_linux_aarch64//:bun"],
|
||||
":darwin_x86_64": ["@bun_darwin_x64//:bun"],
|
||||
":darwin_aarch64": ["@bun_darwin_aarch64//:bun"],
|
||||
":windows_x86_64": ["@bun_windows_x64//:bun"],
|
||||
"//conditions:default": ["@bun_linux_x64//:bun"],
|
||||
}),
|
||||
)
|
||||
|
||||
sh_test(
|
||||
name = "bun_install_workspace_parity_test",
|
||||
size = "large",
|
||||
srcs = ["workspace_parity.sh"],
|
||||
tags = ["exclusive"],
|
||||
args = select({
|
||||
":linux_x86_64": ["$(location @bun_linux_x64//:bun)"],
|
||||
":linux_aarch64": ["$(location @bun_linux_aarch64//:bun)"],
|
||||
":darwin_x86_64": ["$(location @bun_darwin_x64//:bun)"],
|
||||
":darwin_aarch64": ["$(location @bun_darwin_aarch64//:bun)"],
|
||||
":windows_x86_64": ["$(location @bun_windows_x64//:bun)"],
|
||||
"//conditions:default": ["$(location @bun_linux_x64//:bun)"],
|
||||
}),
|
||||
data = select({
|
||||
":linux_x86_64": ["@bun_linux_x64//:bun"],
|
||||
":linux_aarch64": ["@bun_linux_aarch64//:bun"],
|
||||
":darwin_x86_64": ["@bun_darwin_x64//:bun"],
|
||||
":darwin_aarch64": ["@bun_darwin_aarch64//:bun"],
|
||||
":windows_x86_64": ["@bun_windows_x64//:bun"],
|
||||
"//conditions:default": ["@bun_linux_x64//:bun"],
|
||||
}) + [
|
||||
"//:repo_runtime_files",
|
||||
"//bun:repo_runtime_files",
|
||||
"//internal:repo_runtime_files",
|
||||
"//tests:nested_bazel_test.sh",
|
||||
],
|
||||
env_inherit = ["PATH"],
|
||||
)
|
||||
|
||||
sh_test(
|
||||
name = "bun_install_install_flags_shape_test",
|
||||
size = "small",
|
||||
srcs = ["install_flags_shape.sh"],
|
||||
args = ["$(location //internal:bun_install.bzl)"],
|
||||
data = ["//internal:bun_install.bzl"],
|
||||
)
|
||||
|
||||
sh_test(
|
||||
name = "bun_install_repeatability_test",
|
||||
size = "small",
|
||||
srcs = ["repeatability.sh"],
|
||||
tags = ["exclusive"],
|
||||
args = select({
|
||||
":linux_x86_64": ["$(location @bun_linux_x64//:bun)"],
|
||||
":linux_aarch64": ["$(location @bun_linux_aarch64//:bun)"],
|
||||
":darwin_x86_64": ["$(location @bun_darwin_x64//:bun)"],
|
||||
":darwin_aarch64": ["$(location @bun_darwin_aarch64//:bun)"],
|
||||
":windows_x86_64": ["$(location @bun_windows_x64//:bun)"],
|
||||
"//conditions:default": ["$(location @bun_linux_x64//:bun)"],
|
||||
}),
|
||||
data = select({
|
||||
":linux_x86_64": ["@bun_linux_x64//:bun"],
|
||||
":linux_aarch64": ["@bun_linux_aarch64//:bun"],
|
||||
":darwin_x86_64": ["@bun_darwin_x64//:bun"],
|
||||
":darwin_aarch64": ["@bun_darwin_aarch64//:bun"],
|
||||
":windows_x86_64": ["@bun_windows_x64//:bun"],
|
||||
"//conditions:default": ["@bun_linux_x64//:bun"],
|
||||
}) + [
|
||||
"//:repo_runtime_files",
|
||||
"//bun:repo_runtime_files",
|
||||
"//internal:repo_runtime_files",
|
||||
"//tests:nested_bazel_test.sh",
|
||||
],
|
||||
env_inherit = ["PATH"],
|
||||
)
|
||||
|
||||
sh_test(
|
||||
name = "bun_install_lifecycle_scripts_test",
|
||||
size = "small",
|
||||
srcs = ["lifecycle_scripts.sh"],
|
||||
tags = ["exclusive"],
|
||||
args = select({
|
||||
":linux_x86_64": ["$(location @bun_linux_x64//:bun)"],
|
||||
":linux_aarch64": ["$(location @bun_linux_aarch64//:bun)"],
|
||||
":darwin_x86_64": ["$(location @bun_darwin_x64//:bun)"],
|
||||
":darwin_aarch64": ["$(location @bun_darwin_aarch64//:bun)"],
|
||||
":windows_x86_64": ["$(location @bun_windows_x64//:bun)"],
|
||||
"//conditions:default": ["$(location @bun_linux_x64//:bun)"],
|
||||
}),
|
||||
data = select({
|
||||
":linux_x86_64": ["@bun_linux_x64//:bun"],
|
||||
":linux_aarch64": ["@bun_linux_aarch64//:bun"],
|
||||
":darwin_x86_64": ["@bun_darwin_x64//:bun"],
|
||||
":darwin_aarch64": ["@bun_darwin_aarch64//:bun"],
|
||||
":windows_x86_64": ["@bun_windows_x64//:bun"],
|
||||
"//conditions:default": ["@bun_linux_x64//:bun"],
|
||||
}) + [
|
||||
"//:repo_runtime_files",
|
||||
"//bun:repo_runtime_files",
|
||||
"//internal:repo_runtime_files",
|
||||
"//tests:nested_bazel_test.sh",
|
||||
],
|
||||
env_inherit = ["PATH"],
|
||||
)
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user