Hey guys π, Today I'm going to tell you all about github actions and we'll setup a CI/CD workflow
Github Actions
This is tool made by Github that helps us to automate tasks.
Before github actions, we had to push the code, run the tests manually, fix the bugs, test again, fix more bugs.... you know the drill. Github actions help us to automate this workflow. Let's look at CI/CD in detail:
Continous Integration
This involves merging code with existing codebase.
The developers push to a git repo and test suites are run automatically. If there is an error, then the next stage won't start. However, if all goes well, we move on to the next stage(you guessed it.... continuous deployment).
Continous Deployment
This involves sending code to hosting provider.
The pushed code(already tested and hopefully bug free) is pushed to the deployment server which reflects the changes in the live site. For example, after the CI stage, the code is pushed to heroku(hosting service in this example).
Terminology and Concepts
Workflows are automated procedures that live in your GitHub repository. This is the configuration for specifying how the automation works and itβs done with a YAML file.
name: Deploy to Firebase Hosting
on: push
jobs:
build_and_preview:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- run: npm ci && npm run build
- uses: FirebaseExtended/action-hosting-deploy@v0
This is a sample of a configuration file. Don't worry, we'll go through everything in detail later.
Actions
Actions are standalone commands likenpm run test
ornpm run build
. Actions are the building blocks of a workflowSteps
Running an action is called a Step. An action is a single step. One step is to install dependencies, the next is to build app, then the last step could be to deploy to hosting provider.Jobs & Runners
All of these steps create a Job. Jobs execute on a server called a runner. For most cases the runner is hosted on GitHub. You can host your own, but I have no idea how that works, so this blog post only refers to using GitHub hosted runners. When configuring the workflow YAML file youβll see a spot for Jobs.Steps
Steps are tasks that can be can be executed by a job.Job
A job is made up of multiple steps and runs in an instance of the virtual environment. Jobs can run independently of each other or sequential if the current job depends on the previous job to be successful.
That's a lot of terminology... let's get our hands dirty with some code.
First Github Action
Github actions are created in .github/workflows
folder in your root directory. If you want, you can follow along with your own project and we'll automate the hell out of it. You're free to call it anything you want. The actions will show up in the actions
tab in github.
Each action has 3 compulsory properties:
-
name
- name of the action() -
on
- when to run this action(eg. on pushing to repo) -
jobs
- work to be done when action is called(eg run test suite)
YAML/YML
If you don't know about yaml, yaml is basically JSON with brackets. Yaml relies heavily on indentation, make sure you have the right number of spaces/tabs. Let me give you a quick rundown of yaml syntax.
- Indentation
example: 'lorem-ipsum'
example-object:
x: 'y',
abc: 'pqr'
- Arrays/Lists
array:
- a: a
- b: b
Let's create a new file deployment.yml
. For the purpose of this demo, we will be creating an action that deploys to firebase hosting when code is pushed to master branch.
name: learn-github-actions
on: [push]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- run: echo 'PUSH'
We have added the following code into our deployment.yml
file. Let's walk through each line step by step.
name
: The name of the workflow as it will appear in the Actions tab of the GitHub repo.on
: The event to listen to(eg push, pull request etc)jobs
: An array of all the jobsdeploy
: Name of 1st job, can add more jobs in similar fashionruns-on
: Configures the job to run on an Ubuntu Linux runner of the given version.steps
: Array of steps that run in thedeploy
job. Each item in this array is an action or a command
To push the changes, run the following commands in your terminal(after setting up remote origin):
git add .
git commit -m "Adding deployment workflow"
git push origin master
After pushing the changes, go to the actions
tab of your repo
In the actions
tab, if you have done everything correctly, you will find a workflow(It will have a title of the commit message) with a name of learn-github-actions
(name of the workflow in yml file). Click on it.
Once you click on the workflow, you should see our yml file name and the deploy
job in the workflow.
Now, click on the deploy
job. After doing this, you will be able to see the various steps in our job. If you click on one of the steps you can see how it was run in the terminal
Continuous Integration and Testing
Let's implement a workflow that runs tests everytime code is pushed.
name: NodeJS Tests
on: ['push']
jobs:
test_node:
runs-on: ubuntu-latest
strategy:
matrix:
node-version: [12.x, 14.x]
steps:
- uses: actions/checkout@v2
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v1
with:
node-version: ${{ matrix.node-version }}
- run: npm install
- run: npm run build --if-present
- run: npm run coverage
- name: Coveralls
uses: coverallsapp/github-action@master
env:
COVERALLS_REPO_TOKEN: ${{ secrets.COVERALLS_REPO_TOKEN }}
COVERALLS_GIT_BRANCH: ${{ github.ref }}
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
I've called it Node Tests
and it runs on pull requests. I've created a job called test_node
which runs on the latest version of ubuntu. Since we need our source code in our VM, we will use the actions/checkout@v2
community action to bring the code into the current working directory. We'll need node to execute our apps so we'll use another community action called actions/setup-node@v1
and specify our node version.
We're ready to start running our own commands. I've started with installing my dependencies using npm ci
. Then, I'm running my test suite and building the application to make sure the build compiles properly.
If you have a more complex test suite like cypress, there's probably a community action for this.
Adding Continuous Deployment
Let's implement deployment to firebase hosting on merge and pull requests. The basic concepts of actions are the same, these can be used along with various hosting providers.
Most of these providers will have specific does on how to use github actions along with their product. For example, firebase has it's docs about here. There probably is a community action for every popular hosting service.
After running the following command, agree to the options. In the build command section, add a build command if required. Check out the files generated by firebase for me and we'll walk through the code.
firebase init hosting:github
In firebase-hosting-merge.yml:
name: Deploy to Firebase Hosting on merge
'on':
push:
branches:
- master
jobs:
build_and_deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- run: npm ci && npm run build
- uses: FirebaseExtended/action-hosting-deploy@v0
with:
repoToken: '${{ secrets.GITHUB_TOKEN }}'
firebaseServiceAccount: '${{ secrets.auto_generated }}'
channelId: live
projectId: auto_generated_variable
env:
FIREBASE_CLI_PREVIEWS: auto_generated_variable
In places where I've written auto_generated
those are private variables given by firebase which I cannot disclose(otherwise you could access my app).
name
is nothing new... we've looked at this before. on
is set to push. Here we have added a branches
array with the master
branch.
Then we have the jobs
, in which there's a build_and_deploy
job. We've specified runs-on
which is set to ubuntu-latest
. Again, nothing new here.
The uses
keyword tells the job to get v2 of the community action named actions/checkout@v2. This is an action that checks our repository and downloads it into the runner, allowing you to run actions against your code (such as testing tools).
The with
provides input arguments that are needed by the action and env
provides environmental variables.
The other file firebase-hosting-pull-request
has almost identical code. Checkout various community developed actions
here.
Github actions does not stop here. There are a lot more things we can do with actions. Like AI based pull request reviewing, auto code fixing for starters.
Uses for actions
Publish NPM package
As soon as code is pushed to a branch, we can deploy our package to NPMPush to master branch
Run test/deployment on pushing to the master/main branchScheduled background jobs
Used to backup database data(mostly firebase as it is not built-in) to cloud storage buckets
That's all for now, I hope you guys liked this post. Like the post and follow me if you did. Bye π