7 Commits

Author SHA1 Message Date
eric
4f8e27cd74 chore(release): v0.5.0
Some checks failed
CI / test (ubuntu-latest, linux-x64) (push) Failing after 34s
Docs Pages / deploy (push) Failing after 44s
Copilot Setup Steps / copilot-setup-steps (push) Failing after 25s
CI / test (macos-14, darwin-arm64) (push) Has been cancelled
CI / test (windows-latest, windows) (push) Has been cancelled
2026-03-15 09:34:22 +01:00
eric
31c42a8638 fix: tests 2026-03-15 09:34:07 +01:00
eric
769b95d05b chore(release): v0.4.0
Some checks failed
CI / test (ubuntu-latest, linux-x64) (push) Failing after 31s
Copilot Setup Steps / copilot-setup-steps (push) Failing after 36s
CI / test (macos-14, darwin-arm64) (push) Has been cancelled
CI / test (windows-latest, windows) (push) Has been cancelled
2026-03-15 01:20:57 +01:00
eric
2a25cfb91a fix: include .env files 2026-03-15 01:20:45 +01:00
eric
2a9bd09aa4 fix: include .env files 2026-03-15 01:13:52 +01:00
eric
4b7ebb1536 fix: include .env files 2026-03-15 01:07:36 +01:00
73d4625420 Merge pull request 'feature/add-build-compile-rules' (#4) from feature/add-build-compile-rules into main
Some checks failed
CI / test (ubuntu-latest, linux-x64) (push) Failing after 37s
Docs Pages / deploy (push) Failing after 43s
CI / test (macos-14, darwin-arm64) (push) Has been cancelled
CI / test (windows-latest, windows) (push) Has been cancelled
Reviewed-on: #4
2026-03-15 00:01:19 +00:00
14 changed files with 141 additions and 17 deletions

2
.gitignore vendored
View File

@@ -22,4 +22,6 @@ node_modules/
.env .env
!tests/.env !tests/.env
!tests/**/.env
!examples/.env !examples/.env
!examples/**/.env

3
.gitleaksignore Normal file
View 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

View File

@@ -1,6 +1,6 @@
module( module(
name = "rules_bun", name = "rules_bun",
version = "0.2.2", version = "0.5.0",
) )
# Core ruleset dependencies. # Core ruleset dependencies.

4
MODULE.bazel.lock generated
View File

@@ -193,7 +193,7 @@
"//bun:extensions.bzl%bun": { "//bun:extensions.bzl%bun": {
"general": { "general": {
"bzlTransitiveDigest": "lzOUyaXDbkH922ruNkkwEF2cnI4m0XpzrOti0qypwtA=", "bzlTransitiveDigest": "lzOUyaXDbkH922ruNkkwEF2cnI4m0XpzrOti0qypwtA=",
"usagesDigest": "/0BcCMA6AOzLhQaRK6DquxrCfpPHJUjSUaFz4zmQrsM=", "usagesDigest": "iOEuN6Lhr5Bejh9GRDT3yaCI7umBsNZo5CLQSzt+tNQ=",
"recordedInputs": [ "recordedInputs": [
"REPO_MAPPING:,bazel_tools bazel_tools" "REPO_MAPPING:,bazel_tools bazel_tools"
], ],
@@ -284,7 +284,7 @@
"//bun:extensions.bzl%bun_install": { "//bun:extensions.bzl%bun_install": {
"general": { "general": {
"bzlTransitiveDigest": "lzOUyaXDbkH922ruNkkwEF2cnI4m0XpzrOti0qypwtA=", "bzlTransitiveDigest": "lzOUyaXDbkH922ruNkkwEF2cnI4m0XpzrOti0qypwtA=",
"usagesDigest": "f9pNm3AOxJDZmpHhL2vrrCo23IW33im/l/VYCTW2BWM=", "usagesDigest": "eD/dECSVWIFS/qMgEXZ6501CimKmsHt7yTIFPX4XdLo=",
"recordedInputs": [ "recordedInputs": [
"REPO_MAPPING:,bazel_tools bazel_tools" "REPO_MAPPING:,bazel_tools bazel_tools"
], ],

View File

@@ -60,7 +60,7 @@ Release announcements should provide a copy-pasteable module snippet in the
standard ruleset form: standard ruleset form:
```starlark ```starlark
bazel_dep(name = "rules_bun", version = "0.2.2") bazel_dep(name = "rules_bun", version = "0.5.0")
``` ```
Then add the Bun repositories and register the toolchains in `MODULE.bazel`: Then add the Bun repositories and register the toolchains in `MODULE.bazel`:
@@ -225,7 +225,9 @@ bun_compile(
`bun_build` exposes a directory output so Bun can emit HTML, CSS, assets, and `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 split chunks. `bun_compile` produces a single executable artifact and supports
explicit cross-compilation via `compile_executable`. 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 ### `bun_dev` for local development

View File

@@ -1,3 +1,3 @@
0.2.2 0.5.0
stable stable
0 0

View File

@@ -102,7 +102,7 @@ may be requested with `metafile` and `metafile_md`.
| <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-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-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-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. | String | optional | `""` | | <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-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-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_build-target"></a>target | Bun build target environment. | String | optional | `"browser"` |
@@ -481,4 +481,3 @@ js_test(<a href="#js_test-name">name</a>, <a href="#js_test-entry_point">entry_p
| <a id="js_test-srcs"></a>srcs | <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 | | <a id="js_test-kwargs"></a>kwargs | <p align="center"> - </p> | none |

View File

@@ -75,6 +75,11 @@
' "$README" > "$TMP" && mv "$TMP" "$README" ' "$README" > "$TMP" && mv "$TMP" "$README"
''; '';
} }
{
run.script = ''
bazel cquery //tests/... >/dev/null
'';
}
]; ];
postVersion = '' postVersion = ''

View File

@@ -3,6 +3,26 @@
load("//internal:bun_command.bzl", "add_flag", "add_flag_value", "add_flag_values", "add_install_mode", "add_raw_flags") 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") load("//internal:js_library.bzl", "collect_js_sources")
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): def bun_build_transitive_inputs(ctx):
transitive_inputs = [] transitive_inputs = []
if getattr(ctx.attr, "node_modules", None): if getattr(ctx.attr, "node_modules", None):
@@ -11,13 +31,17 @@ def bun_build_transitive_inputs(ctx):
transitive_inputs.append(collect_js_sources(dep)) transitive_inputs.append(collect_js_sources(dep))
return transitive_inputs return transitive_inputs
def add_bun_build_common_flags(args, attr, metafile = None, metafile_md = None): 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_install_mode(args, getattr(attr, "install_mode", "disable"))
add_flag_value(args, "--target", getattr(attr, "target", None)) add_flag_value(args, "--target", getattr(attr, "target", None))
add_flag_value(args, "--format", getattr(attr, "format", None)) add_flag_value(args, "--format", getattr(attr, "format", None))
add_flag(args, "--production", getattr(attr, "production", False)) add_flag(args, "--production", getattr(attr, "production", False))
add_flag(args, "--splitting", getattr(attr, "splitting", False)) add_flag(args, "--splitting", getattr(attr, "splitting", False))
add_flag_value(args, "--root", getattr(attr, "root", None)) add_flag_value(args, "--root", build_root)
sourcemap = getattr(attr, "sourcemap", None) sourcemap = getattr(attr, "sourcemap", None)
if sourcemap == True: if sourcemap == True:

View File

@@ -1,18 +1,34 @@
"""Rules for Bun build outputs and standalone executables.""" """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") load("//internal:bun_build_support.bzl", "add_bun_build_common_flags", "add_bun_compile_flags", "bun_build_transitive_inputs", "infer_entry_point_root")
def _bun_build_impl(ctx): def _bun_build_impl(ctx):
toolchain = ctx.toolchains["//bun:toolchain_type"] toolchain = ctx.toolchains["//bun:toolchain_type"]
bun_bin = toolchain.bun.bun_bin bun_bin = toolchain.bun.bun_bin
output_dir = ctx.actions.declare_directory(ctx.label.name) output_dir = ctx.actions.declare_directory(ctx.label.name)
metafile = ctx.actions.declare_file(ctx.label.name + ".meta.json") if ctx.attr.metafile else None metafile = None
metafile_md = ctx.actions.declare_file(ctx.label.name + ".meta.md") if ctx.attr.metafile_md else 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(ctx.files.entry_points)
transitive_inputs = bun_build_transitive_inputs(ctx)
build_inputs = depset(
direct = ctx.files.entry_points + ctx.files.data,
transitive = transitive_inputs,
)
input_manifest = ctx.actions.declare_file(ctx.label.name + ".inputs")
runner = ctx.actions.declare_file(ctx.label.name + "_runner.sh")
args = ctx.actions.args() args = ctx.actions.args()
args.add(input_manifest.path)
args.add(bun_bin.path)
args.add("--bun") args.add("--bun")
args.add("build") args.add("build")
add_bun_build_common_flags(args, ctx.attr, metafile = metafile, metafile_md = metafile_md) add_bun_build_common_flags(args, ctx.attr, metafile = metafile, metafile_md = metafile_md, root = build_root)
args.add("--outdir") args.add("--outdir")
args.add(output_dir.path) args.add(output_dir.path)
args.add_all(ctx.files.entry_points) args.add_all(ctx.files.entry_points)
@@ -23,12 +39,74 @@ def _bun_build_impl(ctx):
if metafile_md: if metafile_md:
outputs.append(metafile_md) outputs.append(metafile_md)
ctx.actions.write(
output = input_manifest,
content = "".join([file.path + "\n" for file in build_inputs.to_list()]),
)
ctx.actions.write(
output = runner,
is_executable = True,
content = """#!/usr/bin/env bash
set -euo pipefail
manifest="$1"
execroot="$(pwd -P)"
bun_bin="$2"
if [[ "${bun_bin}" != /* ]]; then
bun_bin="${execroot}/${bun_bin}"
fi
shift 2
stage_dir="$(mktemp -d "${TMPDIR:-/tmp}/rules_bun_build.XXXXXX")"
cleanup() {
rm -rf "${stage_dir}"
}
trap cleanup EXIT
while IFS= read -r relpath; do
if [[ -z "${relpath}" ]]; then
continue
fi
src="${execroot}/${relpath}"
dest="${stage_dir}/${relpath}"
mkdir -p "$(dirname "${dest}")"
cp -L "${src}" "${dest}"
done < "${manifest}"
forwarded_args=()
while (($#)); do
case "$1" in
--outdir)
forwarded_args+=("$1" "${execroot}/$2")
shift 2
;;
--metafile=*)
forwarded_args+=("--metafile=${execroot}/${1#--metafile=}")
shift
;;
--metafile-md=*)
forwarded_args+=("--metafile-md=${execroot}/${1#--metafile-md=}")
shift
;;
*)
forwarded_args+=("$1")
shift
;;
esac
done
cd "${stage_dir}"
exec "${bun_bin}" "${forwarded_args[@]}"
""",
)
ctx.actions.run( ctx.actions.run(
executable = bun_bin, executable = runner,
arguments = [args], arguments = [args],
inputs = depset( inputs = depset(
direct = ctx.files.entry_points + ctx.files.data, direct = [input_manifest, bun_bin],
transitive = bun_build_transitive_inputs(ctx), transitive = [build_inputs],
), ),
outputs = outputs, outputs = outputs,
mnemonic = "BunBuild", mnemonic = "BunBuild",

1
tests/binary_test/.env Normal file
View File

@@ -0,0 +1 @@
BUN_ENV_CWD_TEST=from-dotenv

View File

@@ -0,0 +1 @@
BUN_ENV_PARENT_TEST=from-parent-dotenv

View File

@@ -132,6 +132,14 @@ for expected in \
expect_line "${build_output}" "${expected}" expect_line "${build_output}" "${expected}"
done 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")" compile_output="$(run_aquery "BunCompile" "//tests/bundle_test:compiled_cli_with_flags")"
for expected in \ for expected in \

1
tests/script_test/.env Normal file
View File

@@ -0,0 +1 @@
BUN_SCRIPT_ENV_TEST=from-dotenv