hey folks - I'm trying to create a gradle settings...
# community-support
a
hey folks - I'm trying to create a gradle settings plugin that will be applied in the settings file and that is configurable via a plugin extension to enable/disable some settings applied by the plugin - but it seems like I can't use the usual approach that I would use when creating a plugin extension for a project plugin...or at least it seems like the plugin extension I'm registering doesn't seem to do anything. Does anyone know of a good reference I can look at for how to do this? The updated documentation for 8.8 is really great, but I can't seem to find much about writing settings plugins. Thanks in advance šŸ™‚
t
I had a similar question further up. If you're intending to use precompiled script plugins this answer helped me https://gradle-community.slack.com/archives/CAHSN3LDN/p1718858176831369
a
hmm not sure that's quite what I'm looking to do unless I missed something. The linked myRepos settings file doesn't have any conditional logic in it. I want to be able to enable/disable functionality via a property exposed via an extension
v
What is the "usual approach" you mentioned? The horrible
afterEvaluate
that you should avoid at almost any cost?
Basically project plugin and settings plugin work just the same.
a
no not doing any afterEvaluate stuff basically here's the gist of my plugin: override fun apply(settings: Settings) { val extension = settings.extensions.create("mySettings", MySettingsPluginExtension::class.java) extension.failOnProjectRepos.convention(true) if (extension.failOnProjectRepos.get()) { settings.apply { settings.dependencyResolutionManagement.repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS) } }
then I'm trying to set it to false in my settings.gradle.kts or in my gradle.properties but neither seems to work
clearly I am missing something, just not sure what šŸ™‚
v
Of course it does not work like that. You immediately query the value, making it un-lazy. My question was, you said "it seems like I can't use the usual approach that I would use when creating a plugin extension for a project plugin" and I asked which that "usual approach" would have been.
a
yeah probably not using the correct terminology here, but usually I'd be doing this stuff inside a registered task and I don't seem to be able to do that on the settings object
so trying to figure out proper way to accomplish via a settings plugin
v
Ah, I see.
a
sorry, I'm in new uncharted territory for me at the moment šŸ™‚
v
Not really
The problem you have is exactly the same you have in project plugins, if you want to change some configuration based on the property on your extension.
As long as you read all properties only at execution time, you do not have a problem.
The solution is also quite the same. Do not use a property, but have a function in your extension that the consumer of your plugin can call and that does the configuration change in its body.
a
hmm I don't quite follow that, sorry
I am applying this settings plugin directly in the plugins block of my settings.gradle
v
• do not have a property for that in your extension • instead have a function for that in your extension • do the configuration not depending on the property in your
apply
, but in the body of that function • let your consumers call that function instead of setting a property
a
ok, something still not clear to me I guess. How would projects that apply this settings plugin configure the plugin enable/disable enforcement of the repositories mode?
(sorry for being dense about this)
v
Exactly the same as how you planned with the property, just not by setting a property, but by calling a method. I'm not sure which part you don't understand. Maybe you just need to give it a try?
a
I have been trying variations of it all day, still no success šŸ™‚
v
Well, feel free to show one of your variations šŸ™‚
a
ok, so right now I managed to get it "working" using settings.gradle.settingsEvaluated (which is know is not conventionally good practice based on your earlier question about after evaluate
just trying to figure out how to properly modify what I have, but I'll give the contents here in a sec to show what I've currently got:
so in the project settings.gradle that I am applying my published plugin to: ... plugins { id("com.example.my-plugin") version "1.0" } myPluginSettings { failOnProjectRepos = false } my extension is : interface MyPluginExtension { val failOnProjectRepos: Property<Boolean> } and my plugin is: abstract class MyPlugin: Plugin<Settings> { override fun apply(settings: Settings) { val extension = settings.extensions.create("myPluginSettings", MyPluginExtension::class.java) extension.failOnProjectRepos.convention(true) settings.gradle.settingsEvaluated { configureSettings(settings, extension) } } private fun configureSettings(settings: Settings, extension: MyPluginExtension) { if (extension.failOnProjectRepos.get()) { settings.apply { settings.dependencyResolutionManagement.respositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS) } } } }
v
Yeah that's the try with the property and the questionable
settingsEvaluated
. The question is, what did not work with what I suggested.
a
I've noticed that if I try to reload my gradle project it complains about the "myPluginSettings" in the settings.gradle, which I assume is due to the settingsEvaluated stuff
v
Complain in which form?
a
"could not find method myPluginSettings()" on settings .... etc"
but if I use the command line it seems to be fine with building
v
The
settingsEvaluated
should not cause this. But I still highly recommend not using it but doing like I suggested.
But use whatever works for you šŸ™‚
a
yeah definitely on the same page as you - want to get this to work the recommended way
I guess what I'm not clear on is how I would dynamically do this without properties like you're suggesting
still pretty noob at this stuff
the extension block in the settings.gradle: myPluginSettings { failOnProjectRepos = true } this "failOnProjectRepos" is always considered a property, right? Because being able to configure this at the project settings is what I'm hoping to be able to do until we fix all our project-level repo configurations to be more centralized
v
Yes, that is a property and always will be
It will then instead look like
Copy code
myPluginSettings {
  failOnProjectRepos()
}
or
Copy code
myPluginSettings {
  failOnProjectRepos(true)
}
for example
Just follow the simple 4 steps I gave you
a
ahhhhhh ok I think I better understand now
thanks Vampire šŸ™‚
šŸ‘Œ 1
well, I thought I was close, but it turns out I am not really much farther ahead
I've been able to successfully trigger a function in my extension class via the extension block in my consumer project
but I cannot seem to get the compiler to let me use the settings object I am passing in the extension constructor
I updated my extension to look like this: abstract class MyPluginExtension(settings: Settings) { fun test() { settings.apply etc } and the settings object is not properly resolving and letting me call any of it's APIs I updated the apply function in my plugin to look like this: abstract class MyPlugin: Plugin<Settings> { override fun apply(settings: Settings) { val extension = settings.extensions.create("myPluginSettings", MyPluginExtension::class.java, settings) etc...
ĀÆ\_(惄)_/ĀÆ
ok making progress again šŸ™‚ will let you know if I hit any more hangups
got it! thanks Vampire, you are awesome...learned a few things today!
šŸ‘Œ 1