Resolve plugins from JetBrains Marketplace in the latest compatible version

My colleague asked me if it is possible to resolve plugins from JetBrains Marketplace using the latest available version that matches the currently targeted IntelliJ Platform.
I know this is a recurring topic, but today I got a pretty neat idea of how to implement it in a Gradle-compatible way – here it is:

import org.jetbrains.intellij.platform.gradle.extensions.IntelliJPlatformDependenciesExtension
import org.jetbrains.intellij.pluginRepository.PluginRepositoryFactory

val IntelliJPlatformDependenciesExtension.pluginRepository by lazy {
    PluginRepositoryFactory.create("https://plugins.jetbrains.com")
}

fun IntelliJPlatformDependenciesExtension.pluginsInLatestCompatibleVersion(vararg pluginIds: String) =
    plugins(provider {
        pluginIds.map { pluginId ->
            val platformType = intellijPlatform.productInfo.productCode
            val platformVersion = intellijPlatform.productInfo.buildNumber

            val plugin = pluginRepository.pluginManager.searchCompatibleUpdates(
                build = "$platformType-$platformVersion",
                xmlIds = listOf(pluginId),
            ).firstOrNull()
                ?: throw GradleException("No plugin update with id='$pluginId' compatible with '$platformType-$platformVersion' found in JetBrains Marketplace")

            "${plugin.pluginXmlId}:${plugin.version}"
        }
    })

And then:

dependencies {
    // ...

    intellijPlatform {
        // ... 
        pluginsInLatestCompatibleVersion("org.coffeescript", ...)
    }
}

Enjoy! :smiley:

3 Likes

@jakub.chrzanowski nice! :clap: :tada:

Any chance this could be either (a) documented on the SDK site, and/or (b) rolled into the ij gradle plugin 2.* ? :blush:

It’s too tricky to make it a part of the IntelliJ Platform Gradle Plugin, i.e. due to hardcoded hostname, but I’ve added it as a recipe to the docs:

Just for info, the sample code in this thread works, but the sample code in the docs does not compile:

BTW, this code is really useful.
Now, I can test my plugins with the Classic UI with no efforts. Thanks a lot! :smiling_face_with_sunglasses:

I’m also glad you find this helpful!

And thanks for pointing this out – the code sample in docs will get updated shortly.

would be really useful to have that logic as part of standard dependency.intellijPlatform.plugins()

I implemented that yesterday as a compatiblePlugin(id)/compatiblePlugins(ids) helper. It should be available with the upcoming IntelliJ Platform Gradle Plugin release.

2 Likes

How to make it run in runtime? i.e. when

val runUltimate251 by intellijPlatformTesting.runIde.registering {
    type = IntelliJPlatformType.IntellijIdeaUltimate
    version = "2025.1"
}

executing, so it will pick up corespondent plugin’s versions?

Ha, following trick helps:

val pluginRepository: PluginRepository by lazy {
    PluginRepositoryFactory.create("https://plugins.jetbrains.com")
}
fun IntelliJPlatformDependenciesExtension.pluginsInLatestCompatibleVersion() =
    plugins(provider {
        requiredPlugins.addLatestCompatibleVersion(
            platformType = intellijPlatform.productInfo.productCode,
            platformVersion = intellijPlatform.productInfo.buildNumber
        )
    })

private fun List<String>.addLatestCompatibleVersion(platformType: String, platformVersion: String): List<String> =
    map { pluginId ->
        val plugin = pluginRepository.pluginManager.searchCompatibleUpdates(
            build = "$platformType-$platformVersion",
            xmlIds = listOf(pluginId),
        ).firstOrNull()
            ?: throw GradleException("No plugin update with id='$pluginId' compatible with '$platformType-$platformVersion' found in JetBrains Marketplace")

        "${plugin.pluginXmlId}:${plugin.version}"
    }

val requiredPlugins = listOf(
    "PythonCore", // python support (PSI tree)
    "org.intellij.scala",
    "org.jetbrains.plugins.go",
    "PsiViewer",
    // ...
)

dependencies {
    // ...

    intellijPlatform {
        create("IU", "2024.2")
        // ... 
        pluginsInLatestCompatibleVersion()
    }
}

and then

val runUltimate251 by intellijPlatformTesting.runIde.registering {
    type = IntelliJPlatformType.IntellijIdeaUltimate
    version = "2025.1"
    plugins {
        plugins(
            requiredPlugins.addLatestCompatibleVersion(
                platformType = "IU",
                platformVersion = "251.23774.435"
            )
        )
    }
}