How to simplify your deployments with GitHub Actions

A photograph of the author: Brandon Whitaker

By: Brandon Whitaker

Whether you are working on a big enterprise solution or a small company website, getting the continuous integration working seamlessly is vitally important.

As a digital agency we have to manage the deployments of multiple client sites. Some are simple SFTP deployments with gated quality assurance checks. Others are multi-stage deployments with a matrix of dependencies. Without continuous integration in place it can be a nightmare to deploy code. Especially when a project has not been touched in a while and you have to go through documentation and emails to familirize yourself with the deployment steps.

In our experience, companies often think about the deployment phase of software development as second grade. But it is often the stage that is stifling progress for teams that want to work in a more Agile manner.

It is for these reasons we believe continuous integration is a must for all projects. It is self-documenting, repeatable and reliable.

There is plenty of tooling out on the market for continuous integration / deployments, whether through simple, free server applications such as Jenkins, or with more ‘enterprise-level’ solutions like Azure Projects (TFS). Although we have never been entirely happy with either. Jenkins being flakey and ill-supported and solutions like Azure Project locking you into their product offering.

This is where Github Actions comes in and fills a void. It is flexible, optional and platform agnostic.

Create a Simple SFTP Publish Github Action

We are going to create a simple Github Action that deploys a new version of a ReactJS website automatically to a hosted server. This action will be executed whenever there is a change pushed into the master branch of the source code.

At the time of writing this, Github actions is still in beta and planned to go live on 13th November 2019. You can enable Github actions in your account settings. With Github Actions enabled you will see a new option on the repository navigation.

Image for post

Step 1: Create Workflow File

Create a folder in the root of your project .github/. Within this new folder create a file main.yml. (You can also do this through Github UI by clicking ‘Actions’ and selecting ‘Create new Workflow’)

Step 2: Define a Trigger

A trigger is the scenario with will cause your job to run. In our example we have defined a trigger that will execute on all pushes to the master branch.

on:
  push:
    branches:    
      - master
      

.github/main.yml

Step 3: Define the job

The job describes the action to take when the trigger rules have been met. In this action we are using an action project that manages the SFTP upload to our ftp server: SamKirkland/FTP-Deploy-Action@2.0.0.

Add the following job to your main.yml file, below the trigger. Dependent on your hosting provider, you may need to change the port and method defined at the bottom.

jobs:
  FTP-Deploy-Action:
    name: FTP-Deploy-Action
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@master
    
    - name: Use Node.js 12.x
      uses: actions/setup-node@v1
      with:
        node-version: '12.x'
        
    - name: Build Project
      run: |
        npm install
        npm run build --if-present
        
    - name: List output files
      run: ls
      
    - name: FTP-Deploy-Action
      uses: SamKirkland/FTP-Deploy-Action@2.0.0
      env:
        FTP_SERVER: ${{ secrets.FTP_SERVER }}
        FTP_USERNAME: ${{ secrets.FTP_USERNAME }}
        FTP_PASSWORD: ${{ secrets.FTP_PASSWORD }}
        LOCAL_DIR: build
        METHOD: sftp
        PORT: 22
        ARGS: --delete

Step 4: Create the secrets

Because we do not want to expose our hosting details for the world to see on Github, we put these credentials into ‘secrets’. Secrets are unique to your repository. To setup your secrets, do the following;

  1. Go to your project repository
  2. Click ‘Settings’
  3. Click ‘Secrets’
  4. Click ‘Add new secret’
  5. Add the following three secrets;

FTPSERVER: ftp.averment.com, FTPUSERNAME: averment, FTP_PASSWORD: averment

Changing the credentials as required.

Step 5: Validate and Run

Your complete file should look something like this:

on:
  push:
    branches:    
      - master
      
name: Build and Publish Averment
jobs:
  FTP-Deploy-Action:
    name: FTP-Deploy-Action
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@master
    
    - name: Use Node.js 12.x
      uses: actions/setup-node@v1
      with:
        node-version: '12.x'
        
    - name: Build Project
      run: |
        npm install
        npm run build --if-present
        
    - name: List output files
      run: ls
      
    - name: FTP-Deploy-Action
      uses: SamKirkland/FTP-Deploy-Action@2.0.0
      env:
        FTP_SERVER: ${{ secrets.FTP_SERVER }}
        FTP_USERNAME: ${{ secrets.FTP_USERNAME }}
        FTP_PASSWORD: ${{ secrets.FTP_PASSWORD }}
        LOCAL_DIR: build
        METHOD: sftp
        PORT: 22
        ARGS: --delete

Now push a change into master and click ‘Actions’. It may take a couple of minutes for the action to start. But once the action has been executed you will see a breakdown of each of the tasks executed within the action job.

Image for post

Summary

We can create Github actions to simplify our workflow. They allow to concentrate on developing code and worry less about the nuances of each project deployment when it comes to releasing. It also documents our deployment process. Finally, it increases the security as we do not need to share server credentials with contributors to get new changes released.

@AvermentDigital on TwitterFacebook and Instagram