Integrating A CI/CD Pipeline Using Github Actions

An article on creating a CI/CD pipeline to automate deployments on Firebase using Github actions

Integrating A CI/CD Pipeline Using Github Actions

Introduction

It is pretty straightforward to build and deploy a website or app on Firebase manually through CLI using firebase-tool in the case of smaller projects. Doing it manually in large or rapidly developing projects with multiple development environments like development, testing, staging and production etc. will be a nightmare for the developers as it requires a lot of work and time to maintain the environment specific builds and configurations. So to avoid this hassle, it is a good practice to have automated deployments or a CI/CD pipeline setup in place. Rather than worrying about creating and maintaining the environment specific builds and configurations necessary to deploy the application, developers can now focus more on the actual app development.

In this article, we will be going through a detailed step-by-step process to write a custom workflow to setup a CI/CD pipeline to automate the multi environment deployments for a Vue and Firebase applications using GitHub actions.

Prerequisites:

  • An existing Github repository for your project.
  • Firebase project for your application.
  • Multiple deploy or hosting targets setup for different deployment environments.

Contents of the article

  • Using GitHub environment secrets to store and access secure data in GitHub actions.
  • Creating a GitHub workflow to deploy a Firebase application.
  • Creating different jobs for deployments to multiple environments based on the branch to which the changes are pushed.
  • Creating environment-specific env files in the GitHub workflow.
  • Creating the app build and deploying it on Firebase using a GitHub workflow
  • Saving the build folder using the artifacts feature after successful deployment.

Lets code!!!

1. Using GitHub environment secrets to store and access secure data in GitHub actions

Secrets are encrypted environment variables that you create in an organisation, repository, or repository environment and these can only be updated but can't be accessed outside the workflows.

At the time of this article environment specific secrets are limited to public repositories

actions-org-secrets-list.png

Based on the type of repository, you can choose between environment specific secrets for public repositories or organization-specific secrets for a private repository.

Secrets are generally used to store sensitive data. In this case, we will be storing the Firebase auth token and env variables for different environments, etc.

To know more about how to store secrets on GitHub repository, please go through the documentation here

2. Creating a GitHub workflow to deploy Firebase applications

We can also use readily available actions on the GitHub Marketplace to integrate your preferred tools right into your repository. In this article, we will be creating and using a custom GitHub workflow written in a YAML file. The name is displayed in workflows in the actions tab on GitHub as shown:

name: Firebase hosting

The events specified in the on are used to automatically trigger a workflow. Visit this link to learn more about supported events. In our case, we want the workflow to be triggered when any new changes are pushed to either master, staging or testing branches. Enter the following code into your console:

# on action to branches to trigger this workflow 
on:
  push:
    branches: [master, staging, testing]

This runs our workflow whenever any new changes are pushed or merged to the above-specified master, staging and testing branches

3. Creating different jobs for deployments to multiple environments based on the branch to which the changes are pushed

A workflow is made up of one or more jobs, which run in parallel by default. In our case, we will be defining three jobs that are triggered based on the branch to which the new changes are pushed.

We will be using three different branches to hold the code in different environments:

  • master -> production
  • staging -> staging
  • testing -> testing or dev

Visit here to know more about jobs in GitHub workflow. Use the following code to proceed:

jobs:
  # name of the job
  TESTING:
    if: github.ref == 'refs/heads/testing'
    # To define the type of machine to run the job on
    runs-on: ubuntu-latest
    steps:
      # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it
      - uses: actions/checkout@v2

You can specify the environment for the job by adding an environment field inside the job. By specifying the environment your workflow can access the environment-specific secrets and use other environment-specific features GitHub provides using the following code:

jobs:
  # name of the job
  TESTING:
    ......
    ......
    # The environment that the job references 
    environment:
      name: test
      url: <YOUR TESTING WEBSITE URL>
    # To define the type of machine to run the job on
    runs-on: ubuntu-latest
    ......
    ......

Each job can include many steps and each step is defined to perform some task. In our case, the steps are:

i. Installing firebase tools and switching to a specific Firebase project as shown:

   - name: Installing firebase tools
     run: |
     sudo npm install -g firebase-tools
     firebase use <TESTING PROJECT NAME ON FIREBASE> --token ${{ secrets.FIREBASE_TOKEN }}

To install firebase tools and to switch to a specific Firebase project while running the workflow we need to provide a Firebase admin token. We can get the Firebase auth token using the below command and it is highly recommended that the token should be stored in GitHub secrets:

firebase login:ci

ii. Creating necessary env w.r.t the deployment environment while running the workflow.

As the env file holds sensitive data that needs to be accessed while creating the build for the application rather than exposing its content in the GitHub repositories, it is recommended to create them in the workflow run.

In our case, we are using SpicyPizza/create-envfile@v1 library to create an env file in runtime and in order to do this while specifying key-value pairs to create an env file, we should prepend each env key name with envKey_.

Example: To save a key VUE_APP_SECRET_KEY inside the env file you need to specify the envkey_VUE_APP_SECRET_KEY while creating it using SpicyPizza/create-envfile@v1

Use the following code snippet:

   - name: Creating .env file
     uses: SpicyPizza/create-envfile@v1
     with:
       envkey_VUE_APP_SECRET_KEY: ${{ secrets.SECRET_KEY }}
       envkey_VUE_APP_SECRET_KEY_CHECK: ${{ secrets.SECRET_KEY_CHECK }}

iii. Create a build to deploy a website on firebase based on the deployment environment.

The created build folder will contain your static data, CSS, script, vendor folder, etc ready to be deployed. Run the code given below to proceed:

   - name: Build website
     run: |
       yarn
       yarn build

iv. Deploy a website on firebase based on the deployment environment

As the build is ready now, we can use firebase deploy command to deploy our application. In the below command you should specify the hosting environment based on the job and multiple deploy targets you have set up in your firebase project. Example: hosting:testing, hosting:staging and hosting:prod etc. Run the following code:

   - name: Deploy to testing site
     run: firebase deploy --only hosting:testing --non-interactive --token ${{ secrets.FIREBASE_TOKEN }} -m "RunID ${{ github.run_id }} Commit SHA ${{ github.sha }}"

v. Save build artifacts after a successful deployment An artifact is a file or collection of files produced during a workflow run. Artifacts allow you to persist data after a job has been completed, and share that data with another job in the same workflow. One of its popular use cases is to save your build and test output after a workflow run. Run the following code:

  - name: Archive build Artifact
    uses: actions/upload-artifact@master
    with:
      path: dist

Repeat the same steps while creating the other two jobs i.e Staging and production.

Summary

A CI/CD pipeline setup using Github actions is very straightforward and is definitely worth trying out in your projects. The CI/CD pipeline setup is a one-time configuration and is proven to improve developer productivity, testing efforts, and velocity of software delivery. And if you are using Git as a version controller for your project, then you should definitely try out GitHub actions as it provides everything you need to set up the CI/CD pipeline right in your repository. By using the Github actions along with the deployment workflow, you can also add workflows to run your unit and integration tests to automate the testing process before deployment.

If you have any questions, feel free to contact me or comment on this article.

Hope you find this article useful. Thanks and happy learning !