Mach-II Deployment with Apache Ant

One of the (admittedly few) things that bugs me about ColdFusion development is deploying an application. Mach-II alleviated some of this pain with its recent addition of Environment properties, but (unless I’m mistaken) a large problem still exists: being able to deploy your application twice on the same machine or under a different directory name.

Why would you want to do this? Well, at my company we only have a development server and a deployment server. What should we do for staging, QA, or continuous integration deployments? We can fake it by deploying an application under a different name/directory on the same server as another deployment of the same application. We just have to make sure to avoid ApplicationName (and other property) collisions.

I do this with Apache Ant. First we create a Java properties file containing some per-deployment properties (I call this file build.properties):

cf.app.root=myproject
cf.app.dsn=mysql_myproject
cf.app.deploy.dir=/var/www/html/myproject

Then we modify the layout of the Mach-II Skeleton. For this example, all my config files will be put into the ‘config’ directory; Application.cfc is in the ‘base’ directory; all other deployment-agnostic files are in the ’src’ directory.

Let’s take a look at how these mappings look in a basic mach-ii.xml:

<?xml version="1.0" encoding="UTF-8"?>
 
<!DOCTYPE mach-ii PUBLIC "-//Mach-II//DTD Mach-II Configuration 1.6.0//EN"
	  "http://www.mach-ii.com/dtds/mach-ii_1_6_0.dtd" >
 
<mach-ii version="1.6">
  <!-- INCLUDES -->
  <includes>
    <include file="./mach-ii_coldspringProperty.xml" />
  </includes>
 
  <properties>
    <property name="applicationRoot" value="/@cf.app.root@" />
    <property name="defaultEvent" value="home" />
    <property name="eventParameter" value="event" />
    <property name="parameterPrecedence" value="form" />
  </properties>
 
  <!-- LISTENERS -->
  <listeners>
    <listener name="testListener" type="/@cf.app.root@/listeners/TestListener"/>
    <listener name="userListener" type="/@cf.app.root@/listeners/UserListener"/>
    <listener name="reportListener" type="/@cf.app.root@/listeners/ReportListener"/>
  </listeners>
 
  <!-- . . . -->
</mach-ii>

Notice the @cf.app.root@? That tells Ant “We need to replace this with some kind of property value”. Now let’s look at a sample buildfile:

<?xml version="1.0"?>
<project name="myproject" default="dist">
  <description>Buildfile for a Sample Project</description>
 
  <target name="help" description="usage information for common tasks">
    <echo>usage: ant [target]</echo>
    <echo>target can be all, init, dist, deploy, clean, install, help </echo>
  </target>
 
  <target name="init" description="Initializes a project and all relevant data">
    <mkdir dir="build"/>
    <mkdir dir="build/config"/>
    <mkdir dir="dist"/>
  </target>
 
  <target name="clean" depends="init" description="Cleans up the entire project
						   (reset)">
    <delete dir="build"/>
    <delete dir="dist"/>
  </target>
 
  <target name="build" description="Builds the code from source files">
    <copy todir="build">
      <fileset dir="src"/>
      <fileset dir="webapp"/>
    </copy>
    <filter filtersfile="build.properties"/>
    <copy todir="build/config" filtering="true">
      <fileset dir="config"/>
    </copy>
    <copy todir="build" filtering="true">
      <fileset dir="base"/>
    </copy>
  </target>
 
  <target name="dist" depends="build" description="Creates the distribution code">
    <copy todir="dist">
      <fileset dir="build"/>
    </copy>
  </target>
</project>

The magic happens within <copy todir="build" filtering="true">. That tells Ant to copy the files to the ‘build’ directory and replace all the @cf.app.whatever@ tags with values found in the build.properties file mentioned earlier. After running this Ant script, we’ll have the following waiting for us in dist/config/mach-ii.xml:

<mach-ii version="1.6">
 
  <!-- . . . -->
 
  <properties>
    <property name="applicationRoot" value="/myproject" />
 
    <!-- . . . -->
 
  </properties>
 
  <!-- . . . -->
 
</mach-ii>

The goal is to have a perfect distribution of your application ready for you in the ‘dist’ directory. You could easily add additional Ant tasks to deploy your application to its home directory through FTP or a direct copy.

It doesn’t seem like much, but with these small changes I can now modify build.properties and deploy the application wherever I see fit, under any directory. Having multiple deployments on a single server, while not ideal, is perfectly doable.

Ant is an extraordinarily powerful build tool. I enjoy working with it and I’ve only barely tapped into its abilities. Hopefully if you’ve never evaluated it for one of your projects, you will soon. It has really made deployment a non-issue for the projects I use it on.

Post #5 done. Afk bourbon.

Leave a Reply

Powered by WP Hashcash