-
Notifications
You must be signed in to change notification settings - Fork 6
Understanding GitHub Actions & Workflows
Some of the terms can be confusing if you're not already well-versed with GitHub Actions.
This is the name of GitHub's CI system in general, sometimes abbreviated GHA, sometimes shortened to "actions" in sentences, but this can be confusing due to the meaning of an "action" within the system.
This is the top-level of what you define within GHA. The workflow is a single document that specifies:
- The triggers (events) that cause it to be executed.
- The jobs that execute, along with with the relationship between jobs (dependency).
A job is a set of steps to execute. The job is also the unit that gets run on a specific runner (virtual machine).
Other than dependency relationships and concurrency limits, jobs execute in parallel.
A step is a unit of execution (task) within an individual job. The run
step (which runs commands on the runner) is built in.
Other steps use the uses
keyword and reference an action to execute.
Actions are self-contained code hosted in a GitHub repository, that makes up a single step in your workflow (even if it does a lot behind the scenes). Most of what is done within a job is an action of some kind, even very common operations like "checkout" are done as an action, whose code is maintained and hosted in a repository.
When an action is referenced in a step, it also includes a specific ref in the source repo to load, which is how "versioning" is done. The actual clone/checkout for a particular action is handled automatically.
Actions can be written as one of 3 types:
- NodeJS
- Docker
- Composite
Since the GitHub runner application is NodeJS, actions written in node are kind of the "native" type.
Docker actions use a dockerfile, so anything you can package into a container could be used as an action, however they can only be used in Linux runners.
Composite actions run a set of steps, similar to what would be run in a job. Previously, they only supported run
steps, but have recently been expanded to allow the use of actions.
Reusable workflows allow you to define a workflow with optional inputs and outputs, and call it from another workflow.
There are some limitations to this functionality, like not allowing additional nested workflows. In addition, the calling workflow cannot use the called workflow as a piece of a larger job: a individual job defined in the calling workflow can call a single external workflow and do nothing else. That means the reusable workflow defines the entirety of what happens in each of its jobs.
A calling workflow can define additional jobs that have its own steps (jobs that don't call a reusable workflow).
We can relate the pieces of GitHub Actions to Ansible terms. The analogy is not perfect, but may be helpful nonetheless.
The workflow, like an Ansible playbook, is a single document containing one or more plays.
The job is similar to a play: it defines where things will run and some other properties about the run.
The steps
in a job are like the tasks
in a play, each performing some action (in the general sense).
A GitHub action could be thought of like an Ansible module: it's some code that does something, accepts inputs (options), provides outputs (return).
A composite action could be thought of somewhat similarly to an Ansible role, in the sense that you can invoke it as a single step (task) via include_role
in your job (play), and it's made up of several steps (tasks). A slight difference is that Ansible will show each task in the role individually, and GitHub will mostly show the composite action's steps' output combined as a single step.
The playbook/play analogy actually works decently well with reusable workflows, in the sense that when you import_playbook
, in an Ansible playbook, you are bringing the entire playbook in, including all its plays (you can't use it piecemeal within an existing play).
But unlike import_playbook
, reusable workflows do allow for inputs and outputs.