Is there really 0 ways of expressing "task which c...
# community-support
v
Is there really 0 ways of expressing "task which checks everything everywhere and assembles app A" as a explicit task? i.e the equivalent of
./gradlew check :appA:assemble
but as a explicit
buildAppA
task? I really hate pushing complexity/impl details into cli / ci configs. It does not scale. Its what tasks are for
v
What is wrong with configuring that task yourself if that is the behavior you want? Or calling it exactly like that if that is what you want to do?
v
But I cannot configure it, can I? I cannot depend on the aggregate check in a task definition
v
Given all projects apply at least the
lifecycle-base
task, you can just depend on all check tasks in all projects.
v
How? If I define buildAppA in appA, then check refers to that direct check, and nothing else
okay name doesnt fit, lets call it buildWhatever so
./gradlew :appA:buildWhatever
would be the syntax
If i define
buildAppA
in root, its the same thing, isnt it? check is refering to this project's (root) check
Am I missing something?
v
Copy code
tasks.register("buildWhatever") {
    rootProject.allProjects.forEach { dependsOn("${it.path}:check") } 
}
(Written from head, so might need some fix)
v
hmm okay but isnt that some sort of IP violation?
v
No, you don't access the other project (except for static information like its path)
v
okay but that requires the task to exist on those projects for sure, right?
or can I make it optional?
(yes check is everywhere, lets pretend its not, ill be calling my checkVariant due to it being android build)
v
okay but that requires the task to exist on those projects for sure, right?
Yes. That's why I said "Given all projects apply at least the
lifecycle-base
plugin"
or can I make it optional?
Not in that construct, no.
v
why is there such delta between what cli can do and what the tasks dsl can do? am I going against the grain?
v
There is no delta, you can do the same the cli is doing, it's just not good to do so, as it violates IP
v
which makes the dsl a second class citizen, it seems
v
There is a method to get all tasks of all projects with a given name where it exists. But it has the same problems as cross-project configuration / access
From CLI this is irrelevant
v
yea which leads me to believe gradle wants me to have N tasks specified in the cli, and not bundle them in a single task, so I can have a simple cli command
v
Both is fine for Gradle
l
Another option you might consider is to expose every
check
task of each subproject in an outgoing variant of that project with certain attributes. Then, your bulk task can depend on a lenient artifact view of a configuration with project deps on every project, and it will then depend on
check
in all subprojects where it exists without IP violations. This is an approach I've used elsewhere (say, in my central portal publishing plugin) to effectively allow "open" task dependencies that are then set up from the provider side, without IP violations.
v
Yeah, we got that in his other thread. But, never use a "lenient" artifact view for anything even lightly important. Those are only for purely optional things like getting sources if maybe available but doesn't matter if not. "lenient" artifact view ignores almost each and every exception including download errors and so on. A "non-lenient" artifact view is already lenient in the sense that it ignores dependencies that cannot provide the requested variant. Only the originally requested variant has to exist.
l
Good to know. Though that sounds problematic for other reasons and means I have to rethink my use of non-lenient views some places -- how is one supposed to resolve artifact selection, requiring that artifacts exist satisfying selection?
(Also, for this case "lenient" is correct because there may not be a resolvable variant to begin with)
v
But you should simply ensure that the initial variant is there. Otherwise as I said you also ignore most errors that could happen like download errors and so on. Lenient is very seldomly what you want. If you want to ensure that the variants you want to have exist, then directly request it and don't use an artifact view. But that only works if you don't need an artifact transform for the variant to exist.
l
You cannot ensure that the existing variant is there if you are depending on every project, and not every project may expose the thing in question.
And as for the second point -- yes that's exactly the issue. I would assume there is an API to request artifact selection specifically on resolved variants that is not "lenient" in any sense, but it appears there isn't.
v
You cannot ensure that the existing variant is there if you are depending on every project, and not every project may expose the thing in question.
Sure you can. If you have a convention plugin that is applied to all of the projects, that plugin can add such a variant. I know that it works, because I recently did exactly that.
And as for the second point -- yes that's exactly the issue. I would assume there is an API to request artifact selection specifically on resolved variants that is not "lenient" in any sense, but it appears there isn't.
Sure there is, as I said, just directly request that variant directly instead of using an artifact view.
l
If you have a convention plugin...
This is fine for a single project. Less fine for publishing a plugin, which you now require to be a settings plugin for no good reason.
Just directly request the variant directly...
That only works if the artifact in question is the primary artifact set of a variant. If you want artifact(s) that are available only through a view or a secondary artifact set, your only option is to request them via a view, then go through afterwards and validate that you have all the same capabilities as the resolved variants, or some approach of that sort. I think my complaint is that there's some mixing up of artifact and variant resolution happening in this API. Ideally, the axes of what degree you allow variant selection and artifact selection to fail should be controllable and controllable independently; currently, your only options (assuming you're requesting different attributes for both selection steps) are fail-fast variant selection and never-fail artifact selection, or never failing for both. Allowing variant selection to fail but requiring artifact selection from selected variants to succeed, for instance, would be quite useful; similarly for requiring both to succeed.
v
This is fine for a single project. Less fine for publishing a plugin, which you now require to be a settings plugin for no good reason.
... no 1. it is good reason 2. you quoted me and I did not say create a settings plugin, but I said "If you have a convention plugin that is applied to all of the projects" For our corporate convention plugins I for example anyway have a mandatory settings plugin, and a mandatory base plugin to be applied to all projects directly or indirectly. The base plugin verifies that the settings plugin is applied, the settings plugin verifies that all projects have at least the base plugin applied. This way all the corporate convention plugins can be sure that at least the base plugin is applied everywhere and can depend on that like requesting the given variant that is guaranteed to be available on each and every project in the build as it is added by the base plugin.
That only works if the artifact in question is the primary artifact set of a variant. If you want artifact(s) that are available only through a view or a secondary artifact set, your only option is to request them via a view, then go through afterwards and validate that you have all the same capabilities as the resolved variants, or some approach of that sort.
Can you elaborate on that with an MCVE? Which variants are only available through an artifact view? I'm not aware of such a restriction, besides - as I said - if only an artifact transform can produce the variant. Other than that I think you should be able to request all directly also.
I think my complaint is that there's some mixing up of artifact and variant resolution happening in this API.
Yes, that is indeed a bit strange at times. For example some attributes are on configurations / variants, some are on artifacts. And artifact transforms can for example not influence the variant selection even if they could then later provide the requested attributes. There are open FR for such things.
l
The issue is not variants only available through an artifact view, the issue is artifact sets only available through an artifact view. For instance. Any artifact transform who's resulting attributes are incompatible with the attributes requested for variant selection
And your convention plugin example is once again, likely fine for a corporate setup but less fine for a published plugin which now needs to be applied in projects it does nothing in
v
For instance. Any artifact transform who's resulting attributes are incompatible with the attributes requested for variant selection
Yes, as I said multiple times, if only an artifact transform can produce a variant, then an artifact view is necessary. Well, also not fully true iirc. If the transformed attributes are artifact attributes, not variant attributes, then it should even work without artifact view. But - as I said - if no artifact transform is involved at all, no artifact view should be necessary.
And your convention plugin example is once again, likely fine for a corporate setup but less fine for a published plugin which now needs to be applied in projects it does nothing in
Our corporate convention plugins are published to a maven repo internally and applied to builds just like any other published plugin, so I don't see how there would be any difference to a publically published plugin, or why you would need to apply it to somewhere it does nothing in.
l
If no artifact transform is involved at all, no artifact transform is necessary
My point is also true of plain old secondary artifact sets (previously secondary variants). Besides which... Yes, that's the point. You need separate control over the attributes used for artifact and variant selection in some cases. That requires artifact views. Which don't let you enforce successful artifact selection.
As for the plugin issue -- you force consumers to add it to all projects, even if in many projects it does nothing but make an empty variant for the sake of not failing variant selection because there is no API for enforcing successful artifact selection but lenient variant selection. It's silly, having an API flexible enough to resolve those two axes separately would avoid the issue entirely
v
My point is also true of plain old secondary artifact sets (previously secondary variants).
No, it's not if they are built sanely:
Copy code
val foo = configurations.dependencyScope("foo")
val fooClasspath = configurations.resolvable("fooClasspath") {
    extendsFrom(foo)
    attributes {
        attribute(CATEGORY_ATTRIBUTE, project.objects.named(LIBRARY))
        attribute(USAGE_ATTRIBUTE, project.objects.named(JAVA_RUNTIME))
        attribute(LIBRARY_ELEMENTS_ATTRIBUTE, project.objects.named(JAR))
        attribute(BUNDLING_ATTRIBUTE, project.objects.named(EXTERNAL))
    }
}
val bar = configurations.dependencyScope("bar")
val barClasspath = configurations.resolvable("barClasspath") {
    extendsFrom(bar)
    attributes {
        attribute(CATEGORY_ATTRIBUTE, project.objects.named(LIBRARY))
        attribute(USAGE_ATTRIBUTE, project.objects.named(JAVA_RUNTIME))
        attribute(LIBRARY_ELEMENTS_ATTRIBUTE, project.objects.named(CLASSES))
        attribute(BUNDLING_ATTRIBUTE, project.objects.named(EXTERNAL))
    }
}
dependencies {
    foo(projects.foo)
    bar(projects.foo)
}
tasks.register("baz") {
    doLast {
        println("FOO")
        fooClasspath.get().forEach { println(it) }
        println("BAR")
        barClasspath.get().forEach { println(it) }
    }
}
=>
Copy code
FOO
.../showcase/foo/build/libs/foo.jar
BAR
.../showcase/foo/build/classes/java/main
You need separate control over the attributes used for artifact and variant selection in some cases. That requires artifact views
Usually not, because artifact attributes are on the artifact, not on the variant, so if you request them on the resolvable configuration already, they are ignored for the variant selection, as the variant does not provide the attribute you requested which is considered compatible and then on the artifact resolution they are taken into account.
Which don't let you enforce successful artifact selection.
Which is sad sometimes, yes.
it does nothing but make an empty variant
Which is not nothing, so yes it does something that your plugin needs to operate properly on the build and thus is imho ok to be enforced, especially if your settings plugin can simply enforce it, so the consumer only needs to apply the settings plugin.
It's silly, having an API flexible enough to resolve those two axes separately would avoid the issue entirely
Well, open a feature request ticket if there is none yet. 🙂
Actually, you can thumbs-up mine 😄
See last comment
Point 1 is what you are after
I also want artifact views on artifact views: github.com/gradle/gradle/issues/33431 🙂
l
Isn't that just another view on the same configuration? I suppose it's different in the case where the first view has variant reselection and the second doesn't though
v
Exactly, first to do variant reselection, second to do artifact transformation on an attribute that was needed with a different value for the reselection