Skip to content

Commit 3decb69

Browse files
committed
WIP aggregate console report
1 parent 131f4d1 commit 3decb69

File tree

5 files changed

+186
-1
lines changed

5 files changed

+186
-1
lines changed

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

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,13 @@ gradlePlugin {
2626
description = "Sets up a project to consume archrules libraries and run them against the code in the current project"
2727
tags.addAll("nebula", "archunit")
2828
}
29+
create("aggregate") {
30+
id = "com.netflix.nebula.archrules.aggregate"
31+
implementationClass = "com.netflix.nebula.archrules.gradle.ArchrulesAggregateConsoleReportPlugin"
32+
displayName = "ArchRules Aggregate Console Report Plugin"
33+
description = "Consolidates console reports for multiple subprojects"
34+
tags.addAll("nebula", "archunit")
35+
}
2936
}
3037
}
3138
java {
@@ -69,4 +76,4 @@ configurations.named("mainArchRulesRuntime").configure {
6976
}
7077
}
7178
}
72-
}
79+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
package com.netflix.nebula.archrules.gradle
2+
3+
import com.tngtech.archunit.lang.Priority
4+
import org.gradle.api.Plugin
5+
import org.gradle.api.Project
6+
import org.gradle.api.attributes.Category
7+
import org.gradle.api.attributes.VerificationType
8+
import org.gradle.kotlin.dsl.named
9+
import org.gradle.kotlin.dsl.project
10+
import org.gradle.kotlin.dsl.register
11+
12+
class ArchrulesAggregateConsoleReportPlugin : Plugin<Project> {
13+
override fun apply(project: Project) {
14+
val archRulesAggregateDependencies = project.configurations.dependencyScope("archRulesAggregateDependencies") {
15+
description = "projects to collect archrules data from"
16+
}
17+
val archRulesDataFiles = project.configurations.resolvable("archRulesDataFiles") {
18+
extendsFrom(archRulesAggregateDependencies.get())
19+
attributes {
20+
attribute(Category.CATEGORY_ATTRIBUTE, project.objects.named(Category.VERIFICATION))
21+
attribute(VerificationType.VERIFICATION_TYPE_ATTRIBUTE, project.objects.named("arch-rules"))
22+
}
23+
}
24+
project.subprojects {
25+
project.dependencies.add("archRulesAggregateDependencies", project.dependencies.project(":$name"))
26+
}
27+
project.tasks.register<PrintConsoleReportTask>("archRulesAggregateConsoleReport") {
28+
dataFiles.set(archRulesDataFiles.map {
29+
it.incoming.artifactView {
30+
// lenient(true)
31+
}.files
32+
})
33+
summaryForPassingDisabled.set(false)
34+
detailsThreshold.set(Priority.MEDIUM)
35+
}
36+
}
37+
}

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

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,14 @@ import com.netflix.nebula.archrules.gradle.ArchRuleAttribute.ARCH_RULES
44
import com.tngtech.archunit.lang.Priority
55
import org.gradle.api.Plugin
66
import org.gradle.api.Project
7+
import org.gradle.api.artifacts.type.ArtifactTypeDefinition
78
import org.gradle.api.attributes.Bundling
89
import org.gradle.api.attributes.Category
910
import org.gradle.api.attributes.Usage
11+
import org.gradle.api.attributes.VerificationType
12+
import org.gradle.api.component.AdhocComponentWithVariants
1013
import org.gradle.api.plugins.JavaPluginExtension
14+
import org.gradle.api.plugins.internal.JavaConfigurationVariantMapping
1115
import org.gradle.api.tasks.SourceSet
1216
import org.gradle.internal.extensions.stdlib.capitalized
1317
import org.gradle.kotlin.dsl.add
@@ -63,6 +67,20 @@ class ArchrulesRunnerPlugin : Plugin<Project> {
6367
onlyIf { archRulesExt.consoleReportEnabled.get() }
6468
}
6569

