GitHub Actions is an end-to-end GitHub-centric SDLC process. It provides an automation platform and framework previously missing from GitHub and had to be added with other solutions, such as Jenkins or Travis CI.
Relationship of GitHub Actions components
Components
Triggering Workflows
An event can be defined in several different ways:
- A person or a process performs some operations in a GitHub repository.
- A matching external trigger happens—an event from outside of GitHub.
- A schedule is set up to run a workflow at particular times or intervals.
- A workflow is initiated manually without an operation being done first.
This can be described with the on
command. Here are a set of examples:
on: push
on: [push, pull_request]
on:
push:
branches:
- main
- 'rel/v*'
tags:
- v1.*
- beta
paths:
- '**.py'
on:
scheduled:
- cron: '30 5,15 * * *'
on: [workflow-dispatch, repository-dispatch]
on: workflow_call
on: issue_comment
The workflow file should be in the default branch.
Steps
- Steps are the basic unit of execution you deal with when working with GitHub Actions.
- They consist of:
- Either the invocation of a predefined action or
- A shell command is to be run on the runner.
- Any shell commands are executed via a
run
clause. And any predefined actions are pulled in via auses
clause. - The
steps
keyword indicates the start of a series of steps to be run sequentially. - The following code listing shows an example of three basic steps from a workflow. These steps check out a set of code, set up a go environment based on a particular version, and run the go process on a source file.
- In the YAML syntax, the
-
character indicates where a step starts. - The
uses
clause indicates that this step invokes a predefined action. - The
with
clause is used to specify arguments/parameters to pass to the action. - The
run
clause indicates a command to be run in the shell. - Note that steps can have a
name
associated with them as well:
steps:
- uses: actions/checkout@v3
- name: setup Go version
uses: actions/setup-go@v2
with:
go-version: '1.14.0'
- run: go run helloworld.go
Runners
Runners are the physical or virtual computers or containers where the code for a workflow is executed. They can be systems provided and hosted by GitHub (and run within their control) or instances you set up, host, and control.
In either case, the systems are configured to understand how to interact with the GitHub Actions framework. They can interact with GitHub to access workflows and predefined actions, execute steps, and report outcomes.
runs-on: ubuntu-latest
GitHub hosted vs Self-Hosted runners
Category | GitHub-hosted | Self-hosted |
---|---|---|
Provisioning/hosting | Managed by GitHub | Managed by you |
Prereqs | Running GitHub actions runner application (handled by GitHub) | GitHub Actions self-hosted runner application deployed and configured |
Platforms | Windows, Ubuntu Linux, MacOS | Any from the supported architectures and platforms that you choose |
Configurability | Constrained mostly to predefined configurations | Highly configurable |
Ownership | GitHub | As defined |
Lifetime | Clean instance for the life of a job | As defined |
Cost | Free minutes based on your GitHub plan with cost for overages | Free to use with actions, but owner is responsible for any other cost |
Automatic updates | GitHub provides for the OS, installed packages, tools, and hosted runner application | GitHub provides only for self-hosted runner application |
Implementation | Virtual | Virtual or physical |
Limits for Self-Hosted Runners
There are limits imposed on Actions usage when you use self-hosted runners. As of the time of this writing, the limits are those shown in Table 5-4.
Table 5-4. Self-hosted runner limits:
Category | Limit | Action if limit is reached/exceeded |
---|---|---|
Workflow run time | 35 days | Workflow canceled |
Job queue time | 24 hours | Job terminated if not started |
API requests | 1,000 per hour across all actions in a repository | Additional API calls will fail |
Job matrix | 256 jobs per workflow run | Not allowed |
Workflow run queue | 500 workflow runs per 10-second interval per repository | Workflow run terminated and fails to complete |
Queuing by GitHub Actions | Within 30 minutes of being triggered | Workflow not processed (this would most likely only occur if GitHub Actions services are unavailable for an extended time) |
Runners provide the required infrastructure to execute your workflows and thus, GitHub Actions. Runners can be automatically provided by GitHub through their hosting, or you can download the Runner app and use your own systems as runners. Each has advantages and disadvantages, including key factors such as cost, maintenance, control, configurability, and simplicity. Hosted runners are available for Ubuntu Linux, Windows, and macOS for preselected operating system versions and on standardized virtual systems. GitHub periodically updates and maintains these standardized environments. |
Your workflows can choose a particular runner through the runs-on
clause for each job in your workflow. You can also utilize standard OS commands (like calls to apt or brew) to install additional software on the systems if needed.
Self-hosted runners can be made ephemeral so that they execute only one job. This is desirable for autoscaling solutions such as the ARC.
Jobs
Jobs aggregate steps and define which runner to execute them on. An individual job is usually targeted toward accomplishing one particular goal of the overall workflow. An example could be a workflow that implements a CI/CD pipeline with separate building, testing, and packaging jobs.
Aside from the definition of the runner, a job in a workflow is like a function or procedure in a programming language. It comprises a series of individual commands to run and/or predefined actions to call, similar to how a function or procedure in a programming language is made up of individual lines of code and/or calls to other functions or procedures.
Building on the steps and runners previously shown, the next listing shows a simple job that does the checkout and setup and performs a build:
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: setup Go version'
uses: actions/setup-go@v2
with:
go-version: '1.14.0'
- run: go run helloworld.go
Workflow
A workflow is like a pipeline. At a high level, it first defines the types of inputs (events) it will respond to and under what conditions it will react to them. This is what we talked about in the earlier section on events. If the events and conditions match, the response is to execute the series of jobs in the workflow, which, in turn, executes the steps for each job.
The overall flow is like a continuous integration process in that it responds to a particular kind of change and kicks off an automated sequence of work. The next listing shows an example of a simple workflow for processing Go programs built on the previous definitions:
1. name: Simple Go Build
2.
3. on:
4. push:
5. branches:
6. - main
7.
8. jobs:
9. build:
10. runs-on: ubuntu-latest
11. steps:
12. - uses: actions/checkout@v3
13. - name: Setup Go version
14. uses: actions/setup-go@v2
15. with:
16. go-version: '1.15.1'
17. - run: go run hello-world.go
Think of actions as plug-ins or modules in other applications.
The workflows are more like the pipelines or scripts that use those modules or plug-ins.
Context | Purpose | Example properties |
---|---|---|
github |
Data attributes about the workflow run and the event that triggered the run. | github.ref github.event_name github.repository |
env |
Variables that have been set in a workflow, job, or step. | env.<env_name> (to retrieve value) |
vars |
Configuration variables set for a repository, environment, or organization (see also Chapter 12). | vars.<var_name> (to retrieve value) |
job |
Information about the currently running job. | job.container job.services job.status |
jobs |
Only available for reusable workflows. Used to set outputs from reusable workflows. | jobs.<job_id>.results jobs.<job_id>.outputs |
steps |
If a step has an id property associated with it and has already run, this contains information from the run. | steps.<step_id>.outcome steps.<step_id>.outputs |
runner |
Information about the runner executing the current job. | runner.name runner.os runner.arch |
secrets |
Contains names and values associated with a secret; not available in composite workflows but can be passed in. | secrets.GITHUB_TOKEN secrets.<secret_name> (to retrieve value) |
strategy |
If a matrix is used to define a set of items to execute across, this context contains information about the matrix for the current job. | strategy.job-index strategy.max-parallel |
matrix |
For workflows that use a matrix, contains the matrix properties that apply to the current job. | matrix.<property_name> |
needs |
Used to collect output from other jobs; contains output from all jobs that are defined as a direct dependent of the current job. | needs.<job_id> needs.<job_id>.outputs needs.<job_id>.outputs.<output name> |
inputs |
Contains input properties that are passed in to an action, a reusable workflow, or a manually triggered workflow. | inputs.<name> (to retrieve value) |
Review-based workflow deployment is also possible.
GitHub Actions provides several ways to get and set properties of the environment for use in your workflows. Contexts provide data properties associated with key categories such as GitHub, runners, and secrets.
Environment variables can be used to set values in a single workflow and referenced via the env context. Configuration variables can be set at the repository or organizational level, providing mappings for use across workflows. Secrets serve a similar purpose but encapsulate data that needs to be handled securely.
When your workflow needs to access key information or interact more directly with the repository, you may need to adjust its permissions. This can be done by assigning more permissions to the built-in GITHUB_TOKEN. Permissions should be the minimum needed for the workflow or job to accomplish what is needed.
Deployment environments give you a way to provide destinations to deploy items from your workflow into separate areas. You can configure protection rules, tokens, and variables unique to the environment and associate an environment to a job. This setup allows you to exercise more control over what conditions can be used to run your jobs, provide exclusive data values, and provide a way to differentiate your workflow runs for different levels, such as dev, test, prod.
GitHub Actions provides a number of built-in features to help you understand the execution of your workflow runs at multiple levels. This includes clear, easy-to-find status information in the browser interface through the list of workflow runs, job graphs, and selectable filters.
At a lower level, you can dig into logs and turn on debugging information for the steps in your workflow that will be visible in your logs.
At the deepest level, you can enable runner diagnostic logs to see exactly what is being executed on the runner system throughout a workflow run. These logs are generated separately and must be downloaded to access and view.
When you want to provide more diagnostic or information messages in your logging, Actions makes that easy to do with simple workflow commands that can be used to echo out different messages.
Finally, when your jobs are completed, you can provide customized job summaries with as much detail as needed/desired.
name: Verify existence of CONTRIBUTING.md file
on:
push:
pull_request:
jobs:
verify:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- run: |
[[ -f CONTRIBUTING.md ]] ||
( echo "CONTRIBUTING.md file needs to be added to
${{ github.repository }} !" && exit 1 )
strategy:
matrix:
prod: [prod1, prod2]
level: [dev, stage, rel]
include:
- prod: prod3
level: dev
tag: alpha
exclude:
- prod: prod1
level: stage
- level: dev