From f98d308c05b04a84887f9082e925f22d778a98c1 Mon Sep 17 00:00:00 2001 From: Rachel Aurand Date: Wed, 7 Oct 2026 15:50:35 -0700 Subject: [PATCH] fix gradle module.json version in gradle 9.8 --- .../semanticversion/SemanticVersionPlugin.kt | 54 +++++++++++++++++++ .../gradle/semanticversion/ModuleParser.kt | 26 +++++++++ .../SemanticVersionPluginTest.kt | 11 ++++ 3 files changed, 91 insertions(+) create mode 100644 src/test/kotlin/dev/poolside/gradle/semanticversion/ModuleParser.kt diff --git a/src/main/kotlin/dev/poolside/gradle/semanticversion/SemanticVersionPlugin.kt b/src/main/kotlin/dev/poolside/gradle/semanticversion/SemanticVersionPlugin.kt index a34c099..7092f06 100644 --- a/src/main/kotlin/dev/poolside/gradle/semanticversion/SemanticVersionPlugin.kt +++ b/src/main/kotlin/dev/poolside/gradle/semanticversion/SemanticVersionPlugin.kt @@ -1,12 +1,17 @@ package dev.poolside.gradle.semanticversion +import groovy.json.JsonOutput +import groovy.json.JsonSlurper import org.gradle.api.Plugin import org.gradle.api.Project import org.gradle.api.publish.PublishingExtension +import org.gradle.api.publish.maven.MavenPublication import org.gradle.api.publish.maven.tasks.GenerateMavenPom import org.gradle.api.publish.maven.tasks.PublishToMavenRepository +import org.gradle.api.publish.tasks.GenerateModuleMetadata import org.gradle.api.tasks.compile.JavaCompile import org.gradle.kotlin.dsl.withType +import java.io.File class SemanticVersionPlugin : Plugin { override fun apply(project: Project) { @@ -26,6 +31,12 @@ class SemanticVersionPlugin : Plugin { project.tasks.withType { this.dependsOn("semanticVersion") } + project.tasks.withType { + this.dependsOn("semanticVersion") + doLast { + rewriteModuleMetadata(outputFile.get().asFile, project) + } + } project.gradle.projectsEvaluated { val semanticVersionTasks = project.rootProject.allprojects.flatMap { it.tasks.withType(SemanticVersionTask::class.java).toList() @@ -33,6 +44,49 @@ class SemanticVersionPlugin : Plugin { project.tasks.withType().configureEach { dependsOn(semanticVersionTasks) } + project.tasks.withType().configureEach { + dependsOn(semanticVersionTasks) + } } } + + private fun rewriteModuleMetadata(file: File, project: Project) { + val versions = project.rootProject.allprojects + .asSequence() + .mapNotNull { it.extensions.findByType(PublishingExtension::class.java) } + .flatMap { it.publications.withType(MavenPublication::class.java).asSequence() } + .associate { "${it.groupId}:${it.artifactId}" to it.version } + val module = JsonSlurper().parse(file) as? Map<*, *> ?: return + val rewritten = module.mapValues { (key, value) -> + if (key == "variants") rewriteVariants(value, versions) else value + } + + file.writeText(JsonOutput.prettyPrint(JsonOutput.toJson(rewritten))) + } + + private fun rewriteVariants(variants: Any?, versions: Map): Any? = + (variants as? List<*>)?.map { variant -> + if (variant !is Map<*, *>) return@map variant + variant.mapValues { (key, value) -> + if (key == "dependencies" || key == "dependencyConstraints") { + rewriteVersions(value, versions) + } else { + value + } + } + } ?: variants + + private fun rewriteVersions(entries: Any?, versions: Map): Any? = + (entries as? List<*>)?.map { entry -> + if (entry !is Map<*, *>) return@map entry + val key = "${entry["group"]}:${entry["module"]}" + val publishedVersion = versions[key] ?: return@map entry + entry.mapValues { (key, value) -> + if (key == "version" && value is Map<*, *>) { + value + ("requires" to publishedVersion) + } else { + value + } + } + } ?: entries } diff --git a/src/test/kotlin/dev/poolside/gradle/semanticversion/ModuleParser.kt b/src/test/kotlin/dev/poolside/gradle/semanticversion/ModuleParser.kt new file mode 100644 index 0000000..57b721f --- /dev/null +++ b/src/test/kotlin/dev/poolside/gradle/semanticversion/ModuleParser.kt @@ -0,0 +1,26 @@ +package dev.poolside.gradle.semanticversion + +import com.fasterxml.jackson.databind.DeserializationFeature +import com.fasterxml.jackson.databind.ObjectMapper +import com.fasterxml.jackson.module.kotlin.readValue +import com.fasterxml.jackson.module.kotlin.registerKotlinModule +import java.io.File + +object ModuleParser { + fun parse(filePath: String): Module { + val mapper = ObjectMapper() + .registerKotlinModule() + .configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false) + return mapper.readValue(File(filePath)) + } +} + +data class Module(val component: Component, val variants: List) + +data class Component(val group: String, val module: String, val version: String) + +data class Variant(val name: String, val dependencies: List?) + +data class ModuleDependency(val group: String, val module: String, val version: Version) + +data class Version(val requires: String) diff --git a/src/test/kotlin/dev/poolside/gradle/semanticversion/SemanticVersionPluginTest.kt b/src/test/kotlin/dev/poolside/gradle/semanticversion/SemanticVersionPluginTest.kt index 0324acb..244ccca 100644 --- a/src/test/kotlin/dev/poolside/gradle/semanticversion/SemanticVersionPluginTest.kt +++ b/src/test/kotlin/dev/poolside/gradle/semanticversion/SemanticVersionPluginTest.kt @@ -710,6 +710,17 @@ class SemanticVersionPluginTest { assertEquals("0.1.0", lib.version) } } + testProjectDir.walk().filter { it.name.startsWith("module.json") }.forEach { file -> + file.forEachLine { println(it) } + val module = ModuleParser.parse(file.absolutePath) + assertEquals("0.1.0", module.component.version) + module.variants.forEach { variant -> + val dep = variant.dependencies?.find { it.group == "dev.poolside.test" } + if (dep != null) { + assertEquals("0.1.0", dep.version.requires) + } + } + } val valid = mutableListOf( "${mavenRepo.absolutePath}/dev/poolside/test/my-library/0.1.0/my-library-0.1.0.jar", "${mavenRepo.absolutePath}/dev/poolside/test/my-sublibrary/0.1.0/my-sublibrary-0.1.0.jar"