How do you run a terminal command in a Gradle task? - maven

I have the following task:
task installMavenLocal(type: Upload) {
description "Installs the artifacts to the local Maven repository."
configuration = configurations['archives']
repositories {
mavenDeployer {
repository url: repositories.mavenLocal().url
}
}
}
When I run my Gradle command I do the following gradle installMavenLocal -x:test:packageRelease, is there a way I can add that command to my above task so that developers don't need to add the -x:test:packageRelease and it just runs when I do the task?

You could use :
installMavenLocal.dependsOn.remove(tasks.getByPath(":test:packageRelease"))

Related

Get Gradle classpath from command line

With Maven, I can print the build classpath with this command:
mvn dependency:build-classpath
Is there a similar command I can use with Gradle from the command line, preferably without having to modify any of the build scripts?
You can list all the dependencies in a configuration from CLI:
gradle dependencies --configuration=runtimeOnly
Or you can do that via a task:
task classPath {
doFirst {
configurations.runtimeOnly.each { println it }
// This should probably work as well:
// sourceSets.main.runtimeClasspath.each { println it}
}
}

Gradle unable to resolve dynamic version of plugin from mavenLocal, how to get latest version?

I have created a Gradle plugin that creates some extra tasks and am publishing the plugin to MavenLocal with version 0.2.1. I can see the created jar in ~/.m2.
In another Gradle project, I am trying to pull in that plugin within the buildscript section of build.gradle, like this:
buildscript {
repositories {
mavenLocal()
}
dependencies {
classpath 'com.example:myplugin:0.2.+'
}
}
Running gradle tasks (or any other task, for that matter) causes Gradle to fail with the message:
> Plugin with id 'com.example.myplugin' not found.
However, if I change the version from 0.2.+ to 0.2.1 then it works. How do I get the latest version of the plugin into my project?
I just put what I did in here, and hope it helps you.
For example, I install the gradle-tomcat-plugin locally (2.4.1 and 2.4.2).
$ git checkout v2.4.2
$ ./gradlew publishToMavenLocal
$ git checkout v2.4.1
$ ./gradlew publishToMavenLocal
$ ls /Users/ruichen/.m2/repository/com/bmuschko/gradle-tomcat-plugin
2.4.1 maven-metadata-local.xml
2.4.2
And I added a separate task (showClasspath) to build.gradle to show me what is the version got applied:
task showClasspath {
doLast {
buildscript.configurations.classpath.each { println it.name }
}
}
The buildscript block is also pretty much like yours:
buildscript {
repositories {
mavenLocal()
}
dependencies {
classpath "com.bmuschko:gradle-tomcat-plugin:2.4.+"
}
}
The output is expected:
$ ./gradlew showClasspath
> Task :showClasspath
gradle-tomcat-plugin-2.4.2.jar

Multiple artifacts issue with deploying zip to nexus

My program outputs a zip and I want to deploy this zip to the nexus repository. I am using gradle as build system.
Fragment of my configuration:
class DestinationFileTask extends DefaultTask {
File destFile;
}
task generate(type: DestinationFileTask) {
destFile = file('output/file.zip')
}
artifacts {
output generate.destFile
}
uploadArchives {
repositories {
mavenDeployer {
repository(url: "url")
pom.version = "1.01-SNAPSHOT"
pom.artifactId = "ID"
pom.groupId = "com.test.test"
}
}
}
When I am executing gradle uploadArchives I am receiving this error:
> Could not publish configuration 'archives'
> A POM cannot have multiple artifacts with the same type and classifier. Already have MavenArtifact ID:zip:zip:null, trying to add MavenArtifact ID:zip:zip:null.
Even when I try to do this for the first time.
I ran into the same issue while working on Gradle upgrade:
FAILURE: Build failed with an exception.
* What went wrong:
Execution failed for task ':registry:uploadArchives'.
> Could not publish configuration 'archives'
> A POM cannot have multiple artifacts with the same type and classifier. Already have MavenArtifact registry:zip:zip:null, trying to add MavenArtifact registry:zip:zip:null.
Gradle upgrade it self has nothing to do with the error its more related to the plugins you are using.
The error is really misleading and there is not much info on Google about it as well.
But it turns out that the cause of this error is Maven trying to upload artifact on top of the other one.
So first of all check what packaging tasks you are executing, in my case:
task ':registry:bootDistTar',
task ':registry:bootDistZip',
...
task ':registry:distTar',
task ':registry:distZip',
The workaround to fix it is to change the classifier (in my case for spring boot app):
bootDistTar {
classifier = 'bootTar'
}
bootDistZip {
classifier = 'bootZip'
}
Hope this will help for someone else as it was quite hard to figure out.
Github issue where I found the workaround.

How to use gradle Artifactory plugin in gradle subproject

