Gradle:访问构建信息

4
我希望能够在使用Gradle构建项目的Java项目内部访问构建信息。我需要访问的信息是由TeamCity生成的构建编号、构建VCS编号等。这些信息可以很容易地通过Maven访问,并且使用Maven-Replacer-Plugin可以将其替换为属性文件中的内容。首先,Gradle中是否有实现类似功能的替代方法?其次,如何实现? :)
我尝试了此处分享的方法,但我始终得到null作为构建号。
在Maven中,我在项目中放置了一个属性文件(project.properties),以保存键值对,其中键是那些项目信息,例如:

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

我希望使用Gradle访问相同的构建信息。POM文件应如下所示:
                    <!-- 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>

Maven替换器插件的作用是替换属性对象中的值,这些值可以在Java应用程序中使用。

我需要使用Gradle访问相同的属性。

以下是POM中Team City的配置:

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

build.gradle文件中,我定义了如下任务:
task getProjectGroup << {
    ext.projectGroup = System.getProperty("project.group")
    println "Project Group: $projectGroup"
  }

执行此任务时,我获得了以下输出:
:service:getProjectGroup
Project Group: null

BUILD SUCCESSFUL

如果你得到了 null,那么你的 TeamCity 构建没有设置这个系统属性,你也无法从 Maven 中访问它。在属性文件中替换占位符是通过配置 processResources 任务来实现的(请参阅 Gradle Build Language Reference 中的 Copy)。 - Peter Niederwieser
我无法在上面的Maven POM中找到任何TeamCity属性。 - Peter Niederwieser
更新如上。同时添加了团队城市配置以使问题完整。 - Aspirant
除了 build.number 之外,你不能直接从 Gradle 中获取所有这些值吗?例如,project.groupproject.archivesBaseNameproject.version(以及构建日期的 new Date())都可以在 Gradle 脚本中直接访问。 - superEb
我获取了new Date()对象作为构建日期。除此之外都是空的。我已经更新了原问题中的Gradle任务。 - Aspirant
1个回答

1
我在我的项目中也做了类似的事情——将构建信息打包到一个属性文件中,可以从Java应用程序的类路径中读取。
以下是我在Gradle脚本中实现这一点的方法:
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}"
    }
}

在这里,我正在为每个Jar任务(包括War)添加功能,为该存档创建一个属性文件,并将其包含在类路径下your/package/name/here/${project.name}/${jarType}/project.properties
这就是Gradle的美妙之处。它使得像这样的自定义非常简单 - 不需要插件。
然后,为了读取应用程序中的属性,我注入或硬编码预期的文件路径,并像这样加载属性:
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;
}

大家都玩得很开心!

编辑:显然,OP中链接的问题/答案(有关访问build.number)已经有点过时了。您可以使用通过Gradle init脚本隐式添加到项目中的teamcity属性来代替执行System.getProperty("build.number")。上面的代码已被修改以反映此更改。还可以参见this question获取其他示例。


这是一个不错的方法。我会继续努力并保持联系。谢谢。 - Aspirant
好的,我们已经确定您需要在Gradle脚本中设置project.groupproject.version,就像在Maven POM中一样。build.number是由TeamCity定义的系统属性,因此只有在TeamCity代理运行Gradle脚本时才可用。这不起作用吗?看起来您几乎可以从上面复制粘贴我的代码,然后几乎就可以得到您想要的东西了。 - superEb
我使用与上述完全相同的代码。一旦通过TeamCity运行gradle脚本,该文件就会被正确创建。project.groupproject.archivesBaseName正常填充。但其余部分要么是“unspecified”,要么是“null”。 - Aspirant
1
1:对于build.number,不要使用System.getProperty,而是尝试使用project.teamcity["build.number"]。这个方法适用于您的构建步骤使用“Gradle”运行器(应用TeamCity定义的init脚本),但请注意它在本地构建中不可用 - 请参阅此答案以获取更多信息。2:project.version之所以为“未指定”,是因为您没有在Gradle脚本中定义它。您应该设置此值,就像在POM中设置项目version字符串一样。 - superEb
可能是因为JetBrains团队决定以一种不同的、更集成化的方式暴露它,用于Gradle构建。如果这个回答对你有帮助,我会感激一个赞和/或一个“接受的”回答。 - superEb
显示剩余6条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接