Grails 3 - How to publish to Artifactory - gradle

I have several Grails 3 projects. Most are plugins and one is the main app that depends on the plugins.
Can someone who has successfully published a Grails 3 project to an Artifactory repo tell me how you did it? What gradle plugin do you use and what do you need to add to your build.gradle to make it work?
Regards,
Rob

I blogged the answer:
http://rvanderwerf.blogspot.com/2015/07/how-to-publish-grails-3-plugin.html
Basically you need to strip out anything in the POM with no version on it as Grails/Boot managed those deps.

I just started working with grails 3, specifically version 3.2.8.
I found that placing the following entry at the end of build.gradle works where artifactory_user, artifactory_password, artifactory_snapshotUrl, and artifactory_releaseUrl are defined in gradle.properties.
publishing {
repositories {
maven {
credentials {
username artifactory_user
password artifactory_password
}
if (version.endsWith('SNAPSHOT')) {
url artifactory_snapshotUrl
} else {
url artifactory_releaseUrl
}
}
}
}
File gradle.properties reads:
grailsVersion=3.2.8
grailsWrapperVersion=1.0.0
gormVersion=6.0.9.RELEASE
gradleWrapperVersion=3.4.1
app_version=0.0.1-SNAPSHOT
artifactory_user=admin
artifactory_password=password
artifactory_contextUrl=http://myserver.myorg.org:8081/artifactory
artifactory_snapshotUrl=http://myserver.myorg.org:8081/artifactory/libs-snapshot-local
artifactory_releaseUrl=http://myserver.myorg.org:8081/artifactory/libs-release-local

Related

Gradle Version Catalog (Published): How to dynamically set up repository

I'm not that experienced with Gradle and are currently running into problems when trying to use the new version catalog feature.
Goal:
Using a Gradle 7.4.2 version catalog, managed in a standalone GIT repository and published to private JFrog artifactory, in a second project.
Every project member's artifactory credentials are already available in $HOME/.gradle/gradle.properties (auto-generated by JFrog) and are supposed to be re-used.
Issue:
according to the current Gradle documentation, a published version catalog is supposed to be defined in settings.gradle(.kts) within any project that wants to use the catalog;
inserting that piece of code results in an error because Gradle has no repository definition available for artifact look-up
therefore, adding a repository definition:
// my settings.gradle.kts
rootProject.name = "catalog-consumer"
dependencyResolutionManagement {
val catalogVersion = "0.1.0"
val artifactoryUri = "..."
val catalogGAV = "..."
repositories{
maven {
url = uri("$artifactoryUri")
credentials {
// TODO: how to access user's local gradle.properties for credentials?
username = "$artifactory_user" // key as generated by JFrog
password = "$artifactory_password" // key as generated by JFrog
}
}
}
versionCatalogs {
create("libs") {
from("$catalogGAV")
}
}
}
now, facing the problem that the user's gradle.properties does not seem to be loaded, yet - but hardcoding credentials is not viable :)
Question:
Is the only option to manually check for and load the user's gradle.properties file?
Originally, when reading the documentation, I assumed that the settings file would probably try to look up existing repository definitions from the project's build.gradle.kts, but that wasn't the case either. If I understand it correctly, the settings file is evaluated before everything else, isn't it?
Manually loading the user's config just seems odd to me, therefore, I wanted to ask whether or not I'm missing a mechanism or lifecycle hook that would take care of this. Also possible that I use the version catalog feature incorrectly :D
Any hints very much appreciated!
See the docs here: https://docs.gradle.org/current/userguide/declaring_repositories.html#sec:handling_credentials
Named repository credentials
If you named the repository and add credentials(PasswordCredentials::class)...
// ./settings.gradle.kts
dependencyResolutionManagement {
repositories {
maven {
name = "mySecureRepository"
credentials(PasswordCredentials::class)
// url = uri(<<some repository url>>)
}
}
}
then Gradle will automatically fetch the username/pass from the first found definition:
Using a command line argument
./gradlew build -PmySecureRepositoryUsername=my-username
environment variables prefixed with ORG_GRADLE_PROJECT_ (this is useful for CI/CD)
ORG_GRADLE_PROJECT_mySecureRepositoryUsername=my-username
ORG_GRADLE_PROJECT_mySecureRepositoryPassword=my-password
$GRADLE_USER_HOME/gradle.properties
mySecureRepositoryUsername=my-username
mySecureRepositoryPassword=my-password
gradle.properties in the project root - obviously don't put credentials in your project!
gradle.properties in the Gradle installation directory
Manual providers
If you need to manually set the property names, then you can define your own providers.
// ./settings.gradle.kts
val artifactoryUser = providers.gradleProperty("artifactory_user")
val artifactoryPassword = providers.gradleProperty("artifactory_password")
dependencyResolutionManagement {
repositories {
maven {
name = "mySecureRepository"
credentials {
username = artifactoryUser.get()
password = artifactoryPassword.get()
}
// url = uri(<<some repository url>>)
}
}
}
Again, then Gradle will fetch these properties from either
$GRADLE_USER_HOME/gradle.properties
artifactory_user=my-username
artifactory_password=my-password
or environment variables
ORG_GRADLE_PROJECT_artifactory_user=myUsername
ORG_GRADLE_PROJECT_artifactory_password=my-password

