This message was deleted.
# community-support
s
This message was deleted.
t
I think that roughly makes sense. It's something I've been planning to do for my own plugins. Would love to hear your experience wiring that all up
πŸ‘ 1
one thing that comes to mind is I'm not 100% sure that it's guaranteed that the root project will be evaluated before subprojects (
evaluationDependsOn
can mess with ordering, but that's also incompatible with project isolation, so maybe it doesn't matter). And of course you're using properties, so that should be fine so long as they're evaluated during execution and not configuration
j
Is there any way to force that the service should be registered from the root directory? or if the order of execution is different and another project has registered the service, get the service in configuration phase and change a property inside it?
Looks like this works, without configuration cache enabled:
Copy code
val myService =
    target.gradle.sharedServices.registerIfAbsent("myService ", MyBuildService::class) {
        parameters.hasBeenAppliedOnRoot.set(false)
    }

if (target.path == ":") myService .get().parameters.hasBeenAppliedOnRoot.set(true)
Curiously there is still a issue where you can't name properties in params with
is
prefix
With configuration cache enabled, it is no longer working
v
Besides that I would do
if (project == project.rootProject)
or
if (project.parent == null)
, it of course does not work, as you modify the parameter only when executing configuration phase. How to properly do it depends on your other code, where you use that information. For example if you use that at a task implementation, don't give the service to the task, but wire the services boolean property to the task.
j
That doesn't break project isolation?
t
could you register the service in a settings plugin?
j
I haven't tried, my plugin is a project plugin
t
well...
new plugin whose only job is to register the service. your project plugin can then get the service
j
complicated setup because my plugin is not for internal use, it is open source. I think I would have to wait so I can see how project isolation feature evolves
t
ah, got it. you and I have the same problem, then! I have been wondering if I could convert my OSS plugin to a settings plugin
j
I hope that root project has special features, as personally I use for configuration purposes and I don't add code to it
I was thinking about that too
but settings plugin can't change the version of all projects no?
t
the root project is not special at all, not in the way you mean
j
I know, and that is the problem IMO, it should
t
I think there's a missing API here
βž• 1
project isolation is probably years away
j
basically I need to register the task only in the root project, because this task create a git tag, and if all projects create a tag when I run
gw createSemverTag
, boom πŸ’₯, multiple git tags will be created, and at the same time, I have to set the version to all the projects that apply my plugin. So without that missing API, I can't see how to solve this problem supporting project isolation easily.
Maybe the build service should create the tag instead of the task itself?
v
That doesn't break project isolation?
I don't think so, why should it? Or you maybe didn't understand what I mean.
could you register the service in a settings plugin?
What would that change? Settings script execution is part of configuration cache too.
but settings plugin can't change the version of all projects no?
It should be able to without problem, nor sure why you should though
I know, and that is the problem IMO, it should
In what way should root project be special and why?
basically I need to register the task only in the root project, because this task create a git tag
And what hinders you to do it?
Copy code
if (target.parent == null) {
    tasks.register("createSemverTag")
}
So without that missing API, I can't see how to solve this problem supporting project isolation easily.
Which missing API?
Maybe the build service should create the tag instead of the task itself?
I don't think so
t
if you register the service in a settings plugin, you don't have to ask, "am I in the root project", because you already know you're in the root context, and the settings script will only be evaluated once
v
Ah, I see what you mean, but that probably doesn't help for his actual use-case that I'd guess is more complex than shown here.
j
Is it possible to report that the plugin has to be applied to the root project in the case it is not happening?
Supposing the user forgets to apply the plugin to the root, if it call the task it will not exist but it will not get a way to know how to solve the issue without checking the documentation or opening an issue
t
I'll say again that we're at least a year away from project isolation, probably more. So I don't personally think it worth the effort to try be fully compatible, especially given the rules for compatibility are still in flux. Make a best effort and then move on (I'd advise)
πŸ‘ 1
j
Yeah I have read the doc and your post too, but even knowing that I want to learn to get it working with a lot of restrictions because at same time those restrictions are related to how we should create gradle libraries right now
v
There are quite some ways with differences in details on how to do it. Your idea with the service would be one way. Do not inject the service, but the boolean property to the task as I said. Add the task to all projects and in the task action do the check like
if (currentlyOnRootProject) doTag() else if (!pluginHasBeenAppliedToRootProject.get()) logger.warn("apply the plugin to the root project")
.
πŸ‘ 1
j
thank you all, will try :)
v
Additionally you can then have a counter in the service, so that if you have projects root, A, and B and it is applied to A and B that only one of the tasks outputs the warning if you like
πŸ‘ 1
x
I would tweak that idea and instead use the build service to have a single task do the git tag and the other one not do anything. Use the worker limitation on the build service to ensure there's no concurrency and then record in the service that the tag was done and have all the other task do nothing.
that way you don't even need to register on root. All you need is one project with your plugin anywhere and it'll work
Gradle clearly does not have a lot of API to manage applied plugins across many projects, except in Settings. This is where you would do this kind of stuff, but since Settings plugins are optional themselves that's not great either.
j
Thank you! I haven't started to do it yet because I have another use case. To support multimodule, I am allowing that each module can have a different prefix tag, for example, library A can have
v
an library B can have
w
. The rest of libraries has no git tags or uses the root one. The approach I was using before is not very intuitive because I was passing the module name as a property, for example:
Copy code
./gradlew createSemverTag "-Psemver.scope=minor" // all modules except library A and B
Copy code
./gradlew createSemverTag "-Plibrary:semver.scope=minor" // library A, in reality, all v prefix I think...
I think I should avoid that and just pass a different property which should be the tag.
Copy code
./gradlew createSemverTag "-Psemver.scope=minor" "-Psemver.usePrefix=v" // all modules with v prefix
And I am using gradle.properties because you can change the version without creating a tag, for example for publishing to:
Copy code
./gradlew libraryA:publishToMavenLocal "-Psemver.scope=minor" "-Psemver.usePrefix=v"
v
Gradle clearly does not have a lot of API to manage applied plugins across many projects, except in Settings.
Well, probably because it is a bad idea. Projects should be independent.
but since Settings plugins are optional themselves
What do you mean with that? Any plugin is optional.
x
oh yeah I agree that projects should be independent. It's an issue when you publish a plugin that's meant to be used in several projects to connect them a certain way. From the plugin you have no control that the setup is done properly. You can only hope that the user did the right thing. And yes settings are optional, so what I meant is that if you want to use Settings to ensure some plugins are applied to some projects, you have to rely on the user to apply the setting plugin as well. I don't think there's a good way to improve on this. I was just pointing out that the few APIs that allows you to control this on are in the Settings plugins.
βž• 2
j
I was thinking in something similar but on plugins in the root project and that what I mean with root project being β€œspecial”
hard journey but...
πŸ‘Œ 1
πŸ’ͺ 1