Salesforce has multiple methods of deploying changes to production Orgs. Our team has a variety of deployment experience including third-party applications, using change sets, using the metadata API, and most recently, using second-generation packages to deploy our changes. For a project which uses unlocked packages, we decided to use GitHub Actions to explore its CI/CD capabilities and gain more experience with the platform. Our goal for the CI/CD pipeline was to perform all unit tests on every pull request, block merging of any pull requests which failed our checks, and run the workflow for deploying an unlocked package. Not only would this ensure that all code changes passed through the same suite of tests, it also automated an 11-step process which saved developers on average 5 - 6 minutes per pull request and on any subsequent commits made until the pull request was approved for merging.
GitHub Actions has great documentation on workflows that helped us create an automated process which fit our requirements. A workflow consists of a YAML file which defines the process that runs once a specific event is triggered. The workflow can run multiple jobs in parallel by default, or sequentially if required. A job can then be further broken down into individual steps which run sequentially and consist of either an action or shell script to be executed. Steps can also communicate with one another by issuing an output command to set a variable that can be used in any remaining steps within that job.
The other important aspect to a workflow are events. Events are what trigger a workflow to run its jobs and can be triggered on a schedule, manually, or via an activity that takes place in the repo like a pull request being opened. Filters can also be applied to the event to limit when the workflow is triggered. For example, let's say we want different workflows to run when a pull request is open against the develop and main branches. We could accomplish this by creating two workflows, both triggered by a pull request, with one filtering to only include pull requests against develop and the other on pull requests against main.
Utilizing the Github Actions features mentioned above, we decided to split our solution into two workflows, one which runs automatically any time a pull request is opened against our develop branch, and the other a manually triggered workflow which packages our application from the main branch and deploys it to our integration org.
The workflow that runs on a pull request performs multiple jobs. First it checks that the developer has squashed their commits so that only a single commit is in the pull request. This requirement was a decision from our team to help keep our git logs more concise. The workflow also creates a scratch org, pushes the source to the scratch org, and runs our unit tests. Along with running unit tests the workflow also runs our Lightning Web Component tests. The three jobs are performed in parallel and if any fail, the merge is blocked. The developer can then fix the issue, squash their commits, and push up the changes which will then trigger the jobs to run again.
Our deployment workflow is currently manually triggered. While GitHub Actions does have the capability to run on a scheduled basis, or off an event like a pull request or commit, we wanted to maintain deployment control for the time being. The workflow runs off of the main branch and creates a package version, promotes it, and then deploys the package to our integration org.
The flexibility of GitHub Actions when it comes to triggering workflows, performing jobs in parallel or sequentially, and choosing specific branches on which workflows are run made it very easy for us to customize our pipeline to fit the project's needs. An additional advantage to GitHub Actions and GitHub as a whole was its integration with both Jira and Slack. Our Jira integration allowed tickets status to be updated based on the current status of a branch while the Slack integration allowed us to set up a pull request channel which would notify the team when code was ready for review and if any of the workflows failed. Our team really enjoyed the process of creating the Salesforce pipeline with GitHub Actions and we look forward to continuing to use it in our Salesforce development along with trying new offerings like the much anticipated Salesforce’s Devops Center.