Naming deployed jar file with gradle publish?

We're looking at ditching artifactory and are intending to move to reposilite, because artifactory is just too big and maintenance-heavy for our small team.
However, when using gradle publish to deploy to reposilite, I am unable to get control of the name of the actual jar. The pushed jar is always named project-x.x.x-{build-number}.jar.
I would like to do it the way the artifactory plugin did it, which deployed a properly named snapshot jar (just project-x.x.x-SNAPSHOT.jar), letting subsequent snapshots of the same version overwrite each other, which is a more convenient arrangement for us for several reasons that I won't go into right now.
Long story short, is there any way I can tell gradle publish how to name the deployed jar exactly? Our usual setup currently looks like this:
configure<PublishingExtension> {
publications {
create<MavenPublication>("myproject") {
from(components["java"])
groupId = "our.company.myproject"
artifactId = "myproject"
artifact(sourceJar)
}
}
repositories {
maven {
credentials {
username = $mavenUser
password = $mavenPassword
}
url = uri("http://localhost:8080/snapshots") # while testing
authentication {
create<BasicAuthentication>("basic")
}
}
}
}
There isn't really a problem with that configuration. It works. All I want to do is control the exact name of the jar file being deployed in addition to what I'm doing here, and I can't find a way to do it. The jar that is put to the build/libs directory is named properly, it's just the publication throwing me a curve ball.

Missing checksum files when using Gradle maven-publish and signing plugins

I have a Java project that makes use of Gradle to build and package. My purpose is to create artifacts that are published to Maven Central.
As a first step, I configured my Gradle project as shown in the following example from the documentation:
https://docs.gradle.org/current/userguide/publishing_maven.html#publishing_maven:complete_example
When I run gradle publishToMavenLocal, I get the following files installed in my local repository:
maven-metadata-local.xml
my-library-1.0.2-SNAPSHOT.jar
my-library-1.0.2-SNAPSHOT.jar.asc
my-library-1.0.2-SNAPSHOT-javadoc.jar
my-library-1.0.2-SNAPSHOT-javadoc.jar.asc
my-library-1.0.2-SNAPSHOT.pom
my-library-1.0.2-SNAPSHOT.pom.asc
my-library-1.0.2-SNAPSHOT-sources.jar
my-library-1.0.2-SNAPSHOT-sources.jar.asc
The files are all OK. The only issue I have is that checksum files (md5 and sha1) are not generated. However, checksum files are a requirement to have artifacts deployed on Maven Central via OSS Sonatype.
How can I generate the missing checksum files? It seems the maven-publish or signing plugins do not have an option for this purpose? what is wrong?
The solution I found was to use shadow along with ant.checksum:
tasks.withType(Jar) { task ->
task.doLast {
ant.checksum algorithm: 'md5', file: it.archivePath
ant.checksum algorithm: 'sha1', file: it.archivePath
ant.checksum algorithm: 'sha-256', file: it.archivePath, fileext: '.sha256'
ant.checksum algorithm: 'sha-512', file: it.archivePath, fileext: '.sha512'
}
}
Invoking gradle publishShadowPublicationToMavenLocal will generate the signatures as needed, although won't publish them to ~/.m2.
At first I thought those signatures should have been automatic, so I opened https://github.com/johnrengelman/shadow/issues/718 to discuss.
I thought this was a bug in Gradle and I opened an issue, but as described here this actually mimics mvn install behavior. It sounds like Maven Local works a little different than a Maven Repository.
The proper way to test this locally is to use a file based repository. Since you're only using it to test (and not to actually share things with other projects) I think putting that into the build directory is best. Add the repositories section from below to the publishing block. Then when you ./gradlew publish it will publish to your build directory.
Kotlin
repositories {
maven {
// change URLs to point to your repos, e.g. http://my.org/repo
val releasesRepoUrl = uri(layout.buildDirectory.dir("repos/releases"))
val snapshotsRepoUrl = uri(layout.buildDirectory.dir("repos/snapshots"))
url = if (version.toString().endsWith("SNAPSHOT")) snapshotsRepoUrl else releasesRepoUrl
}
}
Groovy
repositories {
maven {
// change URLs to point to your repos, e.g. http://my.org/repo
def releasesRepoUrl = layout.buildDirectory.dir('repos/releases')
def snapshotsRepoUrl = layout.buildDirectory.dir('repos/snapshots')
url = version.endsWith('SNAPSHOT') ? snapshotsRepoUrl : releasesRepoUrl
}
}
These two samples are actually from the link you shared. It's possible they were added later or you (like me) thought that publishToMavenLocal should behave the same as publish (apart from where the files actually go).

