diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..07b230b --- /dev/null +++ b/.editorconfig @@ -0,0 +1,23 @@ +root = true + +[*] +charset = utf-8 +indent_size = 4 +indent_style = space +insert_final_newline = true +max_line_length = 120 +ij_continuation_indent_size = 8 +tab_width = 4 +trim_trailing_whitespace = true + +[{*.kt,*.kts}] +ij_kotlin_allow_trailing_comma = false +ij_kotlin_allow_trailing_comma_on_call_site = false +ij_kotlin_name_count_to_use_star_import_for_members = 20 +ij_kotlin_name_count_to_use_star_import = 20 +ij_kotlin_continuation_indent_size = 4 +ktlint_code_style=intellij_idea + +[*.java] +ij_java_names_count_to_use_import_on_demand = 20 +ij_java_class_count_to_use_import_on_demand = 20 \ No newline at end of file diff --git a/archrules-deprecation/build.gradle.kts b/archrules-deprecation/build.gradle.kts index de14a6d..372da28 100644 --- a/archrules-deprecation/build.gradle.kts +++ b/archrules-deprecation/build.gradle.kts @@ -3,9 +3,7 @@ plugins { id("com.netflix.nebula.archrules.library") } description = "Arch Rules for detecting usage of deprecated code" -repositories { - mavenCentral() -} + dependencies { archRulesImplementation(libs.jspecify) diff --git a/archrules-deprecation/src/archRules/java/com/netflix/nebula/archrules/deprecation/DeprecationRule.java b/archrules-deprecation/src/archRules/java/com/netflix/nebula/archrules/deprecation/DeprecationRule.java index 546a9d2..7307714 100644 --- a/archrules-deprecation/src/archRules/java/com/netflix/nebula/archrules/deprecation/DeprecationRule.java +++ b/archrules-deprecation/src/archRules/java/com/netflix/nebula/archrules/deprecation/DeprecationRule.java @@ -26,7 +26,7 @@ public class DeprecationRule implements ArchRulesService { * - Kotlin @Deprecated annotations * - Kotlin @DeprecatedSinceKotlin annotations */ - public static ArchRule deprecationRule = ArchRuleDefinition.priority(Priority.LOW) + public static final ArchRule deprecationRule = ArchRuleDefinition.priority(Priority.LOW) .noClasses() // Java deprecated .should().dependOnClassesThat().areAnnotatedWith(Deprecated.class) @@ -58,7 +58,7 @@ public boolean test(JavaAnnotation> annotation) { } }; - public static ArchRule deprecationForRemovalRule = ArchRuleDefinition.priority(Priority.MEDIUM) + public static final ArchRule deprecationForRemovalRule = ArchRuleDefinition.priority(Priority.MEDIUM) .noClasses() .should().dependOnClassesThat().areAnnotatedWith(deprecatedForRemoval) .orShould().accessTargetWhere(targetOwner(annotatedWith(deprecatedForRemoval))) diff --git a/archrules-gradle-plugin-development/build.gradle.kts b/archrules-gradle-plugin-development/build.gradle.kts new file mode 100644 index 0000000..e844f58 --- /dev/null +++ b/archrules-gradle-plugin-development/build.gradle.kts @@ -0,0 +1,23 @@ +plugins { + id("com.netflix.nebula.library") + id("com.netflix.nebula.archrules.library") +} + +description = "Arch Rules for detecting bad practices when developing Gradle plugins" + +dependencies { + archRulesImplementation(libs.jspecify) + + archRulesTestImplementation(libs.assertj) + archRulesTestImplementation(libs.logback) + archRulesTestImplementation(gradleApi()) +} +java { + toolchain { + languageVersion = JavaLanguageVersion.of(8) + } +} + +dependencyLocking { + lockAllConfigurations() +} diff --git a/archrules-gradle-plugin-development/gradle.lockfile b/archrules-gradle-plugin-development/gradle.lockfile new file mode 100644 index 0000000..53f13ad --- /dev/null +++ b/archrules-gradle-plugin-development/gradle.lockfile @@ -0,0 +1,27 @@ +# This is a Gradle generated file for dependency locking. +# Manual edits can break the build and are not advised. +# 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-joda:0.4.0=archRules +com.netflix.nebula:archrules-nullability:0.4.0=archRules +com.netflix.nebula:archrules-testing-frameworks:0.4.0=archRules +com.netflix.nebula:nebula-archrules-core:0.3.0=archRules +com.netflix.nebula:nebula-archrules-core:0.5.2=archRulesArchRulesRuntime,archRulesCompileClasspath,archRulesRuntimeClasspath,archRulesTestArchRulesRuntime,archRulesTestCompileClasspath,archRulesTestRuntimeClasspath +com.tngtech.archunit:archunit:1.4.1=archRules,archRulesArchRulesRuntime,archRulesCompileClasspath,archRulesRuntimeClasspath,archRulesTestArchRulesRuntime,archRulesTestCompileClasspath,archRulesTestRuntimeClasspath +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 +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 +org.junit.jupiter:junit-jupiter:5.12.2=archRulesTestArchRulesRuntime,archRulesTestCompileClasspath,archRulesTestRuntimeClasspath +org.junit.platform:junit-platform-commons:1.12.2=archRulesTestArchRulesRuntime,archRulesTestCompileClasspath,archRulesTestRuntimeClasspath +org.junit.platform:junit-platform-engine:1.12.2=archRulesTestArchRulesRuntime,archRulesTestRuntimeClasspath +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 +empty=annotationProcessor,archRulesAnnotationProcessor,archRulesTestAnnotationProcessor,compileClasspath,mainArchRulesRuntime,runtimeClasspath,testAnnotationProcessor,testArchRulesRuntime,testCompileClasspath,testRuntimeClasspath diff --git a/archrules-gradle-plugin-development/src/archRules/java/com/netflix/nebula/archrules/gradleplugins/GradleTaskActionRule.java b/archrules-gradle-plugin-development/src/archRules/java/com/netflix/nebula/archrules/gradleplugins/GradleTaskActionRule.java new file mode 100644 index 0000000..a13f079 --- /dev/null +++ b/archrules-gradle-plugin-development/src/archRules/java/com/netflix/nebula/archrules/gradleplugins/GradleTaskActionRule.java @@ -0,0 +1,123 @@ +package com.netflix.nebula.archrules.gradleplugins; + +import com.netflix.nebula.archrules.core.ArchRulesService; +import com.tngtech.archunit.base.DescribedPredicate; +import com.tngtech.archunit.core.domain.JavaAccess; +import com.tngtech.archunit.core.domain.JavaFieldAccess; +import com.tngtech.archunit.core.domain.JavaMethod; +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; + +/** + * Rules for Gradle task action methods to ensure Gradle 10 compatibility. + */ +@NullMarked +public class GradleTaskActionRule implements ArchRulesService { + + /** + * Prevents {@code @TaskAction} methods from accessing {@code Project}. + *
+ * Accessing {@code Project} in task actions breaks configuration cache and will + * cause runtime errors in Gradle 10+. Move Project access to configuration time + * (constructor/initializer) and use task properties instead. + */ + public static final ArchRule taskActionShouldNotAccessProject = ArchRuleDefinition.priority(Priority.MEDIUM) + .methods() + .that(areAnnotatedWithTaskAction()) + .should(notAccessProject()) + .allowEmptyShould(true) + .because( + "Accessing Project in @TaskAction methods breaks configuration cache and will be removed in Gradle 10. " + + "Move Project access to task configuration time and use task inputs/properties instead. " + + "See https://docs.gradle.org/9.2.0/userguide/upgrading_version_7.html#task_project" + ); + + /** + * Prevents {@code @TaskAction} methods from calling {@code getTaskDependencies()}. + *
+ * Calling {@code getTaskDependencies()} in task actions breaks configuration cache and will
+ * cause runtime errors in Gradle 10+. Task dependencies should be declared at configuration time.
+ */
+ public static final ArchRule taskActionShouldNotCallGetTaskDependencies = ArchRuleDefinition.priority(Priority.MEDIUM)
+ .methods()
+ .that(areAnnotatedWithTaskAction())
+ .should(notCallGetTaskDependencies())
+ .allowEmptyShould(true)
+ .because(
+ "Calling getTaskDependencies() in @TaskAction methods breaks configuration cache and will be removed in Gradle 10. " +
+ "Declare task dependencies at configuration time instead. " +
+ "See https://docs.gradle.org/9.2.0/userguide/upgrading_version_7.html#task_dependencies"
+ );
+
+ private static DescribedPredicate
* The fix: Replace {@code DockerComposeContainer} with {@code ComposeContainer} everywhere.
*/
- public static ArchRule dockerComposeContainerRule = ArchRuleDefinition.priority(Priority.MEDIUM)
+ public static final ArchRule dockerComposeContainerRule = ArchRuleDefinition.priority(Priority.MEDIUM)
.noClasses()
.should().dependOnClassesThat().haveSimpleName("DockerComposeContainer")
.allowEmptyShould(true)
@@ -60,7 +60,7 @@ public class Testcontainers1xRule implements ArchRulesService {
*
* The fix: Change {@code container.getContainerIpAddress()} to {@code container.getHost()}.
*/
- public static ArchRule containerIpAddressMethodRule = ArchRuleDefinition.priority(Priority.MEDIUM)
+ public static final ArchRule containerIpAddressMethodRule = ArchRuleDefinition.priority(Priority.MEDIUM)
.noClasses()
.should().callMethod("org.testcontainers.containers.ContainerState", "getContainerIpAddress")
.allowEmptyShould(true)
@@ -85,7 +85,7 @@ public class Testcontainers1xRule implements ArchRulesService {
*
*
*/
- public static ArchRule noArgConstructorRule = ArchRuleDefinition.priority(Priority.MEDIUM)
+ public static final ArchRule noArgConstructorRule = ArchRuleDefinition.priority(Priority.MEDIUM)
.noClasses()
.should().callConstructorWhere(target(new DescribedPredicate