Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Are Android dynamic feature modules supported #441

Closed
saihemanth121 opened this issue Jul 27, 2023 · 16 comments · Fixed by #445
Closed

Are Android dynamic feature modules supported #441

saihemanth121 opened this issue Jul 27, 2023 · 16 comments · Fixed by #445
Assignees
Labels
Bug Bug issue type S: ready for release Status: merged in the main branch

Comments

@saihemanth121
Copy link

Hi, does Kover support Android Dynamic Feature Modules? When I add the plugin to a DFM in my multiproject and try to run feature:dynamicFeature:koverHtmlReportDebug, I get an error:

FAILURE: Build failed with an exception.

* What went wrong:
Task 'koverHtmlReportDebug' not found in project ':feature:dynamicFeature'.

If I try to create a multiproject report in my app module, by using kover(project(":feature:dynamicFeature")) and running :app:koverHtmlReportDebug, I get below error:

FAILURE: Build failed with an exception.

* What went wrong:
Could not determine the dependencies of task ':app:koverHtmlReportDebug'.
> Could not resolve all task dependencies for configuration ':app:koverExternalArtifactsDebug'.
   > Could not resolve project :feature:dynamicFeature.
     Required by:
         project :app
      > The consumer was configured to find attribute 'kotlinx.kover.android.build-type' with value 'debug'. However we cannot choose between the following variants of project :feature:dynamicFeature:
          - benchmarkApiElements
          - benchmarkReverseMetadataElements
          - benchmarkRuntimeElements
          - debugApiElements
          - debugReverseMetadataElements
          - debugRuntimeElements
          - koverArtifact
          - releaseApiElements
          - releaseReverseMetadataElements
          - releaseRuntimeElements
        All of them match the consumer attributes:
          - Variant 'benchmarkApiElements' capability myProject.feature:dynamicFeature:unspecified:
              - Unmatched attributes:
                  - Provides com.android.build.api.attributes.AgpVersionAttr '7.3.1' but the consumer didn't ask for it
                  - Provides com.android.build.api.attributes.BuildTypeAttr 'benchmark' but the consumer didn't ask for it
                  - Provides com.android.build.gradle.internal.attributes.VariantAttr 'benchmark' but the consumer didn't ask for it
                  - Doesn't say anything about kotlinx.kover.android.build-type (required 'debug')
                  - Provides org.gradle.category 'library' but the consumer didn't ask for it
                  - Provides org.gradle.jvm.environment 'android' but the consumer didn't ask for it
                  - Provides org.gradle.usage 'java-api' but the consumer didn't ask for it
                  - Provides org.jetbrains.kotlin.platform.type 'androidJvm' but the consumer didn't ask for it
          - Variant 'benchmarkReverseMetadataElements' capability myProject.feature:dynamicFeature:unspecified:
              - Unmatched attributes:
                  - Provides com.android.build.api.attributes.BuildTypeAttr 'benchmark' but the consumer didn't ask for it
                  - Provides com.android.build.gradle.internal.attributes.VariantAttr 'benchmark' but the consumer didn't ask for it
                  - Doesn't say anything about kotlinx.kover.android.build-type (required 'debug')
                  - Provides org.gradle.usage 'android-reverse-meta-data' but the consumer didn't ask for it
          - Variant 'benchmarkRuntimeElements' capability myProject.feature:dynamicFeature:unspecified:
              - Unmatched attributes:
                  - Provides com.android.build.api.attributes.AgpVersionAttr '7.3.1' but the consumer didn't ask for it
                  - Provides com.android.build.api.attributes.BuildTypeAttr 'benchmark' but the consumer didn't ask for it
                  - Provides com.android.build.gradle.internal.attributes.VariantAttr 'benchmark' but the consumer didn't ask for it
                  - Doesn't say anything about kotlinx.kover.android.build-type (required 'debug')
                  - Provides org.gradle.category 'library' but the consumer didn't ask for it
                  - Provides org.gradle.jvm.environment 'android' but the consumer didn't ask for it
                  - Provides org.gradle.usage 'java-runtime' but the consumer didn't ask for it
                  - Provides org.jetbrains.kotlin.platform.type 'androidJvm' but the consumer didn't ask for it
          - Variant 'debugApiElements' capability myProject.feature:dynamicFeature:unspecified:
              - Unmatched attributes:
                  - Provides com.android.build.api.attributes.AgpVersionAttr '7.3.1' but the consumer didn't ask for it
                  - Provides com.android.build.api.attributes.BuildTypeAttr 'debug' but the consumer didn't ask for it
                  - Provides com.android.build.gradle.internal.attributes.VariantAttr 'debug' but the consumer didn't ask for it
                  - Doesn't say anything about kotlinx.kover.android.build-type (required 'debug')
                  - Provides org.gradle.category 'library' but the consumer didn't ask for it
                  - Provides org.gradle.jvm.environment 'android' but the consumer didn't ask for it
                  - Provides org.gradle.usage 'java-api' but the consumer didn't ask for it
                  - Provides org.jetbrains.kotlin.platform.type 'androidJvm' but the consumer didn't ask for it
          - Variant 'debugReverseMetadataElements' capability myProject.feature:dynamicFeature:unspecified:
              - Unmatched attributes:
                  - Provides com.android.build.api.attributes.BuildTypeAttr 'debug' but the consumer didn't ask for it
                  - Provides com.android.build.gradle.internal.attributes.VariantAttr 'debug' but the consumer didn't ask for it
                  - Doesn't say anything about kotlinx.kover.android.build-type (required 'debug')
                  - Provides org.gradle.usage 'android-reverse-meta-data' but the consumer didn't ask for it
          - Variant 'debugRuntimeElements' capability myProject.feature:dynamicFeature:unspecified:
              - Unmatched attributes:
                  - Provides com.android.build.api.attributes.AgpVersionAttr '7.3.1' but the consumer didn't ask for it
                  - Provides com.android.build.api.attributes.BuildTypeAttr 'debug' but the consumer didn't ask for it
                  - Provides com.android.build.gradle.internal.attributes.VariantAttr 'debug' but the consumer didn't ask for it
                  - Doesn't say anything about kotlinx.kover.android.build-type (required 'debug')
                  - Provides org.gradle.category 'library' but the consumer didn't ask for it
                  - Provides org.gradle.jvm.environment 'android' but the consumer didn't ask for it
                  - Provides org.gradle.usage 'java-runtime' but the consumer didn't ask for it
                  - Provides org.jetbrains.kotlin.platform.type 'androidJvm' but the consumer didn't ask for it
          - Variant 'koverArtifact' capability myProject.feature:dynamicFeature:unspecified:
              - Unmatched attributes:
                  - Doesn't say anything about kotlinx.kover.android.build-type (required 'debug')
                  - Provides kotlinx.kover.project.path ':feature:dynamicFeature' but the consumer didn't ask for it
                  - Provides kotlinx.kover.variant.name '' but the consumer didn't ask for it
          - Variant 'releaseApiElements' capability myProject.feature:dynamicFeature:unspecified:
              - Unmatched attributes:
                  - Provides com.android.build.api.attributes.AgpVersionAttr '7.3.1' but the consumer didn't ask for it
                  - Provides com.android.build.api.attributes.BuildTypeAttr 'release' but the consumer didn't ask for it
                  - Provides com.android.build.gradle.internal.attributes.VariantAttr 'release' but the consumer didn't ask for it
                  - Doesn't say anything about kotlinx.kover.android.build-type (required 'debug')
                  - Provides org.gradle.category 'library' but the consumer didn't ask for it
                  - Provides org.gradle.jvm.environment 'android' but the consumer didn't ask for it
                  - Provides org.gradle.usage 'java-api' but the consumer didn't ask for it
                  - Provides org.jetbrains.kotlin.platform.type 'androidJvm' but the consumer didn't ask for it
          - Variant 'releaseReverseMetadataElements' capability myProject.feature:dynamicFeature:unspecified:
              - Unmatched attributes:
                  - Provides com.android.build.api.attributes.BuildTypeAttr 'release' but the consumer didn't ask for it
                  - Provides com.android.build.gradle.internal.attributes.VariantAttr 'release' but the consumer didn't ask for it
                  - Doesn't say anything about kotlinx.kover.android.build-type (required 'debug')
                  - Provides org.gradle.usage 'android-reverse-meta-data' but the consumer didn't ask for it
          - Variant 'releaseRuntimeElements' capability myProject.feature:dynamicFeature:unspecified:
              - Unmatched attributes:
                  - Provides com.android.build.api.attributes.AgpVersionAttr '7.3.1' but the consumer didn't ask for it
                  - Provides com.android.build.api.attributes.BuildTypeAttr 'release' but the consumer didn't ask for it
                  - Provides com.android.build.gradle.internal.attributes.VariantAttr 'release' but the consumer didn't ask for it
                  - Doesn't say anything about kotlinx.kover.android.build-type (required 'debug')
                  - Provides org.gradle.category 'library' but the consumer didn't ask for it
                  - Provides org.gradle.jvm.environment 'android' but the consumer didn't ask for it
                  - Provides org.gradle.usage 'java-runtime' but the consumer didn't ask for it
                  - Provides org.jetbrains.kotlin.platform.type 'androidJvm' but the consumer didn't ask for it