Unable to resolve a plugin using the new plugin mechanism in Gradle

While trying to upgrade some of our scripts to Gradle 4.0.1 on of the plugins we are using is failing and I thought of fixing that plugin first. The plugin is a third party open source project.
So I have cloned the project and tried to compile it. However it fails with following message:
c:\source\gradle-xld-plugin>gradlew build
FAILURE: Build failed with an exception.
* Where:
Build file 'C:\source\gradle-xld-plugin\build.gradle' line: 2
* What went wrong:
Plugin [id: 'com.gradle.plugin-publish', version: '0.9.7'] was not found in
any of the following sources:
- Gradle Core Plugins (plugin is not in 'org.gradle' namespace)
- maven(https://artifactory/java-v) (Could not resolve plugin artifact 'com.gradle.plugin-publish:com.gradle.plugin-publish.gradle.plugin:0.9.7')
* Try:
Run with --stacktrace option to get the stack trace. Run with --info or --
debug option to get more log output.
BUILD FAILED in 0s
The build.gradle script for the plugin starts like this:
plugins {
id "com.gradle.plugin-publish" version "0.9.7"
id "com.github.hierynomus.license" version "0.11.0"
id 'nebula.nebula-release' version '4.0.1'
id "com.jfrog.bintray" version "1.7.3"
}
In addition to this the company policy dictates we have to go through an internal artifactory server, so following has been added to the settings.gradle file:
pluginManagement {
repositories {
maven {
url "https://artifactory/java-v"
}
}
}
The jar file exists at following location: https://artifactory/java-v/com/gradle/publish/plugin-publish-plugin/0.9.7/plugin-publish-plugin-0.9.7.jar
but when I look at the error message I am a little puzzled that it says that it cannot find com.gradle.plugin-publish:com.gradle.plugin-publish.gradle.plugin:0.9.7.
It seems to have suffixed the id with .gradle.plugin.
Does anyone know whether I am looking at the wrong location or how come it is suffixing the id with .gradle.plugin. And shouldn't it look at a location that has the GAV like this: com.gradle.plugin-publish:com.gradle.plugin-publish:0.9.7?
And does anyone know about how the resolution mechanism for the new plugin mechanism in Gradle works.
Thanks in advance
Edit
Thanks to Mateusz Chrzaszcz I was able to progress.
The only caveat I have with the solution is that it seems like a workaround rather than a solution. But it works!
In addition to his solution you had to resolve the plugins. I was able to hack my way to actually resolve the appropriate names.
In order to do so one has to do as follows:
In a webbrowser go for the plugin: id "com.github.hierynomus.license" version "0.11.0" go to following URL: https://plugins.gradle.org/api/gradle/4.0.1/plugin/use/com.github.hierynomus.license/0.11.0
The json returned contains the GAV needed in the useModule call. Use that
The following serves as an example:
resolutionStrategy {
eachPlugin {
if (requested.id.namespace == 'com.gradle' && requested.id.name == 'plugin-publish') {
useModule('com.gradle.publish:plugin-publish-plugin:0.9.7')
} else if(requested.id.namespace == 'com.github.hierynomus' && requested.id.name == 'license') {
useModule('nl.javadude.gradle.plugins:license-gradle-plugin:0.11.0')
}
}
}
Try to implement Plugin Resolution Rules.
According to gradle documentation:
Plugin resolution rules allow you to modify plugin requests made in plugins {} blocks, e.g. changing the requested version or explicitly specifying the implementation artifact coordinates.
To add resolution rules, use the resolutionStrategy {} inside the pluginManagement {} block
like that:
pluginManagement {
resolutionStrategy {
eachPlugin {
if (requested.id.namespace == 'com.gradle.plugin-publish') {
useModule('com.gradle.plugin-publish:0.9.7') //try a few combinations
}
}
}
repositories {
maven {
url 'https://artifactory/java-v'
}
}
}
Keep in mind this is incubating feature though.

Include folder in Gradle artifact

Im sure this is amazingly simple but its been a long day and the Gradle docs frustrate me at the best of times (I have looked).
I want to include a folder (libs) inside a predefinined artifact (bundleRelease).
This happens to be on android (aar build) and inside a maven-publish block like
...
releaseJar(MavenPublication) {
...
artifact bundleRelease
}
...
using gradle 2.3.
Thanks for any help here :)
EDIT: answered here Include /libs/ folder in aar
Depends on what you want for the syntax but if you want the jar files in the root of the aar
android {
...
sourceSets {
main {
resources.includes = [ '**/libs/*.jar' ]
}
}
If you want the entire folder included then I think this should be what you want
android {
...
sourceSets {
main {
resources.includes = [ 'pathTo/libs' ]
}
}
All that said you probably don't want to package the libs with the aar because if you publish to somewhere like jcenter or mavenCentral then the maven artifact when uploaded will create a pom file that will note its dependencies and gradle will transparently import them for your lib.

Resources