- Workflow Automation Service offered by the GitHub
- Allows you to automate all kinds of repository-related processes and actions
- Service that offers various automations around the code that is stored on GitHub, around these repositories that hold that code.
- Free for public repositories
- CI/CD processes (Continuous Integration/Continuous Delivery/Continuous Deployment) - methods for automating app development, testing, building and deployment
- Continuous Integration is all about automatic handling code changes - integrating new code or code changes into an existing code base by building that code automatically. So that changed code by testing it automatically and by then merging it into existing code.
- Continuous Delivery or deployment is about publishing new versions of your app or package or website automatically after the code has been tested and integrated
- Example: After we make a change to the website code, we want to automatically upload and publish a new version of our website
- GitHub Actions helps setting up, configuring and running such CI/CD workflows
- It makes it very easy for us to set up processes that do automatically build, test, and publish new versions of our app, website, or package whenever we make a code change.
- Code and repository management - automating:
- code reviews
- issue management
Key Elements
- Workflows
- Jobs
- Steps
- Attached to GitHub repositories
- We can add as many workflows to GitHub repository as we wish
- The first thing we build/create when setting up an automation process with GHA
- Include one or more jobs
- Built to set up some automated process that should be executed
- Not executed all the time but on assigned triggers or events which define when a given workflow will be executed. Here are some examples of events that can be added:
- an event that requires manual activation of a workflow
- an event that executes a workflow whenever a new commit is pushed to a certain branch
- Defined in a YAML file at this path: <repo_root>/.github/workflows/<workflow_name>.y[a]ml
Workflow can have the following elements:
- name - name of the workflow
- on - defines a workflow trigger. It can have some of these values:
- workflow_call - can have the following attributes:
- inputs - an object containing one or more key-value pairs. inputs are only supported for workflow_dispatch (manual trigger). In each such pair a key is the names of the input variable which is used for referencing this input later in yaml document as ${{ inputs.<INPUT_VAR_NAME> }}. A value is an object containing one or more key-value pairs where keys can be:
- required: boolean
- type: string |
- default - string, number or boolean - a default value of the input variable, if one is not specified/set
- pull_request
- Runs the workflow when activity on a pull request in the workflow's repository occurs (by default when a pull request is opened or reopened or when the head branch of the pull request is updated)
- We can use the branches or branches-ignore filter to configure our workflow to only run on pull requests that target specific branches. E.g. if we specify master under branches, that means that this workflow will be triggered on any new/updated Pull Request which has master as a target (base) branch. Name of the feature branch can be arbitrary and is not important.
- Inputs are NOT allowed for workflows triggered by pull_request. The pull_request event does not accept user-defined inputs because it is triggered automatically when a PR is opened, synchronized, or updated.
- If you need dynamic behavior in a pull_request workflow, you can:
- Use environment variables (env)
- Use a GitHub secret or variable (secrets / vars)
- push - run the workflow when a push is made to any branch in the workflow's repository
- [ array of values above ] - if we want to combine multiple different triggers
- permissions - workflow permissions
- jobs - list of jobs. Each job is defined by stating its name followed by semicolon (e.g. jobA:). For each job we can define:
- name: - Descriptive name of the step
- runs-on: e.g. ubuntu-latest
- steps: List of steps. It's a YAML list so each step object needs to be prepended with "- ". For each step we can define:
- name: - step name
- uses: - name of the GitHub action e.g. "actions/checkout@master"
- with: - block used to pass input parameters to an action
- persist-credentials: boolean <-- specific input for certain actions, such as actions/checkout
- run: - if we want to specify raw commands
- env:
- env - define environment variables available in all jobs
- values can be hardcoded or read from GitHub secrets
permissions: examples:
Jobs:
- Contain one or more steps that will be executed in the order in which they're specified
- Define a runner
- Execution environment, the machine and operating system that will be used for executing these steps
- Can either be predefined by GitHub (runners for Linux, Mac OS, and Windows) or custom, configured by ourselves
- Steps will be executed in the specified runner environment/machine
- If we have multiple jobs they run in parallel by default, but we can also configure them to run in sequential order, one job after another
- We can also set up conditional jobs which will not always run, but which instead need a certain condition to be met.
- if: This keyword allows you to specify a condition that must be true for the job or step to execute.
- name - Job name which will be shown in GitHub Actions tab
- needs
- runs-on - runner type: ubuntu-latest or custom
- env - its value is an object containing one or more key-value pairs where key is the environment variable name and value is its value. These environment values have the scope of the current job.
- steps; Steps are listed within steps key
- outputs:
- Define the actual things that will be done
- Example:
- download the code in the first step
- install the dependencies in the second step
- run automated tests in the third step
- Belong to jobs, and a job can have one or more steps
- And a step is either:
- a shell script
- a command in the command line that should be executed (e.g. for simple tasks), or
- an action, which is another important building block
- predefined scripts that performs a certain task
- We can build our own actions or use third party actions
- We must have at least have one step,
- Steps are then executed in order, they don't run in parallel, but instead, step after step
- Steps can also be conditional
- name - step name (step title)
- id - a string uniquely identifying the step within enclosing job. Used in references to this step e.g. ${{ steps.<id>.outputs.<output_variable_name> }}
- run -
- uses - name of the reusable GitHub Action
- with
- env - its value is an object containing one or more key-value pairs where key is the environment variable name and value is its value. These environment values have the scope of the current step. To access its value, use ${process.env.<ENV_VAR_NAME>}.
- environment variable can be used as workflow's internal variable
- some actions require certain environment variables to be defined and set e.g. https://github.com/terraform-linters/tflint/blob/master/docs/user-guide/plugins.md#avoiding-rate-limiting
- continue-on-error - a boolean (true|false) value denoting whether execution of the job can resume even if this step errors out
- run - an arbitrary bash script
How to create a Workflow?
- directly on the remote, via browser
- in the local repo, and then pushed to remote
How to trigger a workflow?
- pushing changes on an arbitrary branch
- creating a pull request (including a draft PR)
- pushing a tag to remote
- manually
- ...