Wednesday, September 26, 2012

version qualifiers with CBI and git

When building an RCP app or feature, you don't want bundle qualifiers that change with every build, that removes the benefit of updating only what has changed. But you do want to be sure that a given version.qualifier is repeatable (built from the same source). One cool little feature that came out of the CBI work was a way to derive bundle qualifiers from git.

The Eclipse Project has been built with PDE build and map files for a long time now. The map file entry told PDE build what version and what location to check out during a build. This checks out org.eclipse.jface from CVS in one of our older builds, and will produce the plugin org.eclipse.jface_3.6.2.M20110210-1200.jar:
plugin@org.eclipse.jface=M20110210-1200,:pserver:anonymous@dev.eclipse.org:/cvsroot/eclipse,
With our move to git, we've updated them to GIT entries so they can be checked out:
plugin@org.eclipse.jface=GIT,tag=v20120817-083647,repo=git://git.eclipse.org/gitroot/platform/eclipse.platform.ui.git,path=bundles/org.eclipse.jface
This will produce org.eclipse.jface_3.8.101.v20120817-083647.jar. But the map based git fetch factory only works because it copies the plugins from the git repo that contains them to the buildDirectory/plugins directory. The tag used both for the qualifier and to check out a version of the bundle for the build.  But when there are multiple bundles are in a git repo and you can only checkout one tag at a time, the CVS pattern doesn't hold up for git.

When moving to the CBI based build, we'd be building all of the bundles in a git repo at the same time. In this scenario, it doesn't make sense to tie the bundle qualifier to a repository tag of some kind. The important functionality is 1) the qualifier doesn't change if the source code doesn't change and 2) the qualifier is repeatable when derived from the same build input.

That's where the notion of using the UTC commit timestamp of the last commit to touch a project came from. Tycho provides tycho-buildtimestamp-jgit, a timestamp provider that can be configured to work with tycho-packaging-plugin (in the 0.16.0 SNAPSHOT, I believe).

Example:

        <plugin>
          <groupId>org.eclipse.tycho</groupId>
          <artifactId>tycho-packaging-plugin</artifactId>
          <version>${tycho.version}</version>
          <dependencies>
            <dependency>
              <groupId>org.eclipse.tycho.extras</groupId>
              <artifactId>tycho-buildtimestamp-jgit</artifactId>
              <version>${tycho-extras.version}</version>
            </dependency>
          </dependencies>
          <configuration>
            <strictBinIncludes>false</strictBinIncludes>
            <format>'v'yyyyMMdd-HHmm</format>
            <timestampProvider>jgit</timestampProvider>
            <jgit.ignore>
            </jgit.ignore>
          </configuration>
        </plugin>

Now building our repo will generate predictable and reproducible qualifiers.  This will also help reduce the number of vDATE-TIME tags we push to our git repo, as only the build input commit needs to be tagged.  In 4.2.2 we get org.eclipse.jface_3.8.101.v20120914-1338.jar.

There are some drawback to this approach, but all in all it provides a qualifier convention that doesn't require a lot of configuration.