Continuous Delivery with Salesforce DX and Jenkins — Differential Deployment enabled

Continuous Deployment — — Yes we need it

Hi Guys,

Welcome back to the new story (maybe an old meat cooked-up with a new spicy sauce 😜). In one of my previous blogs, I was explaining about Continuous Integration to Salesforce with migration tool. Here we will see how we can achieve the same with Salesforce DX. Pretty much there are so many articles on how to setup Continuous Deployment with Salesforce DX. But this blog should be little different (thinking so 😛). This will explain doing the same but just the part where we will deploy the differences alone and not a full deployment. Well lets see how we can do that.

First to go forward we can see what is Salesforce DX.

Developers can now build collaboratively and deliver continuously with Salesforce DX, the open and integrated experience that makes development on the Salesforce Platform easy.

The above explanation is just so simple to read. But kudos to the DX developers. It has really cool features to be used in our projects.

The tools to be installed to work with Salesforce DX is as below

  1. Salesforce CLI — Command-line Interface introduced by Salesforce. A powerful CLI to do everything with Salesforce
  2. Visual Studio Code — Hmm this IDE is mainly for developers who would like to work with Salesforce using Salesforce DX. In the world of developers, who wouldn’t like to work with latest IDE, which has so many cool features for the developers to love it
  3. Salesforce Extension Pack — Visual Studio Code plugin which integrates Salesforce CLI and Visual Studio Code. Now we got a chance to move out of Eclipse and to move in to Visual Studio Code for modern-day development

This blog features three sections

VCS Code and Salesforce DX

Now we will see how we can create a SFDX project in Visual Studio Code with just few steps (Anyhow the devs who knows this process already, please skip this section so as to not waste time, as Time is precious 😆)

  1. Open VCS and press Ctrl+Shift+P, which will open a command palette. Enter SFDX: Create Project to create a new SFDX Project (There are some additional steps on selecting the command SFDX: Create Project. But that’s easy to follow, so we are not covering those steps here)
  2. If you have already created a project with Migration tool, you can simply convert your project to SFDX format with just one command
sfdx force:mdapi:convert — rootdir <src-folder> — outputdir <destination-folder>

src-folder — folder containing the source-code of all metadata with package.xml obtained when using Migration Tool

destination-dir — folder to which the metadata converted into SFDX format should be stored — typically force-app folder which is the main folder used in SFDX project

3. Now you all are set forward with your development in VCS. Authorize yourself with your Salesforce Org which might be Sandbox or Scratch Org. by using command SFDX: Authorize in command palette (which you get after pressing Ctrl+Shift+P). Next edit your code and once you are done to push the code to your Salesforce org or Scratch org to which you are authorized by using command SFDX: Deploy Source Code in command palette.

Now lets concentrate on main part of this blog.

Setup Jenkins to use Salesforce DX

Required things to use Salesforce DX with Jenkins

  • Custom Tools plugin in Jenkins
  • Extra Tools plugin in Jenkins
  • Salesforce CLI — Try to install Salesforce CLI in your Jenkins server. If you have access to Jenkins server, you can directly install Salesforce CLI as you did in your local machine. Else nothing to worry. Go to Manage Jenkins > Global Tools Configuration. Under Custom Tools section, click on Add Custom Tool and Execute Batch Command (or Execute Shell Command in linux machines) and run the below command and just do a dummy trigger from your Jenkins project to install the necessary plugins with Salesforce CLI
curl "<url_for_sfdx_cli>" -o "sfdx.tar.xz"
mkdir sfdx
tar -xvJf sfdx.tar.xz -C sfdx --strip-components=1

<url for sfdx cli> — the manifest file where you can find your specific URL for installing Salesforce CLI in Jenkins

Once Salesforce CLI is installed in your jenkins with necessary plugins as said above, now its time to instruct Jenkins-Slave to use Salesforce CLI installed in Jenkins-Master.

For this purpose, we use Custom Tools plugin and Extra Tools Plugin together.

Go to Jenkins > Manage Jenkins > Global Tool Configuration and we create a new custom tool installation like as shown below

Here Tool Home variable refers to the path where Salesforce CLI is actually installed in Jenkins

Next create a connected app in Salesforce with JWT authorization setup using OpenSSL and give necessary permissions and decide through which user creds will we be authorizing with Salesforce. Probably we will use Jenkins to authorize to Salesforce sandbox or Scratch Org using this connected app. Take a note of Client Id, Username of the user through which we decide to authorize to Salesforce and finally the path of secret.key (private certificate) file which we use to sign the public certificate in Salesforce, which is actually generated through OpenSSL.

With all those points noted above, we create environmental variables in Jenkins as this will be used for all our deployments through Jenkins. Use Credentials Manager plugin in Jenkins and create three global credentials, each pointing to Client Id of the connected app, username through which we authorize to Salesforce and path of secret.key file, respectively.

Lets consider you have named the variables like as below

User_name_DXSecret Text → Username to authenicate to Salesforce

Connect_App_Consumer_KeySecret Text → Consumer key created when creating Connected App in Salesforce

server.keySecret File → secret.key (private key) file which we use to sign the public ceritificate which we created using openSSL and uploaded to Salesforce for JWT Based authorization with the connected app.

Phewww….. Done with basic setups.

Create Jenkins Project for continous deployment

Now we are in our final step. Lets create a simple Jenkins project (a freestyle project — pipeline project is not in this scope though)

First of all, to execute this step, we will be using ant (still I believe it is a powerful tool). Create a new file build.xml with below code in your git project.

Lets see in detail what this build.xml actually meant to be

taskdef node → Have a lib folder in your repo and download ant-contrib-1.0b3.jar which will be used for exeucting for loops in your ant build file

macrodef node named gitDiff→ Execute GIT DIFF command which will be used to find differences between two commits (possibly difference between Previous successfully deployed build commit and current GIT Commit) — This is the key to differential deployment. Don’t worry about GIT_COMMIT and GIT_PREVIOUS_SUCCESSFUL_COMMIT as these are the variables supported by Github plugin in Jenkins to fetch the current Git commit because of which the build is triggered and the previously used Git commit which has been successfully deployed with Jenkins

target node named diffBuilderWithGitCommit → execute the gitDiff command to find the file differences between two git commits as explained above. Check if the one among the differences is under force-app folder(which contains the source code). If so, copy those files and move it to deploy-sf folder(which will be used for deployment). If that file has meta xml file, move that as well to deploy-sf folder (We have these files mainly for Apex classes and lightning components).

Done with your build.xml. Now lets move to the project which we created in Jenkins.

This project which we created in Jenkins should read the code from your github repo

Next we will instruct the Jenkins project to use the environment variables which we created in Jenkins in the above configuration step

Also make your Jenkins project to use the custom tools which we installed in our configuration step above

Now it is our core execution part.

We will make Jenkins to execute the above ant target diffBuilderWithGitCommit. After deploy-sf folder got created with the exact differences to be deployed to Salesforce, get authorized with Salesforce using sfdx:authorize command, make it as default org to deploy and then deploy the deploy-sf folder using sfdx:deploy command

sfdx.cmd force:auth:jwt:grant --clientid "%Connected_App_Consumer_Key%" --username "%User_name_DX%" --jwtkeyfile "%JWT_KEY_FILE%" --instanceurl --setdefaultusername

The above command is used to authorize with Salesforce with client id (created using connected-app in Salesforce which we created with JWT approach), username (username through which we will deploy to Salesforce org) and jwtKeyfile (The path of secret.key private file which we used to sign the public certificate stored in Salesforce created using OpenSSL). Also here we use — setdefaultusername to make this username as default so as to make deploy command to pick this username for deployments

Since Im using Windows, you can see Windows commands. If you are using Mac or other systems for your Jenkins server, the command syntax format might differ a little bit, where we use “${env.variable}” instead of “%env.variable%”

sfdx.cmd force:source:deploy --sourcepath "deploy-sf" --json --loglevel fatal

The above command is to deploy the deploy-sf folder created with the above username

That’s it. It is all done. It is left to the project creator whether they want they want Jenkins to poll the git repo on a periodic basis for deployments, or deploy when and ever there is a push to Git using Git Hooks or do a manual build by clicking on Build Now in their Jenkins project.

Hmm.. That’s it. Sit back and relax now. Kudos, we did a great job. Now edit your class, or Lightning Web Components or object metadata in VCS, save it , push it to Git and trigger the build with Jenkins (either automated or manual). Tadaaa…. Your changes are deployed to your lovely Salesforce org. Cool isn’t it…!!!!!

As usual your likes and comments are much appreciated 😃

Salesforce and UI … May be a bit more :P