Expose "is_tool_configuration" on build configuration to Starlark builtins.

There isn't a good alternative way of doing this at the moment, and this
functionality is needed for internal migrations. We're keeping its usage
locked down, at least initially.

PiperOrigin-RevId: 415299072
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/config/BuildConfigurationValue.java b/src/main/java/com/google/devtools/build/lib/analysis/config/BuildConfigurationValue.java
index 0e18f44..64519a9 100644
--- a/src/main/java/com/google/devtools/build/lib/analysis/config/BuildConfigurationValue.java
+++ b/src/main/java/com/google/devtools/build/lib/analysis/config/BuildConfigurationValue.java
@@ -673,6 +673,18 @@
     return isExecConfiguration() || isHostConfiguration();
   }
 
+  @Override
+  public boolean isToolConfigurationForStarlark(StarlarkThread thread) throws EvalException {
+    RepositoryName repository =
+        BazelModuleContext.of(Module.ofInnermostEnclosingStarlarkFunction(thread))
+            .label()
+            .getRepository();
+    if (!"@_builtins".equals(repository.getName())) {
+      throw Starlark.errorf("private API only for use in builtins");
+    }
+    return isToolConfiguration();
+  }
+
   public boolean checkVisibility() {
     return options.checkVisibility;
   }
diff --git a/src/main/java/com/google/devtools/build/lib/starlarkbuildapi/BuildConfigurationApi.java b/src/main/java/com/google/devtools/build/lib/starlarkbuildapi/BuildConfigurationApi.java
index fad4195..e2f6198 100644
--- a/src/main/java/com/google/devtools/build/lib/starlarkbuildapi/BuildConfigurationApi.java
+++ b/src/main/java/com/google/devtools/build/lib/starlarkbuildapi/BuildConfigurationApi.java
@@ -77,4 +77,7 @@
 
   @StarlarkMethod(name = "stamp_binaries", documented = false, useStarlarkThread = true)
   boolean stampBinariesForStarlark(StarlarkThread thread) throws EvalException;
+
+  @StarlarkMethod(name = "is_tool_configuration", documented = false, useStarlarkThread = true)
+  boolean isToolConfigurationForStarlark(StarlarkThread thread) throws EvalException;
 }
diff --git a/src/test/java/com/google/devtools/build/lib/analysis/config/BuildConfigurationStarlarkTest.java b/src/test/java/com/google/devtools/build/lib/analysis/config/BuildConfigurationStarlarkTest.java
index 464640e..71289c9 100644
--- a/src/test/java/com/google/devtools/build/lib/analysis/config/BuildConfigurationStarlarkTest.java
+++ b/src/test/java/com/google/devtools/build/lib/analysis/config/BuildConfigurationStarlarkTest.java
@@ -14,6 +14,7 @@
 package com.google.devtools.build.lib.analysis.config;
 
 import static com.google.common.truth.Truth.assertThat;
+import static org.junit.Assert.assertThrows;
 
 import com.google.common.collect.ImmutableMap;
 import com.google.devtools.build.lib.analysis.ConfiguredTarget;
@@ -59,4 +60,21 @@
     StructImpl myInfo = (StructImpl) starlarkTarget.get(key);
     assertThat(((Dict) myInfo.getValue("test_env")).get("TEST_ENV_VAR")).isEqualTo("my_value");
   }
+
+  @Test
+  public void testIsToolConfigurationIsBlocked() throws Exception {
+    scratch.file(
+        "example/BUILD", "load(':rule.bzl', 'custom_rule')", "custom_rule(name = 'custom')");
+
+    scratch.file(
+        "example/rule.bzl",
+        "def _impl(ctx):",
+        "  ctx.configuration.is_tool_configuration()",
+        "  return [DefaultInfo()]",
+        "custom_rule = rule(implementation = _impl)");
+
+    AssertionError e =
+        assertThrows(AssertionError.class, () -> getConfiguredTarget("//example:custom"));
+    assertThat(e).hasMessageThat().contains("private API only for use in builtins");
+  }
 }