top of page
Search
  • Shreyas Dhond

Simple SFDX Continuous Integration with Github and Travis CI

Updated: Apr 7

If you are already leveraging SFDX tools and Scratch Orgs next step is to apply a continuous integration process. Especially during these times of Social Distancing during the COVID-19 pandemic as developers are not able to collaborate physically, it is important to bridge the gap to effective delivery using a continuous integration process.


In this blog I am demonstrating a simple but effective configuration using Github and Travis CI that can have you up and running with continuous integration in a matter of a couple of hours.


Pre-requisites

The pre-requisite requirements for this configuration are a github repo with a branching strategy, a travis ci account connected to the github account.


Github Repo

I will be using a test repository with a CustomObjectSearch component that is currently built using aura. The repository branching structure is shown in the screenshot below. 

The initial state of the repo is a "develop" branch for merging development code and a "master" branch for production staging. In our case, we will be building continuous integration only to the develop branch to demonstrate the concept but I will point out how it can be easily extended to a production staging environment.


Travis CI

You can sign up to Travis Ci using your GitHub account. If you don't have a Travis Ci account attached to the GitHub account for your repository. You can sign up and create a new account using this link.


Configuration

The configuration first involves setting up a connected app with JWT authentication flow configured to the DevHub and in our case also our target environment for the "develop" branch. The configuration involves the creation of a self-signed certification using OpenSSL and a connected app setup to authenticate an integration user. In my case for demonstration purposes, I will use my credentials but its generally best practice to create a user specifically for continuous integration with the"Modify Metadata Through Metadata API Functions" permission.


Certificates

The following steps outline the creation of the certificates that will be used by the connected app to authenticate integration user using JWT authentication flow.


Create a "certificates" directory as part of the code repository in the root of the repository.

cd <root-folder-of-the-project>
mkdir certificates

Make sure you have openssl installed to create the certificate.

which openssl
output><something lile /usr/bin/openssl>

If the command doesn't return a path OpenSSL needs to be installed. The list below lists installation alternatives by operating systems:



Create a self-signed certificate using the commands below. When prompted to enter challenge password leave blank by pressing "enter" and skip optional fields by entering ".".

cd certificates
openssl genrsa -des3 -passout pass:<SomePassword> -out server.pass.key 2048
openssl rsa -passin pass:<SomePassword> -in server.pass.key -out server.key
rm server.pass.key
openssl req -new -key server.key -out server.csr
openssl x509 -req -sha256 -days 365 -in server.csr -signkey server.key -out server.crt

The end product should be the following files in your certificates directory:


Connected App


Login to the DevHub org and create an app with the instructions described below:

  • Connected App Name: sfdx travis ci

  • Contact Email: <your email address>

  • Select Enable OAuth Settings.

  • Callback URL: https://localhost:1717/OauthRedirect

  • Select Use digital signatures and upload the server.crt file generated before using the upload file button.

  • Select the following OAuth scopes:

  • Access and manage your data (api)

  • Access your basic information (id, profile, email, address, phone)

  • Provide access to your data via the Web (web)

  • Perform requests on your behalf at any time (refresh_token, offline_access)

  • Click Manage and Edit Policies. Under OAuth Policies in the IP Relaxation field select Relax IP restrictions and Permitted Users field to Admin approved users are preauthorized.

  • Create a permission set with the name sfdx travis ci and add an assignment for your or the integration user you wish to use for continuous integration.

  • Go back to the connected app through the App Manager and click Manage. In the Manage Permission Sets section add the created permission set.

  • Test the connection using the command below and you should see the result as shown in the pic below.

sfdx force:auth:jwt:grant --clientid <consumer-key> --username <devhub-username> --jwtkeyfile <server.key path>

Travis CI

To configure travis ci all that needs to be done is a .travis.yml needs to be included in the root directory of the project. The file below essentially does the following steps:

  1. Set SFDX environment variables. (I have got these from the following repo https://github.com/forcedotcom/sfdx-travisci/blob/master/.travis.yml)

  2. Install sfdc and core plugins using the URL in the env section.

  3. Authenticate using JWT authentication with certificate key (server.key) and username.

  4. Finally run the sfdx deploy command with checkonly flag if pull request and no flag if its a merge.

sudo: true
os: trusty
cache: false

env:
- URL=https://developer.salesforce.com/media/salesforce-cli/sfdx-linux-amd64.tar.xz

before_install:
- export SFDX_AUTOUPDATE_DISABLE=false
- export SFDX_USE_GENERIC_UNIX_KEYCHAIN=true
- export SFDX_DOMAIN_RETRY=300
- export SFDX_DISABLE_APP_HUB=true
- export SFDX_LOG_LEVEL=DEBUG
- mkdir sfdx
- wget -qO- $URL | tar xJ -C sfdx --strip-components 1
- "./sfdx/install"
- export PATH=./sfdx/$(pwd):$PATH
- sfdx --version
- sfdx plugins --core

script:
  - sfdx force:auth:jwt:grant --clientid <consumer-key> \
        --username sdhond@sfdxcontinuousintegrationdemo.com \
        --jwtkeyfile certificates/server.key --setalias target_org \
        --instanceurl <depends on sandbox or production>;
    if [ "$TRAVIS_BRANCH" == "develop" ] && [ "$TRAVIS_PULL_REQUEST" ! = "false" ];
      then
        sfdx force:source:deploy -p ./force-app -u target_org --checkonly;
      else
        sfdx force:source:deploy -p ./force-app -u target_org;

branches:
  only:
    - develop

You can also add a fancy build status image to your readme file by navigating to Travis CI and selecting the image build beside your repository name.


This opens a popup where you can select a link for a specific branch. For our case we will get the build status image for the develop branch as shown below.

The URL in the above window can be copied and included in your Readme.md file in the following format.

This results in a nice image of the build status on the repository's landing page.


Demo


In the above demo, I am committing a change into my working branch and creating a pull request to the develop branch. The creation of the pull request triggers a check only build from Travis CI and the status of the build and any other builds from previous commits is visible on the pull request page. Once the check is complete GitHub displays all checks completed flag and it is safe to merge the pull request to the develop branch. Once the branch is merged another build is triggered by Travis, but this time the build is not a check only build. Upon the success of the build, the changes you committed and pushes are automatically deployed to your target upstream org.


Further limitations to only allow a pull request to be merged on successful build completion can be applied using Branch Protection Rules in GitHub (example rule below).


The below rule enforces the following:

  1. Require pull request reviews before merging: This enforces the requirement of a pull request to merge to an upstream branch. This prevents developers from directly pushing to a shared branch without reviews and approval.

  2. Require status checks to pass before merging: This enforces that a pull request should pass all checks (Travis builds) before it can be merged into the upstream branch. This ensures all merges will result in deployable code. Furthermore, integrations to notify the developer to fix build errors can be automated to truly have a seamless process.

  3. Require branches to be up to date before merging: This enforces that the source branch should be up to date with all changes from develop branch before being able to merge into that branch. This prevents hanging pull requests that developers might do with actually merging changes from develop into their feature branch.

Resources

3 views0 comments
bottom of page