← Back to blog home

Adding CI/CD to Your Projects With GitHub Actions

If you’re hosting your code on GitHub, you can use GitHub Actions to add useful workflows to your project. In this guide, I’ll show you what Actions are, and how you can use them to streamline your development process and add automation.

What are GitHub Actions?

GitHub Actions help you automate tasks within your software development life cycle. GitHub Actions are event-driven, meaning that you can run a series of commands after a specified event has occurred.
— via GitHub Docs

In the simplest sense, Actions allow you to automate tasks. That might include checking code for syntax errors, optimizing image compression, or any other task you want to automate based on a certain *event*. Events can be defined in various ways, but most typically use a git push to trigger an Action. By using Actions to automate tedious or repetitive tasks, you can make your SDLC (Systems Development Life Cycle) more efficient, particularly when multiple people are using the same code base.

Setting Up GitHub Actions

Actions are defined by a YAML file in your repository. To set up your first Action, you’ll need to add a.githubdirectory to the root of your project, with aworkflowsdirectory nested inside. Your Action .yaml (or .yml, either extension is valid) files will go here.

• Project
├─ .github/
│ └─ workflows/
│ └─ action-one.yml
│ └─ action-two.yml
├─ dist/
├─ src/
├─ package.json
└─ package.lock.json

If you haven’t used YAML before, it’s very straightforward, but be aware the syntax is very unforgiving when it comes to whitespace. Make sure you’re using spaces instead of tabs for indentation.

# action-one.yml

name: action-one # Optional: the name of the workflow
on: [push] # Specify the event trigger
jobs: # Groups all the 'action-one' jobs
say-hello: # Defines the 'say-hello' job
runs-on: ubuntu-20.04 # Virtual runner environment
steps: # Groups all the steps for 'say-hello' job
- uses: actions/checkout@v2 # Checks out your repo so Action can access it
- run: echo "Hello" # Run a command on the runner

Theaction-one.ymlAction will work as follows:

  1. Trigger on a git push to the repository
  2. Execute 'job' called 'say-hello'
  3. Use version 20.04 of Ubuntu as a runner environment for the job (virtual machine)
  4. Execute 'say-hello' steps
  5. Use the community actions/checkout@v2 Action to check out the repo and allow access for the current Action
  6. Echo "Hello"

So the.ymlfile provides the instructions, and the GitHub servers take care of all the actual heavy lifting.

You’re free to run self-contained Actions in your workflow, including creating your own scripts to run within an Action. For instance, if you have a script you want to run against your repo written in bash, you could run that script within the workflow like so:

name: action-one
on: [push]
jobs:
say-hello:
runs-on: ubuntu-20.04
steps:
- uses: actions/checkout@v2
- run: ./some-script.sh
shell: bash

This process works the same whatever your Action is, but the possibilities become more powerful once you incorporate Actions from the GitHub marketplace.

Integrating Marketplace Actions

There are thousands of marketplace Actions you can incorporate into your workflows. Typically you only need to define the relevant action in your Action’suses:field within its YAML file, and many can be further configured according to their documentation.

Here’s an Action I use to publish a package to the NPM repository only if I push to the main branch with a commit message that includes the word "deploy" (Note that the emojis are purely decorative):

name: '🚀 publish'

on:
push:
branches:
- main
jobs:
release:
name: 🚀 publish
if:
"contains(github.event.head_commit.message, 'deploy')"
runs-on: ubuntu-latest
steps:
- name: 📚 checkout
uses: actions/checkout@v2.3.3
- name: 🟢 node
uses: actions/setup-node@v1.4.4
with:
node-version: 12
registry-url: https://registry.npmjs.org
- name: 🚀 publish
run: npm publish --access public
env:
NODE_AUTH_TOKEN: ${{secrets.NPM_AUTH_TOKEN}}

The Action uses the marketplace Actions "checkout" and "setup-node", along with aNODE_AUTH_TOKENthat uses my npm login credentials as a Secret. So without having to do anything myself, this Action will publish my package to the npm registry, though it only updates the published package there if there’s been a version change since the last publication.

Here’s an Action from sisodiya2421that automatically creates a Trello card with a list issues of issues from your repo.

The capabilities are nearly limitless, depending on how much configuration you want to do. For example, a workflow might involve a few Actions that cascade:

  1. Use a linter to check for code errors
  2. Run tests
  3. Build for production
  4. Deploy live

If any of the steps in the sequence fail, the workflow could stop, preventing problematic code from reaching production. In a simpler scenario, you might have an action that detects an issue submission, and prompts the user to use a premise template for their issue.

Not every project will need lots of Actions, but they’re an extremely useful tool that can be tailored any way you like (depending on how long you want to spend configuring them). I’m still getting the hang of implementing more complex Actions that I combine with githook checks locally, but I’ve found them to be a very helpful addition to my workflows.

← Back to blog home