How to configure Apache Ant Migration Tool.

In this article we will configure your machine and your project to use Apache Ant.
We will check, install and configure Java, Ant tools. Then write deployment scripts and configure project to use them.
And at the end we will try it out!

Prerequisites

Before you can use the Ant Migration Tool, Java and Ant must be installed and configured correctly. Lets verify what Java and Ant version installed on your computer from a command prompt.


To check the version of Java that’s installed on your system:

  1. Open a command prompt.
  2. At the prompt, type java -version and press Enter.

Java version 1.7.x or later is recommended for better security and for the latest TLS security protocols.

If you have Java version 7, the output looks something like the following.

java version "14.0.1" 2020-04-14
Java(TM) SE Runtime Environment (build 14.0.1+7)
Java HotSpot(TM) 64-Bit Server VM (build 14.0.1+7, mixed mode, sharing)

To install Java, go to Downloads Page and get the latest version of the Java JDK. When you’re finished with the installation, verify by typing java -version at a command prompt(see above).


To check the version of Ant installed on your system:

  1. Open a command prompt.
  2. At the prompt, type ant -version and press Enter.

The output looks something like the following:

Apache Ant version 1.7.0 compiled on December 13 2006

To install and configure Ant:

  1. Download Apache Ant version 1.6 or later to a directory of your choice: http://ant.apache.org/bindownload.cgi. This directory known as ANT_HOME. When the files are on your computer, no further installation is required.
  2. Add the bin directory to your path. (Only the bin and lib directories are required to run Ant.)
  3. If you are using a Windows operation system, create an ANT_HOME environment variable and set the value to where you have installed Ant. Also create a JAVA_HOME environment variable and set the value to the location of your JDK.

For more information, see http://ant.apache.org/manual/install.html.

Install the Ant Migration Tool

  1. Download the .zip file of the Summer ’20 Ant Migration Tool. The download link doesn’t require authentication to Salesforce. If you’re logged in to Salesforce, we recommend you log out before accessing the link in your browser.
  2. Save the .zip file locally, and extract the contents to the directory of your choice.

The Ant Migration Tool uses the ant-salesforce.jar file that’s in the distribution .zip file. If you installed a previous version of the tool and copied ant-salesforce.jar to the Ant lib directory, delete the previous jar file. The lib directory is located in the root folder of your Ant installation. You don’t need to copy the new jar file to the Ant lib directory.

If you plan to run the tool from a directory other than its installation directory, modify the build.xml file to indicate the location of the ant-salesforce.jar file. Update the location attribute on <pathelement> in build.xml to point to ant-salesforce.jar in the installation directory.

Configuring Salesforce project

Once Java and Ant are installed we have to configure our workspace to start working with Ant.

We are assuming you already have salesforce project created somewhere on your machine.

So if you were following all steps now you should have sample folder under downloaded salesforce_ant_49.0 folder.

A sample folder containing a few subfolders and following files:

  • A sample build.properties file that you must edit, specifying your credentials, in order to run the sample ant tasks in build.xml
  • A sample build.xml file, that exercises the deploy and retrieve API calls

build.properties

# build.properties
#

# Specify the login credentials for the desired Salesforce organization
sf.username = <Insert your Salesforce username here>
sf.password = <Insert your Salesforce password here>
#sf.sessionId = <Insert your Salesforce session id here.  Use this or username/password above.  Cannot use both>
#sf.pkgName = <Insert comma separated package names to be retrieved>
#sf.zipFile = <Insert path of the zipfile to be retrieved>
#sf.metadataType = <Insert metadata type name for which listMetadata or bulkRetrieve operations are to be performed>

# Use 'https://login.salesforce.com' for production or developer edition (the default if not specified).
# Use 'https://test.salesforce.com for sandbox.
sf.serverurl = https://login.salesforce.com

sf.maxPoll = 20
# If your network requires an HTTP proxy, see http://ant.apache.org/manual/proxy.html for configuration.
#

build.xml

