Skip to content
How to use GitHub Actions

How To Use GitHub Actions, OAuth and SFDX-CLI for Continuous Integration

Building automation into the software developer lifecycle (SDLC) is the quickest way a Salesforce devops management program will benefit you and your team. SDLC automation relieves developers from babysitting long-running processes. By scripting SDLC activities, Salesforce developers also start to implement continuous integration. This provides the foundation for additional capabilities to be added later, such as continuous testing and developer cybersecurity. In this How To post, I show you how to bypass change sets and use SFDX-CLI, OAuth-style authentication, and get started with a pre-written GitHub Action to automatically deploy an update and run unit tests.

What is GitHub Actions?

GitHub Actions is the built-in scripting environment for GitHub repositories. All GitHub accounts have access to Actions, including free accounts using private repositories. Actions scripts are defined as YML files stored in a repository’s .github/workflows subdirectory. Actions are metered by how many minutes your Actions use each month. You get 500 free minutes per month.

Actions are invoked in response to a variety of repository events. When triggered, GitHub Actions run the commands sequenced in the YML. Actions loads a run-time BASH and NodeJS environment to run the commands. You actually have a choice of environments, including Windows and MacOS. But I recommend you stick with the latest Ubuntu Linux distribution for maximum devops compatibility.  Using Linux allows you to write small scripts using BASH and NPM directly in Actions YML files. More complex scripting is done by writing JavaScript procedures that run on top of a pre-installed NodeJS server.

This short overview has only touched the surface of Actions. There are many more capabilities, including invoking scripts on servers outside of GitHub, so please familiarize yourself with the documentation.

Actions is GitHub’s version of what I call a command server. I decided to come up with the command server nomenclature as an alternative to other common names for what GitHub Actions does, such as CI/CD engine. I did this to help teach developers they are building a small, ephemeral server process. Being aware that a server is being built helps learners to understand how devops pipelines function. For example, we need a server-to-server authentication scheme to get GitHub Actions to talk to Salesforce.

Salesforce OAuth Authentication

It is tricky to authenticate SFDX-CLI from GitHub Actions. An OAuth-style authentication flow is required. There are two ways to use OAuth to authenticate Salesforce from GitHub Actions, and neither way is easy.

The easier of the two ways is to use the SFDX Auth URL string. This is where you first log onto an org using web or device authentication from the Terminal window in VS Code and then get an authentication URL. This is done by showing your OAuth token with the sfdx force:org:display --verbose command. Then, that URL string is stored in a GitHub repository secret.

I decided not to use this method for a couple of reasons. First, the SFDX Auth URL is tied to a developer’s Salesforce user account with their current OAuth token. If that token expires or becomes invalid the GitHub secret must be updated.

The other reason I don’t like SFDX Auth URL is that only one org may be authenticated with an SFDX Auth URL. What if I want to log onto multiple orgs in my GitHub Actions session? So, that’s why I went to the trouble of setting up a special OAuth connection with a Connected App and a self-signed certificate and key.

Development Environment

The development environment used for this How To relies VS Code Remote to power up my workstation. This means I have a Linux server running in my local network that runs most of the VS Code processes. To use a remote server, I launch VS Code on my Windows workstation and connect to that server. Then, all the files, CLIs, and applications on the remote server are available to me in the VS Code interface.

VS Code Remote lets me to use a Mac or PC as a personal workstation, and still use Linux as my devops working environment. I find this to be a powerful way to load the tools and resources I need for SDLC management. For more information, check out this How To post on using VS Code remote with SFDX-CLI.

The Salesforce system setup used for this How To is an Enterprise org with developer and data-sample sandboxes. GitHub is used by pulling needed metadata into a new branch which supports branch-based development.

For this How To experience, I already have new and updated metadata organized in a branch that needs an automation upgrade. The pull request is complete, and the updated branch is ready to deploy to production. All the new and updated metadata has been specified in a package.xml file.

To perform the deployment without a command server, I must manually execute an sfdx force:source:deploy command in the VS Code terminal. Wouldn’t it be nice to just push the branch and get that done automatically?

What Happens in the How To

In this How To exercise, I write a simple YML-only GitHub Action triggered automatically when a PUSH action occurs in the repository with the follow steps.

  1. Set up OAuth JWT Bearer Token authentication
    1. Open VS Code in remote repository
    2. Use openssl to create a self-signed certificate and key
    3. Use Salesforce Admin interface to set up connected app
    4. Test local use of authentication flow
    5. Store self-signed key in repository
  2. Write the GitHub Action
    1. Authenticate the current session with Salesforce
    2. Retrieve the target repository
    3. Deploy metadata and run unit tests on a production org
  3. Activate Action with a repository PUSH
    1. Use GitHub and Salesforce web interfaces to monitor the execution of the Action

Please check out the accompanying YouTube video, you will find a complete step-by-step procedure designed for you to use by following along. You can also use this script used to produce the video to follow along.

How To Set Up OAuth 2.0 JWT Bearer Flow for GitHub Actions

Authentication is very confusing already! And the nomenclature and acronyms associated with OAuth are the worst. My advice on how to deal with JSON Web Token (JWT) bearer flow authentication is to carefully follow the setup-by-step instructions provided by Salesforce. Here is one confusing aspect of this nomenclature of which you will want to be aware. You won’t see any JSON-formatted information while working with this scheme. Here is my summary of the process.

  1. Use the Linux openssl command to generate a self-signed private certificate and key. Enter your business information. When prompted, you may enter a fake Common Name. Put the files in the .ssh/jwt directory in your home directory. Be sure to not back up that directory.
  2. Create a connected app on your Dev Hub org. Name the new app “GitHub Actions”. For most enterprise users, the Dev Hub org is the production org. Create the app exactly according to the Salesforce instructions. Later, you will need the Connected App’s Consumer Key. Get that by selecting the View option in the App Manager.
  3. Refresh any sandboxes.
  4. Test the authentication setup by running the sfdx auth:jwt:grant command on the same workstation from which you created the self-signed certificate.
  5. In the repository Settings tab for the target repository click the Secrets option on the left. Create three secrets:
    1. SALESFORCE_CONSUMER_KEY – The Consumer Key from your Connected App page
    2. SALESFORCE_JWT_SECRET_KEY – The contents of the key file generated in Step #1
    3. SALESFORCE_DEVHUB_USERNAME – The Salesforce username of a user authorized to perform the deployment

How To Use GitHub Actions for Salesforce

To get create the first GitHub Action for your SFDX-CLI project follow these three steps.

  1. Create a .github directory at the root level of your repository.
  2. Create a workflows directory in the .github directory.
  3. Create a new file named push-action-deploy.yml in the workflows directory.

Next, open push-action-deploy.yml with VS Code and paste in this complete GitHub Action definition. Save the file.

Let’s go over the Actions YML file. On line 2, the on statement indicates this action will happen every time we perform a GIT PUSH on the repository. The jobs statement starts a list of one or more named Jobs which will be run. In this case, there is one job named SFDX-CLI-Deploy.

The runs-on statement indicates any run statements will be executed on the latest version of Ubuntu server. Finally, in a list of steps, a series of run and uses statements perform the steps in the action. If an error occurs during the execution of the steps, the Action aborts and GitHub will roll back any operations such as repository changes.

To activate the Action just commit the new file to the repository and push it to GitHub. To check the results of your GitHub Action invocation, visit the repository web page and check under the Actions tab.

And, that’s all folks!

Start Your Salesforce Continuous Integration Journey Today!

I hope you enjoyed this How To post and that you are inspired to try out GitHub Actions. Be sure to check the website for more tutorials. If you have any ideas on other Salesforce devops How To posts, please drop me a line at [email protected].


Thank you to Salesforce, the bloggers, and other writers who helped inspire this post.