spotless icon indicating copy to clipboard operation
spotless copied to clipboard

Configuration 'spotless-*' was resolved during configuration time

Open myjohndoeside opened this issue 3 years ago • 13 comments

Starting to get this warning every time I run spotlessApply command on my new Android app project.

Configuration 'spotless-1972454365' was resolved during configuration time.
This is a build performance and scalability issue.
See https://github.com/gradle/gradle/issues/2298
Run with --info for a stacktrace.

I'm using Gradle 7.4 and here's my root build.gradle.kts.

// Top-level build file where you can add configuration options common to all sub-projects/modules.
plugins {
    id("com.android.application") version "7.3.0" apply false
    id("com.android.library") version "7.3.0" apply false
    id("org.jetbrains.kotlin.android") version "1.7.10" apply false
    id("com.diffplug.spotless") version "6.11.0"
}

subprojects {
    apply(plugin = "com.diffplug.spotless")

    spotless {
        kotlin {
            target("**/*.kt")
            targetExclude("$buildDir/**/*.kt", "bin/**/*.kt")
            ktlint("0.45.2").userData(mapOf("android" to "true"))
            trimTrailingWhitespace()
            endWithNewline()
        }
    }
}

How do I make that warning go away?

myjohndoeside avatar Oct 21 '22 03:10 myjohndoeside

I have the exact same issue. Anyone has any ideas? Seem to have happened upgrading van Gradle 7.3.3 to Gradle 7.4. Spotless is no longer working for me.

BartNijland91 avatar Nov 01 '22 17:11 BartNijland91

Same here, anyone got a solution ?

EsmaeelNabil avatar Dec 16 '22 02:12 EsmaeelNabil

An opensource reproduction would be very welcome, I haven't seen this happen in my usage.

nedtwigg avatar Dec 31 '22 09:12 nedtwigg

Our internal project which uses Gradle 7.6 just encountered this issue. However, this version of Gradle appears to treat this as an error instead of a warning. I stepped through each version of spotless and it appears that the issue originated here.

https://github.com/diffplug/spotless/compare/gradle/6.6.0...gradle/6.6.1

The gradle output includes a reference to https://github.com/gradle/gradle/issues/2298

keith30xi avatar Jan 26 '23 17:01 keith30xi

I hope we get an opensource reproduction someday, but in the meantime I bet that predeclaring deps will solve the issue.

https://github.com/diffplug/spotless/tree/main/plugin-gradle#dependency-resolution-modes

nedtwigg avatar Jan 26 '23 18:01 nedtwigg

@nedtwigg you can find a reproducer here https://github.com/getsentry/sentry-java/pull/2563/files#diff-c0dfa6bc7a8685217f70a860145fbdf416d449eaff052fa28352c5cec1a98c06

I was trying to find a workaround for https://github.com/diffplug/spotless/issues/1572, but unsuccessful - the build is still failing on Gradle 8+ due to an implicit dependency betweenspotlessKotlinGradle and buildCMakeRelWithDebInfo tasks.

just check it out locally (chore/gradle-80 branch) and run ./gradlew build - you'll see both the configuration warning and the build failure caused by the implicit dependency.

We're basically blocked on updating to Gradle 8+ because of this - I'm unsure how to fix it other than disable spotless for .gradle.kts files.

romtsn avatar Feb 23 '23 12:02 romtsn

This bug also reproduces for me. While I don't have an open-source demo app (yet), I do have some extra information I can add.

As others have mentioned, this only reproduces with newer versions of Gradle. But it also only reproduces with newer versions of Spotless. Specifically, we can see this bug was introduced with Spotless 6.6.1. This error is not encountered with 6.6.0.

Adding predeclaration dependencies, as mentioned in @nedtwigg's comment above, restores the 6.6.0 behavior.

However, it seems like there's another bug that was introduced in 6.6.0 that causes Gradle's configuration stage to take ages. Switching from 6.5.2 to 6.6.0 increases the configuration time on my project from 20 seconds to 6 minutes.

So for now, if you need to update Gradle, it appears that you can, at best, use Spotless 6.5.2.

hobindar avatar Feb 23 '23 21:02 hobindar