The plugin works as expected for all non-DFM modules in my project.

@saihemanth121 saihemanth121 added Question Support request issue type S: untriaged Status: issue reported but unprocessed labels Jul 27, 2023
@shanshin
Copy link
Collaborator

Unfortunately, at the moment, Kover has not been tested with Dynamic Features.

Do I understand correctly that only the com.android.dynamic-feature plugin was applied in the :feature:dynamicFeature project?
Kover is looking for Android build variants only in projects that apply com.android.application or com.android.library plugins.

@shanshin shanshin added S: waiting for clarification Status: additional information required to proceed and removed S: untriaged Status: issue reported but unprocessed labels Jul 27, 2023
@kibettheophilus
Copy link

@shanshin @saihemanth121 I have used it in our project which has dynamic feature modules and it is working:smile:, I am using v0.7.0

@saihemanth121 Which version are you using? Can you also share a sample how you have setup the plugin?

some of the things you can check:

  • Confirm that you have applied the kover plugin in your feature module(s)

@shanshin
Copy link
Collaborator

@kibettheophilus, perhaps you added a Kover dependency on the app module of your feature?

@kibettheophilus
Copy link

@kibettheophilus, perhaps you added a Kover dependency on the app module of your feature?

@shanshin can you rephrase your question?

@shanshin
Copy link
Collaborator

