Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,15 @@ This repository contains several libraries of ArchRules which can be used in pro
[![Maven Central](https://img.shields.io/maven-central/v/com.netflix.nebula/archrules-deprecation?style=for-the-badge&color=01AF01)](https://repo1.maven.org/maven2/com/netflix/nebula/archrules-deprecation/)

## Gradle Plugin Development
[![Maven Central](https://img.shields.io/maven-central/v/com.netflix.nebula/archrules-gradle-plugin-development?style=for-the-badge&color=01AF01)](https://repo1.maven.org/maven2/com/netflix/nebula/gradle-plugin-development/)
[![Maven Central](https://img.shields.io/maven-central/v/com.netflix.nebula/archrules-gradle-plugin-development?style=for-the-badge&color=01AF01)](https://repo1.maven.org/maven2/com/netflix/nebula/archrules-gradle-plugin-development/)

These rules enforce best practices when developing Gradle plugins.

## Guava Rules
[![Maven Central](https://img.shields.io/maven-central/v/com.netflix.nebula/archrules-guava?style=for-the-badge&color=01AF01)](https://repo1.maven.org/maven2/com/netflix/nebula/archrules-guava/)

These rules detect the usage of certain APIs from Guava which have standard library replacements.

## Javax Rules
[![Maven Central](https://img.shields.io/maven-central/v/com.netflix.nebula/archrules-joda?style=for-the-badge&color=01AF01)](https://repo1.maven.org/maven2/com/netflix/nebula/archrules-javax/)

Expand Down
16 changes: 6 additions & 10 deletions archrules-deprecation/gradle.lockfile
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,12 @@
# This file is expected to be part of source control.
ch.qos.logback:logback-classic:1.5.20=archRulesTestArchRulesRuntime,archRulesTestCompileClasspath,archRulesTestRuntimeClasspath
ch.qos.logback:logback-core:1.5.20=archRulesTestArchRulesRuntime,archRulesTestCompileClasspath,archRulesTestRuntimeClasspath
com.netflix.nebula:archrules-joda:0.3.0=archRules
com.netflix.nebula:archrules-joda:0.6.0=archRulesArchRulesRuntime,archRulesTestArchRulesRuntime,mainArchRulesRuntime,testArchRulesRuntime
com.netflix.nebula:archrules-nullability:0.3.0=archRules
com.netflix.nebula:archrules-nullability:0.6.0=archRulesArchRulesRuntime,archRulesTestArchRulesRuntime,mainArchRulesRuntime,testArchRulesRuntime
com.netflix.nebula:archrules-testing-frameworks:0.3.0=archRules
com.netflix.nebula:archrules-testing-frameworks:0.6.0=archRulesArchRulesRuntime,archRulesTestArchRulesRuntime,mainArchRulesRuntime,testArchRulesRuntime
com.netflix.nebula:nebula-archrules-core:0.2.3=archRules
com.netflix.nebula:nebula-archrules-core:0.3.0=archRulesRuntimeClasspath
com.netflix.nebula:nebula-archrules-core:0.4.0=mainArchRulesRuntime,testArchRulesRuntime
com.netflix.nebula:nebula-archrules-core:0.5.3=archRulesArchRulesRuntime,archRulesCompileClasspath,archRulesTestArchRulesRuntime,archRulesTestCompileClasspath,archRulesTestRuntimeClasspath
com.netflix.nebula:archrules-joda:0.6.0=archRules,archRulesArchRulesRuntime,archRulesTestArchRulesRuntime,mainArchRulesRuntime,testArchRulesRuntime
com.netflix.nebula:archrules-nullability:0.6.0=archRules,archRulesArchRulesRuntime,archRulesTestArchRulesRuntime,mainArchRulesRuntime,testArchRulesRuntime
com.netflix.nebula:archrules-security:0.6.0=archRules,archRulesArchRulesRuntime,archRulesTestArchRulesRuntime,mainArchRulesRuntime,testArchRulesRuntime
com.netflix.nebula:archrules-testing-frameworks:0.6.0=archRules,archRulesArchRulesRuntime,archRulesTestArchRulesRuntime,mainArchRulesRuntime,testArchRulesRuntime
com.netflix.nebula:nebula-archrules-core:0.5.2=archRules,mainArchRulesRuntime,testArchRulesRuntime
com.netflix.nebula:nebula-archrules-core:0.5.5=archRulesArchRulesRuntime,archRulesCompileClasspath,archRulesRuntimeClasspath,archRulesTestArchRulesRuntime,archRulesTestCompileClasspath,archRulesTestRuntimeClasspath
com.tngtech.archunit:archunit:1.4.1=archRules,archRulesArchRulesRuntime,archRulesCompileClasspath,archRulesRuntimeClasspath,archRulesTestArchRulesRuntime,archRulesTestCompileClasspath,archRulesTestRuntimeClasspath,mainArchRulesRuntime,testArchRulesRuntime
net.bytebuddy:byte-buddy:1.17.7=archRulesTestArchRulesRuntime,archRulesTestCompileClasspath,archRulesTestRuntimeClasspath
org.apiguardian:apiguardian-api:1.1.2=archRulesTestCompileClasspath
Expand Down
19 changes: 7 additions & 12 deletions archrules-gradle-plugin-development/gradle.lockfile
Original file line number Diff line number Diff line change
Expand Up @@ -3,23 +3,18 @@
# This file is expected to be part of source control.
ch.qos.logback:logback-classic:1.5.20=archRulesTestArchRulesRuntime,archRulesTestCompileClasspath,archRulesTestRuntimeClasspath
ch.qos.logback:logback-core:1.5.20=archRulesTestArchRulesRuntime,archRulesTestCompileClasspath,archRulesTestRuntimeClasspath
com.netflix.nebula:archrules-deprecation:0.4.0=archRules
com.netflix.nebula:archrules-deprecation:0.6.0=archRulesArchRulesRuntime,archRulesTestArchRulesRuntime,mainArchRulesRuntime,testArchRulesRuntime
com.netflix.nebula:archrules-joda:0.4.0=archRules
com.netflix.nebula:archrules-joda:0.6.0=archRulesArchRulesRuntime,archRulesTestArchRulesRuntime,mainArchRulesRuntime,testArchRulesRuntime
com.netflix.nebula:archrules-nullability:0.4.0=archRules
com.netflix.nebula:archrules-nullability:0.6.0=archRulesArchRulesRuntime,archRulesTestArchRulesRuntime,mainArchRulesRuntime,testArchRulesRuntime
com.netflix.nebula:archrules-testing-frameworks:0.4.0=archRules
com.netflix.nebula:archrules-security:0.6.0=archRulesArchRulesRuntime,archRulesTestArchRulesRuntime,mainArchRulesRuntime,testArchRulesRuntime
com.netflix.nebula:archrules-testing-frameworks:0.6.0=archRulesArchRulesRuntime,archRulesTestArchRulesRuntime,mainArchRulesRuntime,testArchRulesRuntime
com.netflix.nebula:nebula-archrules-core:0.3.0=archRules
com.netflix.nebula:nebula-archrules-core:0.4.0=mainArchRulesRuntime,testArchRulesRuntime
com.netflix.nebula:nebula-archrules-core:0.5.2=archRulesRuntimeClasspath
com.netflix.nebula:nebula-archrules-core:0.5.3=archRulesArchRulesRuntime,archRulesCompileClasspath,archRulesTestArchRulesRuntime,archRulesTestCompileClasspath,archRulesTestRuntimeClasspath
com.tngtech.archunit:archunit:1.4.1=archRules,archRulesArchRulesRuntime,archRulesCompileClasspath,archRulesRuntimeClasspath,archRulesTestArchRulesRuntime,archRulesTestCompileClasspath,archRulesTestRuntimeClasspath,mainArchRulesRuntime,testArchRulesRuntime
com.netflix.nebula:nebula-archrules-core:0.5.2=mainArchRulesRuntime,testArchRulesRuntime
com.netflix.nebula:nebula-archrules-core:0.5.5=archRulesArchRulesRuntime,archRulesCompileClasspath,archRulesTestArchRulesRuntime,archRulesTestCompileClasspath,archRulesTestRuntimeClasspath
com.tngtech.archunit:archunit:1.4.1=archRulesArchRulesRuntime,archRulesCompileClasspath,archRulesTestArchRulesRuntime,archRulesTestCompileClasspath,archRulesTestRuntimeClasspath,mainArchRulesRuntime,testArchRulesRuntime
net.bytebuddy:byte-buddy:1.17.7=archRulesTestArchRulesRuntime,archRulesTestCompileClasspath,archRulesTestRuntimeClasspath
org.apiguardian:apiguardian-api:1.1.2=archRulesTestCompileClasspath
org.assertj:assertj-core:3.27.6=archRulesTestArchRulesRuntime,archRulesTestCompileClasspath,archRulesTestRuntimeClasspath
org.jspecify:jspecify:1.0.0=archRules,archRulesArchRulesRuntime,archRulesCompileClasspath,archRulesRuntimeClasspath,archRulesTestArchRulesRuntime,archRulesTestCompileClasspath,archRulesTestRuntimeClasspath,mainArchRulesRuntime,testArchRulesRuntime
org.jspecify:jspecify:1.0.0=archRulesArchRulesRuntime,archRulesCompileClasspath,archRulesTestArchRulesRuntime,archRulesTestCompileClasspath,archRulesTestRuntimeClasspath,mainArchRulesRuntime,testArchRulesRuntime
org.junit.jupiter:junit-jupiter-api:5.12.2=archRulesTestArchRulesRuntime,archRulesTestCompileClasspath,archRulesTestRuntimeClasspath
org.junit.jupiter:junit-jupiter-engine:5.12.2=archRulesTestArchRulesRuntime,archRulesTestRuntimeClasspath
org.junit.jupiter:junit-jupiter-params:5.12.2=archRulesTestArchRulesRuntime,archRulesTestCompileClasspath,archRulesTestRuntimeClasspath
Expand All @@ -29,5 +24,5 @@ org.junit.platform:junit-platform-engine:1.12.2=archRulesTestArchRulesRuntime,ar
org.junit.platform:junit-platform-launcher:1.12.2=archRulesTestArchRulesRuntime,archRulesTestRuntimeClasspath
org.junit:junit-bom:5.12.2=archRulesTestArchRulesRuntime,archRulesTestCompileClasspath,archRulesTestRuntimeClasspath
org.opentest4j:opentest4j:1.3.0=archRulesTestArchRulesRuntime,archRulesTestCompileClasspath,archRulesTestRuntimeClasspath
org.slf4j:slf4j-api:2.0.17=archRules,archRulesArchRulesRuntime,archRulesCompileClasspath,archRulesRuntimeClasspath,archRulesTestArchRulesRuntime,archRulesTestCompileClasspath,archRulesTestRuntimeClasspath,mainArchRulesRuntime,testArchRulesRuntime
empty=annotationProcessor,archRulesAnnotationProcessor,archRulesTestAnnotationProcessor,compileClasspath,runtimeClasspath,testAnnotationProcessor,testCompileClasspath,testRuntimeClasspath
org.slf4j:slf4j-api:2.0.17=archRulesArchRulesRuntime,archRulesCompileClasspath,archRulesTestArchRulesRuntime,archRulesTestCompileClasspath,archRulesTestRuntimeClasspath,mainArchRulesRuntime,testArchRulesRuntime
empty=annotationProcessor,archRulesAnnotationProcessor,archRulesTestAnnotationProcessor,compileClasspath,testAnnotationProcessor,testCompileClasspath,testRuntimeClasspath
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package com.netflix.nebula.archrules.gradleplugins;

import com.tngtech.archunit.base.DescribedPredicate;
import com.tngtech.archunit.core.domain.JavaClass;
import com.tngtech.archunit.core.domain.JavaMember;
import org.jspecify.annotations.NullMarked;

import java.util.Set;
import java.util.function.Function;

@NullMarked
public class ContainAnyMembersInClassHierarchyThatPredicate <T extends JavaMember> extends DescribedPredicate<JavaClass> {
private final Function<JavaClass, Set<T>> getMembers;
private final DescribedPredicate<? super T> predicate;

ContainAnyMembersInClassHierarchyThatPredicate(String memberDescription, Function<JavaClass, Set<T>> getMembers, DescribedPredicate<? super T> predicate) {
super("contain any " + memberDescription + " that " + predicate.getDescription());
this.getMembers = getMembers;
this.predicate = predicate;
}

@Override
public boolean test(JavaClass input) {
return getMembers.apply(input).stream().anyMatch(predicate);
}
}
Original file line number Diff line number Diff line change
@@ -1,28 +1,21 @@
package com.netflix.nebula.archrules.gradleplugins;

import com.netflix.nebula.archrules.core.ArchRulesService;
import com.tngtech.archunit.core.domain.JavaAccess;
import com.tngtech.archunit.core.domain.JavaClass;
import com.tngtech.archunit.lang.ArchCondition;
import com.tngtech.archunit.lang.ArchRule;
import com.tngtech.archunit.lang.ConditionEvents;
import com.tngtech.archunit.lang.Priority;
import com.tngtech.archunit.lang.SimpleConditionEvent;
import com.tngtech.archunit.lang.syntax.ArchRuleDefinition;
import org.jspecify.annotations.NullMarked;

import java.util.HashMap;
import java.util.Map;
import static com.netflix.nebula.archrules.gradleplugins.Predicates.accessDeprecatedGradleApi;
import static com.netflix.nebula.archrules.gradleplugins.Predicates.deprecatedGradleClass;
import static com.tngtech.archunit.lang.conditions.ArchConditions.accessTargetWhere;

/**
* Rules to prevent usage of deprecated Gradle APIs.
* <p>
* Using deprecated Gradle APIs will cause build failures in future Gradle versions.
*/
@NullMarked
public class GradleDeprecatedApiRule implements ArchRulesService {

private static final String GRADLE_API_PACKAGE = "org.gradle";
public class GradleDeprecatedApiRule {

/**
* Prevents plugins from using deprecated Gradle APIs.
Expand All @@ -32,9 +25,10 @@ public class GradleDeprecatedApiRule implements ArchRulesService {
* upgrade guides.
*/
public static final ArchRule pluginsShouldNotUseDeprecatedGradleApis = ArchRuleDefinition.priority(Priority.MEDIUM)
.classes()
.noClasses()
.that().implement("org.gradle.api.Plugin")
.should(notUseDeprecatedGradleApis())
.should().dependOnClassesThat(deprecatedGradleClass)
.orShould(accessTargetWhere(accessDeprecatedGradleApi))
.allowEmptyShould(true)
.because(
"Plugins should not use deprecated Gradle APIs as they will be removed in future versions. " +
Expand All @@ -50,52 +44,15 @@ public class GradleDeprecatedApiRule implements ArchRulesService {
* upgrade guides.
*/
public static final ArchRule tasksShouldNotUseDeprecatedGradleApis = ArchRuleDefinition.priority(Priority.MEDIUM)
.classes()
.noClasses()
.that().areAssignableTo("org.gradle.api.Task")
.and().areNotInterfaces()
.should(notUseDeprecatedGradleApis())
.should().dependOnClassesThat(deprecatedGradleClass)
.orShould(accessTargetWhere(accessDeprecatedGradleApi))
.allowEmptyShould(true)
.because(
"Tasks should not use deprecated Gradle APIs as they will be removed in future versions. " +
"Consult Gradle upgrade guides for modern alternatives. " +
"See https://docs.gradle.org/current/userguide/upgrading_version_8.html"
);

private static ArchCondition<JavaClass> notUseDeprecatedGradleApis() {
return new ArchCondition<JavaClass>("not use deprecated Gradle APIs") {
@Override
public void check(JavaClass javaClass, ConditionEvents events) {
for (JavaAccess<?> access : javaClass.getAccessesFromSelf()) {
if (isDeprecatedGradleApi(access)) {
String message = String.format(
"Class %s uses deprecated Gradle API: %s. " +
"This API will be removed in a future Gradle version. " +
"Consult Gradle upgrade guides for alternatives.",
javaClass.getSimpleName(),
access.getDescription()
);
events.add(SimpleConditionEvent.violated(access, message));
}
}
}

private boolean isDeprecatedGradleApi(JavaAccess<?> access) {
String targetOwnerName = access.getTargetOwner().getName();

if (!targetOwnerName.startsWith(GRADLE_API_PACKAGE)) {
return false;
}

return access.getTarget().isAnnotatedWith(Deprecated.class);
}
};
}

@Override
public Map<String, ArchRule> getRules() {
Map<String, ArchRule> rules = new HashMap<>();
rules.put("gradle-plugin-no-deprecated-apis", pluginsShouldNotUseDeprecatedGradleApis);
rules.put("gradle-task-no-deprecated-apis", tasksShouldNotUseDeprecatedGradleApis);
return rules;
}
}
Original file line number Diff line number Diff line change
@@ -1,18 +1,12 @@
package com.netflix.nebula.archrules.gradleplugins;

import com.netflix.nebula.archrules.core.ArchRulesService;
import com.tngtech.archunit.core.domain.JavaAccess;
import com.tngtech.archunit.core.domain.JavaClass;
import com.tngtech.archunit.lang.ArchCondition;
import com.tngtech.archunit.lang.ArchRule;
import com.tngtech.archunit.lang.ConditionEvents;
import com.tngtech.archunit.lang.Priority;
import com.tngtech.archunit.lang.SimpleConditionEvent;
import com.tngtech.archunit.lang.syntax.ArchRuleDefinition;
import org.jspecify.annotations.NullMarked;

import java.util.HashMap;
import java.util.Map;
import static com.netflix.nebula.archrules.gradleplugins.Predicates.internalGradleClass;
import static com.tngtech.archunit.core.domain.JavaAccess.Predicates.targetOwner;

/**
* Rules to prevent usage of internal Gradle APIs.
Expand All @@ -21,10 +15,7 @@
* or be removed without notice between Gradle versions.
*/
@NullMarked
public class GradleInternalApiRule implements ArchRulesService {

private static final String GRADLE_PACKAGE = "org.gradle";
private static final String INTERNAL_PACKAGE_MARKER = ".internal.";
public class GradleInternalApiRule {

/**
* Prevents plugins from using internal Gradle APIs.
Expand All @@ -33,10 +24,11 @@ public class GradleInternalApiRule implements ArchRulesService {
* and may change or be removed between versions without notice. Use only public
* Gradle APIs to ensure compatibility across Gradle versions.
*/
public static final ArchRule pluginsShouldNotUseInternalGradleApis = ArchRuleDefinition.priority(Priority.HIGH)
.classes()
public static final ArchRule PLUGIN_INTERNAL = ArchRuleDefinition.priority(Priority.MEDIUM)
.noClasses()
.that().implement("org.gradle.api.Plugin")
.should(notUseInternalGradleApis())
.should().dependOnClassesThat(internalGradleClass)
.orShould().accessTargetWhere(targetOwner(internalGradleClass))
.allowEmptyShould(true)
.because(
"Plugins should not use internal Gradle APIs (packages containing '.internal.'). " +
Expand All @@ -51,49 +43,16 @@ public class GradleInternalApiRule implements ArchRulesService {
* and may change or be removed between versions without notice. Use only public
* Gradle APIs to ensure compatibility across Gradle versions.
*/
public static final ArchRule tasksShouldNotUseInternalGradleApis = ArchRuleDefinition.priority(Priority.HIGH)
.classes()
public static final ArchRule TASK_INTERNAL = ArchRuleDefinition.priority(Priority.MEDIUM)
.noClasses()
.that().areAssignableTo("org.gradle.api.Task")
.and().areNotInterfaces()
.should(notUseInternalGradleApis())
.should().dependOnClassesThat(internalGradleClass)
.orShould().accessTargetWhere(targetOwner(internalGradleClass))
.allowEmptyShould(true)
.because(
"Tasks should not use internal Gradle APIs (packages containing '.internal.'). " +
"Internal APIs are not stable and may change or be removed without notice. " +
"Use only public Gradle APIs documented at https://docs.gradle.org/current/javadoc/"
);

private static ArchCondition<JavaClass> notUseInternalGradleApis() {
return new ArchCondition<JavaClass>("not use internal Gradle APIs") {
@Override
public void check(JavaClass javaClass, ConditionEvents events) {
for (JavaAccess<?> access : javaClass.getAccessesFromSelf()) {
if (isInternalGradleApi(access)) {
String message = String.format(
"Class %s uses internal Gradle API: %s. " +
"Internal APIs (packages containing '.internal.') are not stable and may change without notice. " +
"Use public Gradle APIs instead.",
javaClass.getSimpleName(),
access.getDescription()
);
events.add(SimpleConditionEvent.violated(access, message));
}
}
}

private boolean isInternalGradleApi(JavaAccess<?> access) {
String targetPackage = access.getTargetOwner().getPackageName();
return targetPackage.startsWith(GRADLE_PACKAGE) &&
targetPackage.contains(INTERNAL_PACKAGE_MARKER);
}
};
}

@Override
public Map<String, ArchRule> getRules() {
Map<String, ArchRule> rules = new HashMap<>();
rules.put("gradle-plugin-no-internal-apis", pluginsShouldNotUseInternalGradleApis);
rules.put("gradle-task-no-internal-apis", tasksShouldNotUseInternalGradleApis);
return rules;
}
}
Loading