Thanks @romtsn for the reproduction! @hobindar the massive slowdown in 6.6.0 will get fixed soonish, and can be worked around in the meantime by setting line endsings to UNIX or PLATFORM_NATIVE

  • https://github.com/diffplug/spotless/issues/1527#issuecomment-1409142798

nedtwigg avatar Feb 24 '23 01:02 nedtwigg

I'm able to reproduce this on main in this project (linked to a specific commit in case main changes).

EDIT: I was able to work-around this issue by predeclaring my Spotless dependencies. Here's my config:

allprojects {
    val configureSpotless: SpotlessExtension.() -> Unit = {
        kotlin {
            target("**/*.kt", "**/*.kts")
            ktlint("0.48.2")
            endWithNewline()
            indentWithSpaces()
            trimTrailingWhitespace()
        }
    }

    if (project === rootProject) {
        spotless { predeclareDeps() }
        extensions.configure<SpotlessExtensionPredeclare>(configureSpotless)
    } else {
        extensions.configure(configureSpotless)
    }
}

colinrtwhite avatar Mar 08 '23 06:03 colinrtwhite

Just wanted to mention one more path leading to the problem (an attempt to resolve a configuration at configuration-time):

Caused by: org.gradle.api.GradleException: You need to add a repository containing the '[com.google.googlejavaformat:google-java-format:1.17.0]' artifact in 'licensing-api/build.gradle'.
E.g.: 'repositories { mavenCentral() }'
        at com.diffplug.gradle.spotless.GradleProvisioner.lambda$forConfigurationContainer$1(GradleProvisioner.java:132)
        at com.diffplug.gradle.spotless.GradleProvisioner$DedupingProvisioner.provisionWithTransitives(GradleProvisioner.java:79)
        at com.diffplug.spotless.JarState.provisionWithTransitives(JarState.java:69)
        at com.diffplug.spotless.JarState.from(JarState.java:58)
        at com.diffplug.spotless.JarState.from(JarState.java:53)
        at com.diffplug.spotless.java.GoogleJavaFormatStep$State.<init>(GoogleJavaFormatStep.java:130)
        at com.diffplug.spotless.java.GoogleJavaFormatStep.lambda$create$1(GoogleJavaFormatStep.java:73)
        at com.diffplug.spotless.FormatterStepImpl.calculateState(FormatterStepImpl.java:58)
        at com.diffplug.spotless.LazyForwardingEquality.state(LazyForwardingEquality.java:56)
        at com.diffplug.spotless.LazyForwardingEquality.unlazy(LazyForwardingEquality.java:118)
        at com.diffplug.spotless.LazyForwardingEquality.unlazy(LazyForwardingEquality.java:124)
        at com.diffplug.gradle.spotless.JvmLocalCache$LiveCacheKeyImpl.set(JvmLocalCache.java:60)
        at com.diffplug.gradle.spotless.SpotlessTask.setSteps(SpotlessTask.java:169)
        at com.diffplug.gradle.spotless.SpotlessTaskImpl_Decorated.setSteps(Unknown Source)
        at com.diffplug.gradle.spotless.FormatExtension.setupTask(FormatExtension.java:928)
        at com.diffplug.gradle.spotless.JavaExtension.setupTask(JavaExtension.java:434)
        at com.diffplug.gradle.spotless.SpotlessExtensionImpl.lambda$createFormatTasks$6(SpotlessExtensionImpl.java:70)

the JvmLocalCache tries to resolve "LazyForwardingEquality", leading to an attempt to compute the JarState, which tries to resolve the configuration from which google format is loaded. The message here is confusing - the nested exception is actually from palantir's consistent versions plugin, which explicitly forbids resolving configurations before execution (as does newer Gradle, I believe):