Which Android plugin (com.android.application, com.android.library, or com.android.dynamic-feature) was applied in the project that was specified as dependency kover(project(":foo"))?

@kibettheophilus
Copy link

@shanshin Our project has three types of modules: application, library and DFM. Below is sample setup:

app/build.gradle.kts

plugins { 
    id("com.android.application")
    id("org.jetbrains.kotlinx.kover")
}
android {
....
     dynamicFeatures += setOf(":features:foo",":features:bar", ...., ...) // list of DFM modules
}

dependencies {
implementation(project(":data")) // library module
....
}

// Kover configurations
dependencies {
    kover(project(":features:foo"))
    kover(project(":features:bar"))
    kover(project(":data"))
}

koverReport {
    androidReports("debug") {
        filters {
            excludes {
                classes(listOf("**/generated/**"))
            }
        }
        xml {
            filters {
                excludes {
                    classes(listOf("**/generated/**"))
                }
            }
            onCheck = false
            setReportFile(layout.buildDirectory.file("reports/kover/report.xml"))
        }
        html {
            filters {
                excludes {
                    classes(listOf("**/generated/**"))
                }
            }
            onCheck = false
            setReportDir(layout.buildDirectory.dir("reports/kover"))
        }
    }
}

data/build.gradle.kts

plugins { 
    id("com.android.library")
    id("org.jetbrains.kotlinx.kover")
}

....

features/foo/build.gradle.kts

plugins { 
    id("com.android.dynamic-feature")
    id("org.jetbrains.kotlinx.kover")
}

....

features/bar/build.gradle.kts

plugins { 
    id("com.android.dynamic-feature")
    id("org.jetbrains.kotlinx.kover")
}

....

@saihemanth121
Copy link
Author

Thanks for replying @shanshin and @kibettheophilus.

I'm using version 0.7.2.

We use convention plugins in our project which is quite big, so I'll just share the equivalent snippets here:

build.gradle.kts

// We use precompiled plugin scripts from buildSrc, so have to use legacy way.
buildScript {
    dependencies {
        classpath("org.jetbrains.kotlinx:kover-gradle-plugin:0.7.2")
    }
}
    

app/build.gradle.kts

plugins {
    id("com.android.application")
    id("org.jetbrains.kotlinx.kover")
}

