17

I have a gradle plugin that uses the project.version variable.

How ever, the version in the plugin does not update when I change the version in the build.gradle file.

To illustrate:

plugin

// my-plugin
void apply(Project project) {
  project.tasks.create(name: 'printVersionFromPlugin') {
    println project.version
  }
}

build.gradle

version '1.0.1' // used to be 1.0.0

task printVersion {
  println project.version
}

apply plugin: 'my-plugin'

Result

> gradle printVersion
1.0.1
> gradle printVersionFromPlugin
1.0.0
Theodor
  • 5,536
  • 15
  • 41
  • 55

2 Answers2

59

You can use gradle properties to extract project version without adding a dedicated task to the build.gradle file.

For example:

gradle properties -q | awk '/^version:/ {print $2}'
Manfred
  • 2,269
  • 1
  • 5
  • 14
uris
  • 5,993
  • 3
  • 25
  • 24
  • 16
    Better `./gradlew properties --no-daemon --console=plain -q | grep "^version:" | awk '{printf $2}'` in case there's multiple versions. Also you don't need a running daemon for that. – vdimitrov Feb 07 '19 at 03:10
  • 4
    I prefer this solution because it doesn't require changing the build file, which I don't necessarily own. – Ken Williams Feb 22 '19 at 15:47
  • 2
    This is the WRONG solution ever to this problem: in Gradle, the version is an object, not a string. The resulting string containing the version is simply the result of `toString()` on the Version object assigned to to ` project.version`. Using things like grep/awk and so on to parse a build.gradle file is ever the wrong solution. It's like parsing an XML using grep. See https://mrhaki.blogspot.com/2012/09/gradle-goodness-using-objects-for.html – Vinz486 Jul 22 '20 at 08:29
  • For those who goes with this solution, don't forget to add a caret in the beginning of grep. You might have other properties ending with "version:" ( grep "^version:" ). – Reginaldo Santos Nov 27 '20 at 15:14
  • 1
    @Vinz486 — If all you're doing is verifying the version manually to ensure it looks right, a quick hacky solution that nonetheless gets the right answer is fine, and arguably more ideal than a bullet-proof solution that uses the API correctly but requires changes/configuration to the source. So I'd argue that depending on the context, it's not necessarily "WRONG"; same with your example of parsing the `build.gradle` with grep/awk and so on or XML using grep. – M. Justin Dec 10 '20 at 23:10
  • yes, the version is an object, but if I set that version to a String object, then it is particularly fine. Also, the solution does use the api. It is clearly asking gradle what it thinks the version is and the reply is defines to be a key value pair with a colon separator, which is what grep/awk were built for. Obviously, this solution does not work for you if you set your version to a complex object. – Laurent Picquet Feb 06 '21 at 08:51
22

Both the build script and the plugin make the same mistake. They print the version as part of configuring the task, rather than giving the task a behavior (task action). If the plugin is applied before the version is set in the build script (which is normally the case), it will print the previous value of the version property (perhaps one is set in gradle.properties).

Correct task declaration:

task printVersion {
    // any code that goes here is part of configuring the task
    // this code will always get run, even if the task is not executed
    doLast { // add a task action
        // any code that goes here is part of executing the task
        // this code will only get run if and when the task gets executed
        println project.version
    }
}

Same for the plugin's task.

Peter Niederwieser
  • 121,412
  • 21
  • 324
  • 259
  • Cool! I will try this first thing come monday! :) – Theodor Jul 25 '14 at 18:53
  • To get just the version printed and not other gradle stuff use: `./gradlew -q printVersion`. And preferred notation is `tasks.register('printVersion') {` instead of `task printVersion {`. – user1053510 Apr 14 '23 at 07:23