2 Commits

Author SHA1 Message Date
eric
6bd440d3d7 fix: tests 2026-03-04 08:44:11 +01:00
copilot-swe-agent[bot]
8218858498 feat: add phase 6 js_library and ts_library bootstrap
Co-authored-by: Eriyc <50216491+Eriyc@users.noreply.github.com>
2026-03-04 07:31:19 +00:00
19 changed files with 262 additions and 78 deletions

8
.gitlint Normal file
View File

@@ -0,0 +1,8 @@
[general]
ignore=B6
[title-max-length]
line-length=72
[title-match-regex]
regex=^(feat|fix|chore|docs|refactor|test|ci)(\(.+\))?: .+

View File

@@ -34,3 +34,9 @@ Phase 5 bootstrap is in place:
- Bundle rule `bun_bundle` (`/internal/bun_bundle.bzl`) - Bundle rule `bun_bundle` (`/internal/bun_bundle.bzl`)
- Public export via `bun/defs.bzl` - Public export via `bun/defs.bzl`
- Focused output/minify tests (`//tests/bundle_test:all`) - Focused output/minify tests (`//tests/bundle_test:all`)
Phase 6 bootstrap is in place:
- Source grouping rules `js_library` / `ts_library` (`/internal/js_library.bzl`)
- Transitive `deps` propagation wired into `bun_bundle` and `bun_test`
- Focused dependency-propagation tests (`//tests/library_test:all`)

View File

@@ -1,6 +1,7 @@
load("//internal:bun_binary.bzl", _bun_binary = "bun_binary") load("//internal:bun_binary.bzl", _bun_binary = "bun_binary")
load("//internal:bun_bundle.bzl", _bun_bundle = "bun_bundle") load("//internal:bun_bundle.bzl", _bun_bundle = "bun_bundle")
load("//internal:bun_test.bzl", _bun_test = "bun_test") load("//internal:bun_test.bzl", _bun_test = "bun_test")
load("//internal:js_library.bzl", _js_library = "js_library", _ts_library = "ts_library")
load(":toolchain.bzl", _BunToolchainInfo = "BunToolchainInfo", _bun_toolchain = "bun_toolchain") load(":toolchain.bzl", _BunToolchainInfo = "BunToolchainInfo", _bun_toolchain = "bun_toolchain")
visibility("public") visibility("public")
@@ -8,5 +9,7 @@ visibility("public")
bun_binary = _bun_binary bun_binary = _bun_binary
bun_bundle = _bun_bundle bun_bundle = _bun_bundle
bun_test = _bun_test bun_test = _bun_test
js_library = _js_library
ts_library = _ts_library
BunToolchainInfo = _BunToolchainInfo BunToolchainInfo = _BunToolchainInfo
bun_toolchain = _bun_toolchain bun_toolchain = _bun_toolchain

View File

@@ -63,7 +63,7 @@ def bun_repositories(version = BUN_VERSION):
) )
def bun_register_toolchains(version = BUN_VERSION): def bun_register_toolchains(name = "bun", version = BUN_VERSION):
bun_repositories(version = version) bun_repositories(version = version)
native.register_toolchains( native.register_toolchains(
"//bun:darwin_aarch64_toolchain", "//bun:darwin_aarch64_toolchain",

View File

@@ -13,8 +13,15 @@ def _bun_binary_impl(ctx):
content = """#!/usr/bin/env bash content = """#!/usr/bin/env bash
set -euo pipefail set -euo pipefail
exec \"{}\" run \"{}\" \"$@\" runfiles_dir="${{RUNFILES_DIR:-$0.runfiles}}"
""".format(bun_bin.path, entry_point.path), bun_bin="${{runfiles_dir}}/_main/{bun_short_path}"
entry_point="${{runfiles_dir}}/_main/{entry_short_path}"
exec "${{bun_bin}}" run "${{entry_point}}" "$@"
""".format(
bun_short_path = bun_bin.short_path,
entry_short_path = entry_point.short_path,
),
) )
transitive_files = [] transitive_files = []

