Slackbot
05/16/2023, 10:34 AMVampire
05/16/2023, 11:12 AMmavenLocal
if possible or at most with using a repository content filter, because mavenLocal
is broken by design.
Better use a composite build.
To get the "as close as possible to the experience as simply writing a build.gradle
file" write your convention plugins as precompiled script plugins as documented at https://docs.gradle.org/current/userguide/custom_plugins.html#sec:precompiled_pluginsndg
05/16/2023, 11:57 AMndg
05/16/2023, 12:10 PMndg
05/16/2023, 12:11 PMVampire
05/16/2023, 12:25 PMI've created the minimal sample repos/files above with the hope that someone might be able to suggest a few lines of code which demonstrates itThose repos are not accessible, actually.
a Github repo like this is exactly what I would have hoped for from the docshttps://github.com/jjohannes/idiomatic-gradle might be interesting for you, but it might also be way more complex than you actually need and want.
as it appears they require the "common" repo to be checked out locally already,Yes, that's correct.
which may be out-of-dateWell actually it is usally the other way around. By requiring to manually publish the dependency to some repository or local repository or
mavenLocal()
, you always have to go to that module, change something, publish it manually and then use the new version.
With a composite build you can just change something in common
and run the consumer build which will automatically build and use the dependency.
Both have their pros and cons liek always of course, but usually a composite build is much more convenient to work with, at least while developing changes.
I'm curious as to what you mean by "mavenLocal is broken by design" - wonder if that contributes to any of my problems so far.Here are some of the problems documented: https://docs.gradle.org/current/userguide/declaring_repositories.html#sec:case-for-maven-local
ndg
05/16/2023, 12:27 PMndg
05/16/2023, 12:28 PMndg
05/16/2023, 12:28 PMndg
05/16/2023, 12:29 PMndg
05/16/2023, 12:30 PMndg
05/16/2023, 12:47 PMndg
05/16/2023, 1:07 PMVampire
05/16/2023, 1:17 PMA prohibitive limitation of "precompiled script plugins", it seems - it forces you to put the dependency versions in the depending projectsNo, why should it? Believe me, precompiled script plugins is exactly what you want. And yes, it is more like a 2 minute effort. You basically apply the plugin for the DSL you want to use and configure the publishing using
maven-publish
.
Then you can write your convention plugins almost like normal build scripts.ndg
05/16/2023, 1:18 PMndg
05/16/2023, 1:20 PMInvalid plugin request [id: 'com.diffplug.spotless', version: '6.18.0']. Plugin requests from precompiled scripts must not include a version number. Please remove the version from the offending request and make sure the module containing the requested plugin 'com.diffplug.spotless' is an implementation dependency
I got it working by specifying the dependency in the main project referencing the buildSrc as a plugin - which would lead me to think the same would be needed in a multi-repo setup.Vampire
05/16/2023, 1:22 PMcommon/build.gradle(.kts)
ndg
05/16/2023, 1:25 PMbuildscript {
repositories {
maven {
url "<https://plugins.gradle.org/m2/>"
}
}
dependencies {
classpath "com.diffplug.spotless:spotless-plugin-gradle:6.18.0"
}
}
This is what I had in the main project, but buildscript
is not allowed in Groovy script plugins. I'm sure there's another way to express it (I've tried multiple)Vampire
05/16/2023, 1:25 PMmaven-publish
configuration to actually publish it. The actual implementation and usage is the same.ndg
05/16/2023, 1:25 PMVampire
05/16/2023, 1:25 PMThis is what I had in the main project, butWell, you maybe didn't read what I wrote two message ago 🙂is not allowed in Groovy script plugins. I'm sure there's another way to express it (I've tried multiple)buildscript
Vampire
05/16/2023, 1:26 PMVampire [15:22 Uhr]
That is one of the "*almost* like normal build scripts" points.
In the precompiled script plugin you use it without version.
You can define the version in the consuming project, but that's not the idiomatic way.
It is an implementation dependency of your convention plugin.
So you declare it as implementation dependency in the build script for your convention plugin, so incommon/build.gradle(.kts)
ndg
05/16/2023, 1:26 PMndg
05/16/2023, 1:26 PMVampire
05/16/2023, 1:27 PMbuildscript
block of the precompiled script plugin.
That is not even similar to what I said. 😉ndg
05/16/2023, 1:29 PMSo you declare it as implementation dependency in the build script for your convention pluginI'm sure I'm just stupid, but this reads to me like the same thing. Unwrapping the
buildscript
block also yields org.gradle.api.plugins.UnknownPluginException: Plugin with id 'com.diffplug.spotless' not found.
Vampire
05/16/2023, 1:30 PMbuildscript
block inside your convention plugin".
I even told you the exact file where you put and what you put in there to make sure you don't misunderstand like that. 😉ndg
05/16/2023, 1:32 PMndg
05/16/2023, 1:32 PMrepositories {
maven {
url "<https://plugins.gradle.org/m2/>"
}
}
dependencies {
classpath "com.diffplug.spotless:spotless-plugin-gradle:6.18.0"
}
``````ndg
05/16/2023, 1:34 PMVampire
05/16/2023, 1:34 PMVampire
05/16/2023, 1:34 PMis what seems to the same as propagating it to clients to me.Why? It is part of the convention plugin build. The consuming project will not need to specify the version anywhere.
ndg
05/16/2023, 1:35 PMVampire
05/16/2023, 1:39 PMclasspath
by implementation
, put that to the common/build.gradle(.kts)
build script, then use the plugin without version in your convention plugin, that's it.ndg
05/16/2023, 1:46 PM> Failed to apply plugin 'common'.
> org.gradle.api.plugins.UnknownPluginException: Plugin with id 'com.diffplug.spotless' not found.
Vampire
05/16/2023, 2:06 PMcommon/buildSrc
you have yet another standalone build that is built separately to then by applied in common/build.gradle
which is not what you actually want.
You want your common.gradle
in src/main/groovy
and apply groovy-gradle-plugin
in common/build.gradle
.
Then you can apply common
in your appX
builds.
Besides that common
is a bad name, custom convention plugins should always have some namespace (a dot in the name, or a package declaration in the precompiled script plugins). Namespaceless plugin IDs should be reserved for Gradle built-in plugins.ndg
05/16/2023, 2:14 PMcommon
was just quickly picked for the purposes of this PoC - not what I would keep.
So I've moved the apply of groovy-gradle-plugin
into the common/build.gradle
(well, /build.gradle
, being the repo root)
Are you saying to mv buildSrc/src/main/groovy/common.gradle src/main/groovy/common.gradle
essentially?
Doing that yields Plugin [id: 'common'] was not found in any of the following sources:
ndg
05/16/2023, 2:16 PMVampire
05/16/2023, 2:16 PMcommon
in common/build.gradle
(just using common/
to make sure I'm not talking about appX/build.gradle
).
You want to apply common
in appX/build.gradle
, not in common/build.gradle
.Vampire
05/16/2023, 2:17 PMcommon
the result of building common
. That would be a hen-and-egg situation.ndg
05/16/2023, 2:17 PMVampire
05/16/2023, 2:19 PMcommon
as a standalone version of buildSrc
, which actually is exactly the case.
So basically if you copy buildSrc
out, rename it to common
and add publishing configuration you are almost where you want to be.ndg
05/16/2023, 2:32 PMndg
05/16/2023, 2:33 PMgradlePlugin
of some sort in `common/build.gradle`; and perhaps something else in app1/build.gradle
ndg
05/16/2023, 2:39 PMVampire
05/16/2023, 2:39 PMcommon
is fine, you just did not specify the version of `common`to apply in app1
Vampire
05/16/2023, 2:40 PMVampire
05/16/2023, 2:40 PM0.1
ndg
05/16/2023, 2:42 PMpluginManagement {
repositories {
mavenLocal()
}
}
Except also including the gradle plugin repoVampire
05/16/2023, 2:43 PMVampire
05/16/2023, 2:43 PMgradlePluginPortal()
Vampire
05/16/2023, 2:43 PMndg
05/16/2023, 2:44 PMVampire
05/16/2023, 2:44 PMgradlePluginPortal()
is the default if you have nothing, but if you have anything you have to be explicitndg
05/16/2023, 2:44 PMndg
05/16/2023, 2:46 PMExecution failed for task ':tasks'.
> Could not create task ':spotlessJava'.
> Could not resolve all files for configuration ':spotless865456303'.
> Cannot resolve external dependency com.google.googlejavaformat:google-java-format:1.16.0 because no repositories are defined.
Required by:
project :
Vampire
05/16/2023, 2:46 PMVampire
05/16/2023, 2:48 PMThat most probably is because you have no repositories forCopy codeCannot resolve external dependency com.google.googlejavaformat:google-java-format:1.16.0 because no repositories are defined.
app1
.
So either add it there or to your convention plugin.ndg
05/16/2023, 2:48 PMBryanT
05/16/2023, 2:49 PMndg
05/16/2023, 2:49 PMndg
05/16/2023, 2:54 PMBryanT
05/16/2023, 2:55 PMndg
05/16/2023, 2:56 PMBryanT
05/16/2023, 2:57 PMndg
05/16/2023, 2:57 PMndg
05/16/2023, 2:58 PMndg
05/16/2023, 3:05 PMrootProject.name
1. Would you suggest changing rootProject.name
to `foo.common`; or another route without changing the rootProject.name
itself?
2. I used a group ID of com.example
for the artifact - should the plugin name therefore conventionally be com.example.common
?Vampire
05/16/2023, 3:10 PMrootProject.name
exactly here.
But yeah, if you put your plugin in group com.example
, having com.example.common
or com.example.build.common
or whatever surely sounds sensible.ndg
05/16/2023, 3:12 PMrootProject.name
, which is inferred by the name of the project directory (common
)Vampire
05/16/2023, 3:14 PMsettings.gradle(.kts)
and that should define the root project name to be independent from directory name.ndg
05/16/2023, 3:14 PMrootProject.name
in settings.gradle
(I don't think the value of rootProject.name
is best-practice expected to contain dots?), or rather: concatenate the groupId with rootProject.name
ndg
05/16/2023, 3:15 PMrootProject.name
to be com.example.common
then, if that sounds sensibleVampire
05/16/2023, 3:18 PMndg
05/16/2023, 3:18 PMndg
05/16/2023, 3:18 PM