Skip to content

Commit bce49df

Browse files
committed
use Usage attribute instead of custom attribute
this will solve issues when projects create custom configurations that aren't aware of archrules
1 parent 801aa7e commit bce49df

File tree

11 files changed

+223
-98
lines changed

11 files changed

+223
-98
lines changed

nebula-archrules-gradle-plugin/build.gradle.kts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ description = "Plugins for authoring and running Nebula ArchRules"
66
dependencies {
77
implementation(project(":nebula-archrules-core"))
88
implementation("tools.jackson.core:jackson-databind:3.0.2")
9+
910
testImplementation("net.javacrumbs.json-unit:json-unit-assertj:5.0.0")
1011
testImplementation("org.json:json:20250517")
1112
}

nebula-archrules-gradle-plugin/gradle.lockfile

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,13 @@
44
cglib:cglib-nodep:3.2.2=testRuntimeClasspath
55
com.fasterxml.jackson.core:jackson-annotations:2.20=compileClasspath,implementationDependenciesMetadata,mainArchRulesRuntime,runtimeClasspath,testArchRulesRuntime,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath
66
com.jayway.jsonpath:json-path:2.9.0=testArchRulesRuntime,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath
7-
com.netflix.nebula:archrules-deprecation:0.7.1=archRules,mainArchRulesRuntime,testArchRulesRuntime
8-
com.netflix.nebula:archrules-joda:0.7.1=archRules,mainArchRulesRuntime,testArchRulesRuntime
9-
com.netflix.nebula:archrules-nullability:0.7.1=archRules,mainArchRulesRuntime,testArchRulesRuntime
10-
com.netflix.nebula:archrules-security:0.7.1=archRules,mainArchRulesRuntime,testArchRulesRuntime
11-
com.netflix.nebula:archrules-testing-frameworks:0.7.1=archRules,mainArchRulesRuntime,testArchRulesRuntime
12-
com.netflix.nebula:nebula-archrules-core:0.5.5=archRules,mainArchRulesRuntime,testArchRulesRuntime
7+
com.netflix.nebula:archrules-common:0.8.0=archRules,mainArchRulesRuntime,testArchRulesRuntime
8+
com.netflix.nebula:archrules-deprecation:0.8.0=archRules,mainArchRulesRuntime,testArchRulesRuntime
9+
com.netflix.nebula:archrules-joda:0.8.0=archRules,mainArchRulesRuntime,testArchRulesRuntime
10+
com.netflix.nebula:archrules-nullability:0.8.0=archRules,mainArchRulesRuntime,testArchRulesRuntime
11+
com.netflix.nebula:archrules-security:0.8.0=archRules,mainArchRulesRuntime,testArchRulesRuntime
12+
com.netflix.nebula:archrules-testing-frameworks:0.8.0=archRules,mainArchRulesRuntime,testArchRulesRuntime
13+
com.netflix.nebula:nebula-archrules-core:0.7.0=archRules,mainArchRulesRuntime,testArchRulesRuntime
1314
com.netflix.nebula:nebula-test:11.11.3=testArchRulesRuntime,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath
1415
com.tngtech.archunit:archunit:1.4.1=archRules,compileClasspath,implementationDependenciesMetadata,mainArchRulesRuntime,runtimeClasspath,testArchRulesRuntime,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath
1516
io.github.java-diff-utils:java-diff-utils:4.12=kotlinInternalAbiValidation

