Salesforce DX Pilot — first impressions

This post was originally written for Ebury Labs.

I applied to be one of the lucky members to be part of the Salesforce DX Pilot and I was selected! Salesforce DX Pilot started on the 22nd of February and it is still going on, but I wanted to share with you my impressions so far.

What is Salesforce DX

Salesforce DX is a set of tools and features to develop and deploy applications in an automated, continuous and collaborative way.

One of the main weak points of the Force.com platform is the lack of tools to develop and release apps in an automated way. Not all metadata can be released automatically, and there are many steps and configurations that need manual interaction. This is really a pain. Salesforce DX is here to solve those problems by offering a set of tools to integrate our development processes with our continuous integration and continuous delivery systems.

The main goal of Salesforce DX is to align with the industry standards regarding the life cycle of software development.

These are the highlights of Salesforce DX:

  • Scratch Orgs: These are orgs that you can create on the fly to push your new application or changes. These orgs are temporary, currently they expire after 7 days, and are meant to be used only as part of the development. Once the development is finished, the scratch org is meant to be deleted. A scratch org is not a sandbox. A sandbox contains a copy of all your prod metadata while the scratch org doesn’t, it is empty. The scratch org will only have the metadata that you push to it.
  • CLI (Command Line Interface): Salesforce has built a complete set of commands to manage the different tools. I just need to thank Salesforce for doing this. I love commands and this is something I really missed in force.com.
  • Version Control Systems as “source of truth”, this is opposite to what we have now where the code that sits in our orgs is the source. This is a big step.
  • Integration with Continuous Integration (CI) and Continuous Delivery (CD) systems.
  • Packages 2.0: Up to now, packages have been used by Independent Software Vendors (ISV) to release their applications. Salesforce is defining a new version of packages to be used by clients internally to facilitate the development and deployment of applications internally. This part is not quite mature yet and there is not much information.

This was all theory about Salesforce DX, now I want to present a practical example.

Practical example

I will share a standard use case of Salesforce DX. We will assume that we have an existing Force.com application released in our org and we want to add a new feature to it using Salesforce DX. This scenario is quite interesting because when Salesforce DX becomes GA (General Availability), there is something that we would need to think about. What do we do with our existing applications? How do we move them to Salesforce DX?

Based on the assumption that I already have an application in my dev org and I have defined an unmanaged package containing all the components of my application, I’m going to download that application to my local machine using Salesforce DX. I’m going to convert it to the Salesforce DX format. I’m going to upload it to a scratch org and I’m going to do some changes to it.

I won’t go in detail of all the things that are needed, don’t consider this as a precise guide, my intention is that you get a feeling of what can be done with Salesforce DX.

Create a Salesforce DX workspace

First thing that we need to do is to create a Salesforce DX workspace.

$ sfdx force:workspace:create --workspacename ebury

This creates a folder structure with some defaulted configuration files (sfdx-workspace.json, workspace-scratch-def.json).

|ebury/
| config/
| workspace-scratch-def.json
| force-app/
| main/
| default/
| sfdx-workspace.json

By default, the Salesforce DX app source code is stored under force-app/admin/default. You can change it by editing sfdx-workspace.json.

Since here is where our code is going to live, following good practices, we should initiate a repository here with our preferred control version system, and push our changes to it. This is not integrated with Salesforce DX, this is something you need to do yourself.

Authenticate an org

Now I need to allow Salesforce DX to access to my dev org to download my application. To do this I use the authentication command.

$ sfdx force:auth:web:login --setalias MyDevOrg

–setalias is used to give a friendly name to the org so it is easy for us to reference it in future commands.

This is attacking the url https://login.salesforce.com defined by default in the sfdx-workspace.json configuration file. If we want to specify a different url we would use the parameter –instanceurl.

When we run this command a Salesforce site is opened in your browser and you are prompted to enter your credentials.

List orgs

We can check our authorized orgs with the list org command.

$ sfdx force:org:list

This returns:

=== Organizations
Alias Username Organization ID
──────── ───────────────────────── ─────────────────
MyDevOrg yaiza.bailen@ebury.com 00D0Y000001fwkvUAA
dev-hub-org dxpilot+yaiza.bailen@ebury.com 00D0Y000001K5lVUAS

Retrieve data from a sandbox

Now that we have authorized Salesforce DX to access to our dev org, let’s retrieve our application. I will use the unmanaged package that I have defined in my dev org.

$ sfdx force:mdapi:retrieve -u MyDevOrg -p “Award Nomination” -r myDevOrg-data/

-u MyDevOrg: tells Salesforce DX the org where it has to connect

-p “Award Nomination”: name of the package we are retrieving

