Skip to content

Commit

Permalink
Merge branch 'autonomousapps:main' into simplify-kotlin-compile-confi…
Browse files Browse the repository at this point in the history
…guration
  • Loading branch information
patrick-dedication authored Dec 21, 2024
2 parents baf9e58 + c9b15ef commit 09a71ee
Show file tree
Hide file tree
Showing 29 changed files with 394 additions and 64 deletions.
22 changes: 22 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,27 @@
Dependency Analysis Plugin Changelog

# Version 2.7.0 (unreleased)
* [Feat]: can set severity and filter duplicate class warnings.

New DSL option for configuring duplicate class warnings:
```groovy
// root build.gradle[.kts]
dependencyAnalysis {
issues {
all {
onDuplicateClassWarnings {
severity(<"fail"|"warn"|"ignore">)
// Fully-qualified class reference to exclude, slash- or dot-delimited
exclude("org/jetbrains/annotations/NotNull", "org.jetbrains.annotations.Nullable")
}
}
}
}
```

# Version 2.6.1
* [Fix]: `superClassName` can be null (Object has no superclass).

# Version 2.6.0
* [Feat]: improvements relating to generating project graphs.
* [Fix]: use stable kotlin-metadata 2.0.21.
Expand Down
2 changes: 1 addition & 1 deletion README.asciidoc
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ behaviors, but they may be interesting for some advanced users.
In addition to the dependency-related advice (see above), DAGP provides other advice to help maintain your "build health." This includes the detection of:

1. Unnecessary plugins (currently only `kapt`).
2. Subprojects ("modules") that unnecessarily use the Android plugin, and could instead by "normal" JVM libraries.
2. Subprojects ("modules") that unnecessarily use the Android plugin, and could instead be "normal" JVM libraries.

== Compatibilities

Expand Down
4 changes: 2 additions & 2 deletions RELEASING.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,12 @@ Release procedure for dependency-analysis-android-gradle-plugin
_with_ the `-SNAPSHOT` suffix (we publish a snapshot first for smoke testing).
1. Publish the snapshot to Maven Central: `./gradlew :publishEverywhere`
1. Remove the `-SNAPSHOT` suffix from the version name.
1. `git commit -am "Prepare for release x.y.z."`
1. `git commit -am "chore: prepare for release x.y.z."`
1. Publish again: `./gradlew :publishEverywhere -x :functionalTest`
(this will automatically run the smoke tests, and won't publish if they fail)
1. `git tag -a vx.y.z -m "Version x.y.z."`
1. Update version number in `gradle.properties` to next snapshot version (x.y.z-SNAPSHOT)
1. `git commit -am "Prepare next development version."`
1. `git commit -am "chore: prepare next development version."`
1. `git push && git push --tags`
1. (Optional) Follow instructions in console output to release from Maven Central's staging repo.
This step is now automated via the `:promote` task, and should only be necessary if that task
Expand Down
2 changes: 1 addition & 1 deletion gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ org.gradle.parallel=true
org.gradle.configuration-cache=true
org.gradle.configuration-cache.parallel=true

VERSION=2.6.1-SNAPSHOT
VERSION=2.6.2-SNAPSHOT

dependency.analysis.print.build.health=true

Expand Down
4 changes: 2 additions & 2 deletions settings.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -28,15 +28,15 @@ pluginManagement {
}
}
plugins {
id("com.github.johnrengelman.shadow") version "8.1.1"
id("com.gradleup.shadow") version "8.3.0"
id("com.gradle.develocity") version "3.18.2"
id("com.gradle.plugin-publish") version "1.1.0"
}
}

plugins {
id("com.gradle.develocity")
id("org.gradle.toolchains.foojay-resolver-convention") version("0.8.0")
id("org.gradle.toolchains.foojay-resolver-convention") version "0.8.0"
}

