Gradle plugin which validates the licenses of your dependency graph match what you expect

Overview

Licensee πŸ“œ πŸ‘€

A Gradle plugin which validates the licenses of your dependency graph match what you expect, or it fails your build!

Jump to: Introduction | Usage | Configuration | Development | License

Introduction

Imagine your closed-source product depends on an Apache 2-licensed artifact.

implementation 'com.example:example:1.0'

The developer releases a new version and you dutifully upgrade.

-implementation 'com.example:example:1.0'
+implementation 'com.example:example:1.1'

This new version has a transitive dependency on a GPL-licensed artifact which is incompatible with your closed-source product. Did you catch it?

You may have seen the new dependency in a dependency tree diff, but did you check its license?

-+--- com.example:example:1.0
++--- com.example:example:1.1
+     \--- com.other:other:2.5

With the Licensee plugin applied, you don't have to. First, configure it to allow Apache 2-licensed dependencies.

licensee {
  allow('Apache-2.0')
}

Now attempting to upgrade the dependency will fail the build.

> Task :app:licensee FAILED
com.other:other:2.5
 - SPDX identifier 'GPL-3.0-or-later' is NOT allowed

Crisis averted!

Usage

Add the dependency and apply the plugin to the module whose dependency graph you want to check.

buildscript {
  repository {
    mavenCental()
  }
  dependencies {
    classpath 'app.cash.licensee:licensee-gradle-plugin:1.2.0'
  }
}

apply plugin: 'app.cash.licensee'
Snapshots of the development version are available in Sonatype's snapshots repository.

buildscript {
  repository {
    mavenCental()
    maven {
      url 'https://oss.sonatype.org/content/repositories/snapshots/'
    }
  }
  dependencies {
    classpath 'app.cash.licensee:licensee-gradle-plugin:1.3.0-SNAPSHOT'
  }
}

apply plugin: 'app.cash.licensee'

The plugin's tasks will walk the entire transitive dependency graph, so it only needs to be applied to "leaf" modules (those without downstream dependencies) such as applications and services. If you are building a library, however, apply it to each library module.

Licensee requires a supported language/platform plugin to also be applied to the same module:

  • java-library
  • java
  • com.android.application
  • com.android.library
  • org.jetbrains.kotlin.jvm
  • org.jetbrains.kotlin.js
  • org.jetbrains.kotlin.multiplatform

Configure the list of allowed licenses using the licensee DSL:

licensee {
  allow('Apache-2.0')
}

For more configuration options, see the configuration section.

The licensee task will be added to your build and automatically added as a dependency of the check task. Android and Kotlin multiplatform modules will have variant-specific versions of this task (such as licenseeDebug and licenseeJs) with the licensee task merely aggregating them together.

In addition to failing the build on detection of a disallowed license, the plugin will always generate some report files.

  1. artifacts.json

    A JSON file with license information on every artifact in the depenency graph.

  2. validation.txt

    A plain text report containing each artifact and whether its licenses are allowed or disallowed.

These files are generated into /reports/licensee, or for Android modules /reports/licensee//.

Configuration

The following functions are available on the licensee DSL and/or app.cash.licensee.LicenseeExtension type.

allow

Allow artifacts with a license that matches a SPDX identifier.

licensee {
  allow('Apache-2.0')
  allow('MIT')
}

A full list of supported identifiers is available at spdx.org/licenses/.

allowUrl

Allow artifacts with an unknown (non-SPDX) license which matches a URL.

licensee {
  allowUrl('https://example.com/license.html')
}

allowDependency

Allow an artifact with a specific groupId, artifactId, and version. This is useful for artifacts which contain no license data or have invalid/incorrect license data.

licensee {
  allowDependency('com.example', 'example', '1.0')
}

A reason string can be supplied to document why the dependency is being allowed despite missing or invalid license data.

licensee {
  allowDependency('com.jetbrains', 'annotations', '16.0.1') {
    because 'Apache-2.0, but typo in license URL fixed in newer versions'
  }
}

Reason strings will be included in validation reports.

ignoreDependencies

Ignore a single dependency or group of dependencies during dependency graph resolution. Artifacts targeted with this method will not be analyzed for license information and will not show up in any report files.

This function can be used to ignore internal, closed-source libraries and commercial libraries for which you've purchased a license.

There are overloads which accept either a groupId or a groupId:artifactId pair.

licensee {
  ignoreDependencies('com.mycompany.internal')
  ignoreDependencies('com.mycompany.utils', 'utils')
}

A reason string can be supplied to document why the dependencies are being ignored.

licensee {
  ignoreDependencies('com.example.sdk', 'sdk') {
    because "commercial SDK"
  }
}

An ignore can be marked as transitive which will ignore an entire branch of the dependency tree. This will ignore the target artifact's dependencies regardless of the artifact coordinates or license info. Since it is especially dangerous, a reason string is required.

licensee {
  ignoreDependencies('com.other.sdk', 'sdk') {
    transitive = true
    because "commercial SDK"
  }
}

Development

Updating embedded license info

Run the updateLicenses task to update the embedded SPDX license file in src/main/resources/.

License

Copyright 2021 Square, Inc.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

   http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
