Deployments

Deployment Best Practices. Focuses on CI/CD as this is the current best practice.

Introduction - Why are we even doing it like this

Salesforce deployments are essential for managing and evolving Salesforce environments, especially in a consulting company setting. There are several methods for deploying metadata between organizations, including Change Sets, the Metadata API, and the Salesforce Command Line Interface (CLI). Each method has its unique advantages, but the introduction of Salesforce DX (SFDX) has revolutionized the process, making SFDX-based deployments the standard for the future.

The main reasons are because it is easy to deploy, and easy to revert to a prior version of anything you deploy as well - proper CI/CD depends on GIT being used, which ensures that everything you do can be rolled back in case of bugs.

A table of deployment methods with advantages and disadvantages
Deployment Method Advantages Disadvantages
Change Sets

- Easy to use with a graphical interface

- No additional setup required

- Limited to connected orgs

- Manual and time-consuming

- No version control

- Can be done ad-hoc

Metadata API

- Supports complex deployments

- Can be automated

- Broad coverage

- Requires programming knowledge

- Steeper learning curve

Salesforce CLI (SFDX)

- Advanced automation

- Supports modern DevOps practices

- Version control

- Steeper learning curve

- Initial setup and configuration required

- Requires trained staff to maintain

Third-Party Tools

- User-friendly interfaces

- Advanced features and integrations

- Additional costs

- May have proprietary limitations

Despite the complexity inherent in SFDX-based deployments, the benefits are substantial. They enable easy and frequent deployments, better testing by customers, smoother go-lives, and a general reduction in stress around project development and deployment cycles. The structured approach of SFDX ensures that deployments are reliable, repeatable, and less prone to errors.

To stay fact-based: SFDX deployments allow deploying multiple times a week in a few minutes per deployment. This allows very easy user testing, and also allows finding why a specific issue cropped up. You can check the Examples section to see how and why this is useful.

It is perfectly true that these deployments require more technical knowledge than third-party tools like Gearset or Changesets. It is our opinion that the tradeoff in productivity is worth the extra training and learning curve.

One thing that is often overlooked  - you can NOT do proper CI/CD without plugging the deployment to your project management. This means the entire project management MUST be thought around the deployment logic.

This training is split into the following chapters:

Chapter 1: The Why, When and By Whom

This chapter explores the fundamental considerations of Salesforce deployments within the context of consulting projects. It addresses:

Why do I Deploy ?

In traditional software development, deployments often occur to migrate changes between environments for testing or production releases. However, in the context of Continuous Integration (CI) and Salesforce development, deployments are just synchronization  checkpoints for the application, irrelevant of the organization.

Said differently, in CI/CD Deployments are just a way to push commits to the environments that require them.

CI deployments are frequent, automated, and tied closely to the development cycle.

Deployments are never the focus in CI/CD, and what is important is instead the commits and the way that they tie into the project management - ideally into a ticket for each commit.

In software development, a commit is the action of saving changes to a version-controlled repository. It captures specific modifications to files, accompanied by a descriptive message. Commits are atomic, meaning changes are applied together as a single unit, ensuring version control, traceability of changes, and collaboration among team members.

Commits are part of using Git. 
Git is a distributed version control system used to track changes in source code during software development. It is free and widely used, within Salesforce and elsewhere.

So if deployments are just here to sync commits...

Why do I commit ?

As soon as a commit is useful


Commits should pretty much be done "as soon as they are useful", which often means you have fulfilled one of the following conditions:

This will allow you to pull your changes from the org, commit your changes referencing the ticket number in the Commit Message, and then push to the repository.
This will allow others to work on the same repository without issues and to easily find and revert changes if required.

Take the Salesforce-built "Devops Center" for example.
They tie every commit to a Work Item and allow you to chose which elements from the metadata should be added to the commit. They then ask you to add a quick description and you're done.
This is the same logic we apply to tickets in the above description.

If you're wondering "why not just use DevOps Center", the answer is generally  "you definitely should if you can, but you sometimes can't because it is proprietary and it has limitations you can't work around". Namely the fact that it only uses GitHub for now (2024-06-19).

To tie back to our introduction - this forces a division of work into Work Items, Tickets, or whatever other Agile-ism you use internally, and the project management level.

DevOps makes sense when you work iteratively, probably in sprints, and when the work to be delivered is well defined and packaged.

This is because....

When do I Deploy ?