-r MyDevOrg-data/: folder to store the downloaded data

The execution of this command downloads a .zip file containing all the components defined in the Award Nomination package under the folder myDevOrg-data/. We need to unzip it.

Convert data to Salesforce DX format

We have to convert that data to the format that Salesforce DX understands.

$ sfdx force:mdapi:convert — rootdir myDevOrg-data/

–rootdit myDevOrg-data/: path to the source code to convert

By default the destination folder for the converted code is force-app/main/default/ as it is defined in the sfdx-workspace.json configuration file. We can define a different destination folder with the parameter -d.

Create a scratch org

Now that we have our application in our local machine converted to the Salesforce DX format let’s create a scratch org and upload our application to it.

To create a scratch org:

$ sfdx force:org:create — definitionfile ./config/workspace-scratch-def.json — setalias MyScratchOrg — setdefaultusername

–definitionfile config/workspace-scratch-def.json: configuration file we are using to create the scratch org. In this file you can define all the features you need for your org (Lightning, Community, Chatter, Opportunity Teams, etc)

–setalias MyScratchOrg: defines an alias for our scratch org

–setdefaultusername: If we don’t specify the username in future commands, by default Salesforce DX will attack to this scratch org.

Open a scratch org

We can open our scratch org directly from the command line. This command opens a window in our browser redirecting it to our scratch org.

$ sfdx force:org:open

Push changes

Let’s upload our Salesforce DX application to the scratch org.

$ sfdx force:source:push

We are not specifying where our code is, because by default it is looking at force-app/admin/default/ and our code is there. We are not specifying either where to push our code because we defined our scratch org as default on creation.

When we run this command, if we go to the scratch org we can see our application there.

If you have layouts you would need to assign those layouts manually to your admin user.

If you have new fields in your application, you can give them field-level security (FLS) permission manually, or if you have defined a permission set as part of your application you could assign that permission set to your user directly from the console.

Assign a permission set

$ sfdx force:user:permset:assign -n Award_Nomination

This commands assign the Award_Nomination permission set to your admin user.

Source code status

Now that we have our application working in our scratch org we are ready to add a new feature to it. We could edit it in our scratch org directly, for example, adding a new field to the Case, and we could also edit in our local machine editing a class, for example.

We can track the changes that we do to our application with the status command, that tells us where the changes have been done if locally or remotely.

$ sfdx force:source:status

In our example, this would return:

State           Full Name      Type          Workspace Path
──────────── ──────────── ────────── ─────────────────────
Local Changed NomCntroller ApexClass force-main/default/classes/NomCntroller.cls-meta.xml
Local Changed   NomCntroller   ApexClass     force-app/main/default/classes/NomCntroller.cls
Remote Changed  Case           CustomObject  force-app/main/default/objects/Case.object-meta.xml

Pull / Push changes

If we have changes remotely and locally we need to synchronise them. We use the push and pull commands to do that.

To upload our local changes we use push.

$ sfdx force:source:push

This time it only uploads the changed files, not all our code again.

If we run the status command now:

$ sfdx force:source:status

We would see:

State           Full Name    Type          Workspace Path
────────────── ─────────── ─────────── ──────────────────
Remote Changed Case CustomObject force-app/main/default/objects/Case.object-meta.xml

And to retrieve the changes done in the org we use pull.

$ sfdx force:source:pull

Run tests

Finally, we can run our tests from the command line.

$ sfdx force:apex:test:run -r human -c

You can specify which tests you want to run with the parameter –classnames.

It returns something like this:

=== Test Results
Test Name                                    Outcome Runtime (ms)
─────────────────────────────────────────── ─────── ──────────
DO_CreateNominationControllerTest.testNominate Pass 1846
=== Test Summary
Name                 Value
────────────── ────────────────────────────────────────────
Outcome Passed
Tests Ran 1
Passing 1
Failing 0
Pass Rate 100%
Fail Rate 0%
Test Start Time Jun 10, 2017 1:06 PM
Test Execution Time 1846 ms
Test Total Time 1846 ms
Command Time 8423 ms
Test Run Id 7073D000000M9rd
Hostname https://fun-innovation-8417-dev- ed.cs70.my.salesforce.com
Org Id 00D3D0000008jmdUAA
Username scratchorg1497091840759@yaizacompany.com
User Id 0053D000000IH8nQAG
=== Apex Code Coverage
Id                 Name               % Covered Uncovered Lines
────────────────── ────────────────── ───────────────────────
01p3D000000UsJoQAK NomCntroller 100%

And that’s all for now. I hope this post helps to understand what Salesforce DX is and what we can do with it.

I’m really excited about it and I’m sure it will change the way we develop and deploy Force.com applications.