Caused by: org.gradle.api.GradleException: Not allowed to resolve configuration ':licensing-api:spotless865457264' at configuration time (https://guides.gradle.org/performance/#don_t_resolve_dependencies_at_configuration_time). Please upgrade your plugins and double-check your gradle scripts (see stacktrace)
        at com.palantir.gradle.versions.VersionsPropsPlugin.lambda$setupConfiguration$13(VersionsPropsPlugin.java:223)
.... [snip]
        at com.diffplug.gradle.spotless.GradleProvisioner.lambda$forConfigurationContainer$1(GradleProvisioner.java:126)

dweiss avatar Sep 19 '23 06:09 dweiss

I do have a small repro, although I'm no longer sure - maybe it's palantir plugin's fault... The problem seems to surface only when there is a lazy task dependency in the task graph. Essentially something like this:

plugins {
    id("java-library")
    id("com.palantir.consistent-versions").version("2.15.0")
    id("com.diffplug.spotless").version("6.21.0")
}

allprojects {
    repositories {
        mavenCentral()
    }

    val tidy by tasks.registering {}

    // This block is crucial - it creates a dependency in the task graph, which
    // leads to configuration resolution when the task graph is finalized.
    tasks.matching { task -> task.name == "spotlessApply" }.all {
        tidy.configure {
            dependsOn(this@all)
        }
    }

    extensions.configure<SpotlessExtension> {
        java {
            googleJavaFormat("1.17.0")
        }
    }
}

The code is here: https://github.com/dweiss/spotless-conf-resolution-bug

It fails every time (gradlew spotlessApply --stacktrace).

I also took a look at what palantir's plugin does behind the scenes - it attaches an action block to all configurations to explicitly forbid those configurations from being resolved in the configuration phase:

            conf.getIncoming().beforeResolve(_resolvableDependencies -> {
                if (GradleWorkarounds.isConfiguring(subproject.getState())) {
                    throw new GradleException(String.format(
                            "Not allowed to resolve %s at "
                                    + "configuration time (https://guides.gradle.org/performance/"
                                    + "#don_t_resolve_dependencies_at_configuration_time). Please upgrade your "
                                    + "plugins and double-check your gradle scripts (see stacktrace)",
                            conf));
                }
            });

I don't know whether this is an incorrect assumption on their behalf or maybe spotless indeed shouldn't rely on resolved artifacts as part of the lazy cache (instead, perhaps it should rely on the full module id?).

Sorry it's not more helpful in solving the issue. :(

dweiss avatar Sep 19 '23 08:09 dweiss

Android studio build analyzer:

com.diffplug.spotless: not compatible You could save about 0.2s by turning Configuration cache on. With Configuration cache, Gradle can skip the configuration phase entirely when nothing that affects the build configuration has changed.

The version of this plugin used in this build is not compatible with Configuration cache and we don’t know the version when it becomes compatible.

Plugin version: 6.21.0 Plugin dependency: com.diffplug.spotless:spotless-plugin-gradle

Here is my build.gradle(project):

import org.jetbrains.kotlin.gradle.tasks.KotlinCompile

buildscript {
    repositories {
        google()
        mavenCentral()
    }
    dependencies {
        classpath "com.android.tools.build:gradle:8.1.1"
        classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:1.8.20"
        classpath "com.google.dagger:hilt-android-gradle-plugin:2.47"
        classpath "com.google.android.libraries.mapsplatform.secrets-gradle-plugin:secrets-gradle-plugin:2.0.1"
    }
}

plugins {
    id 'com.android.application' version '8.1.0' apply false
    id 'com.android.library' version '8.1.0' apply false
    id 'org.jetbrains.kotlin.android' version '1.8.22' apply false
    id 'com.diffplug.spotless' version '6.21.0' apply false
    id 'org.jetbrains.kotlin.jvm' version '1.9.0' apply false
    id 'org.jetbrains.kotlin.plugin.serialization' version '1.9.0' apply false
    id "org.jetbrains.kotlin.kapt" version "1.9.0" apply false
    id 'com.google.dagger.hilt.android' version '2.47' apply false
}

subprojects {
    apply plugin: 'com.diffplug.spotless'
    spotless {
        lineEndings 'UNIX'
        kotlin {
            target '**/*.kt'
            targetExclude("$buildDir/**/*.kt")
            targetExclude('bin/**/*.kt')
            ktlint("0.50.0")
        }
    }

    tasks.withType(KotlinCompile).configureEach {
        compilerOptions {
            // Use experimental APIs
            freeCompilerArgs.add('-opt-in=kotlin.RequiresOptIn')
        }
    }
    // androidx.test and hilt are forcing JUnit, 4.12. This forces them to use 4.13
    configurations.configureEach {
        resolutionStrategy {
            force "junit:junit:4.13.2"
        }
    }
}

khahani avatar Sep 21 '23 16:09 khahani

Happens also in the libgdx builds

SimonIT avatar Apr 06 '24 17:04 SimonIT