First Impressions with Salesforce DX and Source Driven Development

Salesforce DX provides development teams with an integrated, end-to-end lifecycle for high-performance agile development – designed to be open and flexible so you can build together with tools you love. The project was announced at Dreamforce 2016 and since then there has been a lot of interest across the entire Salesforce developer community. A few weeks ago, the Salesforce Developer Relations team got our first access to the internal developer preview – and I have to say it’s blowing my mind.

A Shift in (Salesforce) Developer Mentality

Typically in Salesforce, everything you build revolves around your org. Whether you’re working in a production org with dependent sandboxes or in a developer edition, the canonical source of truth is hosted in your Salesforce environment.

Development Workflow

This is different from workflows you may be familiar with if you develop on other platforms, where your source of truth is often a version control system, and modern software development tools have made automated testing and delivery a commodity.

Given these expectations as a developer, I feel like I’m waking up in a place that is both familiar and strange all at once. So what’s Salesforce DX and how does it change the work of a Salesforce developer?

The Tools

With Salesforce DX, you’ll continue working with a number of familiar tools, but you get access to a whole lot more. For me, the most significant new features that underlay the developer workflow are new APIs, the environment hub, scratch orgs, and a powerful new command line interface. Let’s go over these quickly:

Environment Hub

The Environment Hub is a new feature that you will see in an org when Salesforce DX has been enabled. It is similar to the list of Sandboxes in Setup that you are likely familiar with already. The difference is Environment Hub allows you to track all of the orgs you use. When Environment Hub is enabled in an org, it establishes that org as a central management point for other orgs. Users in that org can be granted permissions to create, delete, and manage orgs. Licenses for development, and testing orgs are linked to Environment Hub.

Speaking of orgs, that brings us to another new feature.

Scratch Orgs

I have at least 100 Developer Editions – possibly more. I don’t even know what they were all for, but I needed them once…a long time ago. So I keep them around. Scratch Orgs represent a significant change in how we think of our developer and test environments. They are quick to provision, accessible primarily by a single user (developer, test engineer or admin), and both temporary and easy to destroy. Scratch orgs are created using a straightforward JSON descriptor file that can be kept and maintained in source control.

New APIs and new Salesforce CLI

While all the APIs you know and love continue to be available, we’ve created new APIs to help you work with the Environment Hub and Scratch Orgs and to make it easy to integrate these new features into your workflows.

Wrapping these new and existing APIs is a new command-line interface that represents a significant enhancement to the Salesforce developer lifecycle. Whether you want to work directly in a terminal, create scripted deployments, or use it as the foundation for building all-new tools, the CLI gives a single interface to access many different APIs in a simple declarative way.

And More…

There are new development pipeline and continuous delivery tools that we’re building as part of Salesforce DX leveraging existing Heroku tooling. We have a next generation of the Force.com IDE. We’re also working on making the process of syncing local source to org source more straightforward. We’ll wait to go into details about those in a future post. But if you want a sneak peak, I put some video links at the end of this post.

Get Into the Salesforce DX Flow

The new workflow I’ve begun to work with in Salesforce DX goes as follows:

Clone a source repository

Here, I clone a repo where from a source project and checkout a new branch.

$ git clone sfdx-dreamhouse sfdx-demo                                                              
Cloning into ‘sfdx-demo’…
done.
$ cd sfdx-demo/
$ git checkout -b slider-component
Switched to a new branch ‘slider-component’

Sign Into Environment Hub

Now that I’ve got source code to work with, I need an org. Environment Hub is what gives me permissions to manage orgs, so I’m going to connect my local workspace to Environment Hub.

$ heroku force:org:authorize
Successfully authorized hub org: 00D0Y000000ZHNPUA4                                                
You may now close the browser

This command launches an OAuth flow where I sign into an the Environment Hub org. Again, I won’t be doing work here, but it provides me with powerful capabilities to manage all of my orgs in one place!

Provision a Workspace Org

This next step is similar to checking out the latest source from a version control system in traditional team development. Before I can start working on my code, I need to build my developer environment. Of course in our world, the org is the runtime, but let’s dive right in!

First I generate a scratch org. To tell Salesforce DX what I want that org to look like (for example, edition, configuration parameters, and other items) recall we use a JSON file to specify those configurations.

$ heroku force:org:create -f config/workspace-scratch-def.json
Successfully created workspace org: 00D5C000000H54YUAS, username: workspaceorg1480091790559@democompany.com

