I wish to access the build information from inside my java project which uses gradle to build the project. The information I need to access is the build number generated by teamcity, build vcs number etc. These are easily accessed by maven and using the maven-replacer-plugin these can be replaced in a properties file. Firstly, is there an alternative in gradle to achieve the same? And then, how to do it? :)

I tried the approach shared here, but I always get null as the build number.

In maven I placed a properties file (project.properties) in the project to hold key value pairs with keys being those project information like

project.groupId, project.artifactId, project.version, maven.build.timestamp

I wish to access the same build information using gradle. . The pom would look like below:

                    <!-- Write project version number to file -->
                <plugin>
                    <groupId>com.google.code.maven-replacer-plugin</groupId>
                    <artifactId>maven-replacer-plugin</artifactId>
                    <version>1.3.8</version>
                    <executions>
                        <execution>
                            <phase>prepare-package</phase>
                            <goals>
                                <goal>replace</goal>
                            </goals>
                        </execution>
                    </executions>
                    <configuration>
                        <includes>
                            <!-- replace the token in this file -->
                            <include>target/classes/project.properties</include>
                        </includes>
                        <replacements>
                            <replacement>
                                <token>PROJECT_GROUP</token>
                                <value>${project.groupId}</value>
                            </replacement>
                            <replacement>
                                <token>PROJECT_ARTIFACT</token>
                                <value>${project.artifactId}</value>
                            </replacement>
                            <replacement>
                                <token>PROJECT_VERSION</token>
                                <value>${project.version}</value>
                            </replacement>
                            <replacement>
                                <token>PROJECT_BUILD_DATE</token>
                                <value>${maven.build.timestamp}</value>
                            </replacement>
                            <replacement>
                                <token>BUILD_NUMBER</token>
                                <value>${build.number}</value>
                            </replacement>
                        </replacements>
                    </configuration>
                </plugin>

What the maven replacer plugin does is replace the values in the properties object, that can be used in the java application.

I need to access the same properties using gradle.

Team City configuration in the pom is below:

<ciManagement>
    <system>Team City</system>
    <url>http://teamcity.mycompany.com/teamcity/project.html?projectId=bt007
    </url>
</ciManagement>

In the build.gradle file, I have a task defined as below:

task getProjectGroup << {
    ext.projectGroup = System.getProperty("project.group")
    println "Project Group: $projectGroup"
  }

I get the following output when executing this task:

:service:getProjectGroup
Project Group: null

BUILD SUCCESSFUL
有帮助吗?

解决方案

I do something very similar on my project - packaging up build info into a properties file that can be read from the classpath in your Java application.

Here's how I accomplish that in a Gradle script:

tasks.withType(Jar).all { Jar jar ->
    jar.doFirst {
        String jarType = jar.extension
        if(jar.classifier) jarType = jar.classifier
        String fileName = "project.properties"
        ant.propertyfile(file: "${jar.temporaryDir}/${fileName}") {
            entry(key: "PROJECT_GROUP", value: project.group)
            entry(key: "PROJECT_ARTIFACT", value: project.archivesBaseName)
            entry(key: "PROJECT_VERSION", value: project.version)
            entry(key: "PROJECT_BUILD_DATE", value: new Date())
            entry(key: "BUILD_NUMBER", value: hasProperty("teamcity") ? teamcity["build.number"] : "local")
        }
        String intoPath = "your/package/name/here/${project.name}/${jarType}"
        jar.from(jar.temporaryDir) {
            include fileName
            if(jar instanceof War) intoPath = "WEB-INF/classes/${intoPath}"
            into(intoPath)
        }
        println "\tCreated ${intoPath}/${fileName}"
    }
}

Here, I'm adding functionality to every Jar task (including War) that creates a properties file for that archive and includes it on the classpath under your/package/name/here/${project.name}/${jarType}/project.properties.

This is the beauty of Gradle. It makes customizations like this very simple - no plugin required.

Then, to read the properties in my app, I inject or hardcode the expected path to the file and load the properties like this:

public Properties lookupClassPathResource(String pathToResource) {
    Properties p = null;
    org.springframework.core.io.Resource r = new org.springframework.core.io.ClassPathResource(pathToResource);
    if(r.exists()) {
        try {
            p = org.springframework.core.io.support.PropertiesLoaderUtils.loadProperties(r);
        } catch (IOException e) {
            //log or wrap/rethrow exception
        }
    }
    return p;
}

And fun times are had by all!

EDIT: Apparently the question/answer linked in the OP (about accessing build.number) is a little out-of-date. Instead of doing System.getProperty("build.number"), you can use the teamcity properties that TeamCity implicitly adds to your project via a Gradle init script. The code above has been modified to reflect this. Also see this question for other examples.

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top