70+
project.configurations.consumable("archRulesReportElements") {
71+
description = "Report data for ArchRules"
72+
outgoing.artifacts(
73+
project.provider { (project.tasks.withType<CheckRulesTask>().flatMap { it.outputs.files }) }
74+
){
75+
type = ArtifactTypeDefinition.BINARY_DATA_TYPE
76+
builtBy(project.tasks.withType<CheckRulesTask>())
77+
}
78+
attributes {
79+
attribute(Category.CATEGORY_ATTRIBUTE, project.objects.named(Category.VERIFICATION))
80+
attribute(VerificationType.VERIFICATION_TYPE_ATTRIBUTE, project.objects.named("arch-rules"))
81+
}
82+
}
83+
6684
val enforceTask = project.tasks.register<EnforceArchRulesTask>("enforceArchRules") {
6785
dependsOn(checkTasks)
6886
dataFiles.set(
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
package com.netflix.nebula.archrules.gradle
2+
3+
import nebula.test.dsl.TestKitAssertions.assertThat
4+
import nebula.test.dsl.main
5+
import nebula.test.dsl.plugins
6+
import nebula.test.dsl.properties
7+
import nebula.test.dsl.repositories
8+
import nebula.test.dsl.rootProject
9+
import nebula.test.dsl.run
10+
import nebula.test.dsl.src
11+
import nebula.test.dsl.subProject
12+
import nebula.test.dsl.testProject
13+
import org.junit.jupiter.api.Test
14+
import org.junit.jupiter.api.io.TempDir
15+
import java.io.File
16+
17+
class ArchrulesAggregateConsoleReportPluginTest {
18+
@TempDir
19+
lateinit var projectDir: File
20+
21+
@Test
22+
fun test() {
23+
val runner = testProject(projectDir) {
24+
properties {
25+
buildCache(true)
26+
}
27+
rootProject {
28+
plugins {
29+
id("com.netflix.nebula.archrules.aggregate")
30+
}
31+
}
32+
subProject("library") {
33+
plugins {
34+
id("java")
35+
id("com.netflix.nebula.archrules.runner")
36+
}
37+
src {
38+
main {
39+
exampleLibraryClass()
40+
}
41+
}
42+
}
43+
subProject("sub1") {
44+
plugins {
45+
id("java")
46+
id("com.netflix.nebula.archrules.runner")
47+
}
48+
repositories {
49+
mavenCentral()
50+
}
51+
dependencies(
52+
"""implementation(project(":library"))""",
53+
"""archRules("com.netflix.nebula:archrules-deprecation:0.+")"""
54+
)
55+
src {
56+
main {
57+
exampleDeprecatedUsage("FailingCode1")
58+
}
59+
}
60+
}
61+
subProject("sub2") {
62+
plugins {
63+
id("java")
64+
id("com.netflix.nebula.archrules.runner")
65+
}
66+
repositories{
67+
mavenCentral()
68+
}
69+
dependencies(
70+
"""implementation(project(":library"))""",
71+
"""archRules("com.netflix.nebula:archrules-deprecation:0.+")"""
72+
)
73+
src {
74+
main {
75+
exampleDeprecatedUsage("FailingCode2")
76+
}
77+
}
78+
}
79+
}
80+
81+
runner.run("dI", "--configuration", "archRulesDataFiles", "--dependency", "sub1"){
82+
forwardOutput()
83+
}
84+
val result = runner.run("archRulesAggregateConsoleReport", "build") {
85+
forwardOutput()
86+
}
87+
assertThat(result.output)
88+
.contains("deprecatedForRemoval MEDIUM (2 failures)")
89+
.contains("deprecated LOW (4 failures)")
90+
}
91+
}

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

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -165,6 +165,26 @@ class ArchrulesRunnerPluginTest {
165165
.contains("Note: In order to see details of rules with priority less than MEDIUM,")
166166
}
167167

168+
@ParameterizedTest
169+
@EnumSource(SupportedGradleVersion::class)
170+
fun `plugin produces outgoing variants for reports`(gradleVersion: SupportedGradleVersion) {
171+
val runner = testProject(projectDir) {
172+
setupConsumerProject()
173+
}
174+
175+
val result = runner.run("outgoingVariants") {
176+
withGradleVersion(gradleVersion.version)
177+
forwardOutput()
178+
}
179+
180+
containsInOrder(result.output,
181+
"Variant archRulesReportElements",
182+
"- org.gradle.category = verification",
183+
"- org.gradle.verificationtype = arch-rules",
184+
"- build/reports/archrules/main.data (artifactType = binary)",
185+
"- build/reports/archrules/test.data (artifactType = binary)")
186+
}
187+
168188
@Test
169189
fun `plugin checks each sourceset from its runtime`() {
170190
val runner = testProject(projectDir) {
@@ -600,4 +620,16 @@ archRules {
600620
assertThat(deprecationResult).isNotNull
601621
assertThat(deprecationResult!!.rule.priority).isEqualTo(Priority.LOW)
602622
}
623+
624+
private fun containsInOrder(actual: String, vararg expected: String) {
625+
var i = 0
626+
for (e in expected) {
627+
assertThat(actual).contains(e)
628+
val newIndex = actual.indexOf(e, i)
629+
assertThat(newIndex)
630+
.`as`("$e found at $newIndex but should be after $i")
631+
.isGreaterThan(i)
632+
i = newIndex
633+
}
634+
}
603635
}

0 commit comments

Comments
 (0)