View File

@@ -1,5 +1,7 @@
"""Rule for bundling JS/TS sources with Bun.""" """Rule for bundling JS/TS sources with Bun."""
load("//internal:js_library.bzl", "BunSourcesInfo")
def _output_name(target_name, entry): def _output_name(target_name, entry):
stem = entry.basename.rsplit(".", 1)[0] stem = entry.basename.rsplit(".", 1)[0]
@@ -13,6 +15,11 @@ def _bun_bundle_impl(ctx):
transitive_inputs = [] transitive_inputs = []
if ctx.attr.node_modules: if ctx.attr.node_modules:
transitive_inputs.append(ctx.attr.node_modules[DefaultInfo].files) 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)
outputs = [] outputs = []
for entry in ctx.files.entry_points: for entry in ctx.files.entry_points:
@@ -59,6 +66,7 @@ bun_bundle = rule(
allow_files = [".js", ".ts", ".jsx", ".tsx", ".mjs", ".cjs"], allow_files = [".js", ".ts", ".jsx", ".tsx", ".mjs", ".cjs"],
), ),
"node_modules": attr.label(), "node_modules": attr.label(),
"deps": attr.label_list(),
"data": attr.label_list(allow_files = True), "data": attr.label_list(allow_files = True),
"target": attr.string( "target": attr.string(
default = "browser", default = "browser",

View File

@@ -1,5 +1,7 @@
"""Rule for running test suites with Bun.""" """Rule for running test suites with Bun."""
load("//internal:js_library.bzl", "BunSourcesInfo")
def _shell_quote(value): def _shell_quote(value):
return "'" + value.replace("'", "'\"'\"'") + "'" return "'" + value.replace("'", "'\"'\"'") + "'"
@@ -9,7 +11,7 @@ def _bun_test_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
src_args = " ".join([_shell_quote(src.path) for src in ctx.files.srcs]) src_args = " ".join([_shell_quote(src.short_path) for src in ctx.files.srcs])
launcher = ctx.actions.declare_file(ctx.label.name) launcher = ctx.actions.declare_file(ctx.label.name)
ctx.actions.write( ctx.actions.write(
output = launcher, output = launcher,
@@ -17,16 +19,22 @@ def _bun_test_impl(ctx):
content = """#!/usr/bin/env bash content = """#!/usr/bin/env bash
set -euo pipefail set -euo pipefail
extra_args=() 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}}" test {src_args} --test-name-pattern "${{TESTBRIDGE_TEST_ONLY}}" --coverage "$@"
fi
if [[ -n "${{TESTBRIDGE_TEST_ONLY:-}}" ]]; then if [[ -n "${{TESTBRIDGE_TEST_ONLY:-}}" ]]; then
extra_args+=("--test-name-pattern" "${{TESTBRIDGE_TEST_ONLY}}") exec "${{bun_bin}}" test {src_args} --test-name-pattern "${{TESTBRIDGE_TEST_ONLY}}" "$@"
fi fi
if [[ -n "${{COVERAGE_DIR:-}}" ]]; then if [[ -n "${{COVERAGE_DIR:-}}" ]]; then
extra_args+=("--coverage") exec "${{bun_bin}}" test {src_args} --coverage "$@"
fi fi
exec "{bun_bin}" test {src_args} "${{extra_args[@]}}" "$@" exec "${{bun_bin}}" test {src_args} "$@"
""".format( """.format(
bun_bin = bun_bin.path, bun_short_path = bun_bin.short_path,
src_args = src_args, src_args = src_args,
), ),
) )
@@ -34,6 +42,11 @@ exec "{bun_bin}" test {src_args} "${{extra_args[@]}}" "$@"
transitive_files = [] transitive_files = []
if ctx.attr.node_modules: if ctx.attr.node_modules:
transitive_files.append(ctx.attr.node_modules[DefaultInfo].files) 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)
runfiles = ctx.runfiles( runfiles = ctx.runfiles(
files = [bun_bin] + ctx.files.srcs + ctx.files.data, files = [bun_bin] + ctx.files.srcs + ctx.files.data,
@@ -56,6 +69,7 @@ bun_test = rule(
allow_files = [".js", ".ts", ".jsx", ".tsx", ".mjs", ".cjs"], allow_files = [".js", ".ts", ".jsx", ".tsx", ".mjs", ".cjs"],
), ),
"node_modules": attr.label(), "node_modules": attr.label(),
"deps": attr.label_list(),
"data": attr.label_list(allow_files = True), "data": attr.label_list(allow_files = True),
}, },
test = True, test = True,

