[SalesForce] Deploy Selected Classes with Ant

Supposing you want to deploy only selected classes using ant from the force.com ide to various orgs. This can be tricky because you need to ensure both your package.xml and your payload (either your classes directory or a zipfile) contain exactly the same files.

Is there a neat way to do this by defining set ant targets with wildcards for the files to be included?

Best Answer

First, you need to ensure your package.xml contains at least what you are deploying. It may contain more, but not less.

<types>
    <members>Class1</members>
    <members>Class2</members>
    <members>Class3</members>
    <name>ApexClass</name>
</types>

UPDATE: It is even easier to do this:

<types>
    <members>*</members>
    <name>ApexClass</name>
</types>

Next, setup an ant target in your build.xml which looks something like this:

<target name="QADeployClass1And2">
    <delete file="deploy.zip"/>
    <zip destfile="deploy.zip">
        <fileset dir="src" includes="classes/Class1.*"/>
        <fileset dir="src" includes="classes/Class2.*"/>
        <fileset dir="src" includes="package.xml"/>
    </zip>
    <sf:deploy zipFile="deploy.zip" allowMissingFiles="true"
        username="user@org.com.qa" password="**********" 
        serverurl="https://test.salesforce.com"/>
    <delete file="deploy.zip"/>
</target>

When you run this target you will deploy only Class1.cls and Class2.cls. I also find it useful to place the username, password and serverurl on the target so that I can use a different ant target for each target org without having to switch out the build.properties file.

I use the zipfile approach (1) because this allows me to easily and centrally control which files go into the payload. If you wish to use a folder with deployRoot you need to make a temporary folder and copy in the files you need:

<target name="deploy1">
    <delete>
        <fileset dir=".\deploy\classes" includes="**/*.*"/>
    </delete>
    <copy file="deploy\package1.xml" tofile="deploy\package.xml"/>
    <copy todir=".\deploy\classes">
        <fileset dir=".\src\classes\" includes="Class1.*"/>
        <fileset dir=".\src\classes\" includes="Class2.*"/>
    </copy>
    <sf:deploy allowMissingFiles="true" username="${sf.username}" password="${sf.password}" serverurl="${sf.serverurl}" deployRoot="deploy"/>
</target>

In this example you could setup package1.xml to only include the files you want to deploy and it will overwrite package.xml when you run this ant target thus making allowMissingFiles="true" superfluous.