Skip to content

Commit 1db4192

Browse files
committed
fix(bazel): filter runfiles originating from deps and srcs in spec_bundle
Wraps the esbuild target created by the `spec_bundle` macro with a custom rule that removes runfiles originating from `deps` and `srcs`. This prevents duplicate spec execution by ensuring downstream targets like `jasmine_test` only receive the bundle's output files in their runfiles tree. Retains the runfiles aggregation behavior as before: alan-agius4/rules_esbuild@e088dc3
1 parent 9e99c5a commit 1db4192

1 file changed

Lines changed: 51 additions & 4 deletions

File tree

bazel/spec-bundling/index.bzl

Lines changed: 51 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,59 @@
11
load("@aspect_rules_esbuild//esbuild:defs.bzl", "esbuild")
2+
load("@aspect_rules_js//js:providers.bzl", "JsInfo")
23
load("@devinfra//bazel/spec-bundling:spec-entrypoint.bzl", "spec_entrypoint")
34

5+
# This rule filters out runfiles originating from `deps` and `srcs` to retain the same behavior
6+
# as before https://github.com/aspect-build/rules_esbuild/commit/e088dc3cdb8d8877ce632f01121eadc8952a2999.
7+
def _filter_runfiles_impl(ctx):
8+
bundle = ctx.attr.bundle
9+
files = bundle[DefaultInfo].files
10+
runfiles = ctx.runfiles(transitive_files = files)
11+
providers = [
12+
DefaultInfo(
13+
files = files,
14+
runfiles = runfiles,
15+
),
16+
]
17+
if JsInfo in bundle:
18+
providers.append(bundle[JsInfo])
19+
return providers
20+
21+
_filter_runfiles = rule(
22+
implementation = _filter_runfiles_impl,
23+
attrs = {
24+
"bundle": attr.label(mandatory = True),
25+
},
26+
)
27+
428
def spec_bundle(name, deps, srcs = [], bootstrap = [], testonly = True, config = {}, **kwargs):
29+
"""Bundles spec files and their dependencies into a single spec bundle using esbuild.
30+
31+
Args:
32+
name: Name of the bundle target.
33+
deps: Dependencies containing spec files and sources.
34+
srcs: Additional source files.
35+
bootstrap: Bootstrap files to load before the specs.
36+
testonly: Whether the target is testonly.
37+
config: Additional esbuild configuration options.
38+
**kwargs: Additional attributes to pass to esbuild.
39+
"""
540
spec_entrypoint(
641
name = "%s_entrypoint" % name,
742
deps = deps,
843
bootstrap = bootstrap,
944
testonly = testonly,
1045
)
1146

47+
visibility = kwargs.pop("visibility", None)
48+
tags = kwargs.pop("tags", None)
49+
esbuild_name = "_%s_bundle" % name
50+
1251
esbuild(
13-
name = name,
14-
# Note: `deps` are added here to automatically collect transitive NPM
15-
# sources etc. and make them available for bundling.
16-
srcs = srcs + deps + [
52+
name = esbuild_name,
53+
srcs = srcs + [
1754
":%s_entrypoint" % name,
1855
],
56+
deps = deps,
1957
config = dict({
2058
# Bundling specs may result in classes being aliased to avoid collisions. e.g. when
2159
# everything is bundled into a single AMD bundle. To avoid test failures for assertions
@@ -34,5 +72,14 @@ def spec_bundle(name, deps, srcs = [], bootstrap = [], testonly = True, config =
3472
platform = kwargs.pop("platform", "node"),
3573
entry_point = ":%s_entrypoint" % name,
3674
output = "%s.spec.js" % name,
75+
visibility = ["//visibility:private"],
3776
**kwargs
3877
)
78+
79+
_filter_runfiles(
80+
name = name,
81+
bundle = ":%s" % esbuild_name,
82+
testonly = testonly,
83+
visibility = visibility,
84+
tags = tags,
85+
)

0 commit comments

Comments
 (0)