Pretty much all the time, but not everywhere.

In Salesforce CI/CD, the two main points of complexity in your existing pipeline are going to be:

The reasons for this are similar but different.

In the case of the first integration of a commit into the pipeline, most of the time, things should be completely fine. The problem is one that everyone in the Salesforce space knows very well. The Metadata API sucks. And sadly, SFDX... also isn't perfect.
So sometimes, you might do everything right, but the MDAPI will throw some file or some setting that while valid in output, is invalid in input. Meaning Salesforce happily gives you something you can't deploy.
If this happens, you will get an error when you first try to integrate your commit to an org. This is why some pre-merge checks ensure that the commit you did can be deployed back to the org.

In the case of merging multiple commits, the reasons is also that the Metadata API sucks. It will answer the same calls with metadata that is not ordered the same way within the same file, which will lead Git to think there's tons-o-changes... Except not really. This is mostly fine as long as you don't have to merge your work with someone else's where they worked on the same piece of metadata - if so, there is a non-zero chance that the automated merging will fail.

In both cases, the answer is "ask your senior how to solve this if the pipeline errors out". In both cases also, the pipeline should be setup to cover these cases and error out gracefully.

"What does that have to do with when I deploy? Like didn't you get lost somewhere?"

The relation is simple - you should deploy pretty much ASAP to your remote repo, and merge frequently to the main work repository. You should also pull the remote work frequently to ensure you are in sync with others.
Deploying to remote will run the integration checks to ensure things can be merged, and merging will allow others to see your work. Pulling the other's work will ensure you don't overwrite stuff.

Deploying to QA or UAT should be something tied to the project management cycle and is not up to an individual contributor.
For example, you can deploy to QA every sprint end, and deploy to UAT once EPICs are flagged as ready for UAT (a manual step).

Who Deploys ?

Different people across the lifecycle of the project.

On project setup, the DevOps engineer that sets up the pipeline should deploy and setup.
For standard work, you should deploy to your own repo, and the automated system should merge to common if all's good.
For end of sprints, the automated pipeline should deploy to QA.
For UAT, the Architect assigned to the project should run the required pipelines.

In most cases, the runs should be automatic, and key points should be covered by technical people.

Chapter 2: Software List

This chapter explores the actual tools we are using in our example, the basic understanding needed for each tool, and an explanation of why we're doing things this way.

In short, our example relies on:

You can completely use other tools if your project, your client, or your leadership want you do use other things.
The main reason we are using these in this example is that it relies on a tech stack that is very present with customers and widely used at a global level, while also leveraging reusable things as much as possible - technically speaking a lot of the configuration we do here is directly reusable in another pipeline provider, and the link to tickets is also something that can be integrated using another provider.

In short "use this, or something else if you know what you're doing".

So What are we using

The CLI

The first entrypoint into the pipeline is going to be the Salesforce Command Line.You can download it here.
If you want a graphical user interface, you should set up VSCode, which you can do by following this Trailhead. You can start using the CLI directly via the terminal if you already know what you're doing otherwise. If you're using VSCode, download Azul as well to avoid errors down the line.

We'll be using the Salesforce CLI to:
- login to organizations, and avoid that pesky MFA;
- pull changes from an organization once our config is done;
- rarely, push hotfixes to a UAT org.

For some roles, mainly architects and developers, we will also use it to:

What this actually does is allow you to interact with Salesforce. We will use it to get the configuration, security, and setting files that we will then deploy.

This allows us not only to deploy, but also to have a backup of the configuration, and an easy way to edit it via text edition software.

The configuration needed is literally just the installation to start - we'll set up a full project later down the line.

GIT

You'll then need to download Git, as well as a GUI if you're not used to using it directly from the command line. Git is VERY powerful but also quite annoying to learn fully, which is why we will keep its usage simple in our case.

We'll be using Git to:
- version our work so we can easily go back to earlier configurations in case of issues;
- document what we did when we modified something;
- get the work that other people have done;
- upload our work to the repositories for the project.

