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

Related tags

Plugin licensee
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.0.2'
  }
}

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.1.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 <buildDir>/reports/licensee, or for Android modules <buildDir>/reports/licensee/<variant name>/.

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
    • actions/setup-java v3
    .github/workflows/gradle-wrapper.yaml
    • actions/checkout v3
    • gradle/wrapper-validation-action v1
    .github/workflows/release.yaml
    • actions/checkout v3
    • 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
  • Feature Request: Add configuration to disable unused spdx-identifier, license-url and dependency warnings

    Feature Request: Add configuration to disable unused spdx-identifier, license-url and dependency warnings

    Imagine one wants to provide a centralized configuration of allowed libraries open for everyone to use. It would be nice to have the ability to disable the warnings, otherwise one might get spammed with the warnings, because a centralized catalogue might most possibly cover more licenses than you actually use.

    opened by mervyn-mccreight 2
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-android-scala-plugin adds scala language support to official gradle android plugin

gradle-android-scala-plugin gradle-android-scala-plugin adds scala language support to official gradle android plugin. See also sample projects at htt

saturday06 345 Dec 10, 2022
Ownership-gradle-plugin - Gradle code ownership verification plugin

Gradle code ownership verification plugin A gradle plugin that will verify owner

null 4 Dec 15, 2022
Gradle plugin which helps you analyze the size of your Android apps.

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

Spotify 913 Dec 28, 2022
Helper to upload Gradle Android Artifacts, Gradle Java Artifacts and Gradle Kotlin Artifacts to Maven repositories (JCenter, Maven Central, Corporate staging/snapshot servers and local Maven repositories).

GradleMavenPush Helper to upload Gradle Android Artifacts, Gradle Java Artifacts and Gradle Kotlin Artifacts to Maven repositories (JCenter, Maven Cen

 Vorlonsoft LLC 21 Oct 3, 2022
Gradle plugin which downloads and manages your Android SDK.

DEPRECATED This plugin is deprecated and is no longer being developed. Tools and dependencies are automatically downloaded using version 2.2.0 of the

Jake Wharton 1.4k Dec 29, 2022
Add a different ribbon to each of your Android app variants using this gradle plugin. Of course, configure it as you will

Easylauncher gradle plugin for Android Modify the launcher icon of each of your app-variants using simple gradle rules. Add ribbons of any color, over

Mikel 960 Dec 18, 2022
A powerful Gradle Plugin to help you demonstrate your android app

English | įŽ€äŊ“中文 sample-gradle-plugin ?? A powerful Gradle Plugin to help you demonstrate your android app. We often write demo applications that contai

Yoo Zhou 12 Nov 5, 2022
A Gradle plugin for providing your secrets to your Android project.

Secrets Gradle Plugin for Android A Gradle plugin for providing your secrets securely to your Android project. This Gradle plugin reads secrets from a

Google 560 Jan 8, 2023
GPP is Android's unofficial release automation Gradle Plugin. It can do anything from building, uploading, and then promoting your App Bundle or APK to publishing app listings and other metadata.

Gradle Play Publisher Gradle Play Publisher is Android's unofficial release automation Gradle Plugin. It can do anything from building, uploading, and

null 3.9k Dec 30, 2022
A Gradle plugin to report the number of method references in your APK on every build.

Dexcount Gradle Plugin A Gradle plugin to report the number of method references in your APK, AAR, or java module. This helps you keep tabs on the gro

Keepsafe 3k Dec 29, 2022
A flutter plugin through which you can get audios, videos, or images from the local storage.

Getter Made flutter easier. Description A flutter plugin through which you can get audios, videos or images from the local storage. Dependencies Befor

Younes Lagmah 3 Sep 11, 2021
K6-intellij-plugin - IntelliJ-based Plugin to run k6 tests locally or in the k6 Cloud from your IntelliJ IDE

IntelliJ-based Plugin to run k6 tests locally or in the k6 Cloud from your Intel

Mikhail Bolotov 8 Jan 2, 2023
This is an android studio plugin that allows you to creates new color in hex format based on a percentage (0-100) and a base color you specify.

alpha-color Description This is an android studio plugin that allows you to creates new color in hex format based on a percentage (0-100) and a base c

null 1 Nov 12, 2021
A Gradle plugin to support the Groovy language for building Android apps

Groovy language support for Android Deprecated: This plugin has been deprecated in favor of Kotlin which has the full support of JetBrains and Google.

Groovy programming language 853 Dec 21, 2022
A Gradle Plugin that removes unused resources in Android projects.

#Lint Cleaner Plugin Removes unused resources reported by Android lint including strings, colors and dimensions. Depracated As of Android Studio 2.0+

Marco RS 705 Nov 25, 2022
Gradle plugin for Google Protocol Buffers

Gradle Protobuf Plugin Author: Andrew Kroh Download: See maven central License: Apache License, Version 2.0 Requirements: Java 1.5+ Google Protocol Bu

Andrew Kroh 36 May 29, 2022
IntelliJ plugin that provides some useful utilities to support the daily work with Gradle.

IntelliJ Gradle Utilities Plugin This IntelliJ plugin provides some useful utilities to support the daily work with Gradle. It's available on the offi

Marcel Kliemannel 6 Jul 29, 2022
Gradle plugin to use git tags as project version names

Version Name Gradle Plugin This plugin adds a kotlin extension function that provides a version name based on the latest git tag. How to use it ?? App

Doist 3 Mar 9, 2022