Skip to content

Commit 520db46

Browse files
committed
add setting for failureThreshold
1 parent d718ab6 commit 520db46

File tree

9 files changed

+225
-70
lines changed

9 files changed

+225
-70
lines changed

README.md

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,8 @@ dependencies {
140140
}
141141
```
142142

143+
#### Report Configuration
144+
143145
The plugin can generate JSON and console reports. Both are enabled by default. The console report can be disabled:
144146
```kotlin
145147
archRules {
@@ -154,6 +156,8 @@ archRules {
154156
}
155157
```
156158

159+
#### Configuring which code is tested
160+
157161
You can skip running rules on a specific source set:
158162
```kotlin
159163
archRules {
@@ -162,6 +166,16 @@ archRules {
162166
```
163167
The `archRulesTest` source set is skipped by default.
164168

169+
#### Configuring Build Failures
170+
171+
You can define which rules should cause a build to fail be setting a failure threshold:
172+
```kotlin
173+
archRules {
174+
failureThreshold("HIGH")
175+
}
176+
```
177+
Any rules which fail with that priority or higher will cause the build to fail. By default, the build will not fail on any priority.
178+
165179
## How it works
166180

167181
The Archrules Library plugin produces a separate Jar for the `archRules` sourceset, which is exposed as an alternate variant of the library. It also will automatically generate a `META-INF/services` file which contains a reference for each implementation of `com.netflix.nebula.archrules.core.ArchRulesService` to declare it as a service provider.

nebula-archrules-gradle-plugin/gradle.lockfile

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +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.4.0=archRules,mainArchRulesRuntime,testArchRulesRuntime
8-
com.netflix.nebula:archrules-joda:0.4.0=archRules,mainArchRulesRuntime,testArchRulesRuntime
9-
com.netflix.nebula:archrules-nullability:0.4.0=archRules,mainArchRulesRuntime,testArchRulesRuntime
10-
com.netflix.nebula:archrules-testing-frameworks:0.4.0=archRules,mainArchRulesRuntime,testArchRulesRuntime
11-
com.netflix.nebula:nebula-archrules-core:0.3.0=archRules
12-
com.netflix.nebula:nebula-archrules-core:0.5.2=mainArchRulesRuntime,testArchRulesRuntime
13-
com.netflix.nebula:nebula-test:11.10.1=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
13+
com.netflix.nebula:nebula-test:11.11.3=testArchRulesRuntime,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath
1414
com.tngtech.archunit:archunit:1.4.1=archRules,compileClasspath,implementationDependenciesMetadata,mainArchRulesRuntime,runtimeClasspath,testArchRulesRuntime,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath
1515
io.github.java-diff-utils:java-diff-utils:4.12=kotlinInternalAbiValidation
1616
net.bytebuddy:byte-buddy:1.17.7=testArchRulesRuntime,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath

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

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,17 +2,18 @@
22

33
import org.gradle.api.Named;
44
import org.gradle.api.attributes.Attribute;
5-
import org.jspecify.annotations.NonNull;
5+
import org.jspecify.annotations.NullMarked;
66

77
/**
88
* Attribute used to denote an archrules library, and to resolve archrules variants
99
*/
10+
@NullMarked
1011
public interface ArchRuleAttribute extends Named {
1112

1213
/**
1314
* Attribute used to denote an archrules library, and to resolve archrules variants
1415
*/
15-
Attribute<@NonNull ArchRuleAttribute> ARCH_RULES_ATTRIBUTE =
16+
Attribute<ArchRuleAttribute> ARCH_RULES_ATTRIBUTE =
1617
Attribute.of("com.netflix.nebula.archrules", ArchRuleAttribute.class);
1718

1819
/**

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

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package com.netflix.nebula.archrules.gradle
22

3+
import com.tngtech.archunit.lang.Priority
34
import org.gradle.api.provider.ListProperty
45
import org.gradle.api.provider.Property
56

@@ -15,10 +16,20 @@ abstract class ArchrulesExtension {
1516
abstract val skipPassingSummaries: Property<Boolean>
1617
abstract val sourceSetsToSkip: ListProperty<String>
1718

19+
abstract val failureThreshold: Property<Priority>
20+
1821
/**
1922
* Add a source set to the list of sourcesets to skip
2023
*/
2124
fun skipSourceSet(name: String) {
2225
sourceSetsToSkip.add(name)
2326
}
27+
28+
fun failureThreshold(priority: Priority) {
29+
failureThreshold.set(priority)
30+
}
31+
32+
fun failureThreshold(priority: String) {
33+
failureThreshold.set(Priority.valueOf(priority))
34+
}
2435
}

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

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,8 +54,18 @@ class ArchrulesRunnerPlugin : Plugin<Project> {
5454
onlyIf { archRulesExt.consoleReportEnabled.get() }
5555
}
5656

57+
val enforceTask = project.tasks.register<EnforceArchRulesTask>("enforceArchRules"){
58+
dependsOn(checkTasks)
59+
dataFiles.set(
60+
project.provider { (project.tasks.withType<CheckRulesTask>().flatMap { it.outputs.files }) }
61+
)
62+
failureThreshold.set(archRulesExt.failureThreshold)
63+
onlyIf { failureThreshold.isPresent }
64+
}
65+
5766
project.tasks.named("check") {
5867
dependsOn(checkTasks)
68+
dependsOn(enforceTask)
5969
finalizedBy(jsonReportTask, consoleReportTask)
6070
}
6171
}
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
package com.netflix.nebula.archrules.gradle
2+
3+
import com.tngtech.archunit.lang.Priority
4+
import org.gradle.api.DefaultTask
5+
import org.gradle.api.provider.ListProperty
6+
import org.gradle.api.provider.Property
7+
import org.gradle.api.tasks.*
8+
import java.io.File
9+
10+
@CacheableTask
11+
abstract class EnforceArchRulesTask : DefaultTask() {
12+
13+
/**
14+
* The data files to read in. These files should container binary data representing [RuleResult]s
15+
* @return all data files to process
16+
*/
17+
@get:InputFiles
18+
@get:PathSensitive(PathSensitivity.RELATIVE)
19+
abstract val dataFiles: ListProperty<File>
20+
21+
/**
22+
* The data files to read in. These files should container binary data representing [RuleResult]s
23+
* @return all data files to process
24+
*/
25+
@get:Input
26+
@get:Optional
27+
abstract val failureThreshold: Property<Priority>
28+
29+
@TaskAction
30+
fun enforce() {
31+
val criticalFailures = dataFiles.get()
32+
.filter { it.exists() }
33+
.flatMap { ViolationsUtil.readDetails(it) }
34+
.filter { it.status == RuleResultStatus.FAIL }
35+
.filter { shouldFail(it.rule.priority) }
36+
if (criticalFailures.isNotEmpty()) {
37+
throw RuntimeException(
38+
"ArchRules failed: ${
39+
criticalFailures.joinToString("\n") {
40+
"${it.rule.ruleName} (${it.rule.priority})"
41+
}
42+
}"
43+
)
44+
}
45+
}
46+
47+
fun shouldFail(failurePriority: Priority): Boolean {
48+
return when (failureThreshold.orNull) {
49+
Priority.HIGH -> failurePriority == Priority.HIGH
50+
Priority.MEDIUM -> failurePriority == Priority.MEDIUM || failurePriority == Priority.HIGH
51+
Priority.LOW -> true
52+
null -> false
53+
}
54+
}
55+
}

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

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ class ArchrulesRunnerPluginTest {
4747
fun `plugin checks each sourceset`(gradleVersion: SupportedGradleVersion) {
4848
val runner = testProject(projectDir) {
4949
properties {
50-
gradleCache(true)
50+
buildCache(true)
5151
property("org.gradle.configuration-cache", "true")
5252
}
5353
settings {
@@ -97,6 +97,9 @@ class ArchrulesRunnerPluginTest {
9797
.`as`("archRules console report runs by default")
9898
.hasOutcome(TaskOutcome.SUCCESS)
9999

100+
assertThat(result.task(":enforceArchRules"))
101+
.hasOutcome(TaskOutcome.SKIPPED)
102+
100103
assertThat(result)
101104
.hasNoMutableStateWarnings()
102105
.hasNoDeprecationWarnings()
@@ -129,7 +132,7 @@ class ArchrulesRunnerPluginTest {
129132
fun `plugin checks each sourceset from its runtime`() {
130133
val runner = testProject(projectDir) {
131134
properties {
132-
gradleCache(true)
135+
buildCache(true)
133136
}
134137
settings {
135138
name("consumer")
@@ -191,7 +194,7 @@ class ArchrulesRunnerPluginTest {
191194
fun `console report can be disabled`(gradleVersion: SupportedGradleVersion) {
192195
val runner = testProject(projectDir) {
193196
properties {
194-
gradleCache(true)
197+
buildCache(true)
195198
}
196199
settings {
197200
name("consumer")
@@ -249,7 +252,7 @@ archRules {
249252
fun `plugin checks additional sourcesets`(gradleVersion: SupportedGradleVersion) {
250253
val runner = testProject(projectDir) {
251254
properties {
252-
gradleCache(true)
255+
buildCache(true)
253256
}
254257
settings {
255258
name("consumer")
@@ -287,7 +290,7 @@ archRules {
287290
fun `passing summaries print by default`() {
288291
val runner = testProject(projectDir) {
289292
properties {
290-
gradleCache(true)
293+
buildCache(true)
291294
}
292295
settings {
293296
name("consumer")
@@ -333,7 +336,7 @@ archRules {
333336
fun `passing summaries can be disabled`() {
334337
val runner = testProject(projectDir) {
335338
properties {
336-
gradleCache(true)
339+
buildCache(true)
337340
}
338341
settings {
339342
name("consumer")
@@ -386,7 +389,7 @@ archRules {
386389
fun `plugin skips archrules library test sourceset by default`() {
387390
val runner = testProject(projectDir) {
388391
properties {
389-
gradleCache(true)
392+
buildCache(true)
390393
}
391394
settings {
392395
name("consumer")
@@ -438,7 +441,7 @@ archRules {
438441
fun `plugin can skip configured source sets`() {
439442
val runner = testProject(projectDir) {
440443
properties {
441-
gradleCache(true)
444+
buildCache(true)
442445
}
443446
settings {
444447
name("consumer")

0 commit comments

Comments
 (0)