// Yes, this is also in pluginManagement above. This is required for normal dependencies.
Expand Down
2 changes: 1 addition & 1 deletion shadowed/antlr/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
plugins {
`java-library`
antlr
id("com.github.johnrengelman.shadow")
id("com.gradleup.shadow")
groovy
id("convention")
// This project doesn't need Kotlin, but it is now applied thanks to `convention`. problem?
Expand Down
2 changes: 1 addition & 1 deletion shadowed/asm-relocated/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
// SPDX-License-Identifier: Apache-2.0
plugins {
`java-library`
id("com.github.johnrengelman.shadow")
id("com.gradleup.shadow")
id("convention")
// This project doesn't need Kotlin, but it is now applied thanks to `convention`. problem?
}
Expand Down
2 changes: 1 addition & 1 deletion shadowed/kotlin-editor-relocated/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
plugins {
id("convention")
id("com.github.johnrengelman.shadow")
id("com.gradleup.shadow")
}

version = "${libs.versions.kotlineditor.core.get()}.1-SNAPSHOT"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,12 +27,12 @@ final class DuplicateClasspathSpec extends AbstractJvmSpec {
then:
assertThat(result.task(':consumer:compileJava').outcome).isEqualTo(TaskOutcome.FAILED)
// assertThat(gradleProject.rootDir.toPath().resolve('consumer/build.gradle').text).contains(
// '''\
// dependencies {
// implementation project(':producer-2')
// }'''.stripIndent()
// )
// assertThat(gradleProject.rootDir.toPath().resolve('consumer/build.gradle').text).contains(
// '''\
// dependencies {
// implementation project(':producer-2')
// }'''.stripIndent()
// )
where:
gradleVersion << [GRADLE_LATEST]
Expand Down Expand Up @@ -71,6 +71,57 @@ final class DuplicateClasspathSpec extends AbstractJvmSpec {
gradleVersion << [GRADLE_LATEST]
}
def "buildHealth reports filters duplicates (#gradleVersion)"() {
given:
def project = new DuplicateClasspathProject('com/example/producer/Producer$Inner')
gradleProject = project.gradleProject
when:
def result = buildAndFail(gradleVersion, gradleProject.rootDir, 'buildHealth')
then:
assertThat(result.output).contains(
'''\
Warnings
Some of your classpaths have duplicate classes, which means the compile and runtime behavior can be sensitive to the classpath order.
Source set: main
\\--- compile classpath
\\--- com/example/producer/Producer is provided by multiple dependencies: [:producer-1, :producer-2]
\\--- runtime classpath
\\--- com/example/producer/Producer is provided by multiple dependencies: [:producer-1, :producer-2]'''
.stripIndent()
)
and:
assertAbout(buildHealth())
.that(project.actualProjectAdvice())
.isEquivalentIgnoringModuleAdviceAndWarnings(project.expectedProjectAdvice)
where:
gradleVersion << [GRADLE_LATEST]
}
def "buildHealth reports ignores duplicates (#gradleVersion)"() {
given:
def project = new DuplicateClasspathProject(null, 'ignore')
gradleProject = project.gradleProject
when:
def result = buildAndFail(gradleVersion, gradleProject.rootDir, 'buildHealth')
then:
assertThat(result.output).doesNotContain('Warnings')
and:
assertAbout(buildHealth())
.that(project.actualProjectAdvice())
.isEquivalentIgnoringModuleAdviceAndWarnings(project.expectedProjectAdvice)
where:
gradleVersion << [GRADLE_LATEST]
}
@PendingFeature(reason = "This feature was reverted")
def "can report on which of the duplicates is needed for binary compatibility (#gradleVersion)"() {
given:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,26 +13,17 @@ final class DuplicateClasspathProject extends AbstractProject {

final GradleProject gradleProject

DuplicateClasspathProject() {
this.gradleProject = build()
DuplicateClasspathProject(String filter = null, String severity = null) {
this.gradleProject = build(filter, severity)
}

private GradleProject build() {
private GradleProject build(String filter, String severity) {
def configuration = new DagpConfiguration(filter, severity).toString()

return newGradleProjectBuilder()
.withRootProject { r ->
r.withBuildScript { bs ->
bs.withGroovy(
'''\
dependencyAnalysis {
issues {
all {
onAny {
severity 'fail'
}
}
}
}'''.stripIndent()
)
bs.withGroovy(configuration)
}
}
// :consumer uses the Producer class.
Expand Down Expand Up @@ -187,4 +178,43 @@ final class DuplicateClasspathProject extends AbstractProject {
emptyProjectAdviceFor(':producer-1'),
emptyProjectAdviceFor(':producer-2'),
]

static class DagpConfiguration {

private final String filter
private final String severity

DagpConfiguration(String filter, String severity) {
this.filter = filter
this.severity = severity
}

@Override
String toString() {
def builder = new StringBuilder()
builder.append('dependencyAnalysis {\n')
builder.append(' issues {\n')
builder.append(' all {\n')
builder.append(' onAny {\n')
builder.append(' severity \'fail\'\n')
builder.append(' }\n')

if (filter || severity) {
builder.append(' onDuplicateClassWarnings {\n')
if (severity) {
builder.append(" severity \'$severity\'\n")
}
if (filter) {
builder.append(" exclude \'$filter\'\n")
}
builder.append(' }\n')
}

builder.append(' }\n')
builder.append(' }\n')
builder.append('}')

return builder.toString()
}
}
}
4 changes: 4 additions & 0 deletions src/main/kotlin/com/autonomousapps/extension/IssueHandler.kt
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,10 @@ abstract class IssueHandler @Inject constructor(
return globalDslService.unusedAnnotationProcessorsIssueFor(projectPath)
}

internal fun onDuplicateClassWarnings(projectPath: String): List<Provider<Behavior>> {
return globalDslService.onDuplicateClassWarnings(projectPath)
}

internal fun redundantPluginsIssueFor(projectPath: String): Provider<Behavior> {
return globalDslService.redundantPluginsIssueFor(projectPath)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,15 @@ import javax.inject.Inject
* ignoreSourceSet(...)
*
* // Specify severity and exclude rules for all types of dependency violations.
* onAny { ... }
* onAny {
* severity(<"fail"|"warn"|"ignore">)
*
* // using version catalog accessors
* exclude(libs.guava, ...)
*
* // using basic string coordinates
* exclude("com.google.guava:guava", ...)
* }
*
* // Specify severity and exclude rules for unused dependencies.
* onUnusedDependencies { ... }
Expand All @@ -47,8 +55,15 @@ import javax.inject.Inject
*
* // Specify severity and exclude rules for module structure advice.
* onModuleStructure {
* severity(<'fail'|'warn'|'ignore'>)
* exclude('android')
* severity(<"fail"|"warn"|"ignore">)
* exclude("android")
* }
*
* onDuplicateClassWarnings {
* severity(<"fail"|"warn"|"ignore">)
*
* // Fully-qualified class reference to exclude, slash- or dot-delimited
* exclude("org/jetbrains/annotations/NotNull", "org.jetbrains.annotations.Nullable")
* }
* }
* }
Expand Down Expand Up @@ -76,6 +91,7 @@ abstract class ProjectIssueHandler @Inject constructor(
internal val runtimeOnlyIssue = objects.newInstance<Issue>()
internal val redundantPluginsIssue = objects.newInstance<Issue>()
internal val moduleStructureIssue = objects.newInstance<Issue>()
internal val duplicateClassWarningsIssue = objects.newInstance<Issue>()

internal val ignoreSourceSets = objects.setProperty<String>()

Expand Down Expand Up @@ -125,4 +141,8 @@ abstract class ProjectIssueHandler @Inject constructor(
fun onModuleStructure(action: Action<Issue>) {
action.execute(moduleStructureIssue)
}

fun onDuplicateClassWarnings(action: Action<Issue>) {
action.execute(duplicateClassWarningsIssue)
}
}
Loading

0 comments on commit 09a71ee

Please sign in to comment.