40
internal/js_library.bzl Normal file
View File

@@ -0,0 +1,40 @@
"""Lightweight JS/TS source grouping rules."""
BunSourcesInfo = provider(fields = ["transitive_sources"])
def _bun_library_impl(ctx):
transitive_sources = [
dep[BunSourcesInfo].transitive_sources
for dep in ctx.attr.deps
if BunSourcesInfo in dep
]
all_sources = depset(
direct = ctx.files.srcs,
transitive = transitive_sources,
)
return [
BunSourcesInfo(transitive_sources = all_sources),
DefaultInfo(files = all_sources),
]
js_library = rule(
implementation = _bun_library_impl,
attrs = {
"srcs": attr.label_list(
allow_files = [".js", ".jsx", ".mjs", ".cjs"],
),
"deps": attr.label_list(),
},
)
ts_library = rule(
implementation = _bun_library_impl,
attrs = {
"srcs": attr.label_list(
allow_files = [".ts", ".tsx"],
),
"deps": attr.label_list(),
},
)

View File

@@ -4,10 +4,6 @@ load("@rules_shell//shell:sh_test.bzl", "sh_test")
bun_binary( bun_binary(
name = "hello_js_bin", name = "hello_js_bin",
entry_point = "hello.js", entry_point = "hello.js",
target_compatible_with = [
"@platforms//cpu:x86_64",
"@platforms//os:linux",
],
) )
sh_test( sh_test(
@@ -15,19 +11,11 @@ sh_test(
srcs = ["run_binary.sh"], srcs = ["run_binary.sh"],
args = ["$(location :hello_js_bin)", "hello-js"], args = ["$(location :hello_js_bin)", "hello-js"],
data = [":hello_js_bin"], data = [":hello_js_bin"],
target_compatible_with = [
"@platforms//cpu:x86_64",
"@platforms//os:linux",
],
) )
bun_binary( bun_binary(
name = "hello_ts_bin", name = "hello_ts_bin",
entry_point = "hello.ts", entry_point = "hello.ts",
target_compatible_with = [
"@platforms//cpu:x86_64",
"@platforms//os:linux",
],
) )
sh_test( sh_test(
@@ -35,8 +23,4 @@ sh_test(
srcs = ["run_binary.sh"], srcs = ["run_binary.sh"],
args = ["$(location :hello_ts_bin)", "hello-ts"], args = ["$(location :hello_ts_bin)", "hello-ts"],
data = [":hello_ts_bin"], data = [":hello_ts_bin"],
target_compatible_with = [
"@platforms//cpu:x86_64",
"@platforms//os:linux",
],
) )

View File

@@ -3,18 +3,10 @@ load("//bun:defs.bzl", "bun_test")
bun_test( bun_test(
name = "passing_suite", name = "passing_suite",
srcs = ["passing.test.ts"], srcs = ["passing.test.ts"],
target_compatible_with = [
"@platforms//cpu:x86_64",
"@platforms//os:linux",
],
) )
bun_test( bun_test(
name = "failing_suite", name = "failing_suite",
srcs = ["failing.test.ts"], srcs = ["failing.test.ts"],
tags = ["manual"], tags = ["manual"],
target_compatible_with = [
"@platforms//cpu:x86_64",
"@platforms//os:linux",
],
) )

View File

@@ -4,20 +4,12 @@ load("@rules_shell//shell:sh_test.bzl", "sh_test")
bun_bundle( bun_bundle(
name = "simple_bundle", name = "simple_bundle",
entry_points = ["main.ts"], entry_points = ["main.ts"],
target_compatible_with = [
"@platforms//cpu:x86_64",
"@platforms//os:linux",
],
) )
bun_bundle( bun_bundle(
name = "minified_bundle", name = "minified_bundle",
entry_points = ["main.ts"], entry_points = ["main.ts"],
minify = True, minify = True,
target_compatible_with = [
"@platforms//cpu:x86_64",
"@platforms//os:linux",
],
) )
sh_test( sh_test(
@@ -25,10 +17,6 @@ sh_test(
srcs = ["verify_bundle.sh"], srcs = ["verify_bundle.sh"],
args = ["$(location :simple_bundle)"], args = ["$(location :simple_bundle)"],
data = [":simple_bundle"], data = [":simple_bundle"],
target_compatible_with = [
"@platforms//cpu:x86_64",
"@platforms//os:linux",
],
) )
sh_test( sh_test(
@@ -42,8 +30,4 @@ sh_test(
":simple_bundle", ":simple_bundle",
":minified_bundle", ":minified_bundle",
], ],
target_compatible_with = [
"@platforms//cpu:x86_64",
"@platforms//os:linux",
],
) )

View File

@@ -1,23 +1,71 @@
load("@rules_shell//shell:sh_test.bzl", "sh_test") load("@rules_shell//shell:sh_test.bzl", "sh_test")
config_setting(
name = "linux_x86_64",
constraint_values = [
"@platforms//os:linux",
"@platforms//cpu:x86_64",
],
)
config_setting(
name = "linux_aarch64",
constraint_values = [
"@platforms//os:linux",
"@platforms//cpu:aarch64",
],
)
config_setting(
name = "darwin_x86_64",
constraint_values = [
"@platforms//os:macos",
"@platforms//cpu:x86_64",
],
)
config_setting(
name = "darwin_aarch64",
constraint_values = [
"@platforms//os:macos",
"@platforms//cpu:aarch64",
],
)
sh_test( sh_test(
name = "bun_install_clean_install_test", name = "bun_install_clean_install_test",
srcs = ["clean_install.sh"], srcs = ["clean_install.sh"],
args = ["$(location @bun_linux_x64//:bun)"], args = select({
data = ["@bun_linux_x64//:bun"], ":linux_x86_64": ["$(location @bun_linux_x64//:bun)"],
target_compatible_with = [ ":linux_aarch64": ["$(location @bun_linux_aarch64//:bun)"],
"@platforms//cpu:x86_64", ":darwin_x86_64": ["$(location @bun_darwin_x64//:bun)"],
"@platforms//os:linux", ":darwin_aarch64": ["$(location @bun_darwin_aarch64//: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"],
"//conditions:default": ["@bun_linux_x64//:bun"],
}),
) )
sh_test( sh_test(
name = "bun_install_stale_lockfile_test", name = "bun_install_stale_lockfile_test",
srcs = ["stale_lockfile.sh"], srcs = ["stale_lockfile.sh"],
args = ["$(location @bun_linux_x64//:bun)"], args = select({
data = ["@bun_linux_x64//:bun"], ":linux_x86_64": ["$(location @bun_linux_x64//:bun)"],
target_compatible_with = [ ":linux_aarch64": ["$(location @bun_linux_aarch64//:bun)"],
"@platforms//cpu:x86_64", ":darwin_x86_64": ["$(location @bun_darwin_x64//:bun)"],
"@platforms//os:linux", ":darwin_aarch64": ["$(location @bun_darwin_aarch64//: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"],
"//conditions:default": ["@bun_linux_x64//:bun"],
}),
) )

View File

@@ -8,7 +8,10 @@ trap 'rm -rf "${workdir}"' EXIT
cat >"${workdir}/package.json" <<'JSON' cat >"${workdir}/package.json" <<'JSON'
{ {
"name": "stale-lockfile-test", "name": "stale-lockfile-test",
"version": "1.0.0" "version": "1.0.0",
"dependencies": {
"left-pad": "1.3.0"
}
} }
JSON JSON
@@ -19,7 +22,7 @@ cat > "${workdir}/package.json" <<'JSON'
"name": "stale-lockfile-test", "name": "stale-lockfile-test",
"version": "1.0.0", "version": "1.0.0",
"dependencies": { "dependencies": {
"left-pad": "1.3.0" "left-pad": "1.1.3"
} }
} }
JSON JSON
@@ -34,7 +37,7 @@ if [[ ${code} -eq 0 ]]; then
exit 1 exit 1
fi fi
if [[ "${output}" != *"lockfile"* && "${output}" != *"frozen"* ]]; then if [[ ${output} != *"lockfile"* && ${output} != *"frozen"* ]]; then
echo "Expected lockfile-related error, got:" >&2 echo "Expected lockfile-related error, got:" >&2
echo "${output}" >&2 echo "${output}" >&2
exit 1 exit 1

View File

@@ -0,0 +1,26 @@
load("//bun:defs.bzl", "bun_bundle", "bun_test", "ts_library")
load("@rules_shell//shell:sh_test.bzl", "sh_test")
ts_library(
name = "helper_lib",
srcs = ["helper.ts"],
)
bun_bundle(
name = "bundle_with_deps",
entry_points = ["app.ts"],
deps = [":helper_lib"],
)
sh_test(
name = "bundle_dep_propagation_test",
srcs = ["verify_bundle.sh"],
args = ["$(location :bundle_with_deps)"],
data = [":bundle_with_deps"],
)
bun_test(
name = "test_with_deps",
srcs = ["app.test.ts"],
deps = [":helper_lib"],
)

View File

@@ -0,0 +1,6 @@
import { expect, test } from "bun:test";
import { greeting } from "./helper";
test("uses helper from ts_library dep", () => {
expect(greeting("test")).toBe("hello-test");
});

View File

@@ -0,0 +1,3 @@
import { greeting } from "./helper";
console.log(greeting("bundle"));

View File

@@ -0,0 +1,3 @@
export function greeting(name: string): string {
return `hello-${name}`;
}

View File

@@ -0,0 +1,9 @@
#!/usr/bin/env bash
set -euo pipefail
bundle="$1"
if [[ ! -s "${bundle}" ]]; then
echo "Expected bundled output to exist and be non-empty: ${bundle}" >&2
exit 1
fi

View File

@@ -1,12 +1,52 @@
load("@rules_shell//shell:sh_test.bzl", "sh_test") load("@rules_shell//shell:sh_test.bzl", "sh_test")
config_setting(
name = "linux_x86_64",
constraint_values = [
"@platforms//os:linux",
"@platforms//cpu:x86_64",
],
)
config_setting(
name = "linux_aarch64",
constraint_values = [
"@platforms//os:linux",
"@platforms//cpu:aarch64",
],
)
config_setting(
name = "darwin_x86_64",
constraint_values = [
"@platforms//os:macos",
"@platforms//cpu:x86_64",
],
)
config_setting(
name = "darwin_aarch64",
constraint_values = [
"@platforms//os:macos",
"@platforms//cpu:aarch64",
],
)
sh_test( sh_test(
name = "bun_version_test", name = "bun_version_test",
srcs = ["toolchain_version.sh"], srcs = ["toolchain_version.sh"],
args = ["$(location @bun_linux_x64//:bun)"], args = select({
data = ["@bun_linux_x64//:bun"], ":linux_x86_64": ["$(location @bun_linux_x64//:bun)"],
target_compatible_with = [ ":linux_aarch64": ["$(location @bun_linux_aarch64//:bun)"],
"@platforms//cpu:x86_64", ":darwin_x86_64": ["$(location @bun_darwin_x64//:bun)"],
"@platforms//os:linux", ":darwin_aarch64": ["$(location @bun_darwin_aarch64//: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"],
"//conditions:default": ["@bun_linux_x64//:bun"],
}),
) )