diff --git a/bazel/integration/index.bzl b/bazel/integration/index.bzl index 582083fa6..5b404edfe 100644 --- a/bazel/integration/index.bzl +++ b/bazel/integration/index.bzl @@ -6,19 +6,25 @@ def _serialize_file(file): return struct(path = file.path, shortPath = file.short_path) -def _serialize_and_expand_location(ctx, value): - """Expands Bazel make location expressions for the given value. Returns a JSON +def _serialize_and_expand_value(ctx, value, description): + """Expands Bazel make variable and location expressions for the given value. Returns a JSON serializable dictionary matching the `BazelExpandedValue` type in the test runner.""" - new_value = ctx.expand_location(value, targets = ctx.attr.data) + expanded_location_value = ctx.expand_location(value, targets = ctx.attr.data) + + # Note: `expand_make_variables` is deprecated but there is no reasonable replacement + # yet. It's also still discussed whether the deprecation was reasonable to begin with: + # https://github.com/bazelbuild/bazel/issues/5859. If this ever gets deleted, we can + # directly use `ctx.var` but would have switch users from e.g. `$(VAR)` to `{VAR}`. + expanded_make_value = ctx.expand_make_variables(description, expanded_location_value, {}) return { - "value": new_value, - "containsExpandedValue": new_value != value, + "value": expanded_make_value, + "containsExpansion": expanded_make_value != value, } def _split_and_expand_command(ctx, command): - """Splits a command into the binary and its arguments. Also Bazel locations are expanded.""" - return [_serialize_and_expand_location(ctx, v) for v in command.split(" ", 1)] + """Splits a command into the binary and its arguments. Bazel make expression are expanded.""" + return [_serialize_and_expand_value(ctx, v, "command") for v in command.split(" ", 1)] def _serialize_and_expand_environment(ctx, environment_dict): """Converts the given environment dictionary into a JSON-serializable dictionary @@ -27,7 +33,7 @@ def _serialize_and_expand_environment(ctx, environment_dict): for variable_name in environment_dict: value = environment_dict[variable_name] - result[variable_name] = _serialize_and_expand_location(ctx, value) + result[variable_name] = _serialize_and_expand_value(ctx, value, "environment") return result @@ -61,7 +67,6 @@ def _unwrap_label_keyed_mappings(dict, description): def _integration_test_config_impl(ctx): """Implementation of the `_integration_test_config` rule.""" - npmPackageMappings, npmPackageFiles = \ _unwrap_label_keyed_mappings(ctx.attr.npm_packages, "NPM package") toolMappings, toolFiles = _unwrap_label_keyed_mappings(ctx.attr.tool_mappings, "Tool") @@ -111,7 +116,7 @@ _integration_test_config = rule( List of commands to run as part of the integration test. The commands can rely on the global tools made available through the tool mappings. - Commands can also use Bazel make location expansion.""", + Commands can also use Bazel make configuration variable or location expansion.""", ), "npm_packages": attr.label_keyed_string_dict( allow_files = True, @@ -131,9 +136,9 @@ _integration_test_config = rule( Dictionary of environment variables and their values. This allows for custom environment variables to be set when integration commands are invoked. - The environment variable values can use Bazel make location expansion similar - to the `commands` attribute. Additionally, values of `<TMP>` are replaced with - a unique temporary directory. This can be useful when providing `HOME` for + The environment variable values can use Bazel make variable or location expansion, + similar to the `commands` attribute. Additionally, values of `<TMP>` are replaced + with a unique temporary directory. This can be useful when providing `HOME` for bazelisk or puppeteer as as an example. """, ), @@ -147,6 +152,7 @@ def integration_test( npm_packages = {}, tool_mappings = {}, environment = {}, + toolchains = [], data = [], tags = [], **kwargs): @@ -157,6 +163,7 @@ def integration_test( _integration_test_config( name = config_target, + testonly = True, srcs = srcs, data = data, commands = commands, @@ -164,6 +171,7 @@ def integration_test( tool_mappings = tool_mappings, environment = environment, tags = tags, + toolchains = toolchains, ) nodejs_test( diff --git a/bazel/integration/test_runner/bazel.ts b/bazel/integration/test_runner/bazel.ts index e83c92336..5c85d7ad5 100644 --- a/bazel/integration/test_runner/bazel.ts +++ b/bazel/integration/test_runner/bazel.ts @@ -24,15 +24,17 @@ export interface BazelFileInfo { } /** - * Interface describing a Bazel-expanded value. A integration command for example could - * use a Bazel location expansion to resolve a binary. Such resolved values are captured in - * a structure like this. + * Interface describing a Bazel-expanded value, including both location and + * configuration variable expansion. + * + * A integration command for example could use a Bazel location expansion to resolve a + * binary. Such resolved values are captured in a structure like this. */ export interface BazelExpandedValue { /** Actual value, with expanded Make expressions if it contained any. */ value: string; - /** Whether the value contains an expanded value. */ - containsExpandedValue: boolean; + /** Whether the value contains an expanded value (either location or variable). */ + containsExpansion: boolean; } /** Resolves the specified Bazel file to an absolute disk path. */ diff --git a/bazel/integration/test_runner/runner.ts b/bazel/integration/test_runner/runner.ts index 1a27db680..78eee1bc6 100644 --- a/bazel/integration/test_runner/runner.ts +++ b/bazel/integration/test_runner/runner.ts @@ -191,7 +191,7 @@ export class TestRunner { for (let [variableName, value] of Object.entries(this.environment)) { let envValue: string = value.value; - if (value.containsExpandedValue) { + if (value.containsExpansion) { envValue = await resolveBinaryWithRunfiles(envValue); } else if (envValue === ENVIRONMENT_TMP_PLACEHOLDER) { envValue = path.join(testDir, `.tmp-env-${i++}`); @@ -215,7 +215,7 @@ export class TestRunner { for (const [binary, ...args] of this.commands) { // Only resolve the binary if it contains an expanded value. In other cases we would // not want to resolve through runfiles to avoid accidentally unexpected resolution. - const resolvedBinary = binary.containsExpandedValue + const resolvedBinary = binary.containsExpansion ? await resolveBinaryWithRunfiles(binary.value) : binary.value; const evaluatedArgs = expandEnvironmentVariableSubstitutions(