ANT Series – Getting Specific 1


In the previous post on ANT, we learned how to retrieve components in bulk.  In this post, we’re going to learn how to retrieve specific metadata components and deploy them to an organization after removing them.

First thing is first, please make sure that you’ve spun up a new developer org for following this exercise.  They are free! Don’t worry!  You can get a new one here.

In the last post, we configured the build properties.  If you haven’t you’ll want to make sure to go back and look at how to do that before proceeding.  In this post there are three commands that I’ll be using to do things:

  1. ant retrieveUnpackaged – this gets metadata
  2. ant deployUnpackagedCheckOnly – this validates changes
  3. ant deployUnpackaged – this deploys changes !!! WARNING – THIS CANNOT BE UNDONE !!!

Before moving on, let’s talk about two kinds of changes that you can make to an org via deployment:

  1. package.xml – this contains components that you’d like to add to your organization.
  2. destructiveChanges.xml – this, much like the name implies, destroys things.  When I do this, sometimes in the back of my head I have this image going

exterminate

 

Further, you can specify if you want the destructive changes to happen before or after the deployment of new components by using destructiveChangesPre.xml or destructiveChangesPost.xml respectively.

 

Let’s make a package!

Say that you wanted deploy a net new custom object to an organization called Projects (original, I know right?).  Go ahead and make a new project object in your developer org and add the following:

  1. A picklist called “RYG” with values of “Red”, “Yellow” and “Green.”
  2. A date field called “Proposed Go Live Date”.
  3. A date field called “Go Live Date”.
  4. A long text area field called “Comments”.

That’s all we really need to demonstrate the concept.  I know it’s not a heavy custom object but bear with me.  Next we’re going to create an xml file.  Open up your favorite word editor.  All package files and destructive changes files include the header:

<?xml version="1.0" encoding="UTF-8"?>
<Package xmlns="http://soap.sforce.com/2006/04/metadata">

 

And the footer, which specifies the API version:

  <version>34.0</version>
</Package>

 

Notice that the <Package> tag, much like HTML markup is always has a closing tag. Now, we’ll make a package for our custom object:

<?xml version="1.0" encoding="UTF-8"?>
<Package xmlns="http://soap.sforce.com/2006/04/metadata">
  <types>
    <members>Project__c</members>
    <name>CustomObject</name>
  </types>
  <version>36.0</version>
</Package>

That’s it.  That’s all you need to get your custom object to deploy it to production.

 

Let’s get some commands!

We have to now specify all of the commands in order to get the metadata, check the deployment and deploy.  I’ll break each one down below:

  1. Getting metadata
<!-- Retrieve an unpackaged set of metadata from your org -->
<!-- The file unpackaged/package.xml lists what is to be retrieved -->
<target name="retrieveUnpackaged">
   <delete dir="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>

Breaking it down:

  • target – the command you’ll put in the command prompt
  • delete dir – delete the retrieveUnpackaged directory
    • Note: You can remove this but it will add all components to this directory, which can make it difficulty incase you perform multiple retrieves.
  • mkdir – make the directory retrieveUnpackaged
  • sf:retrieve – this is actually where the magic happens.  This is the retrieve command.  The two important commands that weren’t covered in the last post are:
    • retrieveTarget – where you are going to save the file.  In this case, it is the retrieveUnpackaged directory.
    • unpackaged – the full location of where the package.xml is.  In this case, it is in the unpackaged directory as package.xml.

 

All you have to do then, is combine this with your ant build functions from last week and type:

ant retrieveUnpackaged

 

The magic will happen and you will get something a lot like this:

 

antRetrieve

 

In your directory, “RetrieveUnpackaged” you will then have the package.xml used to retrieve the package and you will also have the objects directory, which will contain the data definition for the Project object.  Feel free to remove these files, as we will not need them to continue the exercise.

 

  1. Checking changes

Add the following command to your build properties file:

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

This is called with ant deployUnpackagedCheckOnly.  The important things to explain here are that:

  1. The deployRoot specifies the directory that is being deployed from.
  2. The rollbackOnError attribute specifies that we’re going to roll back changes if there’s an oopsie.
  3. The checkOnly specifies that it’s only a validation
  4. The singlePackage attribute specifies that all changes should be treated as a single package (needed for destructive changes).

