tags:

views:

692

answers:

6

I am developing a desktop app using Java and Swing Application Framework. I have an application about box and I'd like to have that box contain some indication of what version is being tested. My preference is for that value to be changed in an automated fashion. I'm using CruiseControl to build the application triggered off the commits to SVN.

What mechanism to others use to do this job? Is there an about box version number library or set of ant related tools that I can just drop in place in my build process?

I'm not looking for deployment options or anyway to automatically check for updates or anything like that. I just want to be able to ask a tester what version is in the about box and get a reliable answer.

+2  A: 

You're making it too complicated. SVN provides the version number as a macro, like CVS.

Create a simple inverface containing a constant, and have SVN instantiate that through a macro, like

public interface IVersionNumber {
    public static final String version = "$Id$" ;
}

You need to tell SVN to use keywords on that file, as

$ svn propset svn:keywords "Id" IVersion.java

You can read about properties here.

Charlie Martin
It can't be from just a file though. SVN provides a macro to get the last revision number for that file. My goal is not to have to touch that file every time I do a commit.
Jay R.
I'd have to call svnrevision to get the value I want. It would be better to have that call happen from CruiseControl.
Jay R.
No, setting up keywords substitution is exactly what you want. You don't have to touch the file; SVN handles that. And remember that since SVN uses atomic revisions the version number is the same for *all* the files.
Charlie Martin
This is exactly the way I've handled it under Cruise Control on multiple projects.
Charlie Martin
Svn keywords are updated only when the file where they appear is updated. Unrelated changes to other files won't update the Id svn keyword. The fact that Svn uses atomic revisions doesn't mean that all files in the repository have the same revision number.
Juliano
No, that's not true. Keyword substitution happens when you co a new copy, which Cruise Control etc does when it starts a build. If you have enabled keyword substitution on a file, the $Id symbol will be updated to the current revision of the repository.
Charlie Martin
Shouldn't the above code reference $Id$ ?
Brian Agnew
@Charlie: Are you sure? I just created a new repository with svn 1.5.1. rev 1: added file a and b (with a containing $Id$ keyword and with svn:keywords set), rev 2: changed file b. I then proceeded to create a fresh checkout: the ID keyword in file a was expanded to indicate that revision 1 was the last change. A fresh checkout behaves exactly like an update with regards to svn:keywords
Wim Coenen
@Brian, yeah, typo. @wc, *reasonably* sure, since it was working for me. Might need to use $rev$ instead of $id$. But I was successfully using it in a product.
Charlie Martin
Charlie, sorry but you are WRONG! http://svnbook.red-bean.com/en/1.5/svn.advanced.props.special.keywords.html . It is all over the page, but quoting: "Since the repository has a single, globally increasing revision number, many people assume that it is this number that is reflected by the $Rev$ keyword's value. But $Rev$ expands to show the last revision in which the file changed, not the last revision to which it was updated." Other keywords are the same.
Juliano
+5  A: 

Have the build script create a property file holding the version. It's good idea to grab the revision # directly from SVN. This way you can refer to it in tests. Place this property file into the packaged jar and read it in run time. We usually have major and minor versions set as parameters to ant scrpt while revision is managed automatically by SVN and gives consistent build number for the references.

This snippet target runs svn command line and outputs into a temp file (svndump). Then constructing xx.yy.zz string, place it in another file which will be later included into jar. Note that xx.yy are taken from external parameters, this is major-minor version.

<target name="getrev">
    <exec executable="svn" output="svndump">
     <arg value="info"/>
     <arg value="${my.svn.url}"/>
    </exec>

    <property file="svndump"/>
    <property name="my.build" value="${Revision}"/>
    <property name="my.rev" value="${my.ver}.${my.build}"/>
    <echo message="current revision is ${my.rev}"/>

    <property name="my.dir.dist" value="${my.dir.root}/dist/${my.rev}"/>
    <echo message="${my.rev}" file="${my.dir.projects}/revision"/>

    <delete file="svndump"/>
</target>
Dima
+1. I do this as well.
Damo
There is a project called SVN-Ant that can do the exec stuff for you.
Jay R.
Yes, svn-ant would also do.. though I remember when I tried it, there were some issues with dependencies. Perhaps now it's more mature, worth trying.
Dima
+3  A: 

With Maven I've used the buildnumber-maven-plugin which gets the revision number from Subversion or uses a sequence or a timestamp, which is then is used to replace a ${buildNumber} placeholder where ever you like. I suppose that other build tools and continuous integration servers have similar features. Search your favorite search engine with "<your-tool> build number".

Esko Luontola
+7  A: 

I will start this post off by stating that I use Apache Maven to build. You could also do a similar sort of thing with Ant or another tool, but this is what I have done using maven.

The best way I have found to handle this is to use the version of your project plus the subversion revision as the build number. From maven you can include the following. This will give you the subversion revision number as ${scm.revision}.

<build>
    <plugins>
      <plugin>
        <artifactId>maven-scm-plugin</artifactId>
        <executions>
          <execution>
            <id>getting-scm.revision</id>
            <phase>validate</phase>
            <goals>
              <goal>update</goal>
            </goals>
          </execution>
        </executions>
      </plugin>
    </plugins>
  </build>

After you have then, I then use this as part of the jar file manifest as the Implementation Version.

  <plugin>
    <artifactId>maven-jar-plugin</artifactId>
    <version>2.1</version>
    <configuration>
      <archive>
        <manifestEntries>
          <Implementation-Version>${this.version}.${scm.revision}</Implementation-Version>
        </manifestEntries>
      </archive>
    </configuration>
  </plugin>

The nice thing about this is that you can access this from code by using the following:

Package p = getClass().getPackage();
String version = p.getImplementationVersion();

That gives you the full build number like "1.0.13525" where the last number is the subversion revision. For more information on setting this up you can check out the full blog post I did a while back on this very issue.

Chris Dail
Nice answer. Thanks.
toolkit
+1  A: 

We've used JReleaseInfo for a long time. You can set it up in your Ant script (we don't use Maven for our projects) and it bumps the version number automatically. It also has some nice additions in that it generates a class containing all the information. You can just call that class within your code to get strings ready to use or call the class from the command line to have it print out the version number without needing to change your code any.

John Munsch
A: 

Since I'm using cruise control and ant to build everything, I ended up at least for now, using the ${label} property passed into the ant call for building the project. In my ant file, I use the ant task "replace" to change the properties file that holds the about box resource named Application.version to include that label.

I'm planning to change from the label incrementer to the svn label incrementer and then use the svn revision number that way. Its just a little more work and it requires that I make changes to the cruise control config file.

Jay R.