A Bit of Help
A Bit of Help

Reputation: 1766

Gradle 7.2: How to apply a custom Gradle SETTINGS plugin?

I am in the process of migrating buildSrc convention plugins into standalone plugins. There are a lot of examples for creating Gradle plugins for Project objects, but a real dearth for Settings and Gradle. I want to centralize the list of repositories that we use in our gradle.settings.kts files, so I've created a Gradle Settings plugin: RepositoriesPlugin.

It is implemented in the same manner at a Project plugin, however, I am unsure about how to interpret the following quote from Gradle's docs: "A plugin can instead receive a parameter of type Settings, in which case the plugin can be applied in a settings script.", as stated in the documentation at this link: Gradle 7.2 Doc

The following example shows how I've applied my settings plugin in a settings.gradle.kts file. Is this how a settings plugin is applied, as per the documentation?

I've included the basic settings plugin code, below, too.

I'd appreciate your help to clarify that I am doing this properly. I am sure that this posting will help others who stray away from just Project plugins.

Thanks for your time and interest..

// settings.gradle.kts

pluginManagement {
    plugins {
        id("com.abitofhelp.gradle.plugins.repositoriesplugin") version "1.0.0-1"
    }

    settings.extensions
        getByType(RepositoriesPluginExtension::class).apply {
            localRepoName = "local-repo"
            localRepositoryPath = "../../local-repo"
        }

    // Set the plugin repositories for all projects.
    //repositories {
    //    maven { name = "localRepo"; url = uri(file("./local-repo")) }
    //    gradlePluginPortal()
    //    mavenCentral()
    //}
}
// repositoriesplugin.kt
open class RepositoriesPlugin: Plugin<Settings> {
    override fun apply(settings: Settings) {
        val extension: RepositoriesPluginExtension =
            settings.extensions.create("repositoriesPlugin", RepositoriesPluginExtension::class.java)

        val localRepositoryName = extension.localRepositoryName?.let { it }?: "../../localRepo"
        val localRepositoryPath = extension.localRepositoryPath?.let { it }?: "../../local-repo"

        settings.pluginManagement.repositories.apply {
            // Set the PLUGIN REPOSITORIES for all subprojects.
            maven { repository ->
                repository.name = localRepositoryName
                repository.url = URI.create(localRepositoryPath)
            }
            gradlePluginPortal()
            mavenCentral()
        }

        settings.dependencyResolutionManagement.repositories.apply {
            // Set the DEPENDENCY REPOSITORIES for all subprojects.
            maven {
                it.name = localRepositoryName
                it.url = URI.create(localRepositoryPath)
            }
            mavenCentral()
            gradlePluginPortal()
        }
    }
}

Upvotes: 6

Views: 7250

Answers (3)

Invitor
Invitor

Reputation: 197

As Justin Warkentin already noted, you first need to add your repo in the pluginManagement section and then you can apply your plugin like any other.

If you want to bypass the repository, you can also add the plugin project as composite build via includeBuild in the pluginManagement section.

In my example I have combined both methods. If the plugin project exists locally, this one is used, otherwise the version from the repo is used. This way you can (temporarily) add your plugin project to develop on it and test it directly in including projects.

pluginManagement {
    repositories {
        // your plugin repo; maybe...
        mavenLocal()
    }

    // use local copy of your plugin if available,
    // otherwise load plugin from repo
    def name = 'your_plugin_project'
    if (file(name).isDirectory()) {
        includeBuild(name)
    }
}

plugins {
    // apply your plugin
    id 'your.plugin.id'
}

Upvotes: 7

Justin Warkentin
Justin Warkentin

Reputation: 10241

I just had to figure this out myself. You weren't far off with your initial attempt but the plugins block actually has to go after the pluginManagement block. The basic layout of my working implementation looks like this:

// settings.gradle.kts

rootProject.name = "myProject"

pluginManagement {
    repositories {
        maven {
            url = uri("/tmp/maven-local")
            gradlePluginPortal()
        }
    }
}

plugins {
    id("com.example.my-plugin") version "1.0-SNAPSHOT"
}

Upvotes: 5

rene
rene

Reputation: 1

I believe you need to add the plugin to settings.gradle classpath via buildscript closure. pluginManagement.plugins makes the plugin availabile to the root (& sub) project build.gradle classpath, but I think that is a different classpath from the settings.gradle script.

To add to settings gradle, give this a try:

// settings.gradle
    
buildscript {
    repositories {
        maven { url "http://repo.where.plugin.is.published" }
    }

    classpath("complete.maven.coordinates:your-settings-plugin:version")
}

pluginManager.apply(your.settings.plugin.id) 

Upvotes: 0

Related Questions