Thursday, February 28, 2013

Working Sandbox and Production Using the Force Migration Tool


 Easily Switch Between Sandbox and Production  Using the Force Migration Tool

This is a continuation of my previous post Getting Started with Salesforce Ant Migration with Force.com IDE

I'll show you how to create ant build scripts to easily switch between a Sandbox and Production.   I'm using a Mac so Window's users will need to make a few adjustments.

The Ant Migration Tool is significantly faster that using the Force.com IDE.   So, I am beginning to use the command line tool more and the Force.com IDE less.  What I need is an easy way to work with a project and have it quickly switch between a Sandbox and the main Production instance of Salesforce.


At first this is easy enough:  I just need to have two build.properties files. One for the sandbox and the other for production.  Then, keeping it simple, I create two build.xml files that are identical except one uses the sandbox properties and the other uses the production.

Simple, but clearly not a scalable solution.  So, how can I do this better?  By using some form of if-then-else condition processing.   Note, once a property is set in Ant it can not be modified.

Google search locates this answer:
http://stackoverflow.com/questions/5116619/apache-ant-if-then-else-task

Contributors provide two answers.  One uses built in Ant tasks that can do one thing or another.  But, I find that approach difficult to understand and would prefer a more classic "if-then-else" solution.  Further down in the post is another answer that uses a module that needs to be downloaded into your system.   This module provides more than just if-then-else so I feel it is worth the extra effort.

Download, Install and Use the Contrib Module


You can read about what the contrib module provides here
http://ant-contrib.sourceforge.net/tasks/tasks/index.html
Download from here:
http://sourceforge.net/projects/ant-contrib/files/ant-contrib/
Installation instructions from here:
http://ant-contrib.sourceforge.net/


But I'll describe my installation steps here.

OK.  Here is the reward for reading this far!  The download page provides a zip with everything but the jar file.  It took some time to dig our the real download URL that you want.
http://sourceforge.net/projects/ant-contrib/files/ant-contrib/ant-contrib-0.3/
On this page get the bin file ant-contrib-0.3-bin.zip

Unpack the file:

~/Downloads$ ls -l ant-contrib-0.3-bin.zip
-rw-r--r--@ 1 yourRoot  staff    97K 28 Feb 11:00 ant-contrib-0.3-bin.zip
~/Downloads$ mkdir AntContrib
~/Downloads$ mv ant-contrib-0.3-bin.zip AntContrib/
~/Downloads$ cd AntContrib/
~/Downloads/AntContrib$ unzip ant-contrib-0.3-bin.zip


To see the local copy of the API documentation run this:
~/Downloads/AntContrib$ open docs/api/index.html  



The jar file we want is in the lib directory.  Just need to know where to copy it.  With linux systems  you can run 'which' to locate the ant install directory.
~/Downloads/AntContrib$ which ant
/usr/bin/ant







But do a long directory listing and note the directory is actually a link.  After some more exploration I found the actual location to put the jar.  The target directory is owned by the root user so you may need to run the copy command with super user privileges; sudo



~/Downloads/AntContrib$ sudo cp lib/ant-contrib-0.3.jar /usr/share/ant/lib/
Password:
~/Downloads/AntContrib$

Using the If-Then-Else

Now we are ready to use the module.   From the installation notes there is an important first step. In each build file you need to include this:
<taskdef resource="net/sf/antcontrib/antcontrib.properties"/>


Here is a sample file that illustrates the if-then-else

<project name="Try If">
<taskdef resource="net/sf/antcontrib/antcontrib.properties"/>
<if>
 <equals arg1="${foo}" arg2="bar" />
 <then>
   <echo message="The value of property foo is 'bar'" />
 </then>
 <elseif>
  <equals arg1="${foo}" arg2="foo" />
  <then>
   <echo message="The value of property foo is 'foo'" />
  </then>
 </elseif>
 <else>
   <echo message="The value of property foo is not 'foo' or 'bar'" />
 </else>
</if>
</project>


Save the above into a file and call it testif.xml. Invoke ant without a define and with the foo property defined. See the results

~/Documents/salesforce/dev$ ant -f testif.xml
Buildfile: /Users/yourRoot/Documents/salesforce/dev/testif.xml
     [echo] The value of property foo is not bar
     [echo] The value of property foo is not 'foo' or 'bar'

BUILD SUCCESSFUL
Total time: 0 seconds
~/Documents/salesforce/dev$ ant -f testif.xml -Dfoo=bar
Buildfile: /Users/yourRoot/Documents/salesforce/dev/testif.xml
     [echo] The value of property foo is bar
     [echo] The value of property foo is 'bar'

BUILD SUCCESSFUL
Total time: 0 seconds


Using If-Then-Else to Select Test or Prod Properties

Create two build properties files. One for Test and another for Prod.  We will use the if-then-else to select the right one based on the command line.  Put the following into a file called build.xml in your root project directory.


<project name="Salesforce Project"  default="work" basedir="." xmlns:sf="antlib:com.salesforce">
<taskdef resource="net/sf/antcontrib/antcontrib.properties"/>

<target name="setup" >
<if>
 <equals arg1="${target}" arg2="test" />
 <then>
   <property file="buildTest.properties"/>
   <property name="system"  value="TEST" />
 </then>
 <elseif>
  <equals arg1="${target}" arg2="prod" />
  <then>
   <property file="buildProd.properties"/>
   <property name="system"  value="PROD" />
  </then>
 </elseif>
 <else>
   <echo message="The value of property target is not 'test' or 'prod'" level="error" />
   <fail/>
 </else>
</if>
</target>

<target name="work"  depends="setup">
   <echo>The ${system} user name is ${sf.username}</echo>
</target>

</project>



Run it with and without the 'target' property

~/Documents/salesforce/dev$ ant -f build.xml
Buildfile: /Users/yourRoot/Documents/salesforce/dev/
build.xml

setup:
     [echo] The value of property target is not 'test' or 'prod'

BUILD FAILED
/Users/
yourRoot/Documents/salesforce/dev/build.xml:20: No message

Total time: 0 seconds
~/Documents/salesforce/dev$ ant -f
build.xml -Dtarget=test
Buildfile: /Users/
yourRoot/Documents/salesforce/dev/build.xml

setup:

work:
     [echo] The TEST user name is myName@myDomain.com.test

BUILD SUCCESSFUL
Total time: 0 seconds



We can now put the real work into the 'work' target and easily switch between Test and Producton




1 comment: