Skip to content

Commit df37fca

Browse files
authored
feat: add default DEBUG and VERBOSE_LOGS configuration_env_vars to nodejs_binary (#1080)
- all rules updated to use DEBUG and VERBOSE_LOGS environment variables - added golden_debug attribute golden_file_test to support the case where a rule has different output if DEBUG is set; for example ``` golden_file_test( name = "test", actual = "out.min.js", golden = "output.golden.js_", golden_debug = "output.debug.golden.js_", ) ```
1 parent e04c8c3 commit df37fca

24 files changed

Lines changed: 250 additions & 144 deletions

File tree

.bazelci/presubmit.yml

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,16 @@ tasks:
106106
- "--test_tag_filters=-e2e,-examples,-fix-bazelci-ubuntu"
107107
test_targets:
108108
- "//..."
109+
ubuntu1804_debug:
110+
name: ubuntu1804_debug
111+
platform: ubuntu1804
112+
test_flags:
113+
- "--define=VERBOSE_LOGS=1"
114+
- "--define=DEBUG=1"
115+
- "--test_tag_filters=-e2e,-examples,-fix-bazelci-ubuntu"
116+
test_targets:
117+
- "//..."
118+
- "//packages/terser/test/debug:test_define_DEBUG"
109119
ubuntu1804_e2e:
110120
name: ubuntu1804_e2e
111121
platform: ubuntu1804

.circleci/config.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -152,7 +152,7 @@ jobs:
152152
- *init_bazel
153153
- *hide_node_and_yarn_local_binaries
154154

155-
- run: bazel test ... --test_tag_filters=-e2e,-examples
155+
- run: bazel test --test_tag_filters=-e2e,-examples ...
156156

157157
- store_artifacts:
158158
path: dist/bin/release.tar.gz

DEVELOPING.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,10 @@ To do a full clean run:
2424
yarn clean_all
2525
```
2626

27+
## Debugging
28+
29+
See `Debugging` section under `/docs/index.md`.
30+
2731
## Releasing
2832

2933
Start from a clean checkout at master/HEAD.

common.bazelrc

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,32 @@ test --test_output=errors
2626

2727
# Support for debugging NodeJS tests
2828
# Add the Bazel option `--config=debug` to enable this
29-
test:debug --test_arg=--node_options=--inspect-brk --test_output=streamed --test_strategy=exclusive --test_timeout=9999 --nocache_test_results
29+
# --test_output=streamed
30+
# Stream stdout/stderr output from each test in real-time.
31+
# See https://docs.bazel.build/versions/master/user-manual.html#flag--test_output for more details.
32+
# --test_strategy=exclusive
33+
# Run one test at a time.
34+
# --test_timeout=9999
35+
# Prevent long running tests from timing out
36+
# See https://docs.bazel.build/versions/master/user-manual.html#flag--test_timeout for more details.
37+
# --nocache_test_results
38+
# Always run tests
39+
# --node_options=--inspect-brk
40+
# Pass the --inspect-brk option to all tests which enables the node inspector agent.
41+
# See https://nodejs.org/de/docs/guides/debugging-getting-started/#command-line-options for more details.
42+
# --define=VERBOSE_LOGS=1
43+
# Rules will output verbose logs if the VERBOSE_LOGS environment variable is set. `VERBOSE_LOGS` will be passed to
44+
# `nodejs_binary` and `nodejs_test` via the default value of the `default_env_vars` attribute of those rules.
45+
# --define=DEBUG=1
46+
# Rules may change their build outputs if the DEBUG environment variable is set. For example,
47+
# mininfiers such as terser may make their output more human readable when this is set. `DEBUG` will be passed to
48+
# `nodejs_binary` and `nodejs_test` via the default value of the `default_env_vars` attribute of those rules.
49+
test:debug --test_output=streamed --test_strategy=exclusive --test_timeout=9999 --nocache_test_results --define=VERBOSE_LOGS=1
50+
# Use bazel run with `--config=debug` to turn on the NodeJS inspector agent.
51+
# The node process will break before user code starts and wait for the debugger to connect.
52+
run:debug --define=VERBOSE_LOGS=1 -- --node_options=--inspect-brk
53+
# The following option will change the build output of certain rules such as terser and may not be desirable in all cases
54+
build:debug --define=DEBUG=1
3055

3156
# Turn off legacy external runfiles
3257
# This prevents accidentally depending on this feature, which Bazel will remove.

docs/Terser.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ Bazel will make a copy of your config file, treating it as a template.
8787
8888
If you use the magic strings `"bazel_debug"` or `"bazel_no_debug"`, these will be
8989
replaced with `true` and `false` respecting the value of the `debug` attribute
90-
or the `--define=DEBUG=true` bazel flag.
90+
or the `--define=DEBUG=1` bazel flag.
9191

9292
For example,
9393

@@ -107,7 +107,7 @@ If `config_file` isn't supplied, Bazel will use a default config file.
107107
(*Boolean*): Configure terser to produce more readable output.
108108

109109
Instead of setting this attribute, consider setting the DEBUG variable instead
110-
bazel build --define=DEBUG=true //my/terser:target
110+
bazel build --define=DEBUG=1 //my/terser:target
111111
so that it only affects the current build.
112112

113113

docs/index.md

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,40 @@ See the `examples/program` directory in this repository.
9090

9191
The `examples/program/index.spec.js` file illustrates testing. Another usage is in https://github.com/angular/tsickle/blob/master/test/BUILD
9292

93+
### Debugging
94+
95+
Add the options in the `Support for debugging NodeJS tests` section from https://github.com/bazelbuild/rules_nodejs/blob/master/common.bazelrc to your project's `.bazelrc` file to add support for debugging NodeJS programs.
96+
97+
Using the `--config=debug` command line option with bazel will set a number of flags that are specified there are useful for debugging. See the comments under `Support for debugging NodeJS tests` for details on the flags that are set.
98+
99+
Use `--config=debug` with `bazel test` as follow,
100+
101+
```
102+
bazel test --config=debug //test:...
103+
```
104+
105+
or with `bazel run`,
106+
107+
```
108+
bazel run --config=debug //test:test1
109+
```
110+
111+
to also turn on the NodeJS inspector agent which will break before any user code starts. You should then see,
112+
113+
```
114+
Executing tests from //test:test1
115+
-----------------------------------------------------------------------------
116+
Debugger listening on ws://127.0.0.1:9229/3f20777a-242c-4d18-b88b-5ed4b3fed61c
117+
For help, see: https://nodejs.org/en/docs/inspector
118+
```
119+
120+
when the test is run.
121+
122+
To inspect with Chrome DevTools 55+, open `chrome://inspect` in a Chromium-based browser and attach to the waiting process.
123+
A Chrome DevTools window should open and you should see `Debugger attached.` in the console.
124+
125+
See https://nodejs.org/en/docs/guides/debugging-getting-started/ for more details.
126+
93127
### Stamping
94128

95129
Bazel is generally only a build tool, and is unaware of your version control system.

internal/bazel_integration_test/test_runner.js

Lines changed: 27 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,6 @@
1515
* limitations under the License.
1616
*/
1717

18-
const DEBUG = false;
19-
2018
// Set TEST_MANIFEST to true and use `bazel run` to excersize the MANIFEST
2119
// file code path on Linux and OSX
2220
const TEST_MANIFEST = false;
@@ -26,17 +24,28 @@ const fs = require('fs');
2624
const path = require('path');
2725
const tmp = require('tmp');
2826

27+
const DEBUG = !!process.env['DEBUG'];
28+
const VERBOSE_LOGS = !!process.env['VERBOSE_LOGS'];
29+
30+
function log(...m) {
31+
console.error('[test_runner.js]', ...m);
32+
}
33+
34+
function log_verbose(...m) {
35+
if (VERBOSE_LOGS) console.error('[test_runner.js]', ...m);
36+
}
37+
2938
const config = require(process.argv[2]);
30-
if (DEBUG) console.log(`config: ${JSON.stringify(config, null, 2)}`);
39+
log_verbose(`config: ${JSON.stringify(config, null, 2)}`);
3140

3241
const testArgs = process.argv.slice(3);
33-
if (DEBUG) console.log(`testArgs: ${JSON.stringify(testArgs, null, 2)}`);
42+
log_verbose(`testArgs: ${JSON.stringify(testArgs, null, 2)}`);
3443

3544
/**
36-
* Helper function to log out the contents of a file.
45+
* Helper function to debug log out the contents of a file.
3746
*/
3847
function logFileContents(desc, contents) {
39-
console.log(`\n\n${
48+
log_verbose(`${
4049
desc}\n========================================================================================\n${
4150
contents}\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n`);
4251
}
@@ -82,7 +91,7 @@ function copyFolderSync(from, to) {
8291
if (fs.statSync(src).isFile()) {
8392
mkdirp(path.dirname(dest));
8493
fs.copyFileSync(src, dest);
85-
if (DEBUG) console.log(`copying ${src} -> ${dest}`);
94+
log_verbose(`copying ${src} -> ${dest}`);
8695
} else {
8796
copyFolderSync(src, dest);
8897
}
@@ -130,7 +139,7 @@ function copyWorkspace(workspace) {
130139
const element = key.slice(start.length);
131140
const dest = path.posix.join(to, element);
132141
mkdirp(path.dirname(dest));
133-
if (DEBUG) console.log(`copying (MANIFEST) ${RUNFILES_MANIFEST[key]} -> ${dest}`);
142+
log_verbose(`copying (MANIFEST) ${RUNFILES_MANIFEST[key]} -> ${dest}`);
134143
fs.copyFileSync(RUNFILES_MANIFEST[key], dest);
135144
}
136145
}
@@ -158,7 +167,7 @@ function copyNpmPackage(packagePath) {
158167
return to;
159168
}
160169

161-
if (DEBUG) console.log(`\n\ncopying workspace under test ${config.workspaceUnderTest} to tmp`);
170+
log_verbose(`copying workspace under test ${config.workspaceUnderTest} to tmp`);
162171
const workspaceRoot = copyWorkspace(config.workspaceUnderTest);
163172

164173
// Handle .bazelrc import replacements
@@ -172,7 +181,7 @@ if (bazelrcImportsKeys.length && isFile(bazelrcFile)) {
172181
bazelrcContents = bazelrcContents.replace(importKey, importContents);
173182
}
174183
fs.writeFileSync(bazelrcFile, bazelrcContents);
175-
if (DEBUG) logFileContents('.bazelrc file with replacements:', bazelrcContents);
184+
logFileContents('.bazelrc file with replacements:', bazelrcContents);
176185
}
177186

178187
// Handle appending to .bazelrc
@@ -182,7 +191,7 @@ if (config.bazelrcAppend) {
182191
bazelrcContents += '\n\n# Appended by bazel_integration_test\n';
183192
bazelrcContents += config.bazelrcAppend;
184193
fs.writeFileSync(bazelrcFile, bazelrcContents);
185-
if (DEBUG) logFileContents('.bazelrc file after appending:', bazelrcContents);
194+
logFileContents('.bazelrc file after appending:', bazelrcContents);
186195
}
187196

188197
// Handle WORKSPACE replacements
@@ -206,7 +215,7 @@ if (config.bazelrcAppend) {
206215
}
207216
}
208217
fs.writeFileSync(workspaceFile, workspaceContents);
209-
if (DEBUG) logFileContents('WORKSPACE file with replacements:', workspaceContents);
218+
logFileContents('WORKSPACE file with replacements:', workspaceContents);
210219
}
211220

212221
// Handle package.json replacements
@@ -217,7 +226,7 @@ if (isFile(packageJsonFile)) {
217226
const npmPackageKeys = Object.keys(config.npmPackages);
218227
if (npmPackageKeys.length) {
219228
for (const packageJsonKey of npmPackageKeys) {
220-
if (DEBUG) console.log(`\n\ncopying npm package ${packageJsonKey} to tmp`);
229+
log_verbose(`copying npm package ${packageJsonKey} to tmp`);
221230
const packagePath = copyNpmPackage(config.npmPackages[packageJsonKey]).replace(/\\/g, '/');
222231
const regex = new RegExp(`\"${packageJsonKey}\"\\s*\:\\s*\"[^"]+`)
223232
const replacement = `"${packageJsonKey}": "file:${packagePath}`;
@@ -255,21 +264,21 @@ if (isFile(packageJsonFile)) {
255264
}
256265
}
257266

258-
if (DEBUG) logFileContents('package.json file with replacements:', packageJsonContents);
267+
logFileContents('package.json file with replacements:', packageJsonContents);
259268
}
260269

