From d7f2e8e9637353282a9030683ae7724b3b9b5c83 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 21 Apr 2026 22:14:22 +0000 Subject: [PATCH] feat: add ability to download latest modrinth version when no version is specified Agent-Logs-Url: https://github.com/spartacus04/run-task/sessions/9cb4cf90-352d-4381-9473-7667fc141dcd Co-authored-by: spartacus04 <52862005+spartacus04@users.noreply.github.com> --- .../runtask/pluginsapi/DownloadPluginsSpec.kt | 9 ++++++ .../runtask/pluginsapi/PluginApiDownload.kt | 8 +++-- .../pluginsapi/PluginDownloadServiceImpl.kt | 31 +++++++++++++++++-- .../pluginsapi/modrinth/ModrinthApi.kt | 7 +++++ .../pluginsapi/modrinth/ModrinthApiImpl.kt | 7 +++++ 5 files changed, 56 insertions(+), 6 deletions(-) diff --git a/plugin/src/main/kotlin/xyz/jpenilla/runtask/pluginsapi/DownloadPluginsSpec.kt b/plugin/src/main/kotlin/xyz/jpenilla/runtask/pluginsapi/DownloadPluginsSpec.kt index 4234e03..0e9c844 100644 --- a/plugin/src/main/kotlin/xyz/jpenilla/runtask/pluginsapi/DownloadPluginsSpec.kt +++ b/plugin/src/main/kotlin/xyz/jpenilla/runtask/pluginsapi/DownloadPluginsSpec.kt @@ -142,6 +142,15 @@ public abstract class DownloadPluginsSpec @Inject constructor( modrinth.configure { add(id, version) } } + /** + * Add a plugin download, downloading the latest available version. + * + * @param id plugin id on Modrinth + */ + public fun modrinth(id: String) { + modrinth.configure { add(id) } + } + // github extensions /** diff --git a/plugin/src/main/kotlin/xyz/jpenilla/runtask/pluginsapi/PluginApiDownload.kt b/plugin/src/main/kotlin/xyz/jpenilla/runtask/pluginsapi/PluginApiDownload.kt index b0b0427..8ba8833 100644 --- a/plugin/src/main/kotlin/xyz/jpenilla/runtask/pluginsapi/PluginApiDownload.kt +++ b/plugin/src/main/kotlin/xyz/jpenilla/runtask/pluginsapi/PluginApiDownload.kt @@ -18,6 +18,7 @@ package xyz.jpenilla.runtask.pluginsapi import org.gradle.api.provider.Property import org.gradle.api.tasks.Input +import org.gradle.api.tasks.Optional import xyz.jpenilla.runtask.util.HashingAlgorithm import xyz.jpenilla.runtask.util.calculateHash import xyz.jpenilla.runtask.util.toHexString @@ -71,10 +72,11 @@ public abstract class ModrinthApiDownload : PluginApiDownload() { public abstract val id: Property @get:Input + @get:Optional public abstract val version: Property override fun toString(): String { - return "ModrinthApiDownload{url=${url.get()}, id=${id.get()}, version=${version.get()}}" + return "ModrinthApiDownload{url=${url.get()}, id=${id.get()}, version=${version.orNull ?: "latest"}}" } override fun equals(other: Any?): Boolean { @@ -89,13 +91,13 @@ public abstract class ModrinthApiDownload : PluginApiDownload() { return url.get() == other.url.get() && id.get() == other.id.get() && - version.get() == other.version.get() + version.orNull == other.version.orNull } override fun hashCode(): Int { var result = url.get().hashCode() result = 31 * result + id.get().hashCode() - result = 31 * result + version.get().hashCode() + result = 31 * result + version.orNull.hashCode() return result } } diff --git a/plugin/src/main/kotlin/xyz/jpenilla/runtask/pluginsapi/PluginDownloadServiceImpl.kt b/plugin/src/main/kotlin/xyz/jpenilla/runtask/pluginsapi/PluginDownloadServiceImpl.kt index 85f1130..597780f 100644 --- a/plugin/src/main/kotlin/xyz/jpenilla/runtask/pluginsapi/PluginDownloadServiceImpl.kt +++ b/plugin/src/main/kotlin/xyz/jpenilla/runtask/pluginsapi/PluginDownloadServiceImpl.kt @@ -145,17 +145,37 @@ internal abstract class PluginDownloadServiceImpl : PluginDownloadService { private fun resolveModrinthPlugin(progressLoggerFactory: ProgressLoggerFactory, download: ModrinthApiDownload): Path { val cacheDir = parameters.cacheDirectory.get().asFile.toPath() - val apiVersion = download.version.get() val apiPlugin = download.id.get() val apiUrl = download.url.get() val provider = manifest.modrinthProviders.computeIfAbsent(download.url.get()) { ModrinthProvider() } val plugin = provider.computeIfAbsent(download.id.get()) { PluginVersions() } + + val targetDir = cacheDir.resolve(Constants.MODRINTH_PLUGIN_DIR).resolve(apiPlugin) + + // Resolve the version: if not specified, fetch the latest from the versions list endpoint + val apiVersion: String + if (!download.version.isPresent) { + val latestJsonName = "latest-json" + val latestJsonVersion = plugin[latestJsonName] ?: PluginVersion(fileName = "$apiPlugin-latest-versions.json", displayName = "modrinth:$apiPlugin:latest:metadata") + val latestJsonFile = targetDir.resolve(latestJsonVersion.fileName) + val latestRequestUrl = "$apiUrl/v2/project/$apiPlugin/version" + val latestJsonPath = download( + DownloadCtx(progressLoggerFactory, apiUrl, latestRequestUrl, targetDir, latestJsonFile, latestJsonVersion, setter = { plugin[latestJsonName] = it }, requireValidJar = false) + ) + + @OptIn(ExperimentalSerializationApi::class) + val versionList = latestJsonPath.inputStream().buffered().use { + mapper.decodeFromStream>(it) + } + apiVersion = versionList.firstOrNull()?.id ?: error("Could not find any versions for modrinth project $apiPlugin") + } else { + apiVersion = download.version.get() + } + val jsonVersionName = "$apiVersion-json" val jsonVersion = plugin[jsonVersionName] ?: PluginVersion(fileName = "$apiPlugin-$apiVersion-info.json", displayName = "modrinth:$apiPlugin:$apiVersion:metadata") - val targetDir = - cacheDir.resolve(Constants.MODRINTH_PLUGIN_DIR).resolve(apiPlugin) val jsonFile = targetDir.resolve(jsonVersion.fileName) val versionRequestUrl = "$apiUrl/v2/project/$apiPlugin/version/$apiVersion" @@ -365,6 +385,11 @@ private data class ModrinthVersionResponse( ) } +@Serializable +private data class ModrinthVersionListEntry( + val id: String +) + // github types: private typealias GitHubProvider = MutableMap diff --git a/plugin/src/main/kotlin/xyz/jpenilla/runtask/pluginsapi/modrinth/ModrinthApi.kt b/plugin/src/main/kotlin/xyz/jpenilla/runtask/pluginsapi/modrinth/ModrinthApi.kt index f7edfb8..21d3540 100644 --- a/plugin/src/main/kotlin/xyz/jpenilla/runtask/pluginsapi/modrinth/ModrinthApi.kt +++ b/plugin/src/main/kotlin/xyz/jpenilla/runtask/pluginsapi/modrinth/ModrinthApi.kt @@ -40,4 +40,11 @@ public interface ModrinthApi : PluginApi { * @param version plugin version id */ public fun add(id: String, version: String) + + /** + * Add a plugin download, downloading the latest available version. + * + * @param id plugin id on Modrinth + */ + public fun add(id: String) } diff --git a/plugin/src/main/kotlin/xyz/jpenilla/runtask/pluginsapi/modrinth/ModrinthApiImpl.kt b/plugin/src/main/kotlin/xyz/jpenilla/runtask/pluginsapi/modrinth/ModrinthApiImpl.kt index 4a4f187..749826f 100644 --- a/plugin/src/main/kotlin/xyz/jpenilla/runtask/pluginsapi/modrinth/ModrinthApiImpl.kt +++ b/plugin/src/main/kotlin/xyz/jpenilla/runtask/pluginsapi/modrinth/ModrinthApiImpl.kt @@ -39,6 +39,13 @@ public abstract class ModrinthApiImpl @Inject constructor(private val name: Stri jobs.add(job) } + override fun add(id: String) { + val job = objects.newInstance(ModrinthApiDownload::class) + job.url.set(url.map { it.trimEnd('/') }) + job.id.set(id) + jobs.add(job) + } + override fun copyConfiguration(api: ModrinthApi) { url.set(api.url) jobs.addAll(api.downloads)