Skip to content

Commit 48bb9cc

Browse files
mattemalexeagle
authored andcommitted
fix: allow multiple run_node calls to be made from the same rule context
1 parent 4616f5a commit 48bb9cc

File tree

6 files changed

+105
-4
lines changed

6 files changed

+105
-4
lines changed

internal/linker/link_node_modules.bzl

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -56,12 +56,13 @@ def _link_mapping(label, mappings, k, v):
5656
else:
5757
return True
5858

59-
def write_node_modules_manifest(ctx, extra_data = []):
59+
def write_node_modules_manifest(ctx, extra_data = [], mnemonic = None):
6060
"""Writes a manifest file read by the linker, containing info about resolving runtime dependencies
6161
6262
Args:
6363
ctx: starlark rule execution context
6464
extra_data: labels to search for npm packages that need to be linked (ctx.attr.deps and ctx.attr.data will always be searched)
65+
mnemonic: optional action mnemonic, used to differentiate module mapping files from the same rule context
6566
"""
6667

6768
mappings = {}
@@ -81,7 +82,7 @@ def write_node_modules_manifest(ctx, extra_data = []):
8182
for k, v in getattr(dep, _ASPECT_RESULT_NAME, {}).items():
8283
if _link_mapping(dep.label, mappings, k, v):
8384
# Special case for ts_library module_name for legacy behavior and for AMD name
84-
# work-around. Do not propogate tslibrary root type to runtime as it is not
85+
# work-around. Do not propagate tslibrary root type to runtime as it is not
8586
# needed at runtime. See comment below in _get_module_mappings for more info.
8687
if v[0] == "_tslibrary":
8788
v = ["execroot", v[1]]
@@ -90,7 +91,10 @@ def write_node_modules_manifest(ctx, extra_data = []):
9091

9192
# Write the result to a file, and use the magic node option --bazel_node_modules_manifest
9293
# The launcher.sh will peel off this argument and pass it to the linker rather than the program.
93-
modules_manifest = ctx.actions.declare_file("_%s.module_mappings.json" % ctx.label.name)
94+
prefix = ctx.label.name
95+
if mnemonic != None:
96+
prefix += "_%s" % mnemonic
97+
modules_manifest = ctx.actions.declare_file("_%s.module_mappings.json" % prefix)
9498
content = {
9599
"bin": ctx.bin_dir.path,
96100
"modules": mappings,

internal/providers/node_runtime_deps_info.bzl

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,8 @@ def run_node(ctx, inputs, arguments, executable, **kwargs):
7373
extra_inputs = exec_attr[NodeRuntimeDepsInfo].deps.to_list()
7474
link_data = exec_attr[NodeRuntimeDepsInfo].pkgs
7575

76-
modules_manifest = write_node_modules_manifest(ctx, link_data)
76+
mnemonic = kwargs.get("mnemonic")
77+
modules_manifest = write_node_modules_manifest(ctx, link_data, mnemonic)
7778
add_arg(arguments, "--bazel_node_modules_manifest=%s" % modules_manifest.path)
7879

7980
stdout_file = kwargs.pop("stdout", None)

internal/providers/test/BUILD.bazel

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
load("@build_bazel_rules_nodejs//:index.bzl", "generated_file_test", "nodejs_binary")
2+
load("//internal/providers/test:run_node_test.bzl", "js_write_file")
3+
4+
# two nodejs_binary targets provide two separate executables in the run_node test
5+
nodejs_binary(
6+
name = "writer_bin",
7+
entry_point = "js-write-file.js",
8+
)
9+
10+
nodejs_binary(
11+
name = "writer_bin2",
12+
data = [
13+
# the JS files doesn't actually consume this dependency, but it causes a different modules
14+
# manifest file to be written in for both run_node actions in the js_write_file rule below
15+
"@npm//shelljs",
16+
],
17+
entry_point = "js-write-file.js",
18+
)
19+
20+
js_write_file(
21+
name = "write_file",
22+
content = "test file content",
23+
)
24+
25+
# tests that the rule above generated two files for each run_node action
26+
[
27+
generated_file_test(
28+
name = "run_node_test_%s" % file,
29+
src = "_run_node_out.txt",
30+
generated = "%s.txt" % file,
31+
)
32+
for file in [
33+
"out",
34+
"out2",
35+
]
36+
]
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
test file content
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
const writeFileSync = require('fs').writeFileSync;
2+
3+
const content = process.argv[2];
4+
const outputPath = process.argv[3];
5+
6+
writeFileSync(outputPath, content, {encoding: 'utf8'});
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
"""
2+
Contrived rule for writing some content to a file using run_node
3+
Tests that two run_node calls can be made from the same rule context, where each run_node call
4+
uses a different executable (and therefore the content of the modules manifest file is different)
5+
"""
6+
7+
load("//:providers.bzl", "run_node")
8+
9+
def _js_write_file_impl(ctx):
10+
run_node(
11+
ctx = ctx,
12+
executable = "_writer",
13+
mnemonic = "writer",
14+
inputs = [],
15+
arguments = [
16+
ctx.attr.content,
17+
ctx.outputs.out.path,
18+
],
19+
outputs = [ctx.outputs.out],
20+
)
21+
22+
run_node(
23+
ctx = ctx,
24+
executable = "_writer2",
25+
# mnemonic is left as None here to test the node_modules manifest writer handling None
26+
inputs = [],
27+
arguments = [
28+
ctx.attr.content,
29+
ctx.outputs.out2.path,
30+
],
31+
outputs = [ctx.outputs.out2],
32+
)
33+
34+
js_write_file = rule(
35+
implementation = _js_write_file_impl,
36+
outputs = {
37+
"out": "out.txt",
38+
"out2": "out2.txt",
39+
},
40+
attrs = {
41+
"content": attr.string(),
42+
"_writer": attr.label(
43+
default = Label("//internal/providers/test:writer_bin"),
44+
cfg = "host",
45+
executable = True,
46+
),
47+
"_writer2": attr.label(
48+
default = Label("//internal/providers/test:writer_bin2"),
49+
cfg = "host",
50+
executable = True,
51+
),
52+
},
53+
)

0 commit comments

Comments
 (0)