android {
    dynamicFeatures.addAll(
        listOf(":feature:dynamic:)
    )
}

koverReport { ... }

dependencies {
    kover(project(":feature:dynamic"))
}

feature/dynamic/build.gradle.kts

plugins {
    id("com.android.dynamic-feature")
    id("org.jetbrains.kotlinx.kover")
}

dependencies {
    implementation(project(":app"))
}

You can see in my error stacktrace, that there is koverArtifact configuration created in the DFM, which probably means the kover plugin was applied. However I dont understand why the configuration does not have kotlinx.kover.android.build-type and provides empty kotlinx.kover.variant.name.

@saihemanth121
Copy link
Author

@shanshin to reply to the first question, yes, only com.android.dynamic-feature is applied in my dynamic feature. Also I dont think we can apply more than one of android app/library/dynamic-feature plugin in one module.

@kibettheophilus
Copy link

Thanks for replying @shanshin and @kibettheophilus.

I'm using version 0.7.2.

We use convention plugins in our project which is quite big, so I'll just share the equivalent snippets here:

build.gradle.kts

// We use precompiled plugin scripts from buildSrc, so have to use legacy way.
buildScript {
    dependencies {
        classpath("org.jetbrains.kotlinx:kover-gradle-plugin:0.7.2")
    }
}
    

app/build.gradle.kts

plugins {
    id("com.android.application")
    id("org.jetbrains.kotlinx.kover")
}

android {
    dynamicFeatures.addAll(
        listOf(":feature:dynamic:)
    )
}

koverReport { ... }

dependencies {
    kover(project(":feature:dynamic"))
}

feature/dynamic/build.gradle.kts

plugins {
    id("com.android.dynamic-feature")
    id("org.jetbrains.kotlinx.kover")
}

dependencies {
    implementation(project(":app"))
}

You can see in my error stacktrace, that there is koverArtifact configuration created in the DFM, which probably means the kover plugin was applied. However I dont understand why the configuration does not have kotlinx.kover.android.build-type and provides empty kotlinx.kover.variant.name.

We too use convention plugins, just shared the above as sample

Quick question, have you added the kover plugin to the plugin section in build.gradle.kts?

// We use precompiled plugin scripts from buildSrc, so have to use legacy way.
buildScript {
    dependencies {
        classpath("org.jetbrains.kotlinx:kover-gradle-plugin:0.7.2")
    }
}

apply(plugin = "org.jetbrains.kotlinx.kover") // this

@saihemanth121
Copy link
Author

@kibettheophilus no, havent applied the plugin in root build.gradle.kts. Do you think that may be causing an issue? The reason I didnt apply was because I wanted the full report in my app module, not root.

@kibettheophilus
Copy link

@saihemanth121 not sure, that aside... I remember I encountered this issue while trying out v0.7.2 , can you please try v0.7.0 ?

@kibettheophilus
Copy link

@shanshin @saihemanth121 I confirmed and I am able to reproduce this issue in v0.7.2 and v0.7.3, however, v0.7.0 and v0.7.1 works fine.
Looks like some changes introduced on v0.7.2 broke the support for dynamic feature modules.

@shanshin
Copy link
Collaborator

@shanshin to reply to the first question, yes, only com.android.dynamic-feature is applied in my dynamic feature.

Since this particular plugin is not currently supported, Kover does not find Android build variants and can only generate default reports (for JVM targets or android merged).

Perhaps using mergeWith will be able to work around this problem with the current version, I'll try to reproduce it next week.

@saihemanth121
Copy link
Author

saihemanth121 commented Jul 28, 2023

@kibettheophilus Yes, just confirmed that my project works with 0.7.0. Thanks.
@shanshin Any idea what could have broken in 0.7.2?

@shanshin
Copy link
Collaborator

@shanshin Any idea what could have broken in 0.7.2?

Because now Kover supports now only plugins com.android.application and com.android.library.

The fact that it worked before was a lucky coincidence, which was not thought about, was not tested and most likely did not always work properly.

@shanshin shanshin added Bug Bug issue type S: in progress Status: implementing or design in process and removed S: waiting for clarification Status: additional information required to proceed Question Support request issue type labels Jul 28, 2023
shanshin added a commit that referenced this issue Aug 6, 2023
shanshin added a commit that referenced this issue Sep 22, 2023
Resolves #441

Co-authored-by: gabrielprado-mb <57372429+gabrielprado-mb@users.noreply.github.com>

PR #445
@shanshin shanshin reopened this Sep 22, 2023
@shanshin shanshin removed the S: in progress Status: implementing or design in process label Sep 22, 2023
@shanshin shanshin added the S: ready for release Status: merged in the main branch label Sep 22, 2023
@shanshin
Copy link
Collaborator

Resolved in 0.7.4

shanshin added a commit that referenced this issue Nov 27, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Bug Bug issue type S: ready for release Status: merged in the main branch
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants