Friday, 23 September 2016

Force CLI Part 4 - Deploying Metadata

Force CLI Part 4 - Deploying Metadata

Depfis2

Introduction

In previous posts in this series I’ve covered Getting Started, Extracting Metadata and Accessing Data via the Force CLI. In this post I’ll cover the functionality that I use probably 95% of the time that I use the Force CLI - deploying metadata from the local filesystem to a Salesforce instance.

The Building Blocks

Like other tools for deploying to Salesforce (e.g. migration tool, Eclipse IDE) there are a two items required to deploy via the Force CLI

Project Manifest (aka package.xml)

The package.xml file defines the metadata components that will be deployed - you can find out more about this in the Salesforce Metadata API Developer’s Guide

Metadata Components

The metadata components need to appear in the directory structure expected by the metadata API - e.g. Apex classes in a directory named ‘classes’, Visualforce pages in a directory named ‘pages'

I don’t make the rules (but I do make the deployment directory)

The rule when deploying is that the components specified in the package.xml manifest file need to match those present in the metadata components directory structure. If you specify components that are missing you will get an error, and if you provide additional components that aren’t mentioned in the package.xml, you’ll get a different flavour of error.

My metadata comes from GIT, so the metadata components structure of my entire project is defined there. However, I don’t always want to carry out a full deployment so I create a new structure in a temporary directory and create a package.xml file reflecting that. I also use a naming convention for my temporary directory so that I can look back at the order that I did things in - drop_<YYYYMMDDhhmmss>, where YYYYMMDD is the year/month/day of the date and hmmss is the hours/minutes/seconds of the time. The reason I go with this naming convention is that when I use the ls command, my directories are listed in order of creation:

$ ls -l

drwxr-xr-x  6 kbowden  wheel    204 16 Sep 14:39 drop_20160916141152
drwxr-xr-x  6 kbowden  wheel    204 17 Sep 10:11 drop_20160916184125
drwxr-xr-x  6 kbowden  wheel    204 17 Sep 12:45 drop_20160917121232
drwxr-xr-x  6 kbowden  wheel    204 18 Sep 12:56 drop_20160918092957
drwxr-xr-x  6 kbowden  wheel    204 18 Sep 19:21 drop_20160918185148
drwxr-xr-x  6 kbowden  wheel    204 20 Sep 15:39 drop_20160920152837

To use a very simple example, here’s the directory structure to deploy just the User object. My starting directory is /tmp/drop_20160923080432:

  /tmp/drop_20160923080432/target/objects/User.object
  /tmp/drop_20160923080432/target/package.xml

 My package.xml file just contains an entry to deploy the objects directly (it’s called CustomObject, but covers both standard and custom):

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

Deploy all the Metadata

Once the directory structure and manifest are in place, use the force import command to deploy your metadata, using the -d switch to specify the directory containing the metadata:

force import -d /tmp/drop_20160923080432/target

The Force CLI will update you every five seconds on progress

Not done yet: Queued  Will check again in five seconds.
Not done yet: InProgress  Will check again in five seconds.
Not done yet: InProgress  Will check again in five seconds.
Not done yet: InProgress  Will check again in five seconds.
Not done yet: InProgress  Will check again in five seconds.
Not done yet: InProgress  Will check again in five seconds.

Once the deployment is complete, you’ll get details of successes/failures - the default behaviour is simply the to output the number of each

Failures - 0

Successes - 24
Imported from /tmp/drop_20160923080432/target

While if you specify the -v switch, you'll get full details of each success/failure:

Successes - 24
User.DFP_Id__c
	status: unchanged
	id=00N80000005st6iEAA
User.Default_Tab__c
	status: unchanged
	id=00N80000005st6kEAA
User.Department__c
	status: unchanged
	id=00N80000005st6lEAA

   ...

Deploying to Production

As everyone in the Force.com world knows, in order to deploy metadata to production you need to run some unit tests. The Force CLI provides support for this via the -l switch, which takes the same options as the migration tool:

  • NoTestRun 
  • RunSpecifiedTests
  • RunLocalTests
  • RunAllTestsInOrg

Verification Only

Another very useful switch is -c. This carries out a verification only deployment and rolls back all changes upon completion. I use this as part of our continuous integration environment to make sure I can successfully deploy to a clean development environment.

Related Posts

 

3 comments:

  1. And how to erase a classe in production with Force Cli?

    ReplyDelete
  2. This comment has been removed by a blog administrator.

    ReplyDelete
  3. Can you explain why for unit tests used lower API version?
    Example.
    ClassA has API Veriosn 25.
    ClassB use static method from ClassA has API Version 35.
    UnitTestAbsolutlyUnrelated from ClassA and ClassB has API Version 39.
    We want to deploy only ClassB with all unit tests runs. The deployment falls to API version 25.
    Why?

    ReplyDelete