jaredsburrows / gradle-license-plugin

Gradle plugin that provides a task to generate a HTML license report of your project.
https://jaredsburrows.github.io/gradle-license-plugin/
Apache License 2.0
418 stars 66 forks source link

Empty report generated when a task depends on the LicenseReport task #38

Closed szugyi closed 2 years ago

szugyi commented 6 years ago

I have tried to generate reports every time the project is built, but in case I add the LicenseReport task to run before another task both the generated html and json files are empty. As I can see in the discussion in issue #22 it should be possible since version 0.8.1.

If I run the task individually with ./gradlew licenseDebugReport the generated files contain all the dependencies I have. However if I run the ./gradlew assembleDebug I can see in the logs that the task was run, and it prints that the reports were generated, but they are empty.

@MatthewTamlin Can you see what the problem might be with my configuration?

log:

$ ./gradlew assembleDebug

> Task :app:licenseDebugReport
Wrote HTML report to /Users/szugyiczkicsaba/Downloads/MyApplication/app/build/reports/licenses/licenseDebugReport.html.
Wrote JSON report to /Users/szugyiczkicsaba/Downloads/MyApplication/app/build/reports/licenses/licenseDebugReport.json.

BUILD SUCCESSFUL in 1s
26 actionable tasks: 26 executed

My configuration: Project level build.gradle

// Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript {

    repositories {
        google()
        jcenter()
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:3.0.1'
        classpath "com.jaredsburrows:gradle-license-plugin:0.8.3"
    }
}

allprojects {
    repositories {
        google()
        jcenter()
    }
}

task clean(type: Delete) {
    delete rootProject.buildDir
}

App module build.gradle

apply plugin: 'com.android.application'
apply plugin: "com.jaredsburrows.license"

licenseReport {
    generateHtmlReport = true
    generateJsonReport = true

    // These options are ignored for Java projects
    copyJsonReportToAssets = true
}

android.applicationVariants.all { variant ->
    def variantCapitalized = variant.name.capitalize()

    def assembleTask = tasks.getByName("assemble$variantCapitalized")
    def licenseTask = tasks.getByName("license${variantCapitalized}Report")

    assembleTask.dependsOn licenseTask
}

android {
    compileSdkVersion 26
    defaultConfig {
        applicationId "io.supercharge.myapplication"
        minSdkVersion 21
        targetSdkVersion 26
        versionCode 1
        versionName "1.0"
        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
}

dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])
    implementation 'com.android.support.constraint:constraint-layout:1.0.2'
    implementation 'com.squareup.retrofit2:retrofit:2.4.0'
    testImplementation 'junit:junit:4.12'
    androidTestImplementation 'com.android.support.test:runner:1.0.1'
    androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.1'
}

output open_source_licenses.html

