Add an info item to show the currently inherited client environment Add 'bazel info client-env' which outputs entries for the configuration file that would freeze the current client environment. The main intended use case is to use 'bazel info client-env >> .bazelrc' to keep the project reproducible once a suitable value for the environment variables that used to be taken from the client environment has been found. -- Change-Id: Ib4d14dd824d223f335a4d4de04ee21c4a3ec4d83 Reviewed-on: https://bazel-review.googlesource.com/#/c/6112 MOS_MIGRATED_REVID=133699234
diff --git a/src/main/java/com/google/devtools/build/lib/runtime/CommandEnvironment.java b/src/main/java/com/google/devtools/build/lib/runtime/CommandEnvironment.java index 73c00d3..1208995 100644 --- a/src/main/java/com/google/devtools/build/lib/runtime/CommandEnvironment.java +++ b/src/main/java/com/google/devtools/build/lib/runtime/CommandEnvironment.java
@@ -166,10 +166,10 @@ } /** - * Return an ordered version of the client environment restricted to those variables - * whitelisted by the command-line options to be inheritable by actions. + * Return an ordered version of the client environment restricted to those variables whitelisted + * by the command-line options to be inheritable by actions. */ - private Map<String, String> getCommandlineWhitelistedClientEnv() { + public Map<String, String> getWhitelistedClientEnv() { Map<String, String> visibleEnv = new TreeMap<>(); for (String var : visibleClientEnv) { String value = clientEnv.get(var); @@ -426,7 +426,7 @@ getCommandId(), // TODO(bazel-team): this optimization disallows rule-specified additional dependencies // on the client environment! - getCommandlineWhitelistedClientEnv(), + getWhitelistedClientEnv(), timestampGranularityMonitor); }
diff --git a/src/main/java/com/google/devtools/build/lib/runtime/commands/InfoCommand.java b/src/main/java/com/google/devtools/build/lib/runtime/commands/InfoCommand.java index 0d7fb6a..b5e596f 100644 --- a/src/main/java/com/google/devtools/build/lib/runtime/commands/InfoCommand.java +++ b/src/main/java/com/google/devtools/build/lib/runtime/commands/InfoCommand.java
@@ -193,29 +193,31 @@ static Map<String, InfoItem> getHardwiredInfoItemMap(OptionsProvider commandOptions, String productName) { - List<InfoItem> hardwiredInfoItems = ImmutableList.<InfoItem>of( - new InfoItem.WorkspaceInfoItem(), - new InfoItem.InstallBaseInfoItem(), - new InfoItem.OutputBaseInfoItem(productName), - new InfoItem.ExecutionRootInfoItem(), - new InfoItem.OutputPathInfoItem(), - new InfoItem.BlazeBinInfoItem(productName), - new InfoItem.BlazeGenfilesInfoItem(productName), - new InfoItem.BlazeTestlogsInfoItem(productName), - new InfoItem.CommandLogInfoItem(), - new InfoItem.MessageLogInfoItem(), - new InfoItem.ReleaseInfoItem(productName), - new InfoItem.ServerPidInfoItem(productName), - new InfoItem.PackagePathInfoItem(commandOptions), - new InfoItem.UsedHeapSizeInfoItem(), - new InfoItem.UsedHeapSizeAfterGcInfoItem(), - new InfoItem.CommitedHeapSizeInfoItem(), - new InfoItem.MaxHeapSizeInfoItem(), - new InfoItem.GcTimeInfoItem(), - new InfoItem.GcCountInfoItem(), - new InfoItem.DefaultsPackageInfoItem(), - new InfoItem.BuildLanguageInfoItem(), - new InfoItem.DefaultPackagePathInfoItem(commandOptions)); + List<InfoItem> hardwiredInfoItems = + ImmutableList.<InfoItem>of( + new InfoItem.WorkspaceInfoItem(), + new InfoItem.InstallBaseInfoItem(), + new InfoItem.OutputBaseInfoItem(productName), + new InfoItem.ExecutionRootInfoItem(), + new InfoItem.OutputPathInfoItem(), + new InfoItem.ClientEnv(), + new InfoItem.BlazeBinInfoItem(productName), + new InfoItem.BlazeGenfilesInfoItem(productName), + new InfoItem.BlazeTestlogsInfoItem(productName), + new InfoItem.CommandLogInfoItem(), + new InfoItem.MessageLogInfoItem(), + new InfoItem.ReleaseInfoItem(productName), + new InfoItem.ServerPidInfoItem(productName), + new InfoItem.PackagePathInfoItem(commandOptions), + new InfoItem.UsedHeapSizeInfoItem(), + new InfoItem.UsedHeapSizeAfterGcInfoItem(), + new InfoItem.CommitedHeapSizeInfoItem(), + new InfoItem.MaxHeapSizeInfoItem(), + new InfoItem.GcTimeInfoItem(), + new InfoItem.GcCountInfoItem(), + new InfoItem.DefaultsPackageInfoItem(), + new InfoItem.BuildLanguageInfoItem(), + new InfoItem.DefaultPackagePathInfoItem(commandOptions)); ImmutableMap.Builder<String, InfoItem> result = new ImmutableMap.Builder<>(); for (InfoItem item : hardwiredInfoItems) { result.put(item.getName(), item);
diff --git a/src/main/java/com/google/devtools/build/lib/runtime/commands/InfoItem.java b/src/main/java/com/google/devtools/build/lib/runtime/commands/InfoItem.java index e8dc77f..e8836e5 100644 --- a/src/main/java/com/google/devtools/build/lib/runtime/commands/InfoItem.java +++ b/src/main/java/com/google/devtools/build/lib/runtime/commands/InfoItem.java
@@ -46,6 +46,7 @@ import java.lang.management.MemoryMXBean; import java.lang.management.MemoryUsage; import java.util.Collection; +import java.util.Map; /** * An item that is returned by <code>blaze info</code>. @@ -482,6 +483,29 @@ } } + /** Info item for the effective current client environment. */ + public static final class ClientEnv extends InfoItem { + public ClientEnv() { + super( + "client-env", + "The specifications that need to be added to the project-specific rc file to freeze the" + + " current client environment", + true); + } + + @Override + public byte[] get(Supplier<BuildConfiguration> configurationSupplier, CommandEnvironment env) + throws AbruptExitException { + String result = ""; + for (Map.Entry<String, String> entry : env.getWhitelistedClientEnv().entrySet()) { + // TODO(bazel-team): as the syntax of our rc-files does not support to express new-lines in + // values, we produce syntax errors if the value of the entry contains a newline character. + result += "common --action_env=" + entry.getKey() + "=" + entry.getValue() + "\n"; + } + return print(result); + } + } + /** * Info item for the default package. It is deprecated, it still works, when * explicitly requested, but are not shown by default. It prints multi-line messages and thus
diff --git a/src/test/shell/integration/action_env_test.sh b/src/test/shell/integration/action_env_test.sh index 017aa89..80976ed 100755 --- a/src/test/shell/integration/action_env_test.sh +++ b/src/test/shell/integration/action_env_test.sh
@@ -121,4 +121,26 @@ expect_not_log "FOO=foo" } +function test_env_freezing() { + cat > .${PRODUCT_NAME}rc <<EOF +common --action_env=FREEZE_TEST_FOO +common --action_env=FREEZE_TEST_BAR=is_fixed +common --action_env=FREEZE_TEST_BAZ=will_be_overridden +build --action_env=FREEZE_TEST_BUILD +EOF + + export FREEZE_TEST_FOO=client_foo + export FREEZE_TEST_BAR=client_bar + export FREEZE_TEST_BAZ=client_baz + export FREEZE_TEST_BUILD=client_build + + $bazel info --action_env=FREEZE_TEST_BAZ client-env > $TEST_log + expect_log "common --action_env=FREEZE_TEST_FOO=client_foo" + expect_not_log "FREEZE_TEST_BAR" + expect_log "common --action_env=FREEZE_TEST_BAZ=client_baz" + expect_log "common --action_env=FREEZE_TEST_BUILD=client_build" + + rm -f .${PRODUCT_NAME}rc +} + run_suite "Tests for bazel's handling of environment variables in actions"