Skip to content

Commit

Permalink
Add configuration to disable unused license warnings (#285)
Browse files Browse the repository at this point in the history
* Added config option for handling unused licenses

* Add tests in groovy/KTS

* Renamed UnusedAction.WARN to LOG

* Unused imports
  • Loading branch information
jonapoul authored Jan 16, 2024
1 parent d7f727e commit 9fa4fbc
Show file tree
Hide file tree
Showing 44 changed files with 394 additions and 12 deletions.
1 change: 1 addition & 0 deletions src/main/kotlin/app/cash/licensee/plugin.kt
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ class LicenseePlugin : Plugin<Project> {
it.dependencyConfig.convention(extension.toDependencyTreeConfig())
it.validationConfig.convention(extension.toLicenseValidationConfig())
it.violationAction.convention(extension.violationAction)
it.unusedAction.convention(extension.unusedAction)

it.outputDir.convention(
project.extensions.getByType(ReportingExtension::class.java).baseDirectory.dir(
Expand Down
36 changes: 35 additions & 1 deletion src/main/kotlin/app/cash/licensee/pluginExtension.kt
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,28 @@ interface LicenseeExtension {
*/
fun violationAction(level: ViolationAction)

/**
* Build behavior when a declared license is not found in any dependencies of the project.
*
* This is intended for the case where you have a restricted list of allowed licenses for your
* organisation, so you can simply list them all in the Licensee config block and not have to
* fish through unnecessary warnings in your Gradle logs.
*
* ```
* licensee {
* unusedAction(IGNORE)
* }
* ```
*
* The default behavior is to [warn][UnusedAction.LOG].
*
* Note: Setting this to [ignore][UnusedAction.IGNORE] does not affect the contents of the
* `validation.txt` file which always contains all artifacts and their validation status.
*
* @see UnusedAction
*/
fun unusedAction(level: UnusedAction)

interface AllowUrlOptions {
fun because(reason: String)
}
Expand All @@ -213,6 +235,12 @@ enum class ViolationAction {
IGNORE,
}

@Suppress("unused") // Public API.
enum class UnusedAction {
LOG,
IGNORE,
}

internal abstract class IgnoredCoordinate : Named {
abstract val ignoredDatas: MapProperty<String, IgnoredData>
}
Expand All @@ -223,10 +251,12 @@ internal abstract class MutableLicenseeExtension : LicenseeExtension {
internal abstract val allowedDependencies: MapProperty<DependencyCoordinates, Optional<String>>
internal abstract val ignoredGroupIds: MapProperty<String, IgnoredData>
internal abstract val ignoredCoordinates: NamedDomainObjectContainer<IgnoredCoordinate>

internal abstract val violationAction: Property<ViolationAction>
internal abstract val unusedAction: Property<UnusedAction>

init {
violationAction.convention(ViolationAction.FAIL)
unusedAction.convention(UnusedAction.LOG)
}

fun toDependencyTreeConfig(): Provider<DependencyConfig> {
Expand Down Expand Up @@ -346,6 +376,10 @@ internal abstract class MutableLicenseeExtension : LicenseeExtension {
override fun violationAction(level: ViolationAction) {
violationAction.set(level)
}

override fun unusedAction(level: UnusedAction) {
unusedAction.set(level)
}
}

private fun <T, L, R, V> Provider<T>.zip(left: Provider<L>, right: Provider<R>, merge: (T, L, R) -> V): Provider<V> {
Expand Down
29 changes: 18 additions & 11 deletions src/main/kotlin/app/cash/licensee/task.kt
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,6 @@
*/
package app.cash.licensee

import app.cash.licensee.ViolationAction.FAIL
import app.cash.licensee.ViolationAction.IGNORE
import java.io.File
import java.io.Serializable
import kotlinx.serialization.builtins.ListSerializer
Expand All @@ -39,6 +37,7 @@ import org.gradle.api.artifacts.result.ResolvedComponentResult
import org.gradle.api.artifacts.result.ResolvedVariantResult
import org.gradle.api.attributes.Attribute
import org.gradle.api.file.DirectoryProperty
import org.gradle.api.logging.LogLevel
import org.gradle.api.logging.LogLevel.ERROR
import org.gradle.api.logging.LogLevel.INFO
import org.gradle.api.logging.LogLevel.LIFECYCLE
Expand All @@ -65,6 +64,9 @@ abstract class LicenseeTask : DefaultTask() {
@get:Input
internal abstract val violationAction: Property<ViolationAction>

@get:Input
internal abstract val unusedAction: Property<UnusedAction>

@get:Input
internal abstract val coordinatesToPomInfo: MapProperty<DependencyCoordinates, PomInfo>

Expand Down Expand Up @@ -270,22 +272,27 @@ abstract class LicenseeTask : DefaultTask() {
val validationReport = StringBuilder()

val violationAction = violationAction.get()
val errorLevel = if (violationAction == IGNORE) INFO else ERROR
val warningLevel = if (violationAction == IGNORE) INFO else WARN
val lifecycleLevel = if (violationAction == IGNORE) INFO else LIFECYCLE
val violationErrorLevel = if (violationAction == ViolationAction.IGNORE) INFO else ERROR
val violationWarningLevel = if (violationAction == ViolationAction.IGNORE) INFO else WARN

val unusedAction = unusedAction.get()
val unusedErrorLevel = if (unusedAction == UnusedAction.IGNORE) INFO else ERROR
val unusedWarningLevel = if (unusedAction == UnusedAction.IGNORE) INFO else WARN

val lifecycleLevel = if (violationAction == ViolationAction.IGNORE) INFO else LIFECYCLE

fun logResult(configResult: ValidationResult, prefix: String = "") {
fun logResult(configResult: ValidationResult, error: LogLevel, warning: LogLevel, prefix: String = "") {
when (configResult) {
is ValidationResult.Error -> {
val message = prefix + "ERROR: " + configResult.message
validationReport.appendLine(message)
logger.log(errorLevel, message)
logger.log(error, message)
}

is ValidationResult.Warning -> {
val message = prefix + "WARNING: " + configResult.message
validationReport.appendLine(message)
logger.log(warningLevel, message)
logger.log(warning, message)
}

is ValidationResult.Info -> {
Expand All @@ -296,7 +303,7 @@ abstract class LicenseeTask : DefaultTask() {
}
}
for (configResult in validationResult.configResults) {
logResult(configResult)
logResult(configResult, unusedErrorLevel, unusedWarningLevel)
}
if (validationResult.configResults.isNotEmpty() && validationResult.artifactResults.isNotEmpty()) {
validationReport.appendLine()
Expand All @@ -320,15 +327,15 @@ abstract class LicenseeTask : DefaultTask() {
logger.info(coordinateHeader)
}
for (result in results) {
logResult(result, prefix = " - ")
logResult(result, violationErrorLevel, violationWarningLevel, prefix = " - ")
}
}

val validationReportFile = File(outputDir, "validation.txt")
validationReportFile.parentFile.mkdirs()
validationReportFile.writeText(validationReport.toString())

if (violationAction == FAIL && validationResult.containsErrors) {
if (violationAction == ViolationAction.FAIL && validationResult.containsErrors) {
throw RuntimeException("Artifacts failed validation. See output above.")
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import app.cash.licensee.UnusedAction.IGNORE

plugins {
id("java-library")
alias(libs.plugins.licensee)
}

dependencies {
implementation("com.example:example:1.0.0")
}

licensee {
allowDependency("com.example", "example", "1.0.0")
allowDependency("com.example", "example2", "1.0.0")
unusedAction(IGNORE)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
WARNING: Allowed dependency 'com.example:example2:1.0.0' is unused

com.example:example:1.0.0
- SPDX identifier 'Apache-2.0' is NOT allowed
- Coordinate version is allowed
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<project>
<modelVersion>4.0.0</modelVersion>
<groupId>com.example</groupId>
<artifactId>example</artifactId>
<version>1.0.0</version>
<licenses>
<license>
<name>Apache-2.0</name>
<url>https://www.apache.org/licenses/LICENSE-2.0.txt</url>
</license>
</licenses>
</project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
pluginManagement {
includeBuild("../../test-build-logic")
}

plugins {
id("licenseeTests")
}
14 changes: 14 additions & 0 deletions src/test/fixtures/coordinate-allow-unused-ignored/build.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
plugins {
id("java-library")
alias(libs.plugins.licensee)
}

dependencies {
implementation 'com.example:example:1.0.0'
}

licensee {
allowDependency('com.example', 'example', '1.0.0')
allowDependency('com.example', 'example2', '1.0.0')
unusedAction("IGNORE")
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
WARNING: Allowed dependency 'com.example:example2:1.0.0' is unused

com.example:example:1.0.0
- SPDX identifier 'Apache-2.0' is NOT allowed
- Coordinate version is allowed
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<project>
<modelVersion>4.0.0</modelVersion>
<groupId>com.example</groupId>
<artifactId>example</artifactId>
<version>1.0.0</version>
<licenses>
<license>
<name>Apache-2.0</name>
<url>https://www.apache.org/licenses/LICENSE-2.0.txt</url>
</license>
</licenses>
</project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
pluginManagement {
includeBuild("../../test-build-logic")
}

plugins {
id("licenseeTests")
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import app.cash.licensee.UnusedAction.LOG

plugins {
id("java-library")
alias(libs.plugins.licensee)
}

dependencies {
implementation("com.example:example:1.0.0")
}

licensee {
allowDependency("com.example", "example", "1.0.0")
allowDependency("com.example", "example2", "1.0.0")
unusedAction(LOG)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
WARNING: Allowed dependency 'com.example:example2:1.0.0' is unused

com.example:example:1.0.0
- SPDX identifier 'Apache-2.0' is NOT allowed
- Coordinate version is allowed
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<project>
<modelVersion>4.0.0</modelVersion>
<groupId>com.example</groupId>
<artifactId>example</artifactId>
<version>1.0.0</version>
<licenses>
<license>
<name>Apache-2.0</name>
<url>https://www.apache.org/licenses/LICENSE-2.0.txt</url>
</license>
</licenses>
</project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
pluginManagement {
includeBuild("../../test-build-logic")
}

plugins {
id("licenseeTests")
}
14 changes: 14 additions & 0 deletions src/test/fixtures/coordinate-allow-unused-warn/build.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
plugins {
id("java-library")
alias(libs.plugins.licensee)
}

dependencies {
implementation 'com.example:example:1.0.0'
}

licensee {
allowDependency('com.example', 'example', '1.0.0')
allowDependency('com.example', 'example2', '1.0.0')
unusedAction("LOG")
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
WARNING: Allowed dependency 'com.example:example2:1.0.0' is unused

com.example:example:1.0.0
- SPDX identifier 'Apache-2.0' is NOT allowed
- Coordinate version is allowed
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<project>
<modelVersion>4.0.0</modelVersion>
<groupId>com.example</groupId>
<artifactId>example</artifactId>
<version>1.0.0</version>
<licenses>
<license>
<name>Apache-2.0</name>
<url>https://www.apache.org/licenses/LICENSE-2.0.txt</url>
</license>
</licenses>
</project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
pluginManagement {
includeBuild("../../test-build-logic")
}

plugins {
id("licenseeTests")
}
14 changes: 14 additions & 0 deletions src/test/fixtures/spdx-allow-unused-ignored/build.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
plugins {
id("java-library")
alias(libs.plugins.licensee)
}

dependencies {
implementation 'com.example:example:1.0.0'
}

licensee {
allow('Apache-2.0')
allow('MIT')
unusedAction("IGNORE")
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
WARNING: Allowed SPDX identifier 'MIT' is unused

com.example:example:1.0.0
- SPDX identifier 'Apache-2.0' allowed
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<project>
<modelVersion>4.0.0</modelVersion>
<groupId>com.example</groupId>
<artifactId>example</artifactId>
<version>1.0.0</version>
<licenses>
<license>
<name>Apache-2.0</name>
<url>https://www.apache.org/licenses/LICENSE-2.0.txt</url>
</license>
</licenses>
</project>
7 changes: 7 additions & 0 deletions src/test/fixtures/spdx-allow-unused-ignored/settings.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
pluginManagement {
includeBuild("../../test-build-logic")
}

plugins {
id("licenseeTests")
}
14 changes: 14 additions & 0 deletions src/test/fixtures/spdx-allow-unused-warn/build.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
plugins {
id("java-library")
alias(libs.plugins.licensee)
}

dependencies {
implementation 'com.example:example:1.0.0'
}

licensee {
allow('Apache-2.0')
allow('MIT')
unusedAction("LOG")
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
WARNING: Allowed SPDX identifier 'MIT' is unused

com.example:example:1.0.0
- SPDX identifier 'Apache-2.0' allowed
Binary file not shown.
Loading

0 comments on commit 9fa4fbc

Please sign in to comment.