You'll need a bit more configuration once you're done installing - depending on the GUI you use (or if you're using the command line) the how depends on the exact software, but in short you'll need to configure git with your user name and your user email.

Logging in to Bitbucket and getting your repository from there will come later - once you've given your username and email, and configured your UI, we will consider that you are done for now.

If you're a normal user, this is all you'll see of git.
If you're a Dev or an Architect, you'll also be using the Branches and Merges functions of Git - mostly through the Bitbucket interface (and as such, with Pull Requests instead of Merges).

Bitbucket

As said in intro, we're using bitbucket because we're using bitbucket. You can use Gitlab, Gitea, whatever - but this guide is for bitbucket. If you're using GitHub... why aren't you using DevOps Center ?

Bitbucket, much like Salesforce, is a cloud solution. It is part of the Atlassian cloud offering, which also hosts JIRA, which we'll be configuring as well. You'll need to authenticate to your workspace (maybe get your Administrator to get you logins), in the format https://bitbucket.org/myworkspace

You will see that Bitbucket is a Git Server that contains Git Repositories.
In short, it is the central place where we'll host the different project repositories that we are going to use.
Built on top of the Git server are also subordinate functions such as Pull Requests, Deployments, Pipelines -  which we're all going to use.

Seeing as we want this to be connected with our Atlassian cloud, we'll also ask you to go to https://bitbucket.org/account/settings/app-passwords/ which allows you to create application passwords, and to create one for Git.

In detail:

Extra Stuff

SGD

SGD, or Salesforce-Git-Delta is a command line plugin that allows the CLI to automatically generate a package.xml and a destructivechanges.xml based on the difference between two commits.
It allows you to do in Git what the CLI does alone using Source Tracking.
Why is it useful then ? Because Source Tracking is sometimes buggy, and also because in this case we're using Bitbucket, so it makes generating these deployment files independent from our machines.
SGD is very useful for inter-org deployment, which should technically be quite rare.

SFDMU

SFDMU, or the Salesforce Data Move Utility, is another command line plugin which is dataloader on steroids for when you want to migrate data between orgs or back stuff up to CSVs.
We use this because it allows migrating test data or config data (that last one should be VERY rare what with the presence of CMTD now) very easily including if you have hierarchies (Contacts of Accounts, etc).



Chapter 3: Basic Machine Setup

1 - Install Local Software

If you are admin on your machine, download Visual Studio Code from this link. Otherwise, use whatever your IT has to install software, whether it be Software Center, opening a ticket, or anything else of that ilk.
As long as you're doing that, you can also install a JDK like AZUL, as well as Git, and a nice terminal emulator.
Also remember to install the Salesforce CLI.

These elements are all useful down the line, and doing all the setup at once avoids later issues.

2 - Configure the CLI

Opening your beautiful terminal emulator, run

sf update

You should see @salesforce/cli: Updating CLI run for a bit.

If you see an error saying  sf is not a command or program, something went wrong during the installation in step 1. Contact your IT (or check the installation page of the CLI if you're Admin or not in an enterprise context).

Once that's done, run

sf plugins install sfdmu sfdx-git-delta

Because sgd is not signed, you will get a warning saying that "This plugin is not digitally signed and its authenticity cannot be verified". This is expected, and you will have to answer y (yes) to proceed with the installation.

Once you've done that, run:

git config --global user.name "FirstName LastName" replacing Firstname and Lastname with your own.

git config --global user.email "email@server.tld" replacing the email with yours

If you're running Windows - git config --global core.autocrlf true

If you're running Mac or Linux - git config --global core.autocrlf input

The above commands tell git who you are, and how to handle line endings.
All of this setup has to be done once, and you will probably never touch it again.

Finally, run

java --version

If you don't see an error, and you see something like openjdk 21.0.3 2024-04-16 LT then you installed Zulu properly and you're fine.

3 - Configure VSCode

Open up VSCode.

Go to the Extensions in the side panel (it looks like three squares) screenshot of VSCode extensions icon and search for "Salesforce", then install

Then search for Atlassian and install "Jira and Bitbucket (Atlassian Labs)".

Finally, search for and install "GitLens - Git supercharged".

Then go to Preferences > Settings > Salesforcedx-vscode-core: Detect Conflicts At Sync and check this checkbox.

Once all this is done, I recommend you go to the side panel, click on Source Control, and drag-and-drop both the Commit element and the topmost element to the right of the editor.

All this setup allows you to have more visual functions and shortcuts. If you fail to install some elements, it cannot be guaranteed that you will have all the elements you are supposed to.

This concludes basic machine setup.
All of this should not have to be done again on an already configured machine.


Chapter 4 - Base Project Setup

This chapter explores how to set up your project management and version control integration, ensuring proper tracking from requirement to deployment.

Initial Project Creation

SFDX Project Setup

Create Base Project

sf project generate
    --name "your-project-name"
    --template standard
    --namespace "your_namespace"  # if applicable
    --default-package-dir force-app

Required Project Structure

your-project-name/
├── config/
│   └── project-scratch-def.json
├── force-app/
│   └── main/
│       └── default/
├── scripts/
│   ├── apex/
│   └── soql/
├── .forceignore
├── .gitignore
├── package.json
└── sfdx-project.json

Configuration Files Setup

.forceignore Essential Entries

# Standard Salesforce ignore patterns
**/.eslintrc.json
**/.prettierrc
**/.prettierignore
**/.sfdx
**/.sf
**/.vscode
**/jsconfig.json

# Package directories
**/force-app/main/default/profiles
**/force-app/main/default/settings

.gitignore Essential Entries


# Salesforce cache
.sf/
.sfdx/
.localdevserver/

# VS Code IDE
.vscode/

# System files
.DS_Store
*.log


Bitbucket Repository Integration

Initial Repository Setup

In Bitbucket:

- Create new repository
- Repository name: your-project-name
- Access level: Private
- Include README: Yes
- Include .gitignore: No (we'll use our own)

Linking Local Project to Remote Repository

Initialize Git Repository


cd your-project-name
git init
git add .
git commit -m "Initial project setup"

git remote add origin https://bitbucket.org/your-workspace/your-project-name.git
git push -u origin main

Branch Protection Rules

Configure in Bitbucket Repository Settings:

YAML
Branch Permissions:
  main:
    - Require pull request approvals
    - Minimum approvers: 2
    - Block force pushes
  develop:
    - Require pull request approvals
    - Minimum approvers: 1
    - Block force pushes

Project Configuration Files

sfdx-project.json Configuration

JSON
{
    "packageDirectories": [
        {
            "path": "force-app",
            "default": true,
            "package": "your-project-name",
            "versionName": "Version 1.0",
            "versionNumber": "1.0.0.NEXT"
        }
    ],
    "namespace": "",
    "sourceApiVersion": "60.0"
}

project-scratch-def.json Base Configuration

JSON
{
    "orgName": "Your Project Name",
    "edition": "Enterprise",
    "features": ["EnableSetPasswordInApi"],
    "settings": {
        "lightningExperienceSettings": {
            "enableS1DesktopEnabled": true
        },
        "securitySettings": {
            "passwordPolicies": {
                "enableSetPasswordInApi": true
            }
        }
    }
}

Post-Setup Verification

Run these commands to verify setup:

Bash
# Verify SFDX project
sf project verify

# Verify Git setup
git remote -v

# Verify Bitbucket connection
git fetch origin

# Verify branch protection
git push origin main --dry-run

JIRA Configuration

Required JIRA Workflow States

Text Only
Backlog -> In Progress -> In Review -> Ready for Deploy -> Done

Bitbucket Integration

Work Segmentation

Story Creation Rules

Stories should be:
- Independent (can be deployed alone)
- Small enough to be completed in 1-3 days
- Tagged with proper metadata types
- Linked to an Epic

Required Story Fields

Integration Setup

JIRA to Bitbucket Connection

  1. In JIRA:

    • Navigate to Project Settings
    • Enable "Development" integration
    • Link to Bitbucket repository
  2. In Bitbucket:

    • Configure branch policies
    • Setup automatic JIRA issue transitions
    • Enable smart commits

Commit Message Format

Text Only
[PROJ-123] Brief description

- Detailed changes
- Impact on existing functionality
- Related configuration

Pipeline Configuration

Get the bitbucket-pipelines.yml file

Integrate it and set up the variables

Automation Rules

JIRA Automation

Bitbucket Pipelines

Security and Access

Required Team Roles

Access Matrix

Text Only
Role          | JIRA | Bitbucket | Salesforce
Project Admin | Admin| Admin     | System Admin
Developer     | Write| Write     | Developer
QA           | Write| Read      | Read-only

Remember that this setup needs to be done only once per project, but maintaining the discipline of following these structures is crucial for successful CI/CD implementation.

The key to success is ensuring that:
1. Every piece of work has a ticket
2. Every commit links to a ticket
3. Every deployment is traceable
4. All changes are reviewable

This structured approach ensures that your project management directly ties into your deployment pipeline, making it easier to track changes and maintain quality throughout the development lifecycle.