Comments
  • Add support for Configuration cache

    Add support for Configuration cache

    Instead of resolving the pom files during task action, they are now resolved during configuration. This should not have a negative performance impact, because Gradle fetches the pom files to resolve the dependencies too.

    Problem: dependency-substitution-replace-remote-with-include-build-ignored fails, because I access the incoming configuration before the dependency substitution is resolved. Unfortunately, I don't know, how to solve this.

    Adding a dependency substitution rule to a configuration changes the timing of when that configuration is resolved. https://docs.gradle.org/current/userguide/resolution_rules.html#sec:module_replacement

    Fixes #72

    opened by hfhbd 12
  • Could not initialize class app.cash.licensee.LicensesKt

    Could not initialize class app.cash.licensee.LicensesKt

    project/build.gradle:

    buildscript {
        dependencies {
            classpath 'app.cash.licensee:licensee-gradle-plugin:1.0.2'
        }
    }
    

    project/app/build.gradle:

    apply plugin: 'app.cash.licensee'
    
    licensee {
        allow('Apache-2.0')
    }
    

    Running the task ./gradlew :app:licensee fails the build with the following stacktrace:

    > Task :app:licenseeDebug FAILED
    
    Execution failed for task ':app:licenseeDebug'.
    > Could not initialize class app.cash.licensee.LicensesKt
    
    * Try:
    Run with --info or --debug option to get more log output. Run with --scan to get full insights.
    
    * Exception is:
    org.gradle.api.tasks.TaskExecutionException: Execution failed for task ':app:licenseeDebug'.
    	at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.lambda$executeIfValid$1(ExecuteActionsTaskExecuter.java:200)
    	at org.gradle.internal.Try$Failure.ifSuccessfulOrElse(Try.java:263)
    	at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.executeIfValid(ExecuteActionsTaskExecuter.java:198)
    	at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.execute(ExecuteActionsTaskExecuter.java:179)
    	at org.gradle.api.internal.tasks.execution.CleanupStaleOutputsExecuter.execute(CleanupStaleOutputsExecuter.java:109)
    	at org.gradle.api.internal.tasks.execution.FinalizePropertiesTaskExecuter.execute(FinalizePropertiesTaskExecuter.java:46)
    	at org.gradle.api.internal.tasks.execution.ResolveTaskExecutionModeExecuter.execute(ResolveTaskExecutionModeExecuter.java:62)
    	at org.gradle.api.internal.tasks.execution.SkipTaskWithNoActionsExecuter.execute(SkipTaskWithNoActionsExecuter.java:57)
    	at org.gradle.api.internal.tasks.execution.SkipOnlyIfTaskExecuter.execute(SkipOnlyIfTaskExecuter.java:56)
    	at org.gradle.api.internal.tasks.execution.CatchExceptionTaskExecuter.execute(CatchExceptionTaskExecuter.java:36)
    	at org.gradle.api.internal.tasks.execution.EventFiringTaskExecuter$1.executeTask(EventFiringTaskExecuter.java:77)
    	at org.gradle.api.internal.tasks.execution.EventFiringTaskExecuter$1.call(EventFiringTaskExecuter.java:55)
    	at org.gradle.api.internal.tasks.execution.EventFiringTaskExecuter$1.call(EventFiringTaskExecuter.java:52)
    	at org.gradle.internal.operations.DefaultBuildOperationRunner$CallableBuildOperationWorker.execute(DefaultBuildOperationRunner.java:200)
    	at org.gradle.internal.operations.DefaultBuildOperationRunner$CallableBuildOperationWorker.execute(DefaultBuildOperationRunner.java:195)
    	at org.gradle.internal.operations.DefaultBuildOperationRunner$3.execute(DefaultBuildOperationRunner.java:75)
    	at org.gradle.internal.operations.DefaultBuildOperationRunner$3.execute(DefaultBuildOperationRunner.java:68)
    	at org.gradle.internal.operations.DefaultBuildOperationRunner.execute(DefaultBuildOperationRunner.java:153)
    	at org.gradle.internal.operations.DefaultBuildOperationRunner.execute(DefaultBuildOperationRunner.java:68)
    	at org.gradle.internal.operations.DefaultBuildOperationRunner.call(DefaultBuildOperationRunner.java:62)
    	at org.gradle.internal.operations.DefaultBuildOperationExecutor.lambda$call$2(DefaultBuildOperationExecutor.java:76)
    	at org.gradle.internal.operations.UnmanagedBuildOperationWrapper.callWithUnmanagedSupport(UnmanagedBuildOperationWrapper.java:54)
    	at org.gradle.internal.operations.DefaultBuildOperationExecutor.call(DefaultBuildOperationExecutor.java:76)
    	at org.gradle.api.internal.tasks.execution.EventFiringTaskExecuter.execute(EventFiringTaskExecuter.java:52)
    	at org.gradle.execution.plan.LocalTaskNodeExecutor.execute(LocalTaskNodeExecutor.java:41)
    	at org.gradle.execution.taskgraph.DefaultTaskExecutionGraph$InvokeNodeExecutorsAction.execute(DefaultTaskExecutionGraph.java:372)
    	at org.gradle.execution.taskgraph.DefaultTaskExecutionGraph$InvokeNodeExecutorsAction.execute(DefaultTaskExecutionGraph.java:359)
    	at org.gradle.execution.taskgraph.DefaultTaskExecutionGraph$BuildOperationAwareExecutionAction.execute(DefaultTaskExecutionGraph.java:352)
    	at org.gradle.execution.taskgraph.DefaultTaskExecutionGraph$BuildOperationAwareExecutionAction.execute(DefaultTaskExecutionGraph.java:338)
    	at org.gradle.execution.plan.DefaultPlanExecutor$ExecutorWorker.lambda$run$0(DefaultPlanExecutor.java:127)
    	at org.gradle.execution.plan.DefaultPlanExecutor$ExecutorWorker.execute(DefaultPlanExecutor.java:191)
    	at org.gradle.execution.plan.DefaultPlanExecutor$ExecutorWorker.executeNextNode(DefaultPlanExecutor.java:182)
    	at org.gradle.execution.plan.DefaultPlanExecutor$ExecutorWorker.run(DefaultPlanExecutor.java:124)
    	at org.gradle.internal.concurrent.ExecutorPolicy$CatchAndRecordFailures.onExecute(ExecutorPolicy.java:64)
    	at org.gradle.internal.concurrent.ManagedExecutorImpl$1.run(ManagedExecutorImpl.java:48)
    	at org.gradle.internal.concurrent.ThreadFactoryImpl$ManagedThreadRunnable.run(ThreadFactoryImpl.java:56)
    Caused by: java.lang.NoClassDefFoundError: Could not initialize class app.cash.licensee.LicensesKt
    	at app.cash.licensee.LicenseeTask.execute(task.kt:134)
    	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    	at org.gradle.internal.reflect.JavaMethod.invoke(JavaMethod.java:104)
    	at org.gradle.api.internal.project.taskfactory.StandardTaskAction.doExecute(StandardTaskAction.java:58)
    	at org.gradle.api.internal.project.taskfactory.StandardTaskAction.execute(StandardTaskAction.java:51)
    	at org.gradle.api.internal.project.taskfactory.StandardTaskAction.execute(StandardTaskAction.java:29)
    	at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter$3.run(ExecuteActionsTaskExecuter.java:555)
    	at org.gradle.internal.operations.DefaultBuildOperationRunner$1.execute(DefaultBuildOperationRunner.java:29)
    	at org.gradle.internal.operations.DefaultBuildOperationRunner$1.execute(DefaultBuildOperationRunner.java:26)
    	at org.gradle.internal.operations.DefaultBuildOperationRunner$3.execute(DefaultBuildOperationRunner.java:75)
    	at org.gradle.internal.operations.DefaultBuildOperationRunner$3.execute(DefaultBuildOperationRunner.java:68)
    	at org.gradle.internal.operations.DefaultBuildOperationRunner.execute(DefaultBuildOperationRunner.java:153)
    	at org.gradle.internal.operations.DefaultBuildOperationRunner.execute(DefaultBuildOperationRunner.java:68)
    	at org.gradle.internal.operations.DefaultBuildOperationRunner.run(DefaultBuildOperationRunner.java:56)
    	at org.gradle.internal.operations.DefaultBuildOperationExecutor.lambda$run$1(DefaultBuildOperationExecutor.java:71)
    	at org.gradle.internal.operations.UnmanagedBuildOperationWrapper.runWithUnmanagedSupport(UnmanagedBuildOperationWrapper.java:45)
    	at org.gradle.internal.operations.DefaultBuildOperationExecutor.run(DefaultBuildOperationExecutor.java:71)
    	at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.executeAction(ExecuteActionsTaskExecuter.java:540)
    	at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.executeActions(ExecuteActionsTaskExecuter.java:523)
    	at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.access$300(ExecuteActionsTaskExecuter.java:108)
    	at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter$TaskExecution.executeWithPreviousOutputFiles(ExecuteActionsTaskExecuter.java:271)
    	at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter$TaskExecution.execute(ExecuteActionsTaskExecuter.java:260)
    	at org.gradle.internal.execution.steps.ExecuteStep.lambda$execute$1(ExecuteStep.java:34)
    	at org.gradle.internal.execution.steps.ExecuteStep.execute(ExecuteStep.java:34)
    	at org.gradle.internal.execution.steps.ExecuteStep.execute(ExecuteStep.java:26)
    	at org.gradle.internal.execution.steps.CleanupOutputsStep.execute(CleanupOutputsStep.java:67)
    	at org.gradle.internal.execution.steps.CleanupOutputsStep.execute(CleanupOutputsStep.java:36)
    	at org.gradle.internal.execution.steps.ResolveInputChangesStep.execute(ResolveInputChangesStep.java:49)
    	at org.gradle.internal.execution.steps.ResolveInputChangesStep.execute(ResolveInputChangesStep.java:34)
    	at org.gradle.internal.execution.steps.CancelExecutionStep.execute(CancelExecutionStep.java:43)
    	at org.gradle.internal.execution.steps.TimeoutStep.executeWithoutTimeout(TimeoutStep.java:73)
    	at org.gradle.internal.execution.steps.TimeoutStep.execute(TimeoutStep.java:54)
    	at org.gradle.internal.execution.steps.CreateOutputsStep.execute(CreateOutputsStep.java:44)
    	at org.gradle.internal.execution.steps.SnapshotOutputsStep.execute(SnapshotOutputsStep.java:54)
    	at org.gradle.internal.execution.steps.SnapshotOutputsStep.execute(SnapshotOutputsStep.java:38)
    	at org.gradle.internal.execution.steps.BroadcastChangingOutputsStep.execute(BroadcastChangingOutputsStep.java:42)
    	at org.gradle.internal.execution.steps.CacheStep.executeWithoutCache(CacheStep.java:159)
    	at org.gradle.internal.execution.steps.CacheStep.execute(CacheStep.java:72)
    	at org.gradle.internal.execution.steps.CacheStep.execute(CacheStep.java:43)
    	at org.gradle.internal.execution.steps.StoreExecutionStateStep.execute(StoreExecutionStateStep.java:44)
    	at org.gradle.internal.execution.steps.StoreExecutionStateStep.execute(StoreExecutionStateStep.java:33)
    	at org.gradle.internal.execution.steps.RecordOutputsStep.execute(RecordOutputsStep.java:38)
    	at org.gradle.internal.execution.steps.RecordOutputsStep.execute(RecordOutputsStep.java:24)
    	at org.gradle.internal.execution.steps.SkipUpToDateStep.executeBecause(SkipUpToDateStep.java:92)
    	at org.gradle.internal.execution.steps.SkipUpToDateStep.lambda$execute$0(SkipUpToDateStep.java:85)
    	at org.gradle.internal.execution.steps.SkipUpToDateStep.execute(SkipUpToDateStep.java:55)
    	at org.gradle.internal.execution.steps.SkipUpToDateStep.execute(SkipUpToDateStep.java:39)
    	at org.gradle.internal.execution.steps.ResolveChangesStep.execute(ResolveChangesStep.java:76)
    	at org.gradle.internal.execution.steps.ResolveChangesStep.execute(ResolveChangesStep.java:37)
    	at org.gradle.internal.execution.steps.legacy.MarkSnapshottingInputsFinishedStep.execute(MarkSnapshottingInputsFinishedStep.java:36)
    	at org.gradle.internal.execution.steps.legacy.MarkSnapshottingInputsFinishedStep.execute(MarkSnapshottingInputsFinishedStep.java:26)
    	at org.gradle.internal.execution.steps.ResolveCachingStateStep.execute(ResolveCachingStateStep.java:94)
    	at org.gradle.internal.execution.steps.ResolveCachingStateStep.execute(ResolveCachingStateStep.java:49)
    	at org.gradle.internal.execution.steps.CaptureStateBeforeExecutionStep.execute(CaptureStateBeforeExecutionStep.java:79)
    	at org.gradle.internal.execution.steps.CaptureStateBeforeExecutionStep.execute(CaptureStateBeforeExecutionStep.java:53)
    	at org.gradle.internal.execution.steps.ValidateStep.execute(ValidateStep.java:74)
    	at org.gradle.internal.execution.steps.SkipEmptyWorkStep.lambda$execute$2(SkipEmptyWorkStep.java:78)
    	at org.gradle.internal.execution.steps.SkipEmptyWorkStep.execute(SkipEmptyWorkStep.java:78)
    	at org.gradle.internal.execution.steps.SkipEmptyWorkStep.execute(SkipEmptyWorkStep.java:34)
    	at org.gradle.internal.execution.steps.legacy.MarkSnapshottingInputsStartedStep.execute(MarkSnapshottingInputsStartedStep.java:39)
    	at org.gradle.internal.execution.steps.LoadExecutionStateStep.execute(LoadExecutionStateStep.java:40)
    	at org.gradle.internal.execution.steps.LoadExecutionStateStep.execute(LoadExecutionStateStep.java:28)
    	at org.gradle.internal.execution.impl.DefaultWorkExecutor.execute(DefaultWorkExecutor.java:33)
    	at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.executeIfValid(ExecuteActionsTaskExecuter.java:187)
    	at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.execute(ExecuteActionsTaskExecuter.java:179)
    	at org.gradle.api.internal.tasks.execution.CleanupStaleOutputsExecuter.execute(CleanupStaleOutputsExecuter.java:109)
    	at org.gradle.api.internal.tasks.execution.FinalizePropertiesTaskExecuter.execute(FinalizePropertiesTaskExecuter.java:46)
    	at org.gradle.api.internal.tasks.execution.ResolveTaskExecutionModeExecuter.execute(ResolveTaskExecutionModeExecuter.java:62)
    	at org.gradle.api.internal.tasks.execution.SkipTaskWithNoActionsExecuter.execute(SkipTaskWithNoActionsExecuter.java:57)
    	at org.gradle.api.internal.tasks.execution.SkipOnlyIfTaskExecuter.execute(SkipOnlyIfTaskExecuter.java:56)
    	at org.gradle.api.internal.tasks.execution.CatchExceptionTaskExecuter.execute(CatchExceptionTaskExecuter.java:36)
    	at org.gradle.api.internal.tasks.execution.EventFiringTaskExecuter$1.executeTask(EventFiringTaskExecuter.java:77)
    	at org.gradle.api.internal.tasks.execution.EventFiringTaskExecuter$1.call(EventFiringTaskExecuter.java:55)
    	at org.gradle.api.internal.tasks.execution.EventFiringTaskExecuter$1.call(EventFiringTaskExecuter.java:52)
    	at org.gradle.internal.operations.DefaultBuildOperationRunner$CallableBuildOperationWorker.execute(DefaultBuildOperationRunner.java:200)
    	at org.gradle.internal.operations.DefaultBuildOperationRunner$CallableBuildOperationWorker.execute(DefaultBuildOperationRunner.java:195)
    	at org.gradle.internal.operations.DefaultBuildOperationRunner$3.execute(DefaultBuildOperationRunner.java:75)
    	at org.gradle.internal.operations.DefaultBuildOperationRunner$3.execute(DefaultBuildOperationRunner.java:68)
    	at org.gradle.internal.operations.DefaultBuildOperationRunner.execute(DefaultBuildOperationRunner.java:153)
    	at org.gradle.internal.operations.DefaultBuildOperationRunner.execute(DefaultBuildOperationRunner.java:68)
    	at org.gradle.internal.operations.DefaultBuildOperationRunner.call(DefaultBuildOperationRunner.java:62)
    	at org.gradle.internal.operations.DefaultBuildOperationExecutor.lambda$call$2(DefaultBuildOperationExecutor.java:76)
    	at org.gradle.internal.operations.UnmanagedBuildOperationWrapper.callWithUnmanagedSupport(UnmanagedBuildOperationWrapper.java:54)
    	at org.gradle.internal.operations.DefaultBuildOperationExecutor.call(DefaultBuildOperationExecutor.java:76)
    	at org.gradle.api.internal.tasks.execution.EventFiringTaskExecuter.execute(EventFiringTaskExecuter.java:52)
    	at org.gradle.execution.plan.LocalTaskNodeExecutor.execute(LocalTaskNodeExecutor.java:41)
    	at org.gradle.execution.taskgraph.DefaultTaskExecutionGraph$InvokeNodeExecutorsAction.execute(DefaultTaskExecutionGraph.java:372)
    	at org.gradle.execution.taskgraph.DefaultTaskExecutionGraph$InvokeNodeExecutorsAction.execute(DefaultTaskExecutionGraph.java:359)
    	at org.gradle.execution.taskgraph.DefaultTaskExecutionGraph$BuildOperationAwareExecutionAction.execute(DefaultTaskExecutionGraph.java:352)
    	at org.gradle.execution.taskgraph.DefaultTaskExecutionGraph$BuildOperationAwareExecutionAction.execute(DefaultTaskExecutionGraph.java:338)
    	at org.gradle.execution.plan.DefaultPlanExecutor$ExecutorWorker.lambda$run$0(DefaultPlanExecutor.java:127)
    	at org.gradle.execution.plan.DefaultPlanExecutor$ExecutorWorker.execute(DefaultPlanExecutor.java:191)
    	at org.gradle.execution.plan.DefaultPlanExecutor$ExecutorWorker.executeNextNode(DefaultPlanExecutor.java:182)
    	at org.gradle.execution.plan.DefaultPlanExecutor$ExecutorWorker.run(DefaultPlanExecutor.java:124)
    	at org.gradle.internal.concurrent.ExecutorPolicy$CatchAndRecordFailures.onExecute(ExecutorPolicy.java:64)
    	at org.gradle.internal.concurrent.ManagedExecutorImpl$1.run(ManagedExecutorImpl.java:48)
    	at org.gradle.internal.concurrent.ThreadFactoryImpl$ManagedThreadRunnable.run(ThreadFactoryImpl.java:56)
    

    The project has about 70 modules.

    opened by nodejsjs 8
  • Add Fallback URL for EPL-2.0

    Add Fallback URL for EPL-2.0

    Use case: A pom file has a trailing slash in the license url so it is not recognized as EPL-2.0 although it is inside the json file: - Unknown license URL 'https://www.eclipse.org/legal/epl-2.0/' is NOT allowed

    opened by hfhbd 7
  • Disable dependency verification on created configurations

    Disable dependency verification on created configurations

    When using Gradle dependency verification on projects I believe it is quite common to ignore pom files by setting verify-metadata to false in verification-metadata.xml This means no POM files gets listed in this XML file. However, when running the licensee plugin it adds pom file dependencies which then gets included in dependency verification, causing builds to fail verification. Since the plugin is not adding any dependencies for real to the project I believe it would make sense for it to disable verification on its created, detached configuration as outlined in 1:

    val pomCoordinates = with(id) { "$group:$artifact:$version@pom" } val pomDependency = project.dependencies.create(pomCoordinates) val detachedConfiguration = project.configurations .detachedConfiguration(pomDependency) detachedConfiguration.resolutionStrategy.disableDependencyVerification() val pomConfiguration = detachedConfiguration.resolvedConfiguration .lenientConfiguration

    bug 
    opened by sb-software 7
  • Fails to find license with Kotlin Multiplatform Javascript Target

    Fails to find license with Kotlin Multiplatform Javascript Target

    STEPS TO REPRODUCE

    1. Create a gradle module with multiplatform libraries like com.benasher44:uuid:0.3.1, a javascript target, and applying version 1.3.0 of the licensee plugin. E.g.
    plugins {
        kotlin("multiplatform")
        id("app.cash.licensee")
    }
    kotlin {
        jvm()
        js(IR)
        sourceSets {
            val commonMain by getting {
                dependencies {
                    api("com.benasher44:uuid:0.3.1")
                }
            }
    }
    

    RESULTS Actual:

    com.benasher44:uuid-js:0.3.1
     - ERROR: Artifact declares no licenses!
    

    Expected: It finds the license for the JVM target, so it should also succeed with the Javascript target.

    NOTES I don't know if there's a limitation in the Kotlin Multiplatform Gradle plugin where we need to file an issue with JetBrains, but I thought I'd start here.

    opened by ccjernigan 7
  • "Artifact declares no licenses" error since 1.6.0

    Since version 1.6.0 we suddenly receive the following error. Interestingly only on our CI server and not locally.

     - ERROR: Artifact declares no licenses!
    
    > Task :app:licenseeBeta FAILED
    WARNING: Allowed license URL 'https://api.github.com/licenses/apache-2.0' is unused
    
    com.github.chrisbanes:PhotoView:2.3.0
    

    Downgrading to 1.5.0 "fixes" this.

    opened by svenjacobs 5
  • Feature request: Ability to disable license validation and only generate artifacts.json

    Feature request: Ability to disable license validation and only generate artifacts.json

    First off, thanks for the great plugin! We recently integrated it into our app and it's working well.

    I was wondering if it would be possible to have an option to disable license validation and only generate artifacts.json for the project dependencies? Main reasoning is that we already have a tool that does license validation so we are having to update the plugin manually quite frequently.

    Perhaps, something similar to how we have allow() or ignoreDependencies but allowAll() or equivalent?

    enhancement 
    opened by gchristov 4
  • Change license validation behavior to logical OR

    Change license validation behavior to logical OR

    https://github.com/facebook/rocksdb is licensed under Apache 2 as well as GPLv2. https://repo.maven.apache.org/maven2/org/rocksdb/rocksdbjni/7.2.2/rocksdbjni-7.2.2.pom

    <licenses>
      <license>
        <name>Apache License 2.0</name>
        <url>http://www.apache.org/licenses/LICENSE-2.0.html</url>
        <distribution>repo</distribution>
      </license>
      <license>
        <name>GNU General Public License, version 2</name>
        <url>http://www.gnu.org/licenses/gpl-2.0.html</url>
        <distribution>repo</distribution>
      </license>
    </licenses>
    

    repro:

    plugins {
        kotlin("jvm") version "1.7.0-RC"
        id("app.cash.licensee") version "1.3.1"
    }
    
    repositories {
        mavenCentral()
    }
    
    dependencies {
        implementation("org.rocksdb:rocksdbjni:7.2.2")
    }
    
    licensee {
        allow("Apache-2.0")
    }
    

    dual.zip

    bug 
    opened by hfhbd 3
  • Licensee doesn't find license

    Licensee doesn't find license

    I'm getting this error

    com.freeletics.mad:navigator-runtime:0.3.0-alpha27
     - ERROR: Artifact declares no licenses!
    

    however the license is in the pom and the previous release which looks the same worked just fine. My theory is that licensee gets confused by the newer release using Android's new multi variant publishing, even though that doesn't have any influence on the pom.

    opened by gabrielittner 3
  • Support for Gradle configuration caching

    Support for Gradle configuration caching

    Screen Shot 2021-12-08 at 9 18 40 PM

    Looks like the recursive traversal of loadPomInfo is the root cause:

    https://github.com/cashapp/licensee/blob/trunk/src/main/kotlin/app/cash/licensee/task.kt#L136

    https://github.com/cashapp/licensee/blob/trunk/src/main/kotlin/app/cash/licensee/dependencyGraph.kt#L247

    enhancement good first issue PR welcome 
    opened by jrodbx 3
  • License for com.russhwolf:multiplatform-settings:0.8 can't be retrieved

    License for com.russhwolf:multiplatform-settings:0.8 can't be retrieved

    When using:

    sourceSets.commonMain.dependencies {
      api "com.russhwolf:multiplatform-settings:0.8.0"
    }
    

    I'm getting:

    com.russhwolf:multiplatform-settings:0.8
     - ERROR: Artifact declares no licenses!
    

    Looking at the POM it's present.

    I'm applying the module to my app, while the API is declared in a shared KMP module.

    opened by vanniktech 3
  • Update dependency com.vanniktech:gradle-maven-publish-plugin to v0.23.1

    Update dependency com.vanniktech:gradle-maven-publish-plugin to v0.23.1

    Mend Renovate

    This PR contains the following updates:

    | Package | Change | Age | Adoption | Passing | Confidence | |---|---|---|---|---|---| | com.vanniktech:gradle-maven-publish-plugin | 0.14.2 -> 0.23.1 | age | adoption | passing | confidence |


    Release Notes

    vanniktech/gradle-maven-publish-plugin

    v0.23.1

    Compare Source

    • Also support publishing sources for the java-test-fixtures plugin in Kotlin/JVM projects.
    • Suppress Gradle warnings when publishing a project that uses java-test-fixtures.

    v0.23.0

    Compare Source

    Updated docs can be found on the new website.

    • NEW: It is now possible to set group id, artifact id directly through the DSL
      mavenPublishing {
        coordinates("com.example", "library", "1.0.3")
      }
      
    • project.group and project.version will still be used as default values for group and version if the GROUP/VERSION_NAME Gradle properties do not exist and coordinates was not called, however there are 2 behavior changes:
      • The GROUP and VERSION_NAME Gradle properties take precedence over project.group and project.version instead of being overwritten by them. If you need to define the properties but replace them for some projects, please use the new coordinates method instead.
      • The GROUP and VERSION_NAME Gradle properties will not be explicitly set as project.group and project.version anymore.
    • NEW: Added dropRepository task that will drop a Sonatype staging repository. It is possible to specify which repository to drop by adding a --repository parameter with the id of the staging repository that was printed during publish. If no repository is specified and there is only one staging repository, that one will be dropped.
    • Added workaround to also publish sources for the java-test-fixtures plugin
    • Fixed publishing Kotlin/JS projects with the base plugin.
    • Fixed that a POM configured through the DSL is incomplete when publishing Gradle plugins.
    • The minimum supported Gradle version has been increased to 7.3.

    v0.22.0

    Compare Source

    • NEW: When publishing to maven central by setting SONATYPE_HOST or calling publishToMavenCentral(...) the plugin will now explicitly create a staging repository on Sonatype. This avoids issues where a single build would create multiple repositories
    • The above change means that the plugin supports parallel builds and it is not neccessary anymore to use --no-parallel and --no-daemon together with publish
    • NEW: When publishing with the publish or publishAllPublicationsToMavenCentralRepository tasks the plugin will automatically close the staging repository at the end of the build if it was successful.
    • NEW: Option to also automatically release the staging repository after closing was susccessful
    SONATYPE_HOST=DEFAULT # or S01
    SONATYPE_AUTOMATIC_RELEASE=true
    

    or

    mavenPublishing {
      publishToMavenCentral("DEFAULT", true)
      // or publishToMavenCentral("S01", true)
    }
    
    • in case the option above is enabled, the closeAndReleaseRepository task is not needed anymore
    • when closing the repository fails the plugin will fail the build immediately instead of timing out
    • when closing the repository fails the plugin will try to print the error messages from Nexus
    • increased timeouts for calls to the Sonatype Nexus APIs
    • fixed incompatibility with the com.gradle.plugin-publish plugin
    • added wokaround for Kotlin multiplatform builds reporting disabled build optimizations (see KT-46466)

    v0.21.0

    Compare Source

    Minimum supported Gradle version is now 7.2.0

    Minimum supported Android Gradle Plugin versions are now 7.1.2, 7.2.0-beta02 and 7.3.0-alpha01

    Behavior changes

    The com.vanniktech.maven.publish stops adding Maven Central (Sonatype OSS) as a publishing target and will not enable GPG signing by default. To continue publishing to maven central and signing artifacts either add the following to your gradle.properties:

    SONATYPE_HOST=DEFAULT
    

    v0.20.0

    Compare Source

    Upcoming behavior change

    In the next release after this the com.vanniktech.maven.publish will stop adding Maven Central (Sonatype OSS) as a publishing target and will not enable GPG signing by default. If you are currently relying on this behavior the plugin will print a warning during configuration phase. To continue publishing to maven central and signing artifacts either add this to your build files:

    mavenPublishing {
      publishToMavenCentral() // use publishToMavenCentral("S01") for publishing through s01.oss.sonatype.org
      signAllPublications()
    }
    

    or the following to your gradle.properties:

    SONATYPE_HOST=DEFAULT
    

    v0.19.0

    Compare Source

    • Behavior Change: When using version 7.1.0 or newer of the Android Gradle Plugin we will now publish all variants of a library unless androidVariantToPublish was set in the DSL. This means that for example both debug and release or all flavors.
    • Deprecated androidVariantToPublish. In the future the main plugin will always publish all variants of an Android library. If you need to publish only one variant or a subset take a look at the base plugin APIs.
    • Base plugin: Added AndroidSingleVariantLibrary and AndroidMultiVariantLibrary options that use the new AGP 7.1 APIs under the hood.
    • Base plugin: Deprecated AndroidLibrary option in favor of the above
    • The integration with Sonatype Nexus has been extracted into it's own artifact and is available as com.vanniktech:nexus:<version>

    v0.18.0

    Compare Source

    • The minimum supported Kotlin version is now 1.4.30
    • It's now possible to specify SONATYPE_HOST as a Gradle property, e.g.
      • SONATYPE_HOST=S01 for s01.sonatype.org
      • SONATYPE_HOST= to not add any repository by default
    • Fixed an issue when publishing Kotlin MPP projects with the base plugin
    • Removed checks for presence of properties that aren't used by this plugin anymore

    v0.17.0

    Compare Source

    • Removed the deprecated uploadArchives and installArchives tasks. Use publish and publishToMavenLocal instead.

    v0.16.0

    Compare Source

    • Add pomFromGradleProperties API to base plugin. This configures the pom in the same way the regular plugin does.
    • Add the ability to remove the default mavenCentral repository, by setting sonatypeHost to null
    • Support POM_LICENSE_NAME, POM_LICENSE_URL and POM_LICENSE_DIST properties in addition to LICENCE based properties.
    • Fixes an issue in the base plugin that caused an error during configuration of Android projects.
    • Fixes an issue with javadoc tasks when using Java toolchains.
    • The deprecated nexusOptions and nexus {} methods were removed. closeAndReleaseRepository is automatically configured.

    v0.15.1

    Compare Source

    • The closeAndReleaseRepository task was mistakenly expecting the wrong Gradle properties. The README and changelog also mentioned the wrong properties. The correct ones are mavenCentralUsername and mavenCentralPassword or for environment variables: ORG_GRADLE_PROJECT_mavenCentralUsername and ORG_GRADLE_PROJECT_mavenCentralPassword.
    • Fix signing not being configurable until afterEvaluate
    • Use empty string as in memory signing password when no password is specified
    • Fix statingProfile in nexusOptions not being optional which causes an error when running closeAndReleaseRepository

    v0.15.0

    Compare Source

    • BREAKING: Removed support for deprecated RELEASE_REPOSITORY_URL, SNAPSHOT_REPOSITORY_URL, SONATYPE_NEXUS_USERNAME, SONATYPE_NEXUS_PASSWORD environment variables and properties. For safety reasons the project will fail when finding these. Use mavenCentralUsername and mavenCentralPassword Gradle properties or ORG_GRADLE_PROJECT_mavenCentralUsername and ORG_GRADLE_PROJECT_mavenCentralPassword environment variables instead.
    • BREAKING: Removed deprecated targets API. See README for alternative ways of adding targets.
    • Behavior change: The dokka plugin is not applied by default anymore for Kotlin projects. When it is applied we will still use the dokka tasks to create the javadoc jar.
    • Support for s01.oss.sonatype.org by setting sonatypeHost = "S01".
    • Introduce com.vanniktech.maven.publish.base plugin. This plugin contains all the functionality of the main plugin, but does not configure anything automatically. Instead, it offers a public API, which is also used by the main plugin to do so yourself. This allows for more flexibility and to publish different project types. The API is not final yet, but we're happy to receive feedback.

    Configuration

    πŸ“… Schedule: Branch creation - At any time (no schedule defined), Automerge - At any time (no schedule defined).

    🚦 Automerge: Disabled by config. Please merge this manually once you are satisfied.

    β™» Rebasing: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox.

    πŸ”• Ignore: Close this PR and you won't be reminded about this update again.


    • [ ] If you want to rebase/retry this PR, check this box

    This PR has been generated by Mend Renovate. View repository job log here.

    opened by renovate[bot] 0
  • Dependency Dashboard

    Dependency Dashboard

    This issue lists Renovate updates and detected dependencies. Read the Dependency Dashboard docs to learn more.

    Open

    These updates have all been created already. Click a checkbox below to force a retry/rebase of any.

    Detected dependencies

    github-actions
    .github/workflows/build.yaml
    • actions/checkout v3
    • gradle/wrapper-validation-action v1.0.5
    • actions/setup-java v3
    .github/workflows/release.yaml
    • actions/checkout v3
    • gradle/wrapper-validation-action v1.0.5
    • actions/setup-java v3
    • ffurrer2/extract-release-notes v1
    • softprops/action-gh-release v1
    gradle
    gradle.properties
    dependencies.gradle
    • com.android.tools.build:gradle 7.3.1
    settings.gradle
    build.gradle
    • com.diffplug.spotless:spotless-plugin-gradle 6.12.1
    • com.vanniktech:gradle-maven-publish-plugin 0.14.2
    • org.jetbrains.dokka:dokka-gradle-plugin 1.7.20
    • de.undercouch:gradle-download-task 5.3.0
    • org.jetbrains.kotlinx:kotlinx-serialization-json 1.4.1
    • junit:junit 4.13.2
    • com.google.truth:truth 1.1.3
    • com.google.testparameterinjector:test-parameter-injector 1.10
    gradle-wrapper
    gradle/wrapper/gradle-wrapper.properties
    • gradle 7.6

    • [ ] Check this box to trigger a request for Renovate to run again on this repository
    opened by renovate[bot] 0
  • Dependencies with license name provided as `MIT` can't get identified

    Dependencies with license name provided as `MIT` can't get identified

    Here is the output for using e.g. version 3.1.0, I assume it will be the same for 3.2.0 as well:

    io.github.g0dkar:qrcode-kotlin-jvm:3.1.0
     - ERROR: Unknown license URL 'https://github.com/g0dkar/qrcode-kotlin/blob/main/LICENSE' is NOT allowed
    

    According to https://mvnrepository.com/artifact/io.github.g0dkar/qrcode-kotlin-jvm/3.1.0 the license name is published as MIT, so I assume it should get identfied as MIT when I'm looking at the fallback logic in licenses.kt.

    I used the version 1.6.0 of this plugin to get the described results.

    opened by mervyn-mccreight 7
  • License-url `http://www.eclipse.org/org/documents/edl-v10.php` specified as `unknown`, but it should be `EPL-1.0`

    License-url `http://www.eclipse.org/org/documents/edl-v10.php` specified as `unknown`, but it should be `EPL-1.0`

    When having e.g. org.glassfish.jaxb:jaxb-core:4.0.0 in your dependency tree, the license check fails with the statement that the license-url http://www.eclipse.org/org/documents/edl-v10.php is unknown. But as far as I can see this should resolve to "EPL-1.0" as defined in licenses.kt.

    I'm using version 1.6.0.

    Here are a few examples for dependencies having the same problem:

    com.sun.istack:istack-commons-runtime:4.1.1
     - ERROR: Unknown license URL 'http://www.eclipse.org/org/documents/edl-v10.php' is NOT allowed
    jakarta.activation:jakarta.activation-api:2.1.0
     - ERROR: Unknown license URL 'http://www.eclipse.org/org/documents/edl-v10.php' is NOT allowed
    jakarta.xml.bind:jakarta.xml.bind-api:4.0.0
     - ERROR: Unknown license URL 'http://www.eclipse.org/org/documents/edl-v10.php' is NOT allowed
    org.eclipse.angus:angus-activation:1.0.0
     - ERROR: Unknown license URL 'http://www.eclipse.org/org/documents/edl-v10.php' is NOT allowed
    org.glassfish.jaxb:jaxb-core:4.0.0
     - ERROR: Unknown license URL 'http://www.eclipse.org/org/documents/edl-v10.php' is NOT allowed
    org.glassfish.jaxb:jaxb-runtime:4.0.0
     - ERROR: Unknown license URL 'http://www.eclipse.org/org/documents/edl-v10.php' is NOT allowed
    org.glassfish.jaxb:txw2:4.0.0
     - ERROR: Unknown license URL 'http://www.eclipse.org/org/documents/edl-v10.php' is NOT allowed
    
    opened by mervyn-mccreight 3
Releases(1.6.0)
  • 1.6.0(Oct 26, 2022)

    Added

    • Support for Android dynamic feature module plugin.
    • New fallback URL for EPL-2.0.

    Changed

    • Update SPDX database to version 3.18 (2022-08-12).
    Source code(tar.gz)
    Source code(zip)
  • 1.5.0(Jul 12, 2022)

    Changed

    • Upgrade AGP dependency to 7.2 which requires JDK 11 to run.

    Fixed

    • Include Gradle variant attributes when resolving POMs. This should fix issues with Kotlin JS and Kotlin multiplatform artifacts.
    Source code(tar.gz)
    Source code(zip)
  • 1.4.1(Jun 3, 2022)

  • 1.4.0(May 26, 2022)

    Changed

    • Update SPDX database to version 3.17 (2022-05-08).

    Fixed

    • Do not require accepting all licenses defined in a Maven POM. The specification says that multiple licenses are a logical OR, not a logical AND.
    • Licenses defined in parent poms are only used when the child contains no licenses. Previously both would be honored, but the Maven POM spec defines them as overriding.
    • Disable dependency verification on the Gradle configuration through which the Maven POMs are resolved.
    Source code(tar.gz)
    Source code(zip)
  • 1.3.1(Nov 24, 2021)

  • 1.3.0(Oct 26, 2021)

    Added

    • violationAction build DSL which allows you to choose whether to fail, log, or ignore license validation problems.
    • New fallback URLs for popular licenses such as MIT, Apache 2, LGPL, GPL, BSD, and EPL.

    Fixed

    • Ignore flat-dir repositories which contain no artifact metadata.
    • Support Kotlin multiplatform projects whose JVM target uses withJava().
    Source code(tar.gz)
    Source code(zip)
  • 1.2.0(Jul 27, 2021)

  • 1.1.0(Jun 25, 2021)

    Added

    • Include SCM URL in the JSON output if available from an artifacts POM.

    Fixed

    • Support older versions of Gradle because they leak ancient versions of the Kotlin stdlib onto the plugin classpath.
    Source code(tar.gz)
    Source code(zip)
  • 1.0.2(Jun 9, 2021)

  • 1.0.1(Jun 8, 2021)

    Changed

    • Include Gradle-internal resolution exception in --info log when a POM fails to resolve.
    • Introduce determinism when dealing with multiple license identifiers which use the same license URL. For now, the shortest identifier is selected rather than relying on order of the SPDX license JSON.
    Source code(tar.gz)
    Source code(zip)
  • 1.0.0(May 21, 2021)

Gradle plugin to ease Kotlin IR plugin development and usage in multimodule gradle projects

Gradle plugin to ease Kotlin IR plugin development and usage in multimodule gradle projects. Former: kotlin-ir-plugin-adapter-gradle

null 2 Mar 8, 2022
A Gradle plugin that generates plugin.yml for Bukkit/BungeeCord/Nukkit plugins based on the Gradle project

plugin-yml is a simple Gradle plugin that generates the plugin.yml plugin description file for Bukkit plugins, bungee.yml for Bungee plugins or nukkit.yml for Nukkit plugins based on the Gradle project. Various properties are set automatically (e.g. project name, version or description) and additional properties can be added using a simple DSL.

Plexus 0 Apr 10, 2022
A Gradle plugin to help analyse the dependency between modules and run tasks only on modules impacted by specific set of changes.

Change Tracker Plugin A Gradle plugin to help analyse the dependency between modules and run tasks only on modules impacted by specific set of changes

Ismael Di Vita 110 Dec 19, 2022
A Gradle plugin that guards against unintentional dependency changes.

??️ Dependency Guard A Gradle plugin that helps you guard against unintentional dependency changes. Surface Transitive Dependency Changes Comparison t

Dropbox 195 Dec 31, 2022
Gradle Plugin to automatically upgrade your gradle project dependencies and send a GitHub pull request with the changes

Gradle Plugin to automatically upgrade your gradle project dependencies and send a GitHub pull request with the changes

Dipien 142 Dec 29, 2022
Gradle Plugin that allows you to decompile bytecode compiled with Jetpack Compose Compiler Plugin into Java and check it

decomposer Gradle Plugin that allows you to decompile bytecode compiled with Jetpack Compose Compiler Plugin into Java and check it How to use Run bui

Takahiro Menju 56 Nov 18, 2022
Gradle plugin which analyzes the size of your Android apps

Scope is a Gradle plugin which helps you analyze the size of your Android apps. Motivation App size is an important metric which directly correlates w

Nanashi Li 1 Feb 26, 2022
A Gradle Plugin to determine which modules were affected by a set of files in a commit.

A Gradle Plugin to determine which modules were affected by a set of files in a commit. One use case for this plugin is for developers who would like to only run tests in modules which have changed in a given commit.

Dropbox 491 Dec 23, 2022
A Gradle plugin that helps you speed up builds by excluding unnecessary modules.

?? Focus A Gradle plugin that generates module-specific settings.gradle files, allowing you to focus on a specific feature or module without needing t

Dropbox 314 Jan 2, 2023
A simple gradle plugin that lets you create a download asset from zeplin and convert them to vector drawables automatically

A simple gradle plugin that lets you create a download asset from zeplin and convert them to vector drawables automatically elephant project using 100% Kotlin and be up and running in a few seconds.

Qifan Yang 21 Sep 21, 2022
EasyVersion is a Gradle plugin that manage your app or library version.

EasyVersion EasyVersion is a Gradle plugin that manage your app or library version. Before Downloading Create easy_version.json in your root project d

Kosh Sergani 8 Nov 26, 2022
KMP Ready is a Gradle Plugin that provides actionable advice to make your code Kotlin Multiplatform compatible.

KMP Ready IS ?? UNDER DEVELOPMENT ?? Decisioning Logic Positive Signals βœ… Only Kotlin .kt Source Files Using Kotlin JVM Plugin Uses the Kotlin Multipl

Sam Edwards 58 Dec 22, 2022
Gradle Plugin to enable auto-completion and symbol resolution for all Kotlin/Native platforms.

CompleteKotlin Gradle Plugin to enable auto-completion and symbol resolution for all Kotlin/Native platforms. What this plugin provides This zero-conf

Louis CAD 235 Jan 3, 2023
A Gradle plugin that improves the experience when developing Android apps, especially system tools, that use hidden APIs.

A Gradle plugin that improves the experience when developing Android apps, especially system tools, that use hidden APIs.

Rikka apps 124 Dec 31, 2022
Grazel is a Gradle plugin to automate generation of valid Bazel files for a given Android/Kotlin/Java project.

Grazel Grazel stands for Gradle to Bazel. It is a Gradle plugin that enables you to migrate Android projects to Bazel build system in an incremental a

Grab 228 Jan 2, 2023
Gradle Plugin for Continuous Integration of AppSweep App Testing.

This Gradle plugin can be used to continuously integrate app scanning using AppSweep into your Android app build process

Guardsquare 28 Nov 13, 2022
Artifactory is a gradle plugin to assist in developing Minecraft mods that can target different modloaders.

Artifactory Artifactory is a gradle plugin to assist in developing Minecraft mods that can target different modloaders. Currently, Fabric and Forge ar

Zach Kozar 3 Dec 29, 2021
Android Gradle Plugin -- Auto Check big image and compress image in building.

McImage I will continue to update, please rest assured to use δΈ­ζ–‡ζ–‡ζ‘£ AndroidδΌ˜ι›…ηš„ζ‰“εŒ…ζ—Άθ‡ͺεŠ¨εŒ–θŽ·ε–ε…¨ιƒ¨res衄源 McImage is a Non-invasive plugin for compress all res in

smallSohoSolo 1.1k Dec 28, 2022
Gradle plugin that generates a Swift Package Manager manifest and an XCFramework to distribute a Kotlin Multiplatform library for Apple platforms.

Multiplatform Swift Package This is a Gradle plugin for Kotlin Multiplatform projects that generates an XCFramework for your native Apple targets and

Georg Dresler 262 Jan 5, 2023