For <Nmcp>, I'm using the <lenient configuration a...
# community-support
m
For Nmcp, I'm using the lenient configuration aggregate trick to collect all subprojects that have publishing enabled. In order to make sure I do not collect any project that does not publish, I set
org.gradle.usage: nmcp
as an attribute both on the consumer and on the producer side. This has been serving me well until today where I bumped into an outgoingVariant that does not set
org.gradle.usage
and therefore get collected (because a missing attribute is compatible). What's the best way to fix this?
Should every plugin set
org.gradle.usage
?
👍 1
t
I think that's a non-option because it would require everyone to do something, which realistically will not happen
at what point does an error occur? can you check the artifact in a task action before trying to manipulate it?
v
I'd say the Usage is THE basic attribute that any outgoing variant should have set, yes. This variant that it disturbing you will probably also disturb similar cases elsewhere. Besides that, you indeed could programmatically check and filter for the variants that actually do have the attribute set, it's just a bit tedious to do.
I for example use that to segregate the dependencies into cross-platform dependencies and dependencies per platform
p
I also agree the Usage attribute should be set, and there should be a warning from Gradle if a consumable configuration does not contain that attribute.
m
Issue for warning/error on
org.gradle.usage
missing: https://github.com/gradle/gradle/issues/36124
at what point does an error occur? can you check the artifact in a task action before trying to manipulate it?
@tony this is all happening when creating the zip to upload to Maven Central. The zip contains some source files. I could filter them out in the task before uploading but that feels a bit fragile...
you indeed could programmatically check and filter for the variants that actually do have the attribute set, it's just a bit tedious to do
@Vampire do you have an example of how to do this by any chance?
v
I'll have to check. Not OSS, done in corporate project, but I will check how it was.
But probably easier if possible to just set the attribute on that variant? It is just about aggregating projects, so you should have will under your control?
m
I can do that in projects where I own the whole build but in the plugin, I'm a bit wary of changing the other plugins attributes...
v
Ah, right, forgot that you are authoring a plugin there
Basically this:
Copy code
.resolvedArtifacts.map {
    it.filter { artifactResult ->
        val variantAttributes = artifactResult.variant.attributes
        variantAttributes
            .keySet()
            .filter { it.name == OPERATING_SYSTEM_ATTRIBUTE.name }
            .also {
                if (it.size > 1) {
                    throw AssertionError("Multiple attributes with same name are not expected")
                }
            }
            .singleOrNull()
            ?.let { variantAttributes.getAttribute(it) }
            ?.let {
                when (it) {
                    is OperatingSystemFamily -> it.name
                    is String -> it
                    else -> null
                }
            } == os
    }.map { artifactResult ->
        artifactResult.file
    }
❤️ 1
🏆 1
the
when
is necessary, because the type can be both, depending on whether it was added on-the-fly in the current build or whether it comes from a GMM file
m
Thanks!
p
BTW the mentioned mainSourceElements is a standard configuration provided by gradle that should be fixed.
👍 1
v
Ah, wait, I think I confuse the attribute.
category
should be the one everyone sets I think. And within the category then attributes must be good and significant. For example the configurations for test results or jacoco results that are used for their aggregation also do not have usage set, but within category verification that is probably fine.
p
But why also not usage? I use it for all my custom attributes for another ecosystem 😅
v
Well, all the attributes have to be consistent in an ecosystem, then all is good. Why not also usage, I don't know, maybe because it does not always makes sense, like when having sources or test results or jacoco results. At least not with the usage values defined. 🤷‍♂️ That you can probably discuss in your issue, but if your plugin should probably work in the jvm ecosystem at least, I guess you should always use the category.
Defining (and even more maintaining over time) attributes and their values and how everything fits together is actually a quite challenging task.
t
I agree category should always be set. unfortunately gradle docs are or were silent on this. Or ar least that info is hard to find. I only know it thanks to many discussions with Gradle engineers. I have a library I publish for helping plugin authors create custom variants that ensures a category is always set. Really unclear why Gradle can't provide that out of the box.
m
Hot take but both
org.gradle.usage
and
org.gradle.category
are too loosely defined. I'd like an attribute that maps 1:1 with who's creating/consuming the variant.
t
DAGP sets the category to
dagp.internal
or something like that, so... yeah I agree haha