<project name="Sample usage of Salesforce Ant tasks" default="test" basedir="." xmlns:sf="antlib:com.salesforce">

    <property file="build.properties"/>
    <property environment="env"/>

    <!-- Setting default value for username, password and session id properties to empty string 
         so unset values are treated as empty. Without this, ant expressions such as ${sf.username}
         will be treated literally.
    -->
    <condition property="sf.username" value=""> <not> <isset property="sf.username"/> </not> </condition>
    <condition property="sf.password" value=""> <not> <isset property="sf.password"/> </not> </condition>
    <condition property="sf.sessionId" value=""> <not> <isset property="sf.sessionId"/> </not> </condition>

    <taskdef resource="com/salesforce/antlib.xml" uri="antlib:com.salesforce">
        <classpath>
            <pathelement location="../ant-salesforce.jar" />        	
        </classpath>
    </taskdef>
	
    <!-- Test out deploy and retrieve verbs for package 'mypkg' -->
    <target name="test">
      <!-- Upload the contents of the "mypkg" package -->
      <sf:deploy username="${sf.username}" password="${sf.password}" sessionId="${sf.sessionId}" serverurl="${sf.serverurl}" maxPoll="${sf.maxPoll}" deployRoot="mypkg" rollbackOnError="true"/>
      <mkdir dir="retrieveOutput"/>
      <!-- Retrieve the contents into another directory -->
      <sf:retrieve username="${sf.username}" password="${sf.password}" sessionId="${sf.sessionId}" serverurl="${sf.serverurl}" maxPoll="${sf.maxPoll}" retrieveTarget="retrieveOutput" packageNames="MyPkg"/>
    </target>

    <!-- Retrieve an unpackaged set of metadata from your org -->
    <!-- The file unpackaged/package.xml lists what is to be retrieved -->
    <target name="retrieveUnpackaged">
      <mkdir dir="retrieveUnpackaged"/>
      <!-- Retrieve the contents into another directory -->
      <sf:retrieve username="${sf.username}" password="${sf.password}" sessionId="${sf.sessionId}" serverurl="${sf.serverurl}" maxPoll="${sf.maxPoll}" retrieveTarget="retrieveUnpackaged" unpackaged="unpackaged/package.xml"/>
    </target>

    <!-- Retrieve all the items of a particular metadata type -->
    <target name="bulkRetrieve">
      <sf:bulkRetrieve username="${sf.username}" password="${sf.password}" sessionId="${sf.sessionId}" serverurl="${sf.serverurl}" maxPoll="${sf.maxPoll}" metadataType="${sf.metadataType}" retrieveTarget="retrieveUnpackaged"/>
    </target>

    <!-- Retrieve metadata for all the packages specified under packageNames -->
    <target name="retrievePkg">
      <sf:retrieve username="${sf.username}" password="${sf.password}" sessionId="${sf.sessionId}" serverurl="${sf.serverurl}" maxPoll="${sf.maxPoll}" retrieveTarget="retrieveOutput" packageNames="${sf.pkgName}"/>
    </target>

    <!-- Deploy the unpackaged set of metadata retrieved with retrieveUnpackaged and run tests in this organization's namespace only-->
    <target name="deployUnpackaged">
      <sf:deploy username="${sf.username}" password="${sf.password}" sessionId="${sf.sessionId}" serverurl="${sf.serverurl}" maxPoll="${sf.maxPoll}" deployRoot="retrieveUnpackaged" rollbackOnError="true"/>
    </target>

    <!-- Deploy a zip of metadata files to the org -->
    <target name="deployZip">
      <sf:deploy username="${sf.username}" password="${sf.password}" sessionId="${sf.sessionId}" serverurl="${sf.serverurl}" maxPoll="${sf.maxPoll}" zipFile="${sf.zipFile}" pollWaitMillis="1000" rollbackOnError="true"/>
    </target>

    <!-- Shows deploying code & running tests for code in directory -->
    <target name="deployCode">
      <!-- Upload the contents of the "codepkg" directory, running the tests for just 1 class -->
      <sf:deploy username="${sf.username}" password="${sf.password}" sessionId="${sf.sessionId}" serverurl="${sf.serverurl}" maxPoll="${sf.maxPoll}" deployRoot="codepkg" testLevel="RunSpecifiedTests" rollbackOnError="true">
      	 <runTest>SampleDeployClass</runTest> 
      </sf:deploy>
    </target>
	
	 <!-- Shows deploying code with no TestLevel sepcified -->
    <target name="deployCodeNoTestLevelSpecified">
      <sf:deploy username="${sf.username}" password="${sf.password}" sessionId="${sf.sessionId}" serverurl="${sf.serverurl}" maxPoll="${sf.maxPoll}" deployRoot="codepkg" rollbackOnError="true"/>
    </target>
	
	<!-- Shows deploying code and running tests only within the org namespace -->
	<target name="deployCodeRunLocalTests">
	  <sf:deploy username="${sf.username}" password="${sf.password}" sessionId="${sf.sessionId}" serverurl="${sf.serverurl}" maxPoll="${sf.maxPoll}" deployRoot="codepkg" rollbackOnError="true"  testlevel="RunLocalTests"/>
	</target>
	
    <!-- Shows removing code; only succeeds if done after deployCode -->
    <target name="undeployCode">
      <sf:deploy username="${sf.username}" password="${sf.password}" sessionId="${sf.sessionId}" serverurl="${sf.serverurl}" maxPoll="${sf.maxPoll}" deployRoot="removecodepkg"/>
    </target>

    <!-- Shows retrieving code; only succeeds if done after deployCode -->
    <target name="retrieveCode">
      <!-- Retrieve the contents listed in the file codepkg/package.xml into the codepkg directory -->
      <sf:retrieve username="${sf.username}" password="${sf.password}" sessionId="${sf.sessionId}" serverurl="${sf.serverurl}" maxPoll="${sf.maxPoll}" retrieveTarget="codepkg" unpackaged="codepkg/package.xml"/>
    </target>

    <!-- Shows deploying code, running all tests, and running tests (1 of which fails), and logging. -->
    <target name="deployCodeFailingTest">
      <!-- Upload the contents of the "codepkg" package, running all tests -->
      <sf:deploy username="${sf.username}" password="${sf.password}" sessionId="${sf.sessionId}" serverurl="${sf.serverurl}" maxPoll="${sf.maxPoll}" deployRoot="codepkg" testLevel="RunAllTestsInOrg" rollbackOnError="true" logType="Debugonly"/>
    </target>

    <!-- Shows check only; never actually saves to the server -->
    <target name="deployCodeCheckOnly">
      <sf:deploy username="${sf.username}" password="${sf.password}" sessionId="${sf.sessionId}" serverurl="${sf.serverurl}" maxPoll="${sf.maxPoll}" deployRoot="codepkg" checkOnly="true"/>
    </target>
	
	<!-- Shows quick deployment of recent validation. Set the property sf.recentValidationId to your recent check only deployment Id -->
	<target name="quickDeploy">
	  <sf:deployRecentValidation  username="${sf.username}" password="${sf.password}" sessionId="${sf.sessionId}" serverurl="${sf.serverurl}" maxPoll="${sf.maxPoll}" recentValidationId="${sf.recentValidationId}"/>
	</target>
	
	<!-- Shows cancel deployment of deploy request either pending or in progress. Set property sf.requestId to Id of pending or in progress deploy request -->
	<target name="cancelDeploy">
	  <sf:cancelDeploy  username="${sf.username}" password="${sf.password}" serverurl="${sf.serverurl}" maxPoll="${sf.maxPoll}" requestId="${sf.requestId}"/>
	</target>

	<!-- Retrieve the information of all items of a particular metadata type -->
    <target name="listMetadata">
      <sf:listMetadata username="${sf.username}" password="${sf.password}" sessionId="${sf.sessionId}" serverurl="${sf.serverurl}" metadataType="${sf.metadataType}"/>
    </target>

	<!-- Retrieve the information on all supported metadata type -->
    <target name="describeMetadata">
      <sf:describeMetadata username="${sf.username}" password="${sf.password}" sessionId="${sf.sessionId}" serverurl="${sf.serverurl}"/>
    </target>