<html>
  <head>
    <style>body{font-family: sans-serif} pre{background-color: #eeeeee; padding: 1em; white-space: pre-wrap}</style>
    <title>Open source licenses</title>
  </head>
  <body>
    <h3>None</h3>
  </body>
</html>

output open_source_licenses.json []

jack-bradshaw commented 6 years ago

I was running into the same problem when I opened issue #22. Unfortunately the issue got somewhat sidetracked, and was ultimately closed after I enabled task configuration. It probably should have been renamed or left open.

I played around at length trying to do exactly what you're doing. It seems that for some reason the dependencies haven't been resolved when the license task is bring run, so you're getting empty outputs. I was never able to determine which tasks the license task needs to run after.

szugyi commented 6 years ago

Thank you for the quick response! It would be really useful if we could make the plugin generate the report on every build.

jack-bradshaw commented 6 years ago

Yeah, it would really help for CI and CD.

I was just having a look at the Open Whisper Systems' Witness Plugin. It seems they're using afterEvaluate to execute a task after the dependencies have been resolved. I'm going to set up a test project to see if I can do something similar.

jack-bradshaw commented 6 years ago

Looks like anything involving afterEvaluate will have to be done at the plugin level, just like in the link I posted above. @jaredsburrows thoughts?

jaredsburrows commented 6 years ago

@MatthewTamlin Wasn't #22 your issue that you solved by PR #30?

@szugyi It used to generate after every build, I believe. I believe that #30 may have changed that?

szugyi commented 6 years ago

@jaredsburrows I have just checked out the 0.8.0 version which does not contain the changes from the mentioned PR, but unfortunately the generated reports are also empty if I just run the assembleDebug task. It contains the license info of the dependencies only if I run the licenseReport task individually.

jack-bradshaw commented 6 years ago

30 made it so both JSON and HTML are copied to the assets directory when the task is run, but it didn't do anything to make the task run automatically each time the project is built. It's still necessary to manually run the task.

jaredsburrows commented 6 years ago

@szugyi @MatthewTamlin The reason I do not run after every build is because I do not want to potentially slow down other's builds. If you want to run the license report for updated license results then you can do so and add it to your SCM. Maybe I can look into running it after each build.

szugyi commented 6 years ago

@jaredsburrows Yes, that is how we use the plugin currently, but this can be forgotten easily, especially in a big team to run it every time a dependency is added, updated or removed.

jaredsburrows commented 6 years ago

@szugyi Would you want to make a PR for this?

szugyi commented 6 years ago

@jaredsburrows Unfortunately, I don't think I will have the time for this anytime soon.

jaredsburrows commented 6 years ago

This should be easy to do. I will look into it tomorrow.

szugyi commented 6 years ago

Thanks!

neworld commented 6 years ago

After upgrade android gradle plugin to 3.2.0, license file became empty. Also, another one in build/reports/ license is empty as well. During debugging I found, somehow dependencies can't be resolved, if license generation task depends on another build task.

1540208046

However, launching manually ./gradlew licenseReleseReport assembleRelease works.

hardysim commented 6 years ago

For anyone still struggling with this:

I've switched to https://developers.google.com/android/guides/opensource which works just fine.


Hint: You might want to add a theme to the activities of this library like so (e.g. when using a launcher theme or one without an actionbar):

<activity android:name="com.google.android.gms.oss.licenses.OssLicensesMenuActivity"
  android:theme="@style/Theme.MaterialComponents.Light.DarkActionBar"/>

<activity android:name="com.google.android.gms.oss.licenses.OssLicensesActivity"
  android:theme="@style/Theme.MaterialComponents.Light.DarkActionBar"/>
darrengyles commented 5 years ago

This should be easy to do. I will look into it tomorrow.

Hi @jaredsburrows any update? Thanks!

jaredsburrows commented 5 years ago

I recently updated the tests. This will make adding features and fixing bugs easier. Thanks for the bump.

Jared Burrows

jaredsburrows@gmail.com jaredsburrows@gmail.com LinkedIn: https://www.linkedin.com/in/jaredsburrows

On Fri, Feb 8, 2019 at 11:18 AM darrengyles notifications@github.com wrote:

This should be easy to do. I will look into it tomorrow.

@jaredsburrows https://github.com/jaredsburrows any update? Thanks.

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/jaredsburrows/gradle-license-plugin/issues/38#issuecomment-461914665, or mute the thread https://github.com/notifications/unsubscribe-auth/ABqMSDTcu_1ryJ_G31Gs6QNxH95fM-Y8ks5vLc16gaJpZM4S79IV .

javadude commented 5 years ago

I was having similar issues to this. I played around with the LicenseTask (dropping it in my buildSrc and hacking away), and it looks like the issue is lenientConfiguration hides some conflicts:

set.resolvedConfiguration.lenientConfiguration.artifacts.forEach { artifact ->

When I changed this to use resolvedConfiguration.resolvedArtifacts, I see the submodule conflicts that lenientConfiguration was skipping:

> Could not resolve all dependencies for configuration ':app.bsp:implementation'.
   > Could not resolve project :framework.core.
     Required by:
         project :app.bsp
      > Cannot choose between the following variants of project :framework.core:
          - debugRuntimeElements
          - releaseRuntimeElements
        All of them match the consumer attributes:
          - Variant 'debugRuntimeElements' capability mantis:framework.core:unspecified:
              - Unmatched attributes:
                  - Found com.android.build.api.attributes.BuildTypeAttr 'debug' but wasn't required.
                  - Found com.android.build.api.attributes.VariantAttr 'debug' but wasn't required.
                  - Found com.android.build.gradle.internal.dependency.AndroidTypeAttr 'Aar' but wasn't required.
                  - Found org.gradle.usage 'java-runtime' but wasn't required.
                  - Found org.jetbrains.kotlin.platform.type 'androidJvm' but wasn't required.
          - Variant 'releaseRuntimeElements' capability mantis:framework.core:unspecified:
              - Unmatched attributes:
                  - Found com.android.build.api.attributes.BuildTypeAttr 'release' but wasn't required.
                  - Found com.android.build.api.attributes.VariantAttr 'release' but wasn't required.
                  - Found com.android.build.gradle.internal.dependency.AndroidTypeAttr 'Aar' but wasn't required.
                  - Found org.gradle.usage 'java-runtime' but wasn't required.
                  - Found org.jetbrains.kotlin.platform.type 'androidJvm' but wasn't required.

// and many more...

Gradle dependency resolution not being my area of expertise, I kinda hacked around it a bit by adding to my gradle file to set up configuration sets to focus on release jars for disambiguation:

    def releaseType = project.getObjects().named(BuildTypeAttr.class, "release")

    configurations {
        licenseApi {
            extendsFrom releaseApi
            attributes {
                attribute(AndroidArtifacts.ARTIFACT_TYPE, "jar")
                attribute(BuildTypeAttr.ATTRIBUTE, releaseType)
            }
        }
        // and similar for licenseCompile and licenseImplementation
    }

and then back in the plugin

        val compile = configurations.findByName("compile")
        val api = configurations.findByName("api")
        val implementation = configurations.findByName("implementation")
        val licenseCompile = configurations.findByName("licenseCompile")
        val licenseApi = configurations.findByName("licenseApi")
        val licenseImplementation = configurations.findByName("licenseImplementation")

        // copy the real deps into my helper configs
        compile?.dependencies?.let { licenseCompile?.dependencies?.addAll(it) }
        api?.dependencies?.let { licenseApi?.dependencies?.addAll(it) }
        implementation?.dependencies?.let { licenseImplementation?.dependencies?.addAll(it) }

        fun addDep(artifact: ResolvedArtifact) {
            val id = artifact.moduleVersion.id
            pomDependencies.add(project.dependencies.add(pomConfiguration, "${id.group}:${id.name}:${id.version}@pom"))
        }

        licenseCompile?.resolvedConfiguration?.resolvedArtifacts?.forEach(::addDep)
        licenseApi?.resolvedConfiguration?.resolvedArtifacts?.forEach(::addDep)
        licenseImplementation?.resolvedConfiguration?.resolvedArtifacts?.forEach(::addDep)

Obviously this is waaaay specific to my use case, nowhere near general enough for your plugin, but I thought it might help diagnosis...

I'm sure someone much more familiar with gradle internals would have a simpler solution

jaredsburrows commented 2 years ago

I tested this locally:

tasks.whenTaskAdded {
  if (name == "assembleDebug") {
    dependsOn("licenseDebugReport")
  }
}

tasks.whenTaskAdded {
  if (name == "assembleRelease") {
    dependsOn("licenseReleaseReport")
  }
}