Skip to content

Commit

Permalink
[7.0.0] Automatically add function transition allow list when needed (#…
Browse files Browse the repository at this point in the history
…19855)

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:
#19493 (because whilelist is
ignored and default allowlist is added)

Commit
bb7fb2d

PiperOrigin-RevId: 574226941
Change-Id: If90f78a610d7bd3c107dcd94a39902c7c939aa7b

Co-authored-by: Googler <[email protected]>
  • Loading branch information
bazel-io and comius authored Oct 18, 2023
1 parent f63cd4a commit 60f3319
Show file tree
Hide file tree
Showing 5 changed files with 51 additions and 44 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -502,7 +503,6 @@ public static StarlarkRuleFunction createRule(
}

boolean hasStarlarkDefinedTransition = false;
boolean hasFunctionTransitionAllowlist = false;
for (Pair<String, StarlarkAttrModule.Descriptor> attribute : attributes) {
String name = attribute.getFirst();
StarlarkAttrModule.Descriptor descriptor = attribute.getSecond();
Expand All @@ -518,29 +518,6 @@ public static StarlarkRuleFunction createRule(
}
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())) {
Expand Down Expand Up @@ -653,15 +630,40 @@ public static StarlarkRuleFunction createRule(
}
}

// 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);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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() {}
}
Original file line number Diff line number Diff line change
Expand Up @@ -1303,6 +1303,10 @@ public boolean contains(String name) {
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());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -985,9 +985,10 @@ public void testCannotTransitionOnExperimentalFlag() throws Exception {
}

@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 = [],",
Expand All @@ -1013,7 +1014,7 @@ public void testCannotTransitionWithoutAllowlist() throws Exception {

reporter.removeHandler(failFastHandler);
getConfiguredTarget("//test");
assertContainsEvent("Use of Starlark transition without allowlist");
assertContainsEvent("Non-allowlisted use of Starlark transition");
}

@Test
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -2852,18 +2853,20 @@ public void testBadAnalysisTestRule_notAnalysisTest() throws Exception {
}

@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'])",
Expand All @@ -2887,9 +2890,8 @@ public void testBadAllowlistTransition_noAllowlist() throws Exception {
"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
Expand Down

0 comments on commit 60f3319

Please sign in to comment.