Gradle/Groovy refer to "file-wide/global" variable from inside block - gradle

In my build file I have the following line:
version = '1.1.2'
I want to make an executable "fat jar" using Shadow Jar (see my answer here) and then copy this to another directory (see answer here). But I want to incorporate the project's version number into the name of the jar file so as not to overwrite the existing version.
The Shadow Plugin User Guide explains how to set the name:
shadowJar {
baseName = 'shadow'
classifier = null
version = "7.7.7"
}
... but how might I set the variable version here to use the outer (file-wide/global...) variable version?

In a gradle script, there's a Project instance in scope which everything delegates to. When you say version = '1.1.2' it's actually invoking
getProject().setVersion('1.1.2')
In your shadowJar closure there's a version higher up in the scope which is hiding the project version. So you can do
shadowJar {
version = project.version
...
}

Related

accessing fields from non-root project in gradle

this seems like it should be very simple, but I'm stuck! I have a gradle task that zips some files and creates an archive. I want to suffix the name of the archive with the version string from the project I'm in (this is a subproject in a multi-project build)
there's another task in this same build.gradle file that accesses this version field, that I want to access too. it looks like this:
task releasePublishAuto(dependsOn: [tasks.cppApiVersion, rootProject.tasks.releasePublish]) {
doLast {
println("############################################################")
println("# PUBLISHED CPP API WITH VERSION: $version")
println("############################################################")
}
}
you can see it accessing the version variable and printing it using $version. it prints something like # PUBLISHED CPP API WITH VERSION: 1.256.4-SNAPSHOT
now, my task is a zipping task, so it's a bit different:
task zipGeneratedCppClientApi(type: Zip, group: "code generator", dependsOn: [tasks.cppApiVersion, "generateCormorantCPP"]) {
from(fileTree(dir: "$buildDir/generated/cormorant_cpp", include: "**/*"))
archiveFileName = "$buildDir/distributions/generated-cpp-api-$version"
}
I would expect this to create a zipfile named generated-cpp-api-1.256.4-SNAPSHOT but instead i get one named generated-cpp-api-null. As far as I can tell this is because in the context of my zipping task, version refers to the version of the zipping library (or somesuch), not the version of the current project. I've tried instead accessing rootproject.version but that's also null - this isn't the root project but a subproject thereof!
How can I access the version field in this non-root project in gradle?
to clarify: if I remove type:zip from my task, version points to the correct value, but without type:zip it doesnt create a zipfile and so isnt very helpful.
In the context of a Zip task, the version property refers to the AbstractArchiveTask.version property, as you have somehow guessed, and not to the current project version property. As you can see, this version property has been deprecated on AbstractArchiveTask class, maybe to avoid such confusion.
To use project version instead, simply use ${project.version} as in following example.
in your subproject build script:
version="1.0.0"
tasks.register('packageDistribution', Zip) {
println("version from AbstractArchiveTask : $version") // => here, version will be null
println("version from project: ${project.version}") // => here, version will be "1.0.0" as expected
archiveFileName = "my-distribution-${project.version}.zip" // => my-distribution-1.0.0.zip as expected
destinationDirectory = layout.buildDirectory.dir('dist')
from layout.projectDirectory.dir("src/dist")
}

WIthin nebula/gradle, how can I inject the version being released into the jar being published?

We have a tool that runs from the command line. One of the commands is -version.
Before we converted to the nebula release plugin, the version was in the gradle.properties file, and as part of the build we copied it from there to a src/main/resources/version.txt file, that was later read by the tool to output the version.
But now the version is never in a file that's checked into git. Instead, it is only known during the nebula release process.
We want to obtain that version during the nebula release process and inject it into the jar that nebula is about to publish. For example, it could be added to the manifest.
We've tried to figure out how to do this, but don't see any examples online, and nothing about it in the documentation.
Simply create a task that caches the version that is dynamically inferred by Nebula.
Since you originally copied/created src/main/resources/version.txt, we'll use that that model our task.
Assuming a simple/standard Java project, using the Kotlin DSL:
val cacheNebulaVersion by tasks.registering {
mustRunAfter(tasks.named("release"))
doLast {
val sourceSets = project.extensions.getByName("sourceSets") as SourceSetContainer
sourceSets.getByName(SourceSet.MAIN_SOURCE_SET_NAME).output.resourcesDir?.let {
// If there are not existing resources in your project then you must create
// the resources dir otherwise a FileNotFoundException will be thrown.
if (!it.exists()) {
it.mkdirs()
}
File(it, "version.txt").printWriter().use { out ->
out.println(project.version)
}
}
}
}
When I invoke ./gradlew clean build snapshot cacheNebulaVersion, the version produced by Nebula is cached/created at src/main/resources/version.txt in the build output. The task above does not bundle it with the jar.
Hopefully that gives you an idea what to do.

Gradle equivalent for maven properties