I now have a repo full of metadata, code, and test/seed data – but my org is still empty. Let’s finish setting up the org so it’s ready to work with. The next steps we will perform are as follows:

  1. Push my local source code to the scratch org
  2. Assign my user in the scratch org with permissions to see the existing app
  3. Import my test/seed data
$ heroku force:src:push
Pushing source metadata changes to org 00D5C000000H54YUAS as user workspaceorg1480091790559@democompany.com
State Full Name                     Type                 Workspace Path
───── ───────────────────────────── ──────────────────── ────────────────────────────────────────────────────────────────────────
Add   DreamHouse                    CustomApplication    force-app/main/default/applications/DreamHouse.app-meta.xml
Add   Gallery.COMPONENT             AuraDefinition       force-app/main/default/aura/Gallery/Gallery.cmp-meta.xml
Add   Gallery.COMPONENT             AuraDefinition       force-app/main/default/aura/Gallery/Gallery.cmp
Add   Gallery.STYLE                 AuraDefinition       force-app/main/default/aura/Gallery/Gallery.css
Add   Gallery.CONTROLLER            AuraDefinition       force-app/main/default/aura/Gallery/GalleryController.js
Add   Gallery.HELPER                AuraDefinition       force-app/main/default/aura/Gallery/GalleryHelper.js

Add   DreamHouse                    PermissionSet        force-app/main/default/permissionsets/DreamHouse.permissionset-meta.xml
Add   RejectDuplicateFavoriteTest   ApexClass            force-app/test/default/classes/RejectDuplicateFavoriteTest.cls-meta.xml
Add   RejectDuplicateFavoriteTest   ApexClass            force-app/test/default/classes/RejectDuplicateFavoriteTest.cls

Did you notice the step above where I added the permission set? As I mentioned, we need to assign the permission set to my user in the scratch org so I can see the newly loaded application. Then, I’ll load my test data and open up the org in my browser. We’ll perform all three of these steps via the command line:

$ heroku force:permset:assign -n DreamHouse
Permission Set successfully assigned
$ heroku force:data:import –plan data/sample-data-plan.json                                                        
Reference ID          Type        ID
───────────────────── ─────────── ──────────────────
CarolineBrookerRef    Broker__c   a005C000000riQLQAY
MichaelJonesRef       Broker__c   a005C000000riQMQAY

18HenryStRef          Property__c a025C000000fqJFQAY
24PearlStRef          Property__c a025C000000fqJGQAY
72FrancisStRef        Property__c a025C000000fqJHQAY

And finally, using the command line, I can actually launch the org without having to manually supply a username and password.

$ heroku force:org:open
Access org 00D5C000000H54YUAS as user workspaceorg1480091790559@democompany.com with the following URL: https://inspiration-flow-9502-dev-ed.cs62.my.salesforce.com/secur/frontdoor.jsp?sid=00D5C000000H54Y!AR4AQLn._YAThLFortqKdD13UhC9P5AM_IYndtQRsDV535A59gmZ9PVqusZ73P.hQIRaKTFm8s5DSsNyiOIbkZTiMmC.9Q4i

Build My Feature

At this point, I would set about working on my code changes. For instance, I might use an IDE to make a change to some Apex code or to a Lightning Component. In my case, I modified a Lightning Component.

$ heroku force:src:push
Pushing source metadata changes to org 00D5C000000H54YUAS as user workspaceorg1480091790559@democompany.com
State    Full Name                   Type            Workspace Path
───────  ──────────────────────────  ──────────────  ──────────────────────────────────────────────────────────────────────────
Changed  PropertyExplorer.COMPONENT  AuraDefinition  force-app/main/default/aura/PropertyExplorer/PropertyExplorer.cmp-meta.xml
Changed  PropertyExplorer.COMPONENT  AuraDefinition  force-app/main/default/aura/PropertyExplorer/PropertyExplorer.cmp

It’s worth pointing out one important detail here. I didn’t have to tell Salesforce DX what has changed…it already knew. Likewise, if I change something in the org such as a new object or field, I simply have to do heroku force:src:pull, and that new metadata will be added to the local workspace. This is thanks to new architectural features that allows an org to track changes. To learn more about these changes, check out the on-demand Deep Dive into the New Salesforce Development Experience (DX) Architecture session from Dreamforce.

Wrapping Things Up

Now that I’ve provisioned and configured my org, loaded all of the data and pushed my changes, it’s time to test my feature to make sure it works. If it does, I take care of any VCS housekeeping like commits, pushes, or pull requests and I’m done.

$ git push origin slider-component                                                                  

