GitHub Actions was revamped and relaunched at GitHub Universe 2019 in San Francisco. With the launch, GitHub showcased a variety of use cases to include Continuous Integration (CI) / and Continuous Deployment (CD), but there's much more that GitHub Actions can do to help automate your workflows.
If you are a vendor looking ot integrate with GitHub Actions, or a DevOps Engineer that wants to consider GitHub Actions for your build pipelines, this article is for you!
We'll cover the following:
- What is GitHub Actions, and what are it's components?
- What are Secrets, and how can we leverage them within our organization?
- What are Self-Hosted Runners?
- Much more!
What are GitHub Actions?
GitHub Actions have a few components that all work together to form a world class CI/CD platform. We'll take a look at each of these components below, but I wanted to list a few features of GitHub Actions.
If you've ever built a cross-platform application, or maybe an application that needs to support various versions of a package or framework, matrix builds make this easy.
With a matrix build, you can setup your CI to run across multiple Node versions for example, and across Windows, Mac, and Linux.
Live Streaming Logs
With GitHub Actions, as your workflows are running you can watch the logs live, and link to individual lines to help with dicussions with your team. Once the logs are completed, you can download them as well as various build artifacts if desired.
Built in Secret Store
With GitHub Actions, you'll often want to interact with various external tools and services. GitHub provides an organization-level, and repository-level Secret store that allows you to encrypt strings like API tokens that can then be used in various workflows, pipelines, etc.
GitHub Hosted VM Runners
GitHub provides hosted runners for Linux, macOS, and Windows environments. These builds run free on public repositories as of the time of this writing, and private repositories have various limits before paying build minutes.
Finally, GitHub Actions supports a concept called self-hosted runners, which allows you to setup your own environment to use on builds. This would be great if your application requires specific hardware (such as ARM processors), or specific environment settings that are not included in the GitHub Hosted VM Runners.
Components of GitHub Actions
Let's break down what makes up a GitHub Action, and what each piece does.
What are Workflows?
We'll start with workflows. Workflows are your pipeline as code, and can be equated to Jenkinsfiles, Travis.yml's, etc. They live within the repository they will interact with, and respond to Events (discussed more below) to take action on your code. They're written in YAML syntax.
These workflows are often used for CI/CD, however you could also do something like auto-respond to new issues from first time contributors, welcoming them to your project and thanking them for opening an issue. Other examples could include compliance and legal concerns, such as enforcing branch protections, licensing, and more.
One thing to note is that as of the writing of this article (June 2020), GitHub Actions workflows need to live in the repository themselves. There is a common ask to have organization-level workflows as well, so hopefully we will see this in the future.
What are Events?
Events trigger the workflows we just discussed. GitHub Actions supports almost every Webhook event on GitHub, so things like issues opening/closing, pull requests being merged, deployments, etc. You can also use cron triggers to execute workflows on a set schedule.
What are Actions?
Actions are reusable units of code, and perform specific tasks based on inputs your workflow provides and the event payload contains.
What are Self-Hosted Runners?
The Actions runner source code is open source, and allow you to create your own custom runners with whatever customizations you need (more hardware, a different operation system, on premises, in the cloud, etc).
Self-hosted runners are free to use with GitHub Actions, because you are responsible for the cost of maintaining your runner machine(s).
GitHub Actions API
GitHub's API is really robust, and allows you to do just about anything via code that you could do on the UI. GitHub Actions continues this trend by providing a variety of REST API endpoints.
These endpoints allow you to interact with build artifacts, get information about the workflows being ran, specific build job details, and a way to manage Secrets.
Container actions can be written in any language you like, but only run on the Linux runners currently. They are a little slower, and provide a little less of a user experience, but are still very versatile.
Basically, choose whichever language and environment makes sense for you and your project.
Best Practices for GitHub Actions
When creating GitHub Actions, there are a few best practices to keep in mind.
First, always version your action releases with the releases and tags feature of GitHub. This allows your users to target a specific release, and not always pull the latest which could result in unexpected behavior.
Next, ensure you have proper documentation. You'll want to have a README with a sample workflow to execute your action, and this README is rendered on the GitHub Marketplace listing for your GitHub Action. You should also consider adding CONTRIBUTING docs, and other open source documentation.
Ensure you create an action.yml file, which provides the metadata around your action.
Finally, make sure you post your GitHub Action on the GitHub Marketplace.
When writing an action, there are two approaches that can be taken and should be discussed. These are chainable versus monolithic and are broken out below.
Monolithic Action Example
A monolithic action would mean your action is doing all the things in one "step" of a workflow file. For example, you could have an action that builds, tests, uploads build artifacts, creates a release, and sends a tweet about the release.
While this may sound appealing at first, one action to rule them all is very difficult to maintain and make modular. GitHub Actions shine when they are chainable, as discussed next.
Chainable Action Example
In contrast to a monolithic action, chainable actions are my preference. Consider this workflow as an example. Each bullet could be a seperate step, which means when debugging errors I know exactly what part of my pipeline is failing versus it being abstracted into a single step.
- Checkout code
- Lint code
- Build project
- Run Unit
- Run Integration Tests
- Run UI Tests
- Create a Draft Release
- Generate release notes
- Publish release
- Send tweet about release
As you can see, while there are many more steps to this workflow, they are very clear in what each step does. You can plug and play modular actions into each of these steps, which provides a better user experience.
In conclusion, GitHub Actions are very versatile, powerful, and allow you to automate all sorts of things. Look for future articles on GitHub Actions, and leave a comment about any actions you have built or plan to.