9 – GitHub Actions Tutorial – CI / CD – Deploy Static files using FTP

I have been a big fan of Continuous Integration and Continuous Deployment (CI / CD). I have been using it since 2005, by writing bat scripts all by myself and later on using Microsoft Team Foundation Server (TFS) and now Azure DevOps.

Several months back I was working on GitHub projects and wanted to see if we can do CI/CD, that’s when I learnt about Github Actions. Github Actions uses YAML (YAML Ain’t Markup Language), to define your workflow of CI / CD. Github Actions are easy to read and also powerful enough to perform many things.

Let’s see how we can deploy a static web site on server using Github Actions.

First thing go to your Github repository and click on Actions as shown in screenshot below:

If you are setting up Github Action for the first time, you will need to click on Set up a workflow yourself. If you have already done it in the past, click on New workflow and after that click on Set up a workflow yourself. As shown in below screenshots:

Github will show us an interface using which we can create workflow. File will be created inside .github/workflows directory of your repository. We can give the name to file anything that we want. I am giving it a name main.yml

name: CI

# Controls when the action will run. Triggers the workflow on push or pull request
# events but only for the master branch
on:
  push:
    branches: [ master ]
  pull_request:
    branches: [ master ]

# A workflow run is made up of one or more jobs that can run sequentially or in parallel
jobs:
  # This workflow contains a single job called "deploy"
  deploy:
    # The type of runner that the job will run on
    runs-on: ubuntu-latest

    # Steps represent a sequence of tasks that will be executed as part of the job
    steps:
    # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it
    - uses: actions/[email protected]
    #Deploy on FTP
    - name: FTP Deploy
      uses: SamKirkland/[email protected]
      with:
        # Deployment destination server & path. Formatted as protocol://domain.com:port/full/destination/path/
        ftp-server: ${{ secrets.FTP_HOST }}
        # FTP account username
        ftp-username: ${{ secrets.FTP_USERNAME }}
        # FTP account password
        ftp-password: ${{ secrets.FTP_PASSWORD }}
        # The local folder to copy, defaults to root project folder
        local-dir: # optional
        # Passes through options into git-ftp
        git-ftp-args: # optional

Let’s understand each block of the code.

name: CI

First we specify is what name we want to give to our workflow. We will give it a name CI.

on:
  push:
    branches: [ master ]
  pull_request:
    branches: [ master ]

Next, we specify a trigger. Which will tell when we want this action to execute. We have specified that whenever there is a pull request and push on master branch we want workflow to execute.

jobs:
  # This workflow contains a single job called "deploy"
  deploy:
    # The type of runner that the job will run on
    runs-on: ubuntu-latest

    # Steps represent a sequence of tasks that will be executed as part of the job
    steps:
    # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it
    - uses: actions/[email protected]
    #Deploy on FTP
    - name: FTP Deploy
      uses: SamKirkland/[email protected]
      with:
        # Deployment destination server & path. Formatted as protocol://domain.com:port/full/destination/path/
        ftp-server: ${{ secrets.FTP_HOST }}
        # FTP account username
        ftp-username: ${{ secrets.FTP_USERNAME }}
        # FTP account password
        ftp-password: ${{ secrets.FTP_PASSWORD }}
        # The local folder to copy, defaults to root project folder
        local-dir: # optional
        # Passes through options into git-ftp
        git-ftp-args: # optional

Now, we will specify a job that needs to be performed. One workflow can have multiple jobs. We are right now creating a single job called deploy. A job can have multiple steps to perform. In our case we have two steps to execute.

  1. Check out the Files
  2. Upload Files on FTP.

1st Step is uses: actions/[email protected]. Here we are specifying that we want to checkout our branch using actions/[email protected].

2nd Step is called FTP Deploy and in that we are using one of the FTP Action developed by SamKirkland and is available on Github Marketplace. More details of the same you can get here – SamKirkland/FTP-Deploy-Action

FTP-Deploy-Action takes 5 parameters, out of which two are optional. In ftp-server, ftp-username and ftp-password you can see I am using variable or tokens $${{ secrets.FTP_HOST }}. We dont want to expose sensitive information in repository. We can make use of Github’s secret vault to store sensitive information and retrieve it when needed. To do this, go to Settings of Git repository:

Select, Secrets from the left hand side menu:

Now, on this page you can add secrets and can use it in workflows.

If you do not want to upload root folder to your FTP server, but rather a sub folder you can specify directory which you want to upload on FTP server in local-dir parameter (which is optional parameter).

Once, you have created secrets, and also added secrets / tokens in your yml file (workflow file). Click on Start commit and then on Commit new file.

If you are on master branch itself.. once you click on Commit new file. It will immediately start Action. You can go to Actions in your Github Repository and you will notice your workflow listed there. Our workflow name is CI, we can see it listed there.

You will also notice that workflow has already started, and is executing jobs and steps.

Once job is successful, and you go to FTP, you will see your files uploaded there.

If you see unwanted files being also uploaded to FTP, you can create .git-ftp-ignore file in root folder of your Github repository and you can have content as follows:

.github/*
.git-ftp-ignore
.git-ftp.log
LICENSE
README.md

.git-ftp-ignore uses same syntax as .gitignore file.

We have setup a very basic Github Action right now. Later on we will setup more advance Github Action. As you are already aware that I am developing an Operating System and you can read about its articles on this same blog as well as you can see it on my YouTube Channel, source code of my Operating System is on Github. For My OS, I will write a complex Github Action to create releases.

About the Author