Success! So now that I'm done, what good is it keeping this org around? Why not delete it?

$ heroku force:org:delete –username workspaceorg1480091790559@democompany.com
Enqueue scratch org with name: workspaceorg1480091790559@democompany.com for deletion? Are you sure (y/n)?: y
Successfully marked scratch org workspaceorg1480091790559@democompany.com for deletion

Meet Your Org, The Runtime Environment

This is Salesforce. What you build runs on our servers. But with scratch orgs the environment feel much more like a temporary runtime environment. Working on a feature with Salesforce DX feels a lot more like working in other development frameworks. It is a firm step away from a single environment that is the nexus around which all work must revolve.  

And it is this reduction in the importance of the org that is blowing my mind.

After my initial experimentation with the Salesforce DX developer preview, I am more excited than ever to explore new ways to use the new developer workflow. I also think it will bring about a fundamental shift in thinking on the part of our many developers and admins who have come to expect the production org as the source of truth. 

Hopefully this little taste has you excited. But you might also feel a bit daunted if you aren’t used to working with the command line, or are not a coder. I wouldn’t worry too much. For now the focus of Salesforce DX is on building a foundation for good project lifecycle management. But eventually, this will serve as a base for even better point-and-click tools that give our admins and declarative developers a frictionless and intuitive process as well.

So much more to see in Salesforce DX…

I feel I’m just scratching the surface as I get to know the new Salesforce developer experience. The Developer Relations team will do our best to share more sneak peeks as we get more time with Salesforce DX.

Can’t wait to try it yourself? I bet…I couldn’t either. For now, if you want to find out more, I would suggest one of the excellent Salesforce DX videos that came out of Dreamforce 16. To help people find them, I made a YouTube playlist.

Or you could take a look at these three videos from that playlist individually:

Stay tuned for more soon!

tagged , , , , Bookmark the permalink. Trackbacks are closed, but you can post a comment.
  • Daniel Ballinger

    Your Scratch Org looks like it is a sandbox on CS62. Does that mean it gets limits like a Developer or Developer Pro sandbox? Do we have any control over which sandbox we end up on?

    It would be interesting to see more on the internals of the workspace-scratch-def.json file and the Trialforce Template (0TT) that drives it.

    • pchittum

      There is much too much in Salesforce DX to sum it up in a single blog post. Details of the JSON descriptor files and more about scratch org management is a high priority. Feedback from readers will also help us know how to prioritize which details we drill into in the future. Thanks!

      • Daniel Ballinger

        I can believe there is a lot to cover. I look forward to the future posts.

        With regards to limits and the org type. I guess there are two parts to that.

        Often the Org Type and enabled features will have a big impact on what can and can’t be implemented. Part of that will be being able to toggle features like multi-currency from the JSON file. The other part will larger org edition limits like Professional versus Enterprise.

        One thought with regards to selecting a pod/instance. During the release cycle some sandboxes might be on the pending release and some on the existing production version. It would be useful to create a Scratch org in one or the other.

        I’d also be interested in how the content from source control will also be deployed to existing sandbox and production orgs for deployment. Would deploying to production be a matter of doing a force:src:push to the right remote ref?

        • pchittum

          Currently the workflow outlined is that src:push/pull work to keep your local workspace in sync with your scratch org (the remote runtime). Deploying to other orgs you would use a package or MD API deploy. The CLI has commands for each of these parts of the workflow.

          • Fabien Taillon

            And for the release cycle question ? If we’re at a time where half of the Production environments are in the new release, and half still in the “old” one, do we have a way to choose ? Or is it just random depending on the instance where the scratch org will be created ?

        • Jason Clark

          Regarding selecting instance: Very frustrating today when a new sandbox is provisioned on the same instance as another sandbox I’m actively using, since logging into one logs out of the other. Can happen across clients (I’m a consultant), or even two sandboxes for on client (dev vs UAT). chance to pick instance, or to pick a “pod group” (e.g, A, B, C, D, each has some batch of instances) to still allow SF to load-balance across pods, but let devs separate their instances, would be helpful.

          • Fabien Taillon

            On this it’s not an issue anymore if you activate My Domain, which is mandatory for Lightning Components anyway.

          • pchittum

            That’s definitely frustrating.

            Scratch orgs are provisioned with mydomain enabled automatically. So as Fabien states, not an issue. It should be easy to have several scratch orgs open…scratch org+sandbox, etc. at the same time.

  • RC

    When is this out?

  • Very exciting stuff!!! Cannot wait to get my hands on it. Thanks Peter!!!