How can I add properties in Gradle which are similar to Maven's properties?
The use case is this: I want to have a file which declares all versions for repo dependencies so they are unified in a single place for a multi module project
compile group: 'javax.servlet.jsp.jstl', name: 'jstl', version: '1.2'
In Maven you can have properties like this:
<properties>
<jstlVersion>1.2</jstlVersion>
</properties>
Is it ok to use Gradle's external properties? Or just add them to the gradle.properties file?
Project properties defined in the root build file are available to subprojects. So if you have this in your root build.gradle file:
ext.commonsLangVersion = "2.4"
then you can use that in the dependencies {} block of a subproject like so:
dependencies {
implementation "commons-lang:commons-lang:${commonsLangVersion}"
}
You can also define such properties in the root gradle.properties file instead of the root build file. You use them in the same way.
If you really feel the need to put the versions in a separate file, you can do so. Simply add the following line to the root build file:
apply from: "dependencies.gradle"
Within the dependencies.gradle file, you can define the extra project properties as if they were in the root build file directly:
ext.commonsLangVersion = "2.4"
Note Normally, the values set in the build script take precedence over the values in gradle.properties. But if you set a value in the root build script as above, then any matching value in gradle.properties will override it in subprojects.
This behaviour is somewhat confusing and unique. For behaviour that is consistent with Gradle single-project builds you would need to use the following in the root build script:
allprojects {
apply from: "dependencies.gradle"
}
As a general rule of thumb, any given property should be declared/defined in either the build script or gradle.properties. If users want to override a particular property value, they can do so in $USER_HOME/.gradle/gradle.properties.
[EDIT I have updated the above note to clarify the actual behaviour]
One final thing: Gradle also allows you to control the versions of transitive dependencies via dependency constraints. You can also import Maven BOMs if you're using Gradle 4.6 or newer.
Found this as a possible solution, though I don't really like that uses relative path to the properties file.
Point 7 from here:
https://proandroiddev.com/make-your-build-gradle-great-again-c84cc172a654#8029

Gradle - auto update dependency version

I have Jenkins CI pipeline which releases applications. This process works in a way that person triggers release job for application. This job checks all project dependencies via gradle dependencies command. For all dependencies that are snapshot release jobs are triggered automatically.
Release job simply upgrade lib/application version and deploys it in artifactory.
How can I automaticaly upgrade SNAPSHOT dependency version to release version in gradle?
My build.gradle file looks like this:
Properties versions = new Properties()
versions.load(new FileInputStream(rootProject.projectDir.path + "/version.properties"))
dependencies {
compile("projectA:${versions.projectAVersion}")
compile("projectB:${versions.projectBVersion}")
}
and version.properties file
projectAVersion=1.1.0-SNAPSHOT
projectBVersion=1.1.0-SNAPSHOT
In fact I am looking something similar to maven versions plugin.
Is it possible to automatically upgrade version numer inside build.gradle? How?
And harder version - is it to possible to upgrade version number when version is in external version.properties file?
EDIT
In fact I just need Maven versions-plugin (versions:use-releases and versions:use-next-releases) functionality in Gradle.
I am not that clear with your question. What I understood is that, you need to dynamically update the version value after each build.
What you can do is, get the properties value. Remove -SNAPSHOT. Update 1.1.0 with increment after each build. Like 1.1.1, 1.1.2 etc.
This can be done by
task testing {
Properties props = new Properties()
//getting and loading the property file
//Give proper path to file
File propsFile = new File('version.properties')
props.load(propsFile.newDataInputStream())
//Now strip of -SNAPSHOT and get the last digit and increment it by 1
Integer rand = props.getProperty('lastDigit').toInteger()+1
String variable=rand.toString()
//Append -SNAPSHOT with 'variable and set the property
props.setProperty('version',variable)
props.store(propsFile.newWriter(), null)
}
This will work, if my understading of your problem is correct.

get gradle to ignore version number in jar name

I have a project that has to build about 10 different dummy jars for unit testing. I have a gradle project setup like this
project(':CodeTools_dummydriver-true') {
ext.dummyDriver = true
archivesBaseName = "dummydriver-true"
}
But the problem is the jarfile is still named dummydriver-true-0.0.1.jar. Is there any way I can tell gradle to ignore the standard pattern and please name the output file what I want it to be named? Meaning, without the version number?
The Java plugin defines the jar task to follow the following template for archiveName:
${baseName}-${appendix}-${version}-${classifier}.${extension}
I don't think there's a way to apply a new "naming template", but what you can do is to explicitly set your jar task's archive name, like this. (Also, isn't it a good idea to use the dummyDriver property directly, instead of hardcoding "true" into the archive name?)
archivesBaseName = "dummydriver"
jar.archiveName = "${jar.baseName}-${dummyDriver}.${jar.extension}"
Alternately, set the version property to null or an empty string, like suggested in Circadian's answer, but if you ever want to use the version property for anything, you don't want to destroy it.
For newer gradle you should use:
build.gradle.kts:
tasks.jar {
archiveFileName.set("${project.name}-new-name.jar")
}
build.gradle:
jar.archiveFileName = "new-name.jar"
Because archiveName is deprecated. (You have to specify .jar as well).
Adding a version property and setting its value to an empty string worked for me.
Here is an example:
project(':CodeTools_dummydriver-true') {
ext.dummyDriver = true
archivesBaseName = "dummydriver-true"
version= ""
}
Hope that helps.

Resources