Don’t worry about using this command yet.  We’ll be going through the exercise later!

 

  1. Deploying changes

Add the following command to your build properties file:

  <!-- 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" singlePackage="true"/>
 </target>

This is called with ant deployUnpackaged.  You will notice that all of the attributes are the same as above except for that we did not include “CheckOnly”.

Now,  that our build file is complete with all commands needed for this exercise, we’re going to exterminate some fields (aka use destructive changes).  We will then redeploy the fields back to the organization.

 

Destruction!

The biggest difference between package.xml files and destructive changes is that for destructive changes you must explicitly spell out each component you would like to delete.  Here are some things to remember when deploying a destructive changes:

  1. Even if you’re not deploying something along with your changes, you must include an empty package.xml file for the deployment.  Otherwise, you will get a “Payload error” in the user interface.
  2. Always make sure that you backup your destructive changes with an ant retrieveUnpackaged statement and file them away should you ever need them and don’t forget to backup the data too!!!
  3. Destruction isn’t always needed (at least immediately), you can deprecate the functionality first before saying let’s push that thing on out.  Otherwise, you might find yourself using that backup in step 2 sooner than you think!

 

On to the good stuff!

  1. Create a package.xml file with each of the components that we created earlier on our Project object. Try doing this first before looking below.  You might be surprised how easy it is.

 

<?xml version="1.0" encoding="UTF-8"?>
<Package xmlns="http://soap.sforce.com/2006/04/metadata">
  <types>
    <members>Project__c.RYG__c</members>
    <members>Project__c.Proposed_Go_Live_Date__c</members>
    <members>Project__c.Go_Live_Date__c</members>
    <members>Project__c.Comments__c</members>
    <name>CustomField</name>
  </types>
 <version>36.0</version>
</Package>

How did you do?

Remember our next step?  That’s right, back these suckers up!  Put your package.xml file in your unpackaged directory and call ant retrieveUnpackaged.

  1. Copy the files in your retrieveUnpackaged folder to another directory.  We’ll need these later.
  2. Copy the package.xml file and rename as “destructiveChanges.xml”.
  3. In the package.xml file, remove all component references.  It should look like the below.

 

<?xml version="1.0" encoding="UTF-8"?>
<Package xmlns="http://soap.sforce.com/2006/04/metadata">
  <version>36.0</version>
</Package>

 

  1. Run the ant deployUnpackagedCheckOnly command first.  This ensures that our deployment will pass and also is best practice.

If all goes well, you should be able to login to your organization and see a happy deployment with a big green circle. ANT will also tell you that the deployment succeeded but not with pretty colors, so… there’s that.

deploySuccess

  1. Now that we’ve seen that the deployment worked, run ant deployUnpackaged.  There’s no turning back!  Exterminate!
    1. Hint: You can hit the up arrow in the command line and just remove “CheckOnly” from the previous command.  It will save you some typing.

 

When you go to the project object, you will see that the fields have been removed, where they will be archived for a period of 15 days before being permanently deleted.

antDeploySuccess

 

Redeploying!

Now that we’ve completely removed the fields, let’s deploy back our changes to the organization using the same commands we used earlier: ant deployUnpackagedCheckOnly and ant deployUnpackaged.  Move the old package.xml file and the objects directory back to the retrieved Unpackaged directory.

  1. Run ant deployUnpackagedCheckOnly and verify that it succeeds.
  2. Run ant deployUnpackaged and the fields should be back, along with the “deleted fields” on the project page.

antDeploySuccess2

  1. Considering that we don’t have any data in these fields, unless you added some, this would be the part where you restore the data with your CSV file.

 

That’s it!  You’ve successfully retrieved components, deployed two changes to an org, one destructive and one additive.  Go ahead and give yourself a pat on the back!  This and the last post are fundamental to me doing my job and I hope that they will help you in yours too!


Leave a comment

Your email address will not be published. Required fields are marked *

One thought on “ANT Series – Getting Specific