nebula-archrules-gradle-plugin/src/main/java/com/netflix/nebula/archrules/gradle/ArchRuleAttribute.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,15 @@ public interface ArchRuleAttribute extends Named {
1212

1313
/**
1414
* Attribute used to denote an archrules library, and to resolve archrules variants
15+
* @deprecated needed for backward compatibility until all artifacts are produced with new usage attribute
1516
*/
17+
@Deprecated
1618
Attribute<ArchRuleAttribute> ARCH_RULES_ATTRIBUTE =
1719
Attribute.of("com.netflix.nebula.archrules", ArchRuleAttribute.class);
1820

1921
/**
20-
* The only recognized value of this attribute
22+
* Used in archrules artifacts to allow them to be selected via the variant selection algorithm
2123
*/
2224
String ARCH_RULES = "arch-rules";
25+
2326
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
package com.netflix.nebula.archrules.gradle
2+
3+
import com.netflix.nebula.archrules.gradle.ArchRuleAttribute.ARCH_RULES
4+
import org.gradle.api.attributes.AttributeCompatibilityRule
5+
import org.gradle.api.attributes.CompatibilityCheckDetails
6+
import org.gradle.api.attributes.Usage
7+
8+
@Deprecated("needed for backward compatibility until all artifacts are produced with new usage attribute")
9+
class ArchRuleCompatibilityRule : AttributeCompatibilityRule<Usage> {
10+
override fun execute(t: CompatibilityCheckDetails<Usage>) {
11+
if (t.consumerValue?.name == ARCH_RULES && t.producerValue?.name == Usage.JAVA_RUNTIME) {
12+
t.compatible()
13+
} else if (t.consumerValue?.name == ARCH_RULES && t.producerValue?.name == ARCH_RULES) {
14+
t.compatible()
15+
} else {
16+
t.incompatible()
17+
}
18+
}
19+
}

nebula-archrules-gradle-plugin/src/main/kotlin/com/netflix/nebula/archrules/gradle/ArchrulesLibraryPlugin.kt

Lines changed: 19 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import com.netflix.nebula.archrules.gradle.ArchRuleAttribute.ARCH_RULES
44
import org.gradle.api.Plugin
55
import org.gradle.api.Project
66
import org.gradle.api.artifacts.type.ArtifactTypeDefinition
7+
import org.gradle.api.attributes.Usage
78
import org.gradle.api.component.AdhocComponentWithVariants
89
import org.gradle.api.internal.artifacts.dsl.LazyPublishArtifact
910
import org.gradle.api.internal.project.ProjectInternal
@@ -17,22 +18,26 @@ import org.gradle.api.tasks.TaskProvider
1718
import org.gradle.api.tasks.bundling.Jar
1819
import org.gradle.api.tasks.compile.JavaCompile
1920
import org.gradle.jvm.component.internal.JvmSoftwareComponentInternal
20-
import org.gradle.kotlin.dsl.add
21-
import org.gradle.kotlin.dsl.dependencies
22-
import org.gradle.kotlin.dsl.getByType
23-
import org.gradle.kotlin.dsl.invoke
24-
import org.gradle.kotlin.dsl.named
25-
import org.gradle.kotlin.dsl.register
21+
import org.gradle.kotlin.dsl.*
2622
import org.gradle.kotlin.dsl.support.serviceOf
27-
import org.gradle.kotlin.dsl.withType
2823
import org.gradle.testing.base.TestingExtension
29-
import kotlin.collections.mapOf
3024

3125
class ArchrulesLibraryPlugin : Plugin<Project> {
3226

3327
override fun apply(project: Project) {
3428
val version = determineVersion()
3529
project.pluginManager.withPlugin("java") {
30+
project.dependencies {
31+
attributesSchema {
32+
attribute(Usage.USAGE_ATTRIBUTE){
33+
compatibilityRules.add(ArchRuleCompatibilityRule::class)
34+
}
35+
}
36+
}
37+
project.pluginManager.apply(ConfigureNonArchRulesSourceSetsPlugin::class)
38+
project.plugins.withId("com.google.protobuf") {
39+
project.pluginManager.apply(ProtoSupportPlugin::class)
40+
}
3641
val javaExt = project.extensions.getByType<JavaPluginExtension>()
3742
val archRulesSourceSet = javaExt.sourceSets.create("archRules")
3843
project.configurations.named(archRulesSourceSet.implementationConfigurationName).configure {
@@ -41,11 +46,13 @@ class ArchrulesLibraryPlugin : Plugin<Project> {
4146
project.configurations.named(archRulesSourceSet.runtimeClasspathConfigurationName).configure {
4247
attributes {
4348
attribute(ArchRuleAttribute.ARCH_RULES_ATTRIBUTE, project.objects.named(ARCH_RULES))
49+
attribute(Usage.USAGE_ATTRIBUTE, project.objects.named(ARCH_RULES))
4450
}
4551
}
4652
project.configurations.named(archRulesSourceSet.compileClasspathConfigurationName).configure {
4753
attributes {
4854
attribute(ArchRuleAttribute.ARCH_RULES_ATTRIBUTE, project.objects.named(ARCH_RULES))
55+
attribute(Usage.USAGE_ATTRIBUTE, project.objects.named(ARCH_RULES))
4956
}
5057
}
5158
project.dependencies.add(
@@ -102,12 +109,14 @@ class ArchrulesLibraryPlugin : Plugin<Project> {
102109
extendsFrom(project.configurations.getByName(archRulesSourceSet.runtimeClasspathConfigurationName))
103110
attributes {
104111
attribute(ArchRuleAttribute.ARCH_RULES_ATTRIBUTE, project.objects.named(ARCH_RULES))
112+
attribute(Usage.USAGE_ATTRIBUTE, project.objects.named(ARCH_RULES))
105113
}
106114
}
107115
project.configurations.named(compileClasspathConfigurationName).configure {
108116
extendsFrom(project.configurations.getByName(archRulesSourceSet.compileClasspathConfigurationName))
109117
attributes {
110118
attribute(ArchRuleAttribute.ARCH_RULES_ATTRIBUTE, project.objects.named(ARCH_RULES))
119+
attribute(Usage.USAGE_ATTRIBUTE, project.objects.named(ARCH_RULES))
111120
}
112121
}
113122
}
@@ -145,9 +154,10 @@ class ArchrulesLibraryPlugin : Plugin<Project> {
145154
project.configurations.getByName(sourceSet.implementationConfigurationName),
146155
project.configurations.getByName(sourceSet.runtimeOnlyConfigurationName)
147156
)
148-
outgoing.artifacts.add(jarArtifact);
157+
outgoing.artifacts.add(jarArtifact)
149158
attributes {
150159
attribute(ArchRuleAttribute.ARCH_RULES_ATTRIBUTE, project.objects.named(ARCH_RULES))
160+
attribute(Usage.USAGE_ATTRIBUTE, project.objects.named(ARCH_RULES))
151161
attribute(ArtifactTypeDefinition.ARTIFACT_TYPE_ATTRIBUTE, ArtifactTypeDefinition.JAR_TYPE)
152162
}
153163
}

nebula-archrules-gradle-plugin/src/main/kotlin/com/netflix/nebula/archrules/gradle/ArchrulesRunnerPlugin.kt

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -19,16 +19,24 @@ class ArchrulesRunnerPlugin : Plugin<Project> {
1919
isCanBeConsumed = false
2020
isCanBeResolved = true
2121
attributes {
22-
attribute(
23-
ArchRuleAttribute.ARCH_RULES_ATTRIBUTE,
24-
project.objects.named<ArchRuleAttribute>(ARCH_RULES)
25-
)
26-
attribute(Usage.USAGE_ATTRIBUTE, project.objects.named<Usage>(Usage.JAVA_RUNTIME))
22+
attribute(ArchRuleAttribute.ARCH_RULES_ATTRIBUTE, project.objects.named(ARCH_RULES))
23+
attribute(Usage.USAGE_ATTRIBUTE, project.objects.named(ARCH_RULES))
2724
attribute(Category.CATEGORY_ATTRIBUTE, project.objects.named<Category>(Category.LIBRARY))
2825
attribute(Bundling.BUNDLING_ATTRIBUTE, project.objects.named(Bundling.EXTERNAL))
2926
}
3027
}
3128
project.plugins.withId("java") {
29+
project.dependencies {
30+
attributesSchema {
31+
attribute(Usage.USAGE_ATTRIBUTE){
32+
compatibilityRules.add(ArchRuleCompatibilityRule::class)
33+
}
34+
}
35+
}
36+
project.pluginManager.apply(ConfigureNonArchRulesSourceSetsPlugin::class)
37+
project.plugins.withId("com.google.protobuf") {
38+
project.pluginManager.apply(ProtoSupportPlugin::class)
39+
}
3240
val archRulesExt = project.extensions.create<ArchrulesExtension>("archRules")
3341
archRulesExt.consoleReportEnabled.convention(true)
3442
archRulesExt.skipPassingSummaries.convention(false)
@@ -57,7 +65,7 @@ class ArchrulesRunnerPlugin : Plugin<Project> {
5765
onlyIf { archRulesExt.consoleReportEnabled.get() }
5866
}
5967

60-
val enforceTask = project.tasks.register<EnforceArchRulesTask>("enforceArchRules"){
68+
val enforceTask = project.tasks.register<EnforceArchRulesTask>("enforceArchRules") {
6169
dependsOn(checkTasks)
6270
dataFiles.set(
6371
project.provider { (project.tasks.withType<CheckRulesTask>().flatMap { it.outputs.files }) }
@@ -82,7 +90,8 @@ class ArchrulesRunnerPlugin : Plugin<Project> {
8290
configurations.getByName(sourceSet.runtimeClasspathConfigurationName)
8391
)
8492
attributes {
85-
attribute(ArchRuleAttribute.ARCH_RULES_ATTRIBUTE, project.objects.named<ArchRuleAttribute>(ARCH_RULES))
93+
attribute(ArchRuleAttribute.ARCH_RULES_ATTRIBUTE, project.objects.named(ARCH_RULES))
94+
attribute(Usage.USAGE_ATTRIBUTE, project.objects.named(ARCH_RULES))
8695
}
8796
}
8897
tasks.register<CheckRulesTask>("checkArchRules" + sourceSet.name.capitalized()) {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
package com.netflix.nebula.archrules.gradle
2+
3+
import org.gradle.api.Action
4+
import org.gradle.api.Plugin
5+
import org.gradle.api.Project
6+
import org.gradle.api.plugins.JavaPluginExtension
7+
import org.gradle.kotlin.dsl.getByType
8+
import org.gradle.kotlin.dsl.named
9+
10+
/**
11+
* this is an internal plugin that configures all non-archRule related source sets to resolve the compile classpath with the NOT_ARCH_RULES attribute
12+
* This helps ensure that the archrules variant is not accidentally selected
13+
* it should only be applied in response to the java plugin
14+
*/
15+
class ConfigureNonArchRulesSourceSetsPlugin : Plugin<Project> {
16+
override fun apply(project: Project) {
17+
val javaExt = project.extensions.getByType<JavaPluginExtension>()
18+
javaExt.sourceSets.configureEach(Action {
19+
if (!setOf("archRules", "archRulesTest").contains(this.name)) {
20+
project.configurations.named(compileClasspathConfigurationName).configure {
21+
attributes {
22+
//attribute(ArchRuleAttribute.ARCH_RULES_ATTRIBUTE, project.objects.named(NOT_ARCH_RULES))
23+
}
24+
}
25+
}
26+
})
27+
}
28+
}
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
package com.netflix.nebula.archrules.gradle
2+
3+
import org.gradle.api.Action
4+
import org.gradle.api.Plugin
5+
import org.gradle.api.Project
6+
import org.gradle.api.plugins.JavaPluginExtension
7+
import org.gradle.kotlin.dsl.getByType
8+
import org.gradle.kotlin.dsl.named
9+
10+
/**
11+
* This is an internal plugin which provides interop with the protobuf plugin.
12+
* It should be only applied in response to the proto plugin
13+
*/
14+
class ProtoSupportPlugin : Plugin<Project> {
15+
override fun apply(project: Project) {
16+
project.pluginManager.withPlugin("java") {
17+
val javaExt = project.extensions.getByType<JavaPluginExtension>()
18+
/**
19+
* Ideally we would get the source sets from ProtobufExtension, but it is not exposed
20+
*/
21+
javaExt.sourceSets.configureEach(Action {
22+
val configurationName = if (this.name == "main") "compileProtoPath" else name + "CompileProtoPath"
23+
project.configurations.named(configurationName).configure {
24+
attributes {
25+
// attribute(ArchRuleAttribute.ARCH_RULES_ATTRIBUTE, project.objects.named(NOT_ARCH_RULES))
26+
}
27+
}
28+
})
29+
}
30+
}
31+
}
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
package com.netflix.nebula.archrules.gradle
2+

nebula-archrules-gradle-plugin/src/test/kotlin/com/netflix/nebula/archrules/gradle/ArchrulesLibraryPluginTest.kt

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ class ArchrulesLibraryPluginTest {
3131
fun `plugin produces maven publication`() {
3232
val runner = testProject(projectDir) {
3333
properties {
34-
gradleCache(true)
34+
buildCache(true)
3535
}
3636
settings {
3737
name("library-with-rules")
@@ -123,7 +123,7 @@ class ArchrulesLibraryPluginTest {
123123
fun `main dependencies are included in archRules`() {
124124
val runner = testProject(projectDir) {
125125
properties {
126-
gradleCache(true)
126+
buildCache(true)
127127
}
128128
settings {
129129
name("library-with-rules")
@@ -194,7 +194,7 @@ class ArchrulesLibraryPluginTest {
194194
fun `plugin produces proper outgoingVariants`() {
195195
val runner = testProject(projectDir) {
196196
properties {
197-
gradleCache(true)
197+
buildCache(true)
198198
}
199199
settings {
200200
name("library-with-rules")
@@ -228,8 +228,8 @@ class ArchrulesLibraryPluginTest {
228228
.contains("Variant archRulesRuntimeElements")
229229
.contains("Variant testResultsElementsForArchRulesTest")
230230
.doesNotContain("Variant archRulesApiElements")
231-
.contains("- com.netflix.nebula.archrules = arch-rules")
232-
val indexOfArchRulesVariant = result.output.indexOf("- com.netflix.nebula.archrules = arch-rules")
231+
.contains("- org.gradle.usage = arch-rules")
232+
val indexOfArchRulesVariant = result.output.indexOf("- org.gradle.usage = arch-rules")
233233
assertThat(indexOfArchRulesVariant)
234234
.`as`("archRulesRuntimeElements has arch-rules variant")
235235
.isGreaterThan(0)

0 commit comments

Comments
 (0)