Build and Version Numbering for Java Projects (ant, cvs, hudson)

吃可爱长大的小学妹 提交于 2019-11-27 02:21:00
Marty Lamb

For several of my projects I capture the subversion revision number, time, user who ran the build, and some system information, stuff them into a .properties file that gets included in the application jar, and read that jar at runtime.

The ant code looks like this:

<!-- software revision number -->
<property name="version" value="1.23"/>

<target name="buildinfo">
    <tstamp>
        <format property="builtat" pattern="MM/dd/yyyy hh:mm aa" timezone="America/New_York"/>
    </tstamp>        
    <exec executable="svnversion" outputproperty="svnversion"/>
    <exec executable="whoami" outputproperty="whoami"/>
    <exec executable="uname" outputproperty="buildsystem"><arg value="-a"/></exec>

    <propertyfile file="path/to/project.properties"
        comment="This file is automatically generated - DO NOT EDIT">        
        <entry key="buildtime" value="${builtat}"/>
        <entry key="build" value="${svnversion}"/>
        <entry key="builder" value="${whoami}"/>
        <entry key="version" value="${version}"/>
        <entry key="system" value="${buildsystem}"/>
    </propertyfile>
</target>

It's simple to extend this to include whatever information you might want to add.

user146146

Your build.xml

...
<property name="version" value="1.0"/>
...
<target name="jar" depends="compile">
    <buildnumber file="build.num"/>
    <manifest file="MANIFEST.MF">
        ...
        <attribute name="Main-Class" value="MyClass"/>
        <attribute name="Implementation-Version" value="${version}.${build.number}"/>
        ...
    </manifest>
</target>
...

Your java code

String ver = MyClass.class.getPackage().getImplementationVersion();
  • Build numbers should be associated with a continuous integration server like hudson. Use different jobs for different branches/teams/distributions.
  • To keep the version number in the final build, I would recommend just using maven for build system. It will create a .properties file archived into the final .jar/.war/.whatever-ar on META-INF/maven/<project group>/<project id>/pom.properties. The .properties file will contain the version property.
  • Since I am recommending maven, I would urge you to check out the release plugin to prepare the release on source repository and keep the versions on sync.

Software:

  • SVN
  • Ant
  • Hudson, for continuous integration
  • svntask, an Ant task to find SVN revision: http://code.google.com/p/svntask/

Hudson has three builds/jobs: Continuous, Nightly and Release.

For a Continuous/Nightly build: Build number is the SVN revision, found using svntask.

For a Release build/job: Build number is the Release number, read by Ant, from a Properties file. The properties file can also be distributed with the release for displaying the build number at runtime.

The Ant build script puts the build number in the manifest file of jar/war files that are created during the build. Applies to all builds.

Post-build action for Release builds, done easily using a Hudson plug-in: tag SVN with the build number.

Benefits:

  • For a dev version of a jar/war, the developer can find the SVN revision from the jar/war and look up the corresponding code in SVN
  • For a release, the SVN revision is the one corresponding to the SVN tag that has the release number in it.

Hope this helps.

I'm using Hudson also, although a far more simpler scenario:

My Ant script has a target in it that looks like:

<target name="build-number">
    <property environment="env" />
    <echo append="false" file="${build.dir}/build-number.txt">Build: ${env.BUILD_TAG}, Id: ${env.BUILD_ID}, URL: ${env.HUDSON_URL}</echo>
</target>

Hudson sets these environment variables for me whenever my job runs.

In my case, this project is a webapp and I'm including this build-number.txt file in the root folder of the webapp - I don't really care who sees it.

We don't tag source control when this is done because we already have our Hudson job set up to tag it with the build number/timestamp when the build is successful.

My solution only covers the incremental build numbers for development, we haven't gotten far enough in the project where we are covering release numbers yet.

You may also want to take a look at BuildNumber Maven plugin and Ant task in one jar found at http://code.google.com/p/codebistro/wiki/BuildNumber. I tried to make it simple and straightforward. It is a very small jar file that only depends on command line Subversion installed.

This is how i resolved this:

  • the sources are copied to the build directory
  • then the anttask "versioninfo" is applied
  • compile the modified sources

Here is the java file storing the version info:

public class Settings {

    public static final String VERSION = "$VERSION$";
    public static final String DATE = "$DATE$";

}

And here is the anttask "versioninfo":

    <!-- ================================= 
     target: versioninfo              
     ================================= -->
    <target name="versioninfo"
            depends="init"
            description="gets version info from svn"
    >

        <!-- 
        get svn info from the src folder 
        -->
        <typedef resource="org/tigris/subversion/svnant/svnantlib.xml"
                 classpathref="ant.classpath"
        />
        <svnSetting id="svn.setting"
                    javahl="false"
                    svnkit="true"
                    dateformatter="dd.MM.yyyy"
        />
        <svn refid="svn.setting">
            <info target="src" />
        </svn>

        <!-- 
        if repository is a taged version use "v <tagname>"
        else "rev <revisionnumber> (SVN)" as versionnumber
         -->
        <taskdef resource="net/sf/antcontrib/antcontrib.properties"
                 classpathref="ant.classpath"
        />
        <propertyregex property="version"
                       input="${svn.info.url}"
                       regexp=".*/tags/(.*)/${ant.project.name}/src"
                       select="v \1"
                       defaultvalue="rev ${svn.info.lastRev} (SVN)"
                       override="true"
        />


        <!-- 
        replace date and version in the versionfile ()
         -->
        <replace file="build/${versionfile}">
            <replacefilter token="$DATE$" value="${svn.info.lastDate}" />
            <replacefilter token="$VERSION$" value="${version}" />
        </replace>

    </target>

Here is my 2 cents:

  • My build script creates a build number (with timestamp!) each time I build the app. This creates too many numbers but never too few. If I have a change in the code, the build number will change at least once.

  • I version the build number with every release (though not inbetween). When I update the project and I get a new build number (because someone else did a release), I overwrite my local version and start over. This can lead to a lower build number which is why I've included the timestamp.

  • When a release happens, the build number is committed as the last item in a single commit with the message "build 1547". After that, when it's an official release, the whole tree is tagged. This way, the build file always has all tags and there is a simple 1:1 mapping between tags and build numbers.

[EDIT] I deploy a version.html with my projects and then, I can use a scraper to simply collect an accurate map what is installed where. If you're using Tomcat or similar, put the build number and timestamp in the description element of web.xml. Remember: Never memorize anything when you can have a computer do it for you.

Brian Agnew

We run our build via CruiseControl (insert your favourite build manager here), and perform the main build and tests.

We then increment the version number using Ant and BuildNumber and create a property file with this info plus the date of build and other metadata.

We have a class dedicated to reading this and providing it to GUIs/logs etc.

We then package all of this up and build a deployable tying together the build number and the corresponding build. All our servers dump this meta info on start up. We can go back through the CruiseControl logs and tie the build number to the date and checkins.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!