Create a Salesforce CI/CD pipeline using Gitlab CI (or any other)

With Salesforce DX not being general, available having a good delivery pipeline on Salesforce is quite cumbersome. We show you how to do it using Gitlab CI.

So in short, how this will work:

  1. We setup the needed tools
  2. We grab all the metadata from your Salesforce Org
  3. We commit the relevant parts of your code
  4. We create a pipeline testing and deploying the code to one or more Salesforce Orgs

Need help setting this up? Contact us.

#1 Setting up the tools

We use the Salesforce Metadata API to deploy new code and possibly other things like permissions to different environments. For this you can use the Force.com Migration Tool but that simply s*cks. There is this awesome force-dev-tool (a npm package) that wraps the whole thing much more usable. Install it using:

npm install --global force-dev-tool

Next you should be able to run the following command:

$ force-dev-tool
Usage:
    force-dev-tool <command> [<args>...]
    force-dev-tool -h | --help
    force-dev-tool --version

Configure your different environments (Salesforce orgs).

$ force-dev-tool remote add development user pass --default
$ force-dev-tool remote add production user pass

Check if you can login.

$ force-dev-tool login development
Logged in successfully to remote development.
Use the following URL to open Salesforce in your web browser:

https://mynamespace.my.salesforce.com/secur/frontdoor.jsp?sid=REDACTED

#2 Grabbing the metadata

Create a new folder for your project:

$ mkdir your-sf-project

To download all the latest metadata from your production org (or any other) run:

force-dev-tool fetch --progress production
force-dev-tool package -a production
force-dev-tool retrieve production

This will create a src folder with all your metadata. The src/package.xml file will contain all the different items we want to deploy (sync to other orgs).

The hard part now is to strip the src folder and src/package.xml to only contain the relevant parts you want to have deployed. Let’s say you only want to deploy all things Apex. Edit src/package.xml to only contain something like:

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

Remember, not all types support the * (wildcard) in members.

Next remove all folders from src except:

src/classes/
src/components/
src/triggers/

#3 Committing the code to Gitlab

Get into an empty project directory to grab your Salesforce environment.

$ cd your-sf-project
$ git init . # or an existing Gitlab project repo
$ git add .
$ git commit -m "My first Salesforce metadata."
# Add your remote repo and push your code (to Gitlab / Github / Bitbucket / ..)

#4 Creating an automated pipeline

Your CI/CD pipeline will use two commands. One to test deployments without actually doing a thing. Another to really deploy.

force-dev-tool -ct development # This will do a dry-run
force-dev-tool -t development # This will test and deploy

In Gitlab this is super easy, just create the following .gitlab-ci.yml file:

stages:
  - test
  - deploy
image: node:7.2.0
before_script:
  - npm install --global force-dev-tool --silent &>/dev/null
cache:
  paths:
    - /usr/local/lib/node_modules
  untracked: true

test_deploy_development:
  stage: test
  script:
    - force-dev-tool deploy -ct development

test_deploy_production:
  stage: test
  allow_failure: true
  script:
    - force-dev-tool deploy -ct production

deploy_development:
  stage: deploy
  environment: development
  only:
    - develop
  script:
    - force-dev-tool deploy development

deploy_production:
  stage: deploy
  environment: production
  when: manual
  script:
    # The -t makes sure we run tests
    - force-dev-tool deploy -t production

Commit this file to your repo, push it to Gitlab and whach your changes being deployed automagically. To deploy to your production environment / org you still need to press the play button.

Need help setting this up? Contact us.