Gradle plugin conventions => "Cannot change dependencies of dependency configuration"

Hello,

I am upgrading a Kotlin JVM project to Gradle 7.1.1 using plugin conventions. The java-convention is the basis for all of the others, so it is a plugin in the kotlin, testing, and publishing conventions.

The library project includes these conventions, but fails to build with the following error. Gradle seems to dislike my adding additional dependencies in the library’s build script.

** UPDATE ** When I comment out the publishing convention plugin from the library’s build.gradle.kts plugin block, the isssue disappears. So, the conflict seems to be something in the publishing convention code, below…

** UPDATE2 ** I’ve found that when I comment out the two artifact lines, below, the issue disappears. However whenever one, or both of the artifact lines are uncommented, the error is thrown.

    publications {
        create<MavenPublication>(name) {
            from(components["java"])
            artifact(dokkaJavadocJar)
         //   artifact(dokkaHtmlJar)

I’d really appreciate any guidance… I’ve googled and have found others with this error message, but they were working on Android projects. This is a simple library.

Thank you for your interest and time,
Mike

Caused by: org.gradle.api.InvalidUserDataException: Cannot change dependencies of dependency configuration ':libraries:kotlin:implementation' after it has been included in dependency resolution.
	at org.gradle.api.internal.artifacts.configurations.DefaultConfiguration.preventIllegalMutation(DefaultConfiguration.java:1280)
	at org.gradle.api.internal.artifacts.configurations.DefaultConfiguration.validateMutation(DefaultConfiguration.java:1240)
	at org.gradle.api.internal.artifacts.configurations.DefaultConfiguration.lambda$validateMutationType$1(DefaultConfiguration.java:308)
	at org.gradle.internal.ImmutableActionSet$SingletonSet.execute(ImmutableActionSet.java:225)
	
// file: libraries/build.gradle.kts

plugins {
    // Each of the following conventions include the java-convention.
    // id("java-conventions")
    id("kotlin-conventions")
    id("testing-conventions")
    id("publishing-conventions")
}

dependencies {
    implementation("com.opencsv:opencsv:5.5.1")
    implementation("com.twelvemonkeys.imageio:imageio:3.7.0")
    implementation("commons-codec:commons-codec:1.15")
}
// file: java-conventions.gradle.kts

plugins {
    id("org.jetbrains.kotlin.jvm")
    `java-library`
    idea
}

val applicationClientOrg: String? = project.properties["applicationClientOrg"] as String?
val applicationDeveloper: String? = project.properties["applicationDeveloper"] as String?
val applicationDeveloperOrg: String? = project.properties["applicationDeveloperOrg"] as String?
val applicationDeveloperOrgUri: String? = project.properties["applicationDeveloperOrgUri"] as String?

idea {
    module.isDownloadJavadoc = true
    module.isDownloadSources = true
}

java {
    // Auto JDK setup
    toolchain {
        languageVersion.set(JavaLanguageVersion.of("11"))
        withSourcesJar()
    }

    sourceSets {
        val main by getting
        val test by getting

        val integrationTest by creating {
            compileClasspath += main.output
            runtimeClasspath += main.output
            resources.srcDir("src/integrationTest/resources")
            // Attempting to mark this new sourceset as Testing(green color).
            idea.module.testSourceDirs.addAll(java.srcDirs)
            idea.module.testSourceDirs.addAll(resources.srcDirs)
            // By default, the Java plugin will detect Java sources in src/integrationTest/java
            // By default, the Kotlin plugin will detect Kotlin sources in src/integrationTest/kotlin

        }

        // Ensure that all sourceSets support a kotlin directory.
        sourceSets.map { it.java.srcDir("src/${it.name}/kotlin") }
    }

    configurations {

        getByName("implementation").also { implementation ->
            implementation.resolutionStrategy.failOnVersionConflict()
            getByName("integrationTestImplementation").apply { extendsFrom(implementation) }
        }

        getByName("runtimeOnly").also { runtimeOnly ->
            runtimeOnly.resolutionStrategy.failOnVersionConflict()
            getByName("integrationTestRuntimeOnly").apply { extendsFrom(runtimeOnly) }
        }

        getByName("annotationProcessor").also { annotationProcessor ->
            annotationProcessor.resolutionStrategy.failOnVersionConflict()
            getByName("compileOnly").also { it.extendsFrom(annotationProcessor) }
        }
    }
}

// FIXME: Cannot change dependencies of dependency configuration ':app:implementation' after it has been included in dependency resolution.
//tasks.getByName<Jar>("sourcesJar") {
//    manifest {
//        attributes(
//            buildAttributeMap(
//                project.name,
//                project.version.toString(),
//                project,
//                applicationClientOrg,
//                applicationDeveloper,
//                applicationDeveloperOrgUri
//            )
//        )
//    }
//}

tasks.withType(JavaCompile::class.java) {
    // See: https://docs.oracle.com/en/java/javase/12/tools/javac.html
    @Suppress("SpellCheckingInspection")
    options.compilerArgs.addAll(
        listOf(
            "-Xlint:all",   // Enables all recommended warnings.
            "-Werror"       // Terminates compilation when warnings occur.
        )
    )
    options.encoding = "UTF-8"
}

tasks.withType(
    Wrapper::
    class.java
)
{     // Keeps Gradle at the current release.
    gradleVersion = "7.1.1"
    description = "Generates gradlew[.bat] scripts"
    distributionType = Wrapper.DistributionType.ALL
    distributionSha256Sum = "9bb8bc05f562f2d42bdf1ba8db62f6b6fa1c3bf6c392228802cc7cb0578fe7e0"
}
// file: kotlin-conventions.gradle.kts

plugins {
    id("java-conventions")

    kotlin("jvm")
    kotlin("kapt")

    // Detect kotlin problems.
    id("io.gitlab.arturbosch.detekt")
    // Collect GIT repository information.
    id("com.gorylenko.gradle-git-properties")
}

configurations {
    compileOnly {
        extendsFrom(configurations.annotationProcessor.get())
    }
}

kapt {
    arguments {
        // Set Mapstruct Configuration options here
        // https://kotlinlang.org/docs/reference/kapt.html#annotation-processor-arguments
        // https://mapstruct.org/documentation/stable/reference/html/#configuration-options
        // arg("mapstruct.defaultComponentModel", "spring")
    }
}

detekt {
    ignoreFailures = false
    buildUponDefaultConfig = true // preconfigure defaults
    config = files("$rootDir/detekt.yml")
    reports {
        html.enabled = true // observe findings in your browser with structure and code snippets
        xml.enabled = false // checkstyle like format mainly for integrations like Jenkins
        txt.enabled = false // similar to the console output, contains issue signature to manually edit baseline files
        sarif.enabled =
            false // standardized SARIF format (https://sarifweb.azurewebsites.net/) to support integrations with Github Code Scanning
    }
    parallel = true
}

dependencies {
    // BOMs
    implementation(platform("com.fasterxml.jackson:jackson-bom:2.12.4"))
    implementation(platform("com.squareup.okhttp3:okhttp-bom:5.0.0-alpha.2"))
    implementation(platform("io.gitlab.arturbosch.detekt:detekt-bom:1.17.1"))
    implementation(platform("io.projectreactor:reactor-bom:2020.0.4"))
    implementation(platform("org.jetbrains.kotlin:kotlin-bom:1.5.30-M1"))
    implementation(platform("org.jetbrains.kotlinx:kotlinx-coroutines-bom:1.5.1"))

    // ARTIFACTs
    // Specifically stating the Kotlin version to avoid getting 1.4.x packages in the classpath.
    implementation("com.fasterxml.jackson.datatype:jackson-datatype-jsr310")
    implementation("com.fasterxml.jackson.module:jackson-module-kotlin")
    implementation("com.fasterxml.jackson.module:jackson-module-paranamer")
    implementation("com.fasterxml.jackson.module:jackson-modules-java8:2.12.4")
    implementation("com.squareup.okhttp3:okhttp")
    implementation("com.squareup.retrofit2:converter-jackson:2.9.0")
    implementation("com.squareup.retrofit2:retrofit:2.9.0")
    implementation("io.arrow-kt:arrow-core:0.13.2")
    implementation("io.github.rburgst:okhttp-digest:2.5")
    implementation("io.projectreactor.kotlin:reactor-kotlin-extensions")
    implementation("org.jetbrains.kotlin:kotlin-reflect:1.5.30-M1")
    implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.5.30-M1")
    implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core")
    implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core-jvm")
    implementation("org.jetbrains.kotlinx:kotlinx-coroutines-reactive")
    implementation("org.jetbrains.kotlinx:kotlinx-coroutines-reactor")
    implementation("org.mapstruct:mapstruct:1.4.2.Final")
    kapt("org.mapstruct:mapstruct-processor:1.4.2.Final")
}

tasks.withType<io.gitlab.arturbosch.detekt.Detekt>().configureEach {
    // Target version of the generated JVM bytecode. It is used for type resolution.
    this.jvmTarget = "11"
}

tasks.compileKotlin {
    kotlinOptions {
        @Suppress("SpellCheckingInspection")
        freeCompilerArgs = listOf("-Xjsr305=strict")
        allWarningsAsErrors = true
        jvmTarget = "11"
        languageVersion = "1.5"
        apiVersion = "1.5"
    }
}

tasks.compileTestKotlin {
    kotlinOptions {
        @Suppress("SpellCheckingInspection")
        freeCompilerArgs = listOf("-Xjsr305=strict")
        allWarningsAsErrors = true
        jvmTarget = "11"
        languageVersion = "1.5"
        apiVersion = "1.5"
    }
}
// file: publishing-conventions.gradle.kts

    publications {
        create<MavenPublication>(name) {
            from(components["java"])
          //  artifact(dokkaJavadocJar)
         //   artifact(dokkaHtmlJar)