Skip to content

Commit b114c43

Browse files
authored
Add support for setting 'labels' in prebuilt rules (#993)
In this commit, we add support for setting the 'labels' field to the template for the prebuilt macros. This allows for setting specific lables on dependencies, which can be used for validation and querying logic.
1 parent 8fbd54d commit b114c43

10 files changed

Lines changed: 203 additions & 4 deletions

File tree

CHANGELOG.md

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
* Bug fix to handle export dependencies file path correctly.
88

99
### Version 0.53.3
10-
* Add configuration cleanCacheDir to conditionally delete the cache directory or
10+
* Add configuration cleanCacheDir to conditionally delete the cache directory or
1111
just the existing dependency rules files
1212

1313
### Version 0.54.0
@@ -27,3 +27,16 @@
2727

2828
### Version 0.54.4
2929
* Added support for using Android Lint 31.3+
30+
31+
### Version 0.54.5
32+
* Added `labelsMap` configuration to `externalDependencies` block for adding custom labels to prebuilt dependency rules
33+
* Migrated Robolectric's deprecated code to recommended alternatives:
34+
- Added `:libraries:robolectric-base` to Gradle modules
35+
- Added missing jUnit dependency to robolectric-base
36+
- Replaced deprecated `getAppManifest()` with `getManifestFactory()` and created `BuckManifestFactory`
37+
* Updated GitHub Actions workflows:
38+
- Updated runner image to `ubuntu-24.04` (ubuntu-20.04 is deprecated)
39+
- Updated `actions/checkout` to v4
40+
- Updated `actions/setup-java` to v4 with temurin distribution
41+
- Removed rxPermissions and XLog dependencies
42+
- Updated to Python 3.8

Usage.md

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,10 +61,20 @@ okbuck {
6161
experimental {
6262
transform = true
6363
}
64-
64+
6565
externalDependencies {
6666
cache = "3rdparty/jvm"
6767
cleanCacheDir = true
68+
labelsMap = [
69+
"com.example:library:1.0.0": [
70+
"category=utility",
71+
"license=apache-2.0"
72+
],
73+
"junit:junit:4.13.2": [
74+
"category=testing",
75+
"test_framework=true"
76+
]
77+
]
6878
}
6979
}
7080
@@ -85,6 +95,10 @@ please read the [Exopackage wiki](https://github.com/uber/okbuck/wiki/Exopackage
8595
+ `extraBuckOpts` provides a hook to add additional configuration options for buck [android_binary](https://buckbuild.com/rule/android_binary.html) rules
8696
+ `wrapper` is used to configure creation of the buck wrapper script.
8797
- `repo` - The git url of any custom buck fork. Default is none.
98+
+ `externalDependencies` block configures external dependency resolution and generation:
99+
+ - `cache` - Specifies the folder where external dependency rules are generated. Default is `.okbuck/ext`
100+
+ - `cleanCacheDir` - Whether to delete the cache directory before generating dependency rules. Default is `true`
101+
+ - `labelsMap` - Map of dependency coordinates to labels for prebuilt rules. Keys are Maven coordinates in format `"groupId:artifactId:version"`, values are lists of arbitrary strings. An example usecase could be to tag all test dependencies to easily be able to query them.
88102
+ The keys used to configure various options can be for
89103
- All buildTypes and flavors i.e `app`
90104
- All buildTypes of a particular flavor i.e 'appDemo'

build.gradle

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -237,6 +237,17 @@ okbuck {
237237
"autoValueGson",
238238
"autoValueParcel",
239239
]
240+
// Example: Add labels for specific dependencies
241+
labelsMap = [
242+
"com.example:library:1.0.0": [
243+
"category=utility",
244+
"license=apache-2.0"
245+
],
246+
"junit:junit:4.13.2": [
247+
"category=testing",
248+
"test_framework=true"
249+
]
250+
]
240251
}
241252

242253
dependencies {

buildSrc/build.gradle

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,8 @@ dependencies {
4040
annotationProcessor deps.apt.autoValue
4141
annotationProcessor deps.build.nullaway
4242

43+
testAnnotationProcessor deps.build.nullaway
44+
4345
errorprone deps.build.erroproneCompiler
4446
errorproneJavac deps.build.errorproneJavac
4547

@@ -60,6 +62,7 @@ dependencies {
6062
implementation deps.external.gson
6163

6264
testImplementation deps.test.junit
65+
testImplementation deps.test.mockito
6366
}
6467

6568
rocker {

buildSrc/src/main/java/com/uber/okbuck/composer/java/PrebuiltRuleComposer.java

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,21 +11,39 @@
1111
import com.uber.okbuck.template.core.Rule;
1212
import com.uber.okbuck.template.java.Prebuilt;
1313
import java.util.Collection;
14+
import java.util.Collections;
1415
import java.util.HashMap;
1516
import java.util.List;
17+
import java.util.Map;
18+
import java.util.Set;
1619
import java.util.stream.Collectors;
20+
import javax.annotation.Nullable;
1721

1822
public class PrebuiltRuleComposer extends JvmBuckRuleComposer {
1923

2024
private PrebuiltRuleComposer() {}
2125

26+
// Visibile for testing
27+
static ImmutableSet<String> getLabels(OExternalDependency dependency, @Nullable Map<String, List<String>> labelsMap) {
28+
List<String> labels = (labelsMap == null)
29+
? Collections.emptyList()
30+
: labelsMap.getOrDefault(dependency.getMavenCoordsForValidation(), Collections.emptyList());
31+
32+
return labels == null ? ImmutableSet.of() : ImmutableSet.copyOf(labels);
33+
}
34+
2235
/**
2336
* @param dependencies External Dependencies whose rule needs to be created
2437
* @return List of rules
2538
*/
2639
@SuppressWarnings("NullAway")
2740
public static List<Rule> compose(
2841
Collection<OExternalDependency> dependencies, HashMap<String, String> shaSum256) {
42+
return compose(dependencies, shaSum256, null);
43+
}
44+
45+
public static List<Rule> compose(
46+
Collection<OExternalDependency> dependencies, HashMap<String, String> shaSum256, Map<String, List<String>> labelsMap) {
2947
return dependencies
3048
.stream()
3149
.peek(
@@ -58,6 +76,8 @@ public static List<Rule> compose(
5876
rule.sourcesSha256(sourcesSha256);
5977
});
6078

79+
rule.labels(getLabels(dependency, labelsMap));
80+
6181
rule.ruleType(RuleType.PREBUILT.getBuckName())
6282
.deps(external(dependency.getDeps()))
6383
.name(dependency.getTargetName());

buildSrc/src/main/java/com/uber/okbuck/core/manager/DependencyManager.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -438,8 +438,11 @@ private void processDependencies(
438438

439439
ImmutableList.Builder<Rule> rulesBuilder = ImmutableList.builder();
440440
rulesBuilder.addAll(LocalPrebuiltRuleComposer.compose(localPrebuiltDependencies.build()));
441+
442+
Map<String, List<String>> labelsMap = externalDependenciesExtension.getLabelsMap();
443+
441444
rulesBuilder.addAll(
442-
PrebuiltRuleComposer.compose(prebuiltDependencies.build(), sha256Cache));
445+
PrebuiltRuleComposer.compose(prebuiltDependencies.build(), sha256Cache, labelsMap));
443446
rulesBuilder.addAll(
444447
HttpFileRuleComposer.compose(httpFileDependencies.build(), sha256Cache));
445448

buildSrc/src/main/java/com/uber/okbuck/extension/ExternalDependenciesExtension.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,9 @@ public class ExternalDependenciesExtension {
7373
/** Set the path to the sha256sum caches of external dependency artifacts */
7474
@Input private String sha256Cache = OkBuckGradlePlugin.DEFAULT_OKBUCK_SHA256;
7575

76+
/** Map of dependency coordinates to labels for prebuilt rules */
77+
@Input private Map<String, List<String>> labelsMap = new HashMap<>();
78+
7679
@Nullable private Set<VersionlessDependency> allowAllVersionsSet;
7780

7881
public ExternalDependenciesExtension() {}
@@ -183,4 +186,8 @@ public String getSha256Cache() {
183186
public boolean shouldCleanCacheDir() {
184187
return cleanCacheDir;
185188
}
189+
190+
public Map<String, List<String>> getLabelsMap() {
191+
return labelsMap;
192+
}
186193
}

buildSrc/src/main/rocker/com/uber/okbuck/template/config/OkbuckPrebuilt.rocker.raw

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,8 @@ def @(okbuckPrebuiltRule)(
1313
deps = None,
1414
enable_jetifier = False,
1515
first_level = False,
16-
testonly = False):
16+
testonly = False,
17+
labels = None):
1718
if deps == None:
1819
deps = []
1920

@@ -64,6 +65,7 @@ def @(okbuckPrebuiltRule)(
6465
deps = deps,
6566
visibility = visibility,
6667
enable_jetifier = enable_jetifier,
68+
labels = labels,
6769
)
6870
elif prebuilt_type == "jar":
6971
@(prebuiltJarRule)(
@@ -74,6 +76,7 @@ def @(okbuckPrebuiltRule)(
7476
deps = deps,
7577
visibility = visibility,
7678
enable_jetifier = enable_jetifier,
79+
labels = labels,
7780
)
7881
else:
7982
fail("okbuck_prebuilt not supported for type {}".format(prebuilt_type))

buildSrc/src/main/rocker/com/uber/okbuck/template/java/Prebuilt.rocker.raw

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,13 @@ boolean firstLevel,
1313
}
1414
@if (firstLevel) {
1515
first_level = True,
16+
}
17+
@if (valid(labels)) {
18+
labels = [
19+
@for (label : sorted(labels)) {
20+
"@label",
21+
}
22+
],
1623
}
1724
maven_coords = "@mavenCoords",
1825
sha256 = "@sha256",
Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
package com.uber.okbuck.composer.java;
2+
3+
import static org.junit.Assert.assertEquals;
4+
import static org.junit.Assert.assertNotNull;
5+
import static org.junit.Assert.assertTrue;
6+
import static org.mockito.Mockito.mock;
7+
import static org.mockito.Mockito.when;
8+
9+
import com.uber.okbuck.core.dependency.OExternalDependency;
10+
import java.util.ArrayList;
11+
import java.util.HashMap;
12+
import java.util.List;
13+
import java.util.Map;
14+
import java.util.Set;
15+
import org.junit.Test;
16+
17+
public class PrebuiltRuleComposerTest {
18+
19+
@Test
20+
public void getLabels_withValidLabelsMap_returnsLabels() {
21+
// Arrange
22+
OExternalDependency dependency = mock(OExternalDependency.class);
23+
Map<String, List<String>> labelsMap = new HashMap<>();
24+
List<String> expectedLabels = new ArrayList<>();
25+
expectedLabels.add("test_label=value1,value2");
26+
labelsMap.put("com.example:test-artifact:1.0.0", expectedLabels);
27+
28+
when(dependency.getMavenCoordsForValidation()).thenReturn("com.example:test-artifact:1.0.0");
29+
30+
// Act
31+
Set<String> result = PrebuiltRuleComposer.getLabels(dependency, labelsMap);
32+
33+
// Assert
34+
assertNotNull(result);
35+
assertEquals(expectedLabels.size(), result.size());
36+
assertTrue(result.contains("test_label=value1,value2"));
37+
}
38+
39+
@Test
40+
public void getLabels_withNullLabelsMap_returnsEmptySet() {
41+
// Arrange
42+
OExternalDependency dependency = mock(OExternalDependency.class);
43+
44+
// Act
45+
Set<String> result = PrebuiltRuleComposer.getLabels(dependency, null);
46+
47+
// Assert
48+
assertNotNull(result);
49+
assertTrue(result.isEmpty());
50+
}
51+
52+
@Test
53+
public void getLabels_withEmptyLabelsMap_returnsEmptySet() {
54+
// Arrange
55+
OExternalDependency dependency = mock(OExternalDependency.class);
56+
Map<String, List<String>> emptyLabelsMap = new HashMap<>();
57+
58+
// Act
59+
Set<String> result = PrebuiltRuleComposer.getLabels(dependency, emptyLabelsMap);
60+
61+
// Assert
62+
assertNotNull(result);
63+
assertTrue(result.isEmpty());
64+
}
65+
66+
@Test
67+
public void getLabels_withMissingKey_returnsEmptySet() {
68+
// Arrange
69+
OExternalDependency dependency = mock(OExternalDependency.class);
70+
Map<String, List<String>> labelsMap = new HashMap<>();
71+
List<String> labels = new ArrayList<>();
72+
labels.add("other_label=other_value");
73+
labelsMap.put("com.other:other-artifact:2.0.0", labels);
74+
75+
when(dependency.getMavenCoordsForValidation()).thenReturn("com.example:test-artifact:1.0.0");
76+
77+
// Act
78+
Set<String> result = PrebuiltRuleComposer.getLabels(dependency, labelsMap);
79+
80+
// Assert
81+
assertNotNull(result);
82+
assertTrue(result.isEmpty());
83+
}
84+
85+
@Test
86+
public void getLabels_withNullValue_returnsEmptySet() {
87+
// Arrange
88+
OExternalDependency dependency = mock(OExternalDependency.class);
89+
Map<String, List<String>> labelsMap = new HashMap<>();
90+
labelsMap.put("com.example:test-artifact:1.0.0", null);
91+
92+
when(dependency.getMavenCoordsForValidation()).thenReturn("com.example:test-artifact:1.0.0");
93+
94+
// Act
95+
Set<String> result = PrebuiltRuleComposer.getLabels(dependency, labelsMap);
96+
97+
// Assert
98+
assertNotNull(result);
99+
assertTrue(result.isEmpty());
100+
}
101+
102+
@Test
103+
public void getLabels_withEmptyValue_returnsEmptySet() {
104+
// Arrange
105+
OExternalDependency dependency = mock(OExternalDependency.class);
106+
Map<String, List<String>> labelsMap = new HashMap<>();
107+
labelsMap.put("com.example:test-artifact:1.0.0", new ArrayList<>());
108+
109+
when(dependency.getMavenCoordsForValidation()).thenReturn("com.example:test-artifact:1.0.0");
110+
111+
// Act
112+
Set<String> result = PrebuiltRuleComposer.getLabels(dependency, labelsMap);
113+
114+
// Assert
115+
assertNotNull(result);
116+
assertTrue(result.isEmpty());
117+
}
118+
}

0 commit comments

Comments
 (0)