From 83f225dfaef7999aa704b46c5742fc4c518495fd Mon Sep 17 00:00:00 2001 From: Eric Date: Wed, 4 Mar 2026 15:03:15 +0100 Subject: [PATCH] fix: .env is located next to package.json --- MODULE.bazel | 4 ++-- MODULE.bazel.lock | 11 +---------- README.md | 3 ++- internal/bun_binary.bzl | 23 +++++++++++++++++++--- internal/bun_dev.bzl | 23 +++++++++++++++++++--- tests/binary_test/BUILD.bazel | 14 +++++++++++++ tests/binary_test/env_parent/src/main.ts | 2 ++ tests/binary_test/run_parent_env_binary.sh | 10 ++++++++++ 8 files changed, 71 insertions(+), 19 deletions(-) create mode 100644 tests/binary_test/env_parent/src/main.ts create mode 100755 tests/binary_test/run_parent_env_binary.sh diff --git a/MODULE.bazel b/MODULE.bazel index 1d6a262..cb01764 100644 --- a/MODULE.bazel +++ b/MODULE.bazel @@ -5,8 +5,8 @@ module( bazel_dep(name = "platforms", version = "1.0.0") bazel_dep(name = "rules_shell", version = "0.6.1") -bazel_dep(name = "bazel_skylib", version = "1.8.0") -bazel_dep(name = "stardoc", version = "0.7.1") +bazel_dep(name = "bazel_skylib", version = "1.8.2") +bazel_dep(name = "stardoc", version = "0.7.2") bun_ext = use_extension("//bun:extensions.bzl", "bun") use_repo( diff --git a/MODULE.bazel.lock b/MODULE.bazel.lock index 4d9bec8..ffdfddd 100644 --- a/MODULE.bazel.lock +++ b/MODULE.bazel.lock @@ -48,7 +48,6 @@ "https://bcr.bazel.build/modules/bazel_skylib/1.6.1/MODULE.bazel": "8fdee2dbaace6c252131c00e1de4b165dc65af02ea278476187765e1a617b917", "https://bcr.bazel.build/modules/bazel_skylib/1.7.0/MODULE.bazel": "0db596f4563de7938de764cc8deeabec291f55e8ec15299718b93c4423e9796d", "https://bcr.bazel.build/modules/bazel_skylib/1.7.1/MODULE.bazel": "3120d80c5861aa616222ec015332e5f8d3171e062e3e804a2a0253e1be26e59b", - "https://bcr.bazel.build/modules/bazel_skylib/1.8.0/MODULE.bazel": "2fb3fb53675f6adfc1ca5bfbd5cfb655ae350fba4706d924a8ec7e3ba945671c", "https://bcr.bazel.build/modules/bazel_skylib/1.8.1/MODULE.bazel": "88ade7293becda963e0e3ea33e7d54d3425127e0a326e0d17da085a5f1f03ff6", "https://bcr.bazel.build/modules/bazel_skylib/1.8.2/MODULE.bazel": "69ad6927098316848b34a9142bcc975e018ba27f08c4ff403f50c1b6e646ca67", "https://bcr.bazel.build/modules/bazel_skylib/1.8.2/source.json": "34a3c8bcf233b835eb74be9d628899bb32999d3e0eadef1947a0a562a2b16ffb", @@ -120,13 +119,10 @@ "https://bcr.bazel.build/modules/rules_fuzzing/0.5.2/MODULE.bazel": "40c97d1144356f52905566c55811f13b299453a14ac7769dfba2ac38192337a8", "https://bcr.bazel.build/modules/rules_java/4.0.0/MODULE.bazel": "5a78a7ae82cd1a33cef56dc578c7d2a46ed0dca12643ee45edbb8417899e6f74", "https://bcr.bazel.build/modules/rules_java/5.3.5/MODULE.bazel": "a4ec4f2db570171e3e5eb753276ee4b389bae16b96207e9d3230895c99644b86", - "https://bcr.bazel.build/modules/rules_java/6.0.0/MODULE.bazel": "8a43b7df601a7ec1af61d79345c17b31ea1fedc6711fd4abfd013ea612978e39", - "https://bcr.bazel.build/modules/rules_java/6.4.0/MODULE.bazel": "e986a9fe25aeaa84ac17ca093ef13a4637f6107375f64667a15999f77db6c8f6", "https://bcr.bazel.build/modules/rules_java/6.5.2/MODULE.bazel": "1d440d262d0e08453fa0c4d8f699ba81609ed0e9a9a0f02cd10b3e7942e61e31", "https://bcr.bazel.build/modules/rules_java/7.10.0/MODULE.bazel": "530c3beb3067e870561739f1144329a21c851ff771cd752a49e06e3dc9c2e71a", "https://bcr.bazel.build/modules/rules_java/7.12.2/MODULE.bazel": "579c505165ee757a4280ef83cda0150eea193eed3bef50b1004ba88b99da6de6", "https://bcr.bazel.build/modules/rules_java/7.2.0/MODULE.bazel": "06c0334c9be61e6cef2c8c84a7800cef502063269a5af25ceb100b192453d4ab", - "https://bcr.bazel.build/modules/rules_java/7.3.2/MODULE.bazel": "50dece891cfdf1741ea230d001aa9c14398062f2b7c066470accace78e412bc2", "https://bcr.bazel.build/modules/rules_java/7.6.1/MODULE.bazel": "2f14b7e8a1aa2f67ae92bc69d1ec0fa8d9f827c4e17ff5e5f02e91caa3b2d0fe", "https://bcr.bazel.build/modules/rules_java/8.3.2/MODULE.bazel": "7336d5511ad5af0b8615fdc7477535a2e4e723a357b6713af439fe8cf0195017", "https://bcr.bazel.build/modules/rules_java/8.5.1/MODULE.bazel": "d8a9e38cc5228881f7055a6079f6f7821a073df3744d441978e7a43e20226939", @@ -136,12 +132,9 @@ "https://bcr.bazel.build/modules/rules_jvm_external/4.4.2/MODULE.bazel": "a56b85e418c83eb1839819f0b515c431010160383306d13ec21959ac412d2fe7", "https://bcr.bazel.build/modules/rules_jvm_external/5.1/MODULE.bazel": "33f6f999e03183f7d088c9be518a63467dfd0be94a11d0055fe2d210f89aa909", "https://bcr.bazel.build/modules/rules_jvm_external/5.2/MODULE.bazel": "d9351ba35217ad0de03816ef3ed63f89d411349353077348a45348b096615036", - "https://bcr.bazel.build/modules/rules_jvm_external/5.3/MODULE.bazel": "bf93870767689637164657731849fb887ad086739bd5d360d90007a581d5527d", - "https://bcr.bazel.build/modules/rules_jvm_external/6.1/MODULE.bazel": "75b5fec090dbd46cf9b7d8ea08cf84a0472d92ba3585b476f44c326eda8059c4", "https://bcr.bazel.build/modules/rules_jvm_external/6.3/MODULE.bazel": "c998e060b85f71e00de5ec552019347c8bca255062c990ac02d051bb80a38df0", "https://bcr.bazel.build/modules/rules_jvm_external/6.7/MODULE.bazel": "e717beabc4d091ecb2c803c2d341b88590e9116b8bf7947915eeb33aab4f96dd", "https://bcr.bazel.build/modules/rules_jvm_external/6.7/source.json": "5426f412d0a7fc6b611643376c7e4a82dec991491b9ce5cb1cfdd25fe2e92be4", - "https://bcr.bazel.build/modules/rules_kotlin/1.9.0/MODULE.bazel": "ef85697305025e5a61f395d4eaede272a5393cee479ace6686dba707de804d59", "https://bcr.bazel.build/modules/rules_kotlin/1.9.6/MODULE.bazel": "d269a01a18ee74d0335450b10f62c9ed81f2321d7958a2934e44272fe82dcef3", "https://bcr.bazel.build/modules/rules_kotlin/1.9.6/source.json": "2faa4794364282db7c06600b7e5e34867a564ae91bda7cae7c29c64e9466b7d5", "https://bcr.bazel.build/modules/rules_license/0.0.3/MODULE.bazel": "627e9ab0247f7d1e05736b59dbb1b6871373de5ad31c3011880b4133cafd4bd0", @@ -180,9 +173,7 @@ "https://bcr.bazel.build/modules/rules_swift/3.1.2/source.json": "e85761f3098a6faf40b8187695e3de6d97944e98abd0d8ce579cb2daf6319a66", "https://bcr.bazel.build/modules/stardoc/0.5.1/MODULE.bazel": "1a05d92974d0c122f5ccf09291442580317cdd859f07a8655f1db9a60374f9f8", "https://bcr.bazel.build/modules/stardoc/0.5.3/MODULE.bazel": "c7f6948dae6999bf0db32c1858ae345f112cacf98f174c7a8bb707e41b974f1c", - "https://bcr.bazel.build/modules/stardoc/0.5.6/MODULE.bazel": "c43dabc564990eeab55e25ed61c07a1aadafe9ece96a4efabb3f8bf9063b71ef", "https://bcr.bazel.build/modules/stardoc/0.7.0/MODULE.bazel": "05e3d6d30c099b6770e97da986c53bd31844d7f13d41412480ea265ac9e8079c", - "https://bcr.bazel.build/modules/stardoc/0.7.1/MODULE.bazel": "3548faea4ee5dda5580f9af150e79d0f6aea934fc60c1cc50f4efdd9420759e7", "https://bcr.bazel.build/modules/stardoc/0.7.2/MODULE.bazel": "fc152419aa2ea0f51c29583fab1e8c99ddefd5b3778421845606ee628629e0e5", "https://bcr.bazel.build/modules/stardoc/0.7.2/source.json": "58b029e5e901d6802967754adf0a9056747e8176f017cfe3607c0851f4d42216", "https://bcr.bazel.build/modules/swift_argument_parser/1.3.1.1/MODULE.bazel": "5e463fbfba7b1701d957555ed45097d7f984211330106ccd1352c6e0af0dcf91", @@ -199,7 +190,7 @@ "//bun:extensions.bzl%bun": { "general": { "bzlTransitiveDigest": "oLR98WtKDCc+zh7Tvu9jtakNg8q/T1IPE38QR1FEQtI=", - "usagesDigest": "9s+/cJR+wTifjBrio71E10Knd41B08/GmW4I9zJmU64=", + "usagesDigest": "NfJgMuTjZXXRLr1/kxxFkS1IKV2UyehFyr3fMvAke/k=", "recordedInputs": [ "REPO_MAPPING:,bazel_tools bazel_tools" ], diff --git a/README.md b/README.md index a1e0d1f..0e29f32 100644 --- a/README.md +++ b/README.md @@ -4,6 +4,7 @@ Bazel rules for bun. ## Rule reference +- Published docs site: https://eriyc.github.io/rules_bun/ - Generated API docs: [docs/rules.md](docs/rules.md) - Regenerate: `bazel build //docs:rules_md && cp bazel-bin/docs/rules.md docs/rules.md` @@ -143,7 +144,7 @@ bazel run //path/to:web_dev `bun_binary` and `bun_dev` support `working_dir`: - `"workspace"` (default): runs from the Bazel runfiles workspace root. -- `"entry_point"`: runs from the entry point file's directory. +- `"entry_point"`: runs from the nearest ancestor of the entry point that contains `.env` or `package.json` (falls back to the entry point directory). Use `"entry_point"` when Bun should resolve local files such as colocated `.env` files relative to the program directory. diff --git a/internal/bun_binary.bzl b/internal/bun_binary.bzl index 5691880..e4c22d7 100644 --- a/internal/bun_binary.bzl +++ b/internal/bun_binary.bzl @@ -14,14 +14,31 @@ def _bun_binary_impl(ctx): 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 "$(dirname "${{entry_point}}")" + cd "$(resolve_entrypoint_workdir)" else - cd "${{runfiles_dir}}/_main" + cd "${{workspace_root}}" fi exec "${{bun_bin}}" --bun run "${{entry_point}}" "$@" @@ -71,7 +88,7 @@ Use this rule for non-test scripts and CLIs that should run via `bazel run`. "working_dir": attr.string( default = "workspace", values = ["workspace", "entry_point"], - doc = "Working directory at runtime: `workspace` root or `entry_point` directory.", + doc = "Working directory at runtime: `workspace` root or nearest `entry_point` ancestor containing `.env`/`package.json`.", ), }, executable = True, diff --git a/internal/bun_dev.bzl b/internal/bun_dev.bzl index 3f91ec2..b873418 100644 --- a/internal/bun_dev.bzl +++ b/internal/bun_dev.bzl @@ -15,14 +15,31 @@ def _bun_dev_impl(ctx): 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 "$(dirname "${{entry_point}}")" + cd "$(resolve_entrypoint_workdir)" else - cd "${{runfiles_dir}}/_main" + cd "${{workspace_root}}" fi watch_mode="{watch_mode}" @@ -161,7 +178,7 @@ watch/HMR plus optional full restarts on selected file changes. "working_dir": attr.string( default = "workspace", values = ["workspace", "entry_point"], - doc = "Working directory at runtime: `workspace` root or `entry_point` directory.", + doc = "Working directory at runtime: `workspace` root or nearest `entry_point` ancestor containing `.env`/`package.json`.", ), }, executable = True, diff --git a/tests/binary_test/BUILD.bazel b/tests/binary_test/BUILD.bazel index 369b9c9..fb101cd 100644 --- a/tests/binary_test/BUILD.bazel +++ b/tests/binary_test/BUILD.bazel @@ -57,3 +57,17 @@ sh_test( args = ["$(location :env_cwd_bin)"], data = [":env_cwd_bin"], ) + +bun_binary( + name = "env_parent_cwd_bin", + entry_point = "env_parent/src/main.ts", + data = ["env_parent/.env"], + working_dir = "entry_point", +) + +sh_test( + name = "bun_binary_env_parent_cwd_test", + srcs = ["run_parent_env_binary.sh"], + args = ["$(location :env_parent_cwd_bin)"], + data = [":env_parent_cwd_bin"], +) diff --git a/tests/binary_test/env_parent/src/main.ts b/tests/binary_test/env_parent/src/main.ts new file mode 100644 index 0000000..8edbd2c --- /dev/null +++ b/tests/binary_test/env_parent/src/main.ts @@ -0,0 +1,2 @@ +const value = process.env.BUN_ENV_PARENT_TEST ?? "missing"; +console.log(value); diff --git a/tests/binary_test/run_parent_env_binary.sh b/tests/binary_test/run_parent_env_binary.sh new file mode 100755 index 0000000..0089a2d --- /dev/null +++ b/tests/binary_test/run_parent_env_binary.sh @@ -0,0 +1,10 @@ +#!/usr/bin/env bash +set -euo pipefail + +binary="$1" +output="$(${binary})" + +if [[ ${output} != "from-parent-dotenv" ]]; then + echo "Expected .env value from parent directory, got: ${output}" >&2 + exit 1 +fi