ColdFusion ANT Deployment Scripts - Part One: Versioning

This is the first post of a series in which I will be discussing how I leverage ANT with my ColdFusion applications for various pieces of deployment.  Tentatively, this series will consist of:

  1. Versioning
  2. Generating ColdDoc (javadoc-like CFC documentation)
  3. Automating MXUnit Tests
  4. Deployment (via SSH, FTP, Windows Network)

Note: All files mentioned here should be placed directly in your root project directory.

Step 1 - Create our basic build.xml file

First, we will simply stub out our build file.  For now I simply stub one target, called version.  We will also reference a build.properties file to hold all variables that pertain to the build (we'll build it later).

<project name="CFAntDemo" default="version" 
    basedir=".">
    <property file="build.properties" />
    <target name="version">
    </target>
</project>

Step 2 - Create our version.properties file

This is a very simple properties file to control our versioning.  It contains two properties - the first, version, is a standard major minor version number which we will manually adjust (I'm starting at 1.0 for this demo).  The second, build, will simply get auto incremented by our ANT script each time we call the version target.

version=1.0
build=0

Step 3 - Create our version_stub.cfm file

This file will never actually be referenced by our application (in fact, we don't need to deploy it).  It is solely for use by our version target.  Basically, we will leverage ANT to replace the tokens @version@ and @build@ with the values of their properties from our version.properties file.

<cfscript>
this.version="@version@";
this.build="@build@";
</cfscript>

Step 4 - Create our version.cfm file

Typically, this file will be generated by ANT, but for our first run, let's manually code this file so that we can test our Application.cfc properly.  This file will be cf-included in our Application.cfc, providing properties containing the version number and build number of our current application.

<cfscript>
this.version="1.0";
this.build="0";
</cfscript>

Step 5 - Edit our Application.cfc

We need to add a few things to our root Application.cfc.  First, in the properties section, we need to cfinclude our version.cfm file.

<cfcomponent displayname="Application">
    <cfset this.name="CFAntDemo">
    <cfinclude template="version.cfm">

Next, we need to add code into our onApplicationStart() method, to store this.version and this.build in the Application Scope.  I do this in a single variable called, application.fullversion.

<cffunction name="onApplicationStart" returntype="boolean">
    <!--- all of my normal onAppStart stuff, Singletons, 
    etc... --->
    <cfset application.fullversion = this.version & "-" 
        & this.build>
    <cfreturn true>
</cffunction>

Lastly, I add a hook into my onRequestStart() to call onApplicationStart() whenever this.fullversion does not equal application.fullversion.  Effectively, my application will now refresh itself whenever it's deployed to another server after this target has run.

<cffunction name="onRequestStart" returntype="boolean">
    <cfargument name="targetPage" type="string">
    <cfset this.fullversion = this.version & "-" 
        & this.build>
    <cfif not isDefined('application.fullversion') OR
        this.fullversion neq application.fullversion>
        <cfset onApplicationStart()>
    </cfif>
    <!--- the rest of my onReqStart stuff--->
    <cfreturn true>
</cffunction>

Step 6 - Setup our build.properties file

Create the build.properties file.  For now, we need 2 properties, version.file (points to our version.cfm file), and version.stub (points to our version_stub.cfm file).

version.file=${basedir}/version.cfm
version.stub=${basedir}/version_stub.cfm

Step 7 - Code in our version target on our build.xml file

Replace our stubbed out version target with the following code, which does the following:

  • Only executes if the version.file property has been set (we did this in build.properties)
  • Increments the build property in the version.properties file
  • Copies our version "stub" file over our version.cfm file
  • Replaces our @version@ and @build@ tokens with their values from the updated version.properties file.
<target name="version" if="version.file">
    <propertyfile file="version.properties">
        <entry key="build" type="int" 
            operation="+" default="0" />
    </propertyfile>

    <copy overwrite="true" file="${version.stub}" 
        toFile="${version.file}" />

    <replace file="${version.file}" 
        propertyFile="version.properties">
        <replacefilter token="@version@" 
            property="version" />
        <replacefilter token="@build@" 
            property="build" />
    </replace>
</target>

Fin!

Coming soon, a download with a working example of this, zipped up.