Automate the hell out of your code
When you hear of automation what comes to your mind? Software automation involves all practices that is geared towards using your coding skills and resources to avoid doing repetitive tasks manually and instead we write a script that handles all the repetitive tasks enabling us to be more productive, ship our code faster and actually focus on writing code. In this article i am going to be introducing you to the concept of software automation, we will look at CI/CD, don't worry if you have no idea what those abbreviations mean, by the time you are done with this article, you will be able to automate the hell out of your code. Well let's get started.
Bring your own Repo
For you to follow along with this article you need to create a github repository or you can use one you already created in the past. I will be using github actions to automate our code, you can also use circle CI if that's what you are comfortable with.
Create a github Workflow
To create a github workflow, inside the root directory of your current working directory create a folder named .github and inside it create a workflows directory, it is inside this workflows directory that we will actually write the code that will handle our CI for us.
------.github/-----workflows/-----integrate.yml
Github uses a yml file for it's workflows, every file that ends with a .yml
extension will be treated as a workflow by github and upon whatever condition we specify inside that file github will automatically run the workflow, just know every workflow should have the following syntax; see the github actions documentary
name: WE SPECIFFY THE NAME OF THE JOB
on: # Which event to trigger this workflow
github_event: # e.g pull, pull_request, push, commit etc
banches: [ branch_to_run_workflow_on, another_branch]
# A workflow run is made up of one or more jobs that can run sequentially or in parallel
jobs:
give_the_job_a_name:
runs-on: machine_to_run_on # ubuntu-latest, windows-latest, macos-latest
steps:
- uses: use_already_defined_workflow
- run: terminal command
- run: another terminal command
What is Continuous Integration CI?
Continuous integration is a software development principle that suggests that developers should write small chunks of code and when they push this code to their repository the code should be automatically tested by a script that runs on a remote machine, automating the process of adding new code to the code base. This automates software testing thus increasing the developers productivity and keeping their focus on writing code that passes the tests.
let's edit our integrate.yml
to create a workflow that will automatically test our code whenever there is a pull request on the repository
# This workflow will run on every pull request to the master branch,
# This is the name of the workflow, every workflow needs a name
name: NODE CONTINOUS INTEGRATION WORKFLOW
# Here we specify on which action in the repository that we want to run this workflow, e.g push, pull_request, commit, pull e.t.c
on:
pull_request:
branches: [ master ]
# we define one or more jobs, every workflow should have a job, we can give each job a name
jobs:
automate_our_testing:
# we need to tell it which machine to run the job on
runs-on: ubuntu-latest
# Steps represent a sequence of tasks that will be executed as part of the job
steps:
- uses: actions/checkout@v2 #This pulls our code to the remote machine
- uses: actions/setup-node@v2 # This setsup node js on the machine
with:
node-version: 12
- run: npm ci # installs our project dependencies
- run: npm run build # builds the project
- run: npm test # runs our test command
env:
CI: true
If you created this file locally on your computer, you can save it, commit it and then push it up to github. Once that is done, go to the actions tab, you should see this workflow listed there. If you make one or two changes to your code base and push it up the repo, make a pull request, go back to the actions tab you should see this workflow running and you can obtain information about each step in the workflow. The cool thing is that if our tests fail, we get a log where we can inspect each step in the job to know what broke down, fix it and push it back to the repo and our workflow will run again becuase we have an open pull request and if all test passes successfully we will see check next to each step, then we can merge the pull request. That's continuous integration taken care of.
What is Continuous Deployment CD?
If continuous integration is adding new chunks of code to the code base, then CD is about automating the building and deploying our code to the production environment, this ensures that the production environment is kept in sync with the latest features in the code base. You can read this article for more on CI/CD.
I use firebase hosting, so we can define a workflow that builds and deploys our code to firebase hosting rather than having to do that ourselves.
But we have one or two issues we have to deal with, normally we can deploy code to firebase from our computer because we are logged in from the terminal, but how do we authorize a remote CI server to do this? open up a terminal and run the following command firebase login:ci
it will throw back a FIREBASE_TOKEN that we can use to authenticate CI servers. We need to add this token to github so github can securely encrypt it for us and we can call it as a variable, rather hard coding it inside the workflow which can lead to security issues and concern.
- Open github and the repo you would like to add this CD workflow
- navigate to settings
- under settings click on secrets
- click add new secrete
- give it a name of FIREBASE_TOKEN
- paste the token firebase gave us as the value of the secrete
- click add secrete.
On your local machine we need to create another workflow to handle this deployment, create a new file and name it whatever you like, am going to call it build.yml
------.github/-----workflows/-----integrate.yml
|---build.yml
It should have the following content
# This workflow runs on every push/merge to the master branch
name: FIREBASE_DEPLOY
# Controls when the action will run.
on:
# Triggers the workflow on push or pull request events but only for the master branch
push:
branches: [ master ]
# Allows you to run this workflow manually from the Actions tab
workflow_dispatch:
jobs:
# This workflow contains a single job called "build"
build:
# The type of runner that the job will run on
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2 # import our files to the remote CI server
# Runs a single command using the runners shell
- name: Use Node.js version 12
uses: actions/setup-node@v2 # using node js
with:
node-version: 12
- run: npm ci # clean install of our dependencies
- run: npm run build # building our project
- name: GitHub Action for Firebase
uses: w9jds/firebase-action@v2.0.0 # predefined workflow for firebase
with:
args: deploy --only hosting # deploying only hosting
env:
FIREBASE_TOKEN: ${{ secrets.FIREBASE_TOKEN }}
# using our secrete token to authenticate the remote CI to push code to firebase hosting
Now if we push code directly to the master branch or we merge in a pull request from the master branch, this workflow will automatically be triggered, deploying our code to firebase, but i don't expect everyone to use firebase, sometimes i deploy to netlify too, but i just used firebase as an instance to help you get started. I recommend that you watch this video to learn other things you can do with github actions.
That's it for this article, i hope you find this interesting and learn something, feel free to leave a comment below