Gate your Salesforce deployments with sfdx, Branch Protection Rules, and GitHub Actions

In this article, I'll show you how to can gate or restrict your Salesforce deployments using sfdx and Branch Protection Rules (BPR from now on).

Sponsored by Salto

CPQ Deployments, CI/CD, Impact analysis, and more

30-day free trial here

Use case

So let's say you want to make sure that deployments to production are gated; that is, they require some level of approval before they can be deployed.

Salesforce doesn't have a native way to restrict deployments to an environment. The most effective way to prevent devs from deploying to production is to simply not give them access and only deploy through an API user that is used in your pipeline. What's explained in this article is simply another layer of protection.

I'm also going to assume you are using sfdx and a Git repo and that you are doing Git-based deployments.

Finally, I'm also going to assume you are using GitHub Actions as your CI server.

Branch Protection Rules (BPR)

BPR are rules (duh) that you can create to protect branches in your GitHub repo. Assuming that the main branch represents your Salesforce production org, this is the branch that you want to create rules for.

To create BPR, head over to Settings > Branches in your GitHub repo

When creating a new rule, I've specified that I want to protect the main branch


So what rules are available? There are many

In this case, here's what I want to do:

1- When a pull request (PR) is created against main, I want to trigger a validation deployment against production

I want that validation to pass before I can merge the PR. If the validation doesn't pass, the PR should be blocked. This will ensure that only validated code can be merged into main

2- I also want someone other than myself to review and approve the changes in the PR, and only once the approval is granted, can the PR be merged. If approval is not granted, the PR should be blocked.

3- And finally, when the PR is approved, I want to automatically deploy the changes to production.

So let's break this down a little bit more.

GitHub Actions

To achieve actions 1 and 3, I need 2 CI jobs. One that fires a validation deployment when a PR is created, and another one that fires a real deployment when the PR is approved.

I've already created such actions, and you can find them here,

Validation Action

sfdx-branch-protection/.github/workflows/validate.yml at main · pgonzaleznetwork/sfdx-branch-protection
Sample sfdx repo showing how to use branch protection rules - pgonzaleznetwork/sfdx-branch-protection

Deployment Action

sfdx-branch-protection/.github/workflows/deploy.yml at main · pgonzaleznetwork/sfdx-branch-protection
Sample sfdx repo showing how to use branch protection rules - pgonzaleznetwork/sfdx-branch-protection

Configuring the BPR

Now, I need to create my BPR to

1- Require the Validation action to succeed

2- Require approvals before the PR can be merged

Here's what my rules look like:

NOTE: You won't see the Validate action as an available status check unless that action has run recently. So you must trigger the action, and then come back to the BPR settings. 

Putting it all together

Now let's see what the whole process looks like

Creating the PR

First, I make a few code changes and open a PR against main

Validation deployment

As soon as the PR is created, a validation deployment starts, thanks to our first GitHub Action

After the validation deployment succeeds, notice the action shows as successful, but the PR is still blocked

This is because we configured our BPR to require approvals before merging, so let's do that.

Adding an approver

To add an approver, I'm going to go to Reviewers and add my friend John

Once I add John, he'll receive an email notifying him that he needs to approve the PR

John can then approve the PR and leave comments

And as soon as he does, the 2nd GitHub action kicks in, which triggers a production deployment

And once the deployment succeeds, I can merge the PR, ensuring only validated and approved code can be merged

And that's it! Super easy :)

If using a DevOps product

If you are using a Salesforce DevOps product that integrates with GitHub, you may be wondering how BPR affect the operations of said product.

In Salto, for example, if you have BPR like the ones I described in this article, Salto will honor those rules and block the deployment in Salto.

In the example above, you can see the Deploy button is disabled because the PR that Salto automatically generates for a deployment is still in Pending status, which means it's not mergeable yet.

Once the Salto PR is approved, a Salesforce deployment will automatically start, just like we did with GitHub Actions

If you are using something other than Salto, I recommend you ask them what capabilities they have for gating a deployment, and whether those are built into the product, or if they rely on external PR approvals.

I hope you found this useful!

Subscribe for exclusive Salesforce Engineering tips, expert DevOps content, and previews from my book 'Clean Apex Code' – by the creator of!