</project>

XML above using system salesforce_ant lib that we downloaded before.
We recommend you to store such files as well as additional configuration files inside your project root folder. For example: you have ~/MyCoolProject as root project folder. Simply create new folder called config, ant_config, build_config, libs or whatever and move salesforce_ant.jar file here.

Why it is important to have this file in your project?
Simply because it would be easy to update single file and then commit it to you versioning system instead of updating this file for each of your developers every release.

Once you have ant_config folder created and salesforce_ant.jar was moved here we can continue our configuration.

Move build.xml and build.properties files to the project root folder. Open build.xml and paste code below

<project name="AMVI Cloud Build System" default="deploy" basedir="." xmlns:sf="antlib:com.salesforce">

    <property file="build.properties"/>
    <property environment="env"/>

    <taskdef uri="antlib:com.salesforce"
	resource="com/salesforce/antlib.xml"
	classpath="${basedir}/ant_config/ant-salesforce.jar"/>

    <import file="${basedir}/ant_config/deploy.xml"/>
</project>

As you can see we removed a lot of things from sample build.xml file and imported a single deploy.xml file from ant_config folder. We did this because in future when you will have a lot of different deployment scripts it will be easier to find and update. Lets see what is inside of our new deploy.xml file.

deploy.xml

<project name="Deploy" xmlns:sf="antlib:com.salesforce">
   <!-- set global properties for this build -->
   <property name="src" location="src"/>
   <property name="build" location="build"/>
   <property name="dist" location="dist"/>

   <target name="deploy">
      <antcall target="init_deploy" />
      <antcall target="deploy_with_validate" />
   </target>

   <target name="deploy_without_tests">
      <antcall target="init_deploy" />
      <antcall target="deploy_no_tests" />
   </target>

   <target name="run_all_tests">
      <antcall target="init_deploy" />
      <antcall target="validate_run_tests" />
   </target>

    <target name="deploy_no_tests">
        <sf:deploy singlePackage="true" username="${sf.username}"
            password="${sf.password}" serverurl="${sf.serverurl}" 
            maxPoll="360" pollWaitMillis="20000" logType="Debugonly" 
            rollbackOnError="false" deployroot="${stage.dir}/deploy" >
        </sf:deploy>
        <delete dir="${stage.dir}/deploy" />
    </target>

    <target name="validate_run_tests">
        <sf:deploy singlePackage="true" username="${sf.username}"
            password="${sf.password}" serverurl="${sf.serverurl}" 
            maxPoll="360" pollWaitMillis="20000" logType="Debugonly" 
            rollbackOnError="true" testLevel="RunLocalTests" 
            deployroot="${stage.dir}/deploy" checkOnly="true"> 
        </sf:deploy>
        <delete dir="${stage.dir}/deploy" />
    </target>

    <target name="deploy_with_validate">
        <sf:deploy singlePackage="true" username="${sf.username}" 
            password="${sf.password}" serverurl="${sf.serverurl}" 
            maxPoll="360" pollWaitMillis="20000" logType="Debugonly" 
            rollbackOnError="true" testLevel="RunLocalTests" 
            deployroot="${stage.dir}/deploy">
        </sf:deploy>
        <delete dir="${stage.dir}/deploy" />
    </target>

    <target name="init_deploy">
        <property name="stage.dir" value="stage" />
        <delete dir="${stage.dir}/deploy" />
        <mkdir dir="${stage.dir}" />
        <mkdir dir="${stage.dir}/deploy" />
        <copy todir="${stage.dir}/deploy">
            <fileset dir="${sf.dir}" includes="**" />
        </copy>
    </target>
</project>

init_deploy – command to copy all of source files to single deploy folder
deploy_with_validate – command used to deploy metadata to your org but only when all tests are passed.
validate_run_tests – command to send you changes to your org only for validation.
deploy_no_tests – command to deploy changes event if some of tests are failing.
run_all_tests & deploy_withou_test & deploy – it is just a same as above but running in sequence.

How to start deploying.

Once everything configured you are probably can’t wait to see how it works?
It is easy enough! Open command prompt window, Go to yours project root folder and run some command!

ant deploy_without_tests

If everything was configured correctly you will see the message that your build was completed successfully! Congratulations!

If you need help with this article(or any others) you can contact us using contact form or our email: [email protected]


Useful links

Comments are closed.

Works with AZEXO page builder
© All rights reserved. Theme by AZEXO