· tutorials · 6 min read
Build A Deployment Pipeline With GitHub Actions
Learn how you can use the SF CLI and GitHub Actions to build packages and deploy code. Streamline your workflow by creating a pipeline.
Building change sets by hand is like packing your suitcase for a vacation. It’s an exciting event to get something out the door, but when you arrive at your destination you always manage to forget something. In Salesforce, we can avoid the feeling of “forgetting something” by automating our change manage process.
This process of automating can be done using the Salesforce CLI (formerly known as SFDX) and GitHub. I’ve been using GitHub Actions to speed up my workflow so I can:
- Track Changes.
- Automatically Deploy to Salesforce.
- Not use change sets.
I want to showcase how I am using GitHub Actions to deploy code through a deployment pipeline.
Modeling the Deployment Pipeline
Imagine you are a small team of two developers managing feature requests. A sample deployment pipeline might look something like this:
Each developer is working on their JIRA tickets in their own dedicated sandbox. Changes then get merged in an environment. Finally, the code is tested and deployed to production.
When a developer is using a git-centric workflow, each ticket can be contained in a specific branch named by the JIRA key. From there, these branches can be merged down the pipeline of multiple branches using pull requests.
Pull requests are a great way of bundling commits in git. Each pull request can contain one or many commits. This PR can then be pushed and merged to the master branch.
How are branches related to Salesforce Environments?
Configuring your deployment pipeline depends on your team size and testing steps. In general, I like the following name map of sandbox / branch name
Branch | Salesforce Environment |
---|---|
master | Production |
uat | Full Sandbox |
staging | Partial Sandbox |
develop | Developer Sandbox * |
JIRA-123 | Developer Sandbox ** |
- * Each developer will have their own sandbox related to their development
- ** Each Jira issue is it’s own branch that is merged into the developer’s branch.
From here I like to trim pipeline size / add steps based on the team size.
Building the Deployment Pipeline
Now that we understand how branches are mapped to the environments in a pipeline, let’s dive into automating deployment.
We want to create a hidden folder in the project root called .github
. Inside this folder, create an additional folder:
workflows
Workflows are the yml
elements that contain instructions to deploy your code. Each workflow can contain actions as a step. Actions are sub-elements that can be used across your workflows.
We can use these reusable actions in our workflows. Each individual step can contain an action, or a set of command line instructions. This action can be used in our workflows to streamline deployment. The action is a bash script that builds your SFDX project, and deploys to your target environment. We will use this to build validation and deployment to our pipeline.
Before merging branches, we want to ensure that the code in our pull request is validated in the target environment. This is so we can ensure our pull request has:
- Code that compiles
- Test classes that pass
- Only the necessary files in the deployment
We can perform this by adding the file validate.yml
on in the workflows
directory.
name: Validate Production Pull Request
on:
pull_request:
branches:
- master
paths:
- 'force-app/**'
jobs:
validate:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Validate on ${{ vars.ENVIRONMENT_NAME }}
uses: jawills/[email protected]
with:
SFDX_AUTH_URL: ${{ secrets.SFDX_AUTH_URL }}
DRY_RUN: true
Notice how:
- The workflow is set to run on the
pull_request
event - The workflow is only ran on pull requests with the target of
master
- Only changes within the
force-app
directory trigger the validation - There is a variable called
ENVIRONMENT_NAME
that we can specify as the org name. - We have a secret called
SFDX_AUTH_URL
that stores the authentication to Salesforce.
With this configuration, we are almost complete. We need to specify the ENVIRONMENT_NAME
and SFDX_AUTH_URL
To get the SFDX_AUTH_URL
, enter the following command in your terminal:
sfdx org display --verbose --json -o <MY_TARGET_ORG_ALIAS>
Copy down the value of sfdxAuthUrl
for later.
Inside the settings of your GitHub repository, we can configure these variables. Go to Secrets and variables
-> Actions
to manage these variables.
Inside the secrets tab, create a secret called SFDX_AUTH_URL
with the value copied from sfdxAuthUrl
. Add your environment name under the ENVIRONMENT_NAME
variable in the Variables tab.
Now when a pull request is created, you can see the action running and validating your deployment.
Deploy Code To Environment
To deploy the changes to your environment we can create the file deploy.yml
under the workflows
directory.
name: Close Production Pull Request
# only trigger on pull request closed events
on:
pull_request:
types: [closed]
branches:
- master
paths:
- 'force-app/**'
jobs:
merge_job:
# this job will only run if the PR has been merged
if: github.event.pull_request.merged == true
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Deploy on ${{ vars.ENVIRONMENT_NAME }}
uses: jawills/[email protected]
with:
SFDX_AUTH_URL`: ${{ secrets.SFDX_AUTH_URL }}
DRY_RUN: false
TEST_LEVEL: RunLocalTests
close_job:
# this job will only run if the PR has been closed without being merged
if: github.event.pull_request.merged == false
runs-on: ubuntu-latest
steps:
- run: |
echo PR #${{ github.event.number }} has been closed without being merge
The key differences between the deployment is:
- Workflow is only ran on
pull_request
being closed - We check if the pull request is merged or rejected
This is everything you need to deploy to a single environment using GitHub Actions.
Adding Multiple Environments to the Pipeline
Now it’s time to put the pipe in pipeline. With GitHub Pro / GitHub teams, we can configure the same workflow to run on multiple environments.
To configure, go to Settings
-> Environments
and create a new environment. Notice how the secrets / variables can be configured per environment.
We will also want to chose what environment is associated to the specific branch. We can do so by changing the deployment branches to Selected branches
and adding a rule. This rule will contain your source branch name, like staging
or JIRA-123
. Keep in mind that the GitHub Action will use the branch that is being deployed to, and the environment will use the branch that is being deployed from.
Additionally, we need to specify the environment in our workflow. The validation workflow with an environment can be seen below:
name: Validate Production Pull Request
on:
pull_request:
branches:
- master
paths:
- 'force-app/**'
jobs:
validate:
runs-on: ubuntu-latest
environment: production
steps:
- uses: actions/checkout@v3
- name: Validate on ${{ vars.ENVIRONMENT_NAME }}
uses: jawills/[email protected]
with:
SFDX_AUTH_URL: ${{ secrets.SFDX_AUTH_URL }}
DRY_RUN: true
Any additional environments in your pipeline can be specified as new workflow files. The environment variable will reflect this newly created environments.
Conclusion
That’s everything you need to know to build deployment pipelines in GitHub. You now know:
- How branches are tied to environments
- Create changes with pull requests
- Validate your change set with GitHub Actions (CI)
- Deploy your changes with GitHub Actions (CD)
If you are looking for more Salesforce DevOps content, check out my YouTube video here:
Need Our Help To Get Your Data Into Salesforce?
Join dozens of other companies by learning how you can get all your company's data in one place.