Automatically add function transition allow list when needed
If the allowlist is already present its value is respected (The package paths and label name are fixed/checked. Only repository name can be changed).
Automatically add allowlist with tools repository as defined by rule definition environment.
This fixes the incompatibility introduced in: https://github.com/bazelbuild/bazel/issues/19493 (because whilelist is ignored and default allowlist is added)
PiperOrigin-RevId: 574226941
Change-Id: If90f78a610d7bd3c107dcd94a39902c7c939aa7b
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/starlark/StarlarkRuleClassFunctions.java b/src/main/java/com/google/devtools/build/lib/analysis/starlark/StarlarkRuleClassFunctions.java
index efb3946..81b43f9 100644
--- a/src/main/java/com/google/devtools/build/lib/analysis/starlark/StarlarkRuleClassFunctions.java
+++ b/src/main/java/com/google/devtools/build/lib/analysis/starlark/StarlarkRuleClassFunctions.java
@@ -37,6 +37,7 @@
import com.google.common.collect.Maps;
import com.google.devtools.build.lib.analysis.Allowlist;
import com.google.devtools.build.lib.analysis.BaseRuleClasses;
+import com.google.devtools.build.lib.analysis.PackageSpecificationProvider;
import com.google.devtools.build.lib.analysis.RuleDefinitionEnvironment;
import com.google.devtools.build.lib.analysis.TemplateVariableInfo;
import com.google.devtools.build.lib.analysis.config.ExecutionTransitionFactory;
@@ -502,7 +503,6 @@
}
boolean hasStarlarkDefinedTransition = false;
- boolean hasFunctionTransitionAllowlist = false;
for (Pair<String, StarlarkAttrModule.Descriptor> attribute : attributes) {
String name = attribute.getFirst();
StarlarkAttrModule.Descriptor descriptor = attribute.getSecond();
@@ -518,29 +518,6 @@
}
builder.setHasAnalysisTestTransition();
}
- // Check for existence of the function transition allowlist attribute.
- // TODO(b/121385274): remove when we stop allowlisting starlark transitions
- if (name.equals(FunctionSplitTransitionAllowlist.ATTRIBUTE_NAME)) {
- if (!BuildType.isLabelType(attr.getType())) {
- throw Starlark.errorf("_allowlist_function_transition attribute must be a label type");
- }
- if (attr.getDefaultValueUnchecked() == null) {
- throw Starlark.errorf(
- "_allowlist_function_transition attribute must have a default value");
- }
- Label defaultLabel = (Label) attr.getDefaultValueUnchecked();
- // Check the label value for package and target name, to make sure this works properly
- // in Bazel where it is expected to be found under @bazel_tools.
- if (!(defaultLabel
- .getPackageName()
- .equals(FunctionSplitTransitionAllowlist.LABEL.getPackageName())
- && defaultLabel.getName().equals(FunctionSplitTransitionAllowlist.LABEL.getName()))) {
- throw Starlark.errorf(
- "_allowlist_function_transition attribute (%s) does not have the expected value %s",
- defaultLabel, FunctionSplitTransitionAllowlist.LABEL);
- }
- hasFunctionTransitionAllowlist = true;
- }
try {
if (builder.contains(attr.getName())) {
@@ -653,15 +630,40 @@
}
}
- // TODO(b/121385274): remove when we stop allowlisting starlark transitions
+ boolean hasFunctionTransitionAllowlist = false;
+ // Check for existence of the function transition allowlist attribute.
+ if (builder.contains(FunctionSplitTransitionAllowlist.ATTRIBUTE_NAME)) {
+ Attribute attr = builder.getAttribute(FunctionSplitTransitionAllowlist.ATTRIBUTE_NAME);
+ if (!BuildType.isLabelType(attr.getType())) {
+ throw Starlark.errorf("_allowlist_function_transition attribute must be a label type");
+ }
+ if (attr.getDefaultValueUnchecked() == null) {
+ throw Starlark.errorf("_allowlist_function_transition attribute must have a default value");
+ }
+ Label defaultLabel = (Label) attr.getDefaultValueUnchecked();
+ // Check the label value for package and target name, to make sure this works properly
+ // in Bazel where it is expected to be found under @bazel_tools.
+ if (!(defaultLabel
+ .getPackageName()
+ .equals(FunctionSplitTransitionAllowlist.LABEL.getPackageName())
+ && defaultLabel.getName().equals(FunctionSplitTransitionAllowlist.LABEL.getName()))) {
+ throw Starlark.errorf(
+ "_allowlist_function_transition attribute (%s) does not have the expected value %s",
+ defaultLabel, FunctionSplitTransitionAllowlist.LABEL);
+ }
+ hasFunctionTransitionAllowlist = true;
+ }
if (hasStarlarkDefinedTransition) {
if (!bzlFile.getRepository().getNameWithAt().equals("@_builtins")) {
if (!hasFunctionTransitionAllowlist) {
- throw Starlark.errorf(
- "Use of Starlark transition without allowlist attribute"
- + " '_allowlist_function_transition'. See Starlark transitions documentation"
- + " for details and usage: %s %s",
- builder.getRuleDefinitionEnvironmentLabel(), builder.getType());
+ // add the allowlist automatically
+ builder.add(
+ attr(FunctionSplitTransitionAllowlist.ATTRIBUTE_NAME, LABEL)
+ .cfg(ExecutionTransitionFactory.createFactory())
+ .mandatoryBuiltinProviders(ImmutableList.of(PackageSpecificationProvider.class))
+ .value(
+ ruleDefinitionEnvironment.getToolsLabel(
+ FunctionSplitTransitionAllowlist.LABEL_STR)));
}
builder.addAllowlistChecker(FUNCTION_TRANSITION_ALLOWLIST_CHECKER);
}
diff --git a/src/main/java/com/google/devtools/build/lib/packages/FunctionSplitTransitionAllowlist.java b/src/main/java/com/google/devtools/build/lib/packages/FunctionSplitTransitionAllowlist.java
index 6a6b0ab..00a4291 100644
--- a/src/main/java/com/google/devtools/build/lib/packages/FunctionSplitTransitionAllowlist.java
+++ b/src/main/java/com/google/devtools/build/lib/packages/FunctionSplitTransitionAllowlist.java
@@ -16,14 +16,12 @@
import com.google.devtools.build.lib.cmdline.Label;
-/**
- * This class provides constants associated with the function split transition allowlist.
- */
+/** This class provides constants associated with the function split transition allowlist. */
public class FunctionSplitTransitionAllowlist {
public static final String NAME = "function_transition";
public static final String ATTRIBUTE_NAME = "$allowlist_function_transition";
- public static final Label LABEL =
- Label.parseCanonicalUnchecked("//tools/allowlists/function_transition_allowlist");
+ public static final String LABEL_STR = "//tools/allowlists/function_transition_allowlist";
+ public static final Label LABEL = Label.parseCanonicalUnchecked(LABEL_STR);
private FunctionSplitTransitionAllowlist() {}
}
diff --git a/src/main/java/com/google/devtools/build/lib/packages/RuleClass.java b/src/main/java/com/google/devtools/build/lib/packages/RuleClass.java
index 2d29dcd..88dd1a2 100644
--- a/src/main/java/com/google/devtools/build/lib/packages/RuleClass.java
+++ b/src/main/java/com/google/devtools/build/lib/packages/RuleClass.java
@@ -1303,6 +1303,10 @@
return attributes.containsKey(name);
}
+ public Attribute getAttribute(String name) {
+ return attributes.get(name);
+ }
+
/** Returns a list of all attributes added to this Builder so far. */
public ImmutableList<Attribute> getAttributes() {
return ImmutableList.copyOf(attributes.values());
diff --git a/src/test/java/com/google/devtools/build/lib/analysis/StarlarkRuleTransitionProviderTest.java b/src/test/java/com/google/devtools/build/lib/analysis/StarlarkRuleTransitionProviderTest.java
index 48920e7..0cd0b77 100644
--- a/src/test/java/com/google/devtools/build/lib/analysis/StarlarkRuleTransitionProviderTest.java
+++ b/src/test/java/com/google/devtools/build/lib/analysis/StarlarkRuleTransitionProviderTest.java
@@ -985,9 +985,10 @@
}
@Test
- public void testCannotTransitionWithoutAllowlist() throws Exception {
+ public void testTransitionIsCheckedAgainstDefaultAllowlist() throws Exception {
scratch.overwriteFile(
- "tools/allowlists/function_transition_allowlist/BUILD",
+ TestConstants.TOOLS_REPOSITORY_SCRATCH
+ + "tools/allowlists/function_transition_allowlist/BUILD",
"package_group(",
" name = 'function_transition_allowlist',",
" packages = [],",
@@ -1013,7 +1014,7 @@
reporter.removeHandler(failFastHandler);
getConfiguredTarget("//test");
- assertContainsEvent("Use of Starlark transition without allowlist");
+ assertContainsEvent("Non-allowlisted use of Starlark transition");
}
@Test
diff --git a/src/test/java/com/google/devtools/build/lib/starlark/StarlarkIntegrationTest.java b/src/test/java/com/google/devtools/build/lib/starlark/StarlarkIntegrationTest.java
index c2f72a4..d1f3826 100644
--- a/src/test/java/com/google/devtools/build/lib/starlark/StarlarkIntegrationTest.java
+++ b/src/test/java/com/google/devtools/build/lib/starlark/StarlarkIntegrationTest.java
@@ -58,6 +58,7 @@
import com.google.devtools.build.lib.rules.objc.ObjcProvider;
import com.google.devtools.build.lib.skyframe.AspectKeyCreator.AspectKey;
import com.google.devtools.build.lib.skyframe.ConfiguredTargetAndData;
+import com.google.devtools.build.lib.testutil.TestConstants;
import com.google.devtools.build.lib.testutil.TestRuleClassProvider;
import com.google.devtools.build.lib.vfs.FileSystemUtils;
import com.google.devtools.build.lib.vfs.PathFragment;
@@ -2852,18 +2853,20 @@
}
@Test
- public void testBadAllowlistTransition_noAllowlist() throws Exception {
+ public void testBadAllowlistTransition_automaticAllowlist() throws Exception {
scratch.overwriteFile(
- "tools/allowlists/function_transition_allowlist/BUILD",
+ TestConstants.TOOLS_REPOSITORY_SCRATCH
+ + "tools/allowlists/function_transition_allowlist/BUILD",
"package_group(",
" name = 'function_transition_allowlist',",
" packages = [",
- " '//test/...',",
+ // cross-repo allowlists don't work well
+ analysisMock.isThisBazel() ? "'public'," : "'//test/...',",
" ],",
")");
scratch.file(
"test/rules.bzl",
- "def transition_func(settings):",
+ "def transition_func(settings, attr):",
" return {'t0': {'//command_line_option:cpu': 'k8'}}",
"my_transition = transition(implementation = transition_func, inputs = [],",
" outputs = ['//command_line_option:cpu'])",
@@ -2887,9 +2890,8 @@
"my_rule(name = 'my_rule', dep = ':dep')",
"simple_rule(name = 'dep')");
- reporter.removeHandler(failFastHandler);
getConfiguredTarget("//test:my_rule");
- assertContainsEvent("Use of Starlark transition without allowlist");
+ assertNoEvents();
}
@Test