261270
const isWindows = process.platform === 'win32';
262271
const bazelBinary =
263272
require.resolve(`${config.bazelBinaryWorkspace}/bazel${isWindows ? '.exe' : ''}`);
264273

265-
console.log(`\n\nRunning 'bazel version'`);
274+
log(`running 'bazel version'`);
266275
let spawnedProcess = spawnSync(bazelBinary, ['version'], {cwd: workspaceRoot, stdio: 'inherit'});
267276
if (spawnedProcess.status) {
268277
process.exit(spawnedProcess.status);
269278
}
270279

271-
if (DEBUG) {
272-
console.log(`\n\nRunning 'bazel info'`);
280+
if (VERBOSE_LOGS) {
281+
log_verbose(`running 'bazel info'`);
273282
spawnedProcess = spawnSync(bazelBinary, ['info'], {cwd: workspaceRoot, stdio: 'inherit'});
274283
if (spawnedProcess.status) {
275284
process.exit(spawnedProcess.status);
@@ -286,7 +295,7 @@ for (const bazelCommand of config.bazelCommands) {
286295
} else {
287296
bazelArgs.push(...testArgs);
288297
}
289-
console.log(`\n\nRunning 'bazel ${bazelArgs.join(' ')}'`);
298+
log(`running 'bazel ${bazelArgs.join(' ')}'`);
290299
spawnedProcess = spawnSync(bazelBinary, bazelArgs, {cwd: workspaceRoot, stdio: 'inherit'});
291300
if (spawnedProcess.status) {
292301
process.exit(spawnedProcess.status);

internal/golden_file_test/bin.js

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,9 @@ const path = require('path');
33
const unidiff = require('unidiff');
44

55
function main(args) {
6-
const [mode, golden, actual] = args;
6+
const [mode, golden_no_debug, golden_debug, actual] = args;
7+
const debug = !!process.env['DEBUG'];
8+
const golden = debug ? golden_debug : golden_no_debug;
79
const actualContents = fs.readFileSync(require.resolve(actual), 'utf-8').replace(/\r\n/g, '\n');
810
const goldenContents = fs.readFileSync(require.resolve(golden), 'utf-8').replace(/\r\n/g, '\n');
911

@@ -22,7 +24,8 @@ ${prettyDiff}
2224
2325
Update the golden file:
2426
25-
bazel run ${process.env['BAZEL_TARGET'].replace(/_bin$/, '')}.accept
27+
bazel run ${debug ? '--define=DEBUG=1 ' : ''}${
28+
process.env['BAZEL_TARGET'].replace(/_bin$/, '')}.accept
2629
`);
2730
} else {
2831
throw new Error('unknown mode', mode);

internal/golden_file_test/golden_file_test.bzl

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,23 @@
33
load("@build_bazel_rules_nodejs//:defs.bzl", "nodejs_binary", "nodejs_test")
44

55
def golden_file_test(name, golden, actual, **kwargs):
6+
"""Tests an actual output against a golden output.
7+
8+
Use `golden_debug` if the actual output changes when DEBUG is set.
9+
"""
610
data = [golden, actual, "@npm//unidiff"]
711

12+
golden_debug = kwargs.pop("golden_debug", [])
13+
if golden_debug:
14+
data.extend([golden_debug])
15+
else:
16+
golden_debug = golden
17+
818
loc = "$(location %s)"
919
nodejs_test(
1020
name = name,
1121
entry_point = "@build_bazel_rules_nodejs//internal/golden_file_test:bin.js",
12-
templated_args = ["--verify", loc % golden, loc % actual],
22+
templated_args = ["--verify", loc % golden, loc % golden_debug, loc % actual],
1323
data = data,
1424
**kwargs
1525
)
@@ -18,7 +28,7 @@ def golden_file_test(name, golden, actual, **kwargs):
1828
name = name + ".accept",
1929
testonly = True,
2030
entry_point = "@build_bazel_rules_nodejs//internal/golden_file_test:bin.js",
21-
templated_args = ["--out", loc % golden, loc % actual],
31+
templated_args = ["--out", loc % golden, loc % golden_debug, loc % actual],
2232
data = data,
2333
**kwargs
2434
)

internal/node/node.bzl

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -156,7 +156,7 @@ def _nodejs_binary_impl(ctx):
156156
ctx.outputs.loader.short_path,
157157
])
158158
env_vars = "export BAZEL_TARGET=%s\n" % ctx.label
159-
for k in ctx.attr.configuration_env_vars:
159+
for k in ctx.attr.configuration_env_vars + ctx.attr.default_env_vars:
160160
if k in ctx.var.keys():
161161
env_vars += "export %s=\"%s\"\n" % (k, ctx.var[k])
162162

@@ -269,6 +269,19 @@ _NODEJS_EXECUTABLE_ATTRS = {
269269
allow_files = True,
270270
aspects = [sources_aspect, module_mappings_runtime_aspect, collect_node_modules_aspect],
271271
),
272+
"default_env_vars": attr.string_list(
273+
doc = """Default environment variables that are added to `configuration_env_vars`.
274+
275+
This is separate from the default of `configuration_env_vars` so that a user can set `configuration_env_vars`
276+
without losing the defaults that should be set in most cases.
277+
278+
The set of default environment variables is:
279+
280+
`DEBUG`: rules use this environment variable to turn on debug information in their output artifacts
281+
`VERBOSE_LOGS`: rules use this environment variable to turn on debug output in their logs
282+
""",
283+
default = ["DEBUG", "VERBOSE_LOGS"],
284+
),
272285
"entry_point": attr.label(
273286
doc = """The script which should be executed first, usually containing a main function.
274287

0 commit comments

Comments
 (0)