I have a multi-project gradle build wherein one of the subprojects is applying the Artifactory plugin (version 4.2.0), and configuring the contextUrl and resolve repoKey.
It sets up a simple configuration and dependency entry, and then has a copy task to retrieve the dependency as a zip file and extract it into a directory.
However, when the copy task runs, I get the error below. What am I doing wrong? Is this a problem with the Artifactory plugin, or gradle, or...?
The problem does not appear to be related to whether or not this is a subproject. I get the same error if I remove the multiproject configuration and run the task from the subproject directory.
FAILURE: Build failed with an exception.
* Where:
Build file 'C:\Users\hoobajoob\project\subproject\package.gradle' line: 36
* What went wrong:
A problem occurred evaluating project ':subproject'.
> Could not resolve all dependencies for configuration ':subproject:runtimeDep'.
> Cannot resolve external dependency company.com:artifact-id:1.0.0 because no repositories are defined.
Here are the contents of subproject/package.gradle (Artifactory url/user/password properties are in a gradle.properties file for the subproject):
plugins {
id "com.jfrog.artifactory" version "4.2.0"
}
artifactory {
contextUrl = "${artifactory_contextUrl}"
resolve {
repository {
username = "${artifactory_user}"
password = "${artifactory_password}"
repoKey = 'some-repo'
}
}
}
configurations {
runtimeDep
}
dependencies {
runtimeDep 'company.com:artifact-id:1.0.0#zip'
}
ext.destination = null
task getDependencies(type: Copy) {
from zipTree { configurations.runtimeDep.singleFile }
into ".artifacts/runtime"
}
The root project build script is empty except for the wrapper task. Below is the settings.gradle file:
include 'subproject'
rootProject.children.each { project -> project.buildFileName = "package.gradle" }
While the task setup in my question is different, this appears to be the same symptom as described in this other SO question.
The problem seems to be related to the fact that the Artifactory plugin will not perform dependency resolution until gradle's execution phase. I had assumed that defining the argument to the zipTree step in the getDependencies task with a closure would have the effect of deferring the dependency resolution until that phase.
But, for this to be deferred by the copy task, I need to define the from configuration of the getDependencies task as a closure, and include the zipTree operation in that closure.
It's the difference between:
from zipTree { configurations.runtimeDep.singleFile } // doesn't work
...and
from { zipTree( configurations.runtimeDep.singleFile ) } // works
Making this change gets the resolve working (with no required maven repositories block).
Another solution is to drop the Artifactory configuration altogether (which I can do in this case because I do not need to utilize anything unique to Artifactory) and use the traditional gradle repositories block, as described in the other SO question and by crazyjavahacking. Doing this makes the build script shorter, and I can leave the zipTree step configured as it was originally written:
repositories {
maven {
url "${artifactory_contextUrl}/repo-key"
}
}
configurations {
runtimeDep
}
dependencies {
runtimeDep 'company.com:artifact-id:1.0.0#zip'
}
ext.destination = null
task getDependencies(type: Copy) {
from zipTree { configurations.runtimeDep.singleFile }
into ".artifacts/runtime"
}
As the Gradle print to the console:
You did not define repositories{} block and so it does not know how to download declared dependency.

How to specify module name when publishing to Artifactory from Jenkins

I'm using the gradle artifactory publish plugin documented here: http://www.jfrog.com/confluence/display/RTF/Gradle+1.6+Publishing+Artifactory+Plugin
I'm using the standard config exactly as laid out in the documentation.
When I run the gradle publishArtifactory task from the command line I get output like this. I.e. It deploys to my correct module name.
Deploying artifact: http://<my server>/artifactory/libs-snapshot-local/<my actual module name>/web/0.1-SNAPSHOT/web-0.1-SNAPSHOT.war
When I configure Jenkins to run the gradle publishArtifactory task using the same gradle build file I get output like this. I.e. It uses the Jenkins build for the module name.
Deploying artifact: http://artifactory01.bcinfra.net:8081/artifactory/libs-snapshot-local/<the name of the jenkins build>/web/0.1-SNAPSHOT/web-0.1-SNAPSHOT.war
Any ideas on how to prevent the artifactory plugin from using the Jenkins build name for the module name?
The module name used for uploading is derived from the gradle project name. The default value for a gradle project name is taken from the project folder name. I suspect that on your jenkins job you check out your code into a folder named like your build job. That's why per default this folder name is used as project name.
The cleanest solution is to explicitly set your project name in gradle.
Therefore you need a settings.gradle file in your project root folder that contains the project name:
rootProject.name = "web"
You can also let Gradle single-handedly do the publishing to Artifactory, without the need for the Artifactory plugin in Jenkins.
This way, you can set the names of the artifacts using artifactId "your artifact name" without changing the project's name as suggested by Rene Groeschke.
Here's my publish.gradle that demonstrates this:
buildscript {
repositories {
jcenter()
}
dependencies {
classpath "org.jfrog.buildinfo:build-info-extractor-gradle:3.0.1"
}
}
// Because this is a helper script that's sourced in from a build.gradle, we can't use the ID of external plugins
// We either use the full class name of the plugin without quotes or an init script: http://www.gradle.org/docs/current/userguide/init_scripts.html
apply plugin: org.jfrog.gradle.plugin.artifactory.ArtifactoryPublicationsPlugin
// Pack the sources into a jar
task sourceJar(type: Jar) {
from sourceSets.main.allSource; classifier = "sources"
}
// Pack the Javadoc into a jar
task javadocJar(type: Jar) {
from javadoc.outputs.files; classifier = "javadoc"
}
apply plugin: "maven-publish"
publishing {
publications {
mavenJava(MavenPublication){
from components.java
// Set the base name of the artifacts
artifactId "your artifact name"
artifact jar
artifact sourceJar
artifact javadocJar
}
}
}
artifactory {
contextUrl = "http://localhost:8081/artifactory"
publish {
// Publish these artifacts
defaults{ publications ("mavenJava") }
repository {
repoKey = "libs-release-local"
// Provide credentials like this:
//-Partifactory.publish.password=yourPassword
//-Partifactory.publish.username=yourUsername
}
}
resolve {
repository {
repoKey = "libs-release"
}
}
}
You can use this script in your build.gradle via apply from: "path/to/publish.gradle" and call it like this:
./gradlew artifactoryPublish -Partifactory.publish.username="yourUsername" -Partifactory.publish.password="yourPassword"

Resources