Skip to content

Shared build/stability output causes Gradle implicit dependency failures with Kover #153

@tprochazka

Description

@tprochazka

Environment

  • Compose Stability Analyzer: 0.7.4
  • Kotlin: 2.3.20
  • Gradle: 9.3.1
  • Android Gradle Plugin: 9.1.1
  • Kover: 0.9.8

Problem

An Android application module that applies both com.github.skydoves.compose.stability.analyzer and org.jetbrains.kotlinx.kover can fail Gradle implicit dependency validation when a Kover artifact generation task and Kotlin compile tasks are present in the same task graph.

The relevant part appears to be the shared build/stability directory. Compose Stability Analyzer registers that directory as an output of Kotlin compile tasks. When another task, such as Kover artifact generation, snapshots/uses outputs from the same module, Gradle sees build/stability as an output of Kotlin compile tasks without a declared relationship to the Kover task.

Example setup

plugins {
    id("com.android.application")
    id("org.jetbrains.kotlin.android")
    id("org.jetbrains.kotlinx.kover")
    id("com.github.skydoves.compose.stability.analyzer")
}

android {
    namespace = "com.example.sample"

    buildTypes {
        debug
        release
    }
}

Reproduction

Run a task graph that contains Kotlin compile tasks and a Kover artifact task for the same Android module, for example:

./gradlew \
  :sampleApp:compileDebugUnitTestKotlin \
  :sampleApp:compileReleaseKotlin \
  :sampleApp:compileDebugKotlin \
  :sampleApp:koverGenerateArtifactRelease \
  --stacktrace

Depending on variant names, the Kover task may be named differently, for example koverGenerateArtifact<Variant>.

Observed failure

Some problems were found with the configuration of task ':sampleApp:koverGenerateArtifactRelease' (type 'KoverArtifactGenerationTask').
  - Gradle detected a problem with the following location: '.../sampleApp/build/stability'.

    Reason: Task ':sampleApp:koverGenerateArtifactRelease' uses this output of task ':sampleApp:compileReleaseKotlin' without declaring an explicit or implicit dependency.

The same problem can be reported for other Kotlin compile tasks in the graph, such as:

:sampleApp:compileDebugKotlin
:sampleApp:compileDebugUnitTestKotlin

A similar issue can also appear for a stability task itself, for example:

Task ':sampleApp:debugStabilityCheck' uses this output of task ':sampleApp:compileDebugUnitTestKotlin' without declaring an explicit or implicit dependency.

Why this looks related to Compose Stability Analyzer

Downgrading Kover from 0.9.8 to 0.9.7 did not remove the failure.

PR #101 already mentions that the compiler plugin still creates the same files for different variants and adds mustRunAfter between Stability Analyzer tasks and Kotlin tasks. That helps for the plugin's own tasks, but external consumers such as Kover can still hit the same shared build/stability output.

Expected behavior

Applying Compose Stability Analyzer should not make unrelated Gradle consumers fail implicit dependency validation.

Ideally the plugin would avoid registering one shared build/stability output directory on all Kotlin compile tasks, use variant-specific output locations, or model the task dependencies/ordering in a way that external consumers do not need project-level workarounds.

Current workaround

The following local workaround makes the failing Gradle 9.3.1 graph pass:

val kotlinCompileTasks = tasks.withType<KotlinCompile>()
tasks.matching {
    it.name.startsWith("koverGenerateArtifact") ||
        it.name.endsWith("StabilityCheck") ||
        it.name.endsWith("StabilityDump") ||
        it.name == "stabilityCheck" ||
        it.name == "stabilityDump"
}.configureEach {
    mustRunAfter(kotlinCompileTasks)
}

This is only a workaround. It would be better if the plugin modeled the shared stability output so consumers such as Kover do not need to know about it.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions