GitHub Actions
GitHub Actions were introduced in 2018 to design CI/CD workflows for GitHub projects. Actions are relatively short and reusable pieces of code that simplify the process of creating a CI/CD workflow.
- GitHub Actions Marketplace (19k+ actions)
- GitHub Actions Documentation
- GitHub Actions Quickstart
- GitHub Awesome Actions (22.7k β)
- GitHub Workflow Syntax (βͺ)
Terminology
-
Steps βοΈ: a command or an action such as
run tests
-
Jobs ποΈ: a job is an ordered set of steps to achieve a goal. They can be run in parallel or sequentially.
-
Workflow π: an automated process made of jobs. For instance, we could have a workflow for building and testing the project.
The workflow status is visible next to each commit: (passed).
Basic syntax
Workflows are defined in YAML files stored in .github/workflows/
. Their names are based on the YAML file name (e.g., Build
for build.yml
).
A basic Action executing job_name
on every push
:
name: Action Name
on: [push]
jobs:
job_name:
runs-on: ubuntu-latest
steps:
# unnamed command
- run: echo "Hello, World!"
# named command
- name: Saying Hello
run: echo "Hello, World!"
A runner is an agent executing commands. The runs-on
parameter designates which runner to use. You can use GitHub-hosted runners such as ubuntu-latest
or windows-latest
or use self-hosted runners.
A common action is checkout
to clone your repository:
- name: Check out repository code
uses: actions/checkout@v3
For each step, you may use these optional attributes:
- name: XXX
# only execute based on a condition
if: runner.os == 'Windows'
# run multiple commands
run: |
xxx
xxx
env: # set an environment variable
XXX: xxx
Advanced syntax
Trigger
The on
keyword determines what events can trigger a workflow.
on:
pull_request: # on any pull request
on:
push: # push on main
branches: [ main ]
pull_request: # merge request on main
branches: [ main ]
schedule: # automatically
- cron: '0 3 * * 5'
Strategy
The strategy
keyword lets us define variables. The job below will be executed 4
times as we have 4
values (cartesian product of all variables).
strategy:
matrix:
some_variable: [10, 11, 12, 13]
steps:
- name: Use Version ${{ matrix.some_variable }}
run: echo "use version ${{ matrix.some_variable }}"
Some actions
Java actions
actions/setup-java to install and configure Java.
- name: Set up JDK 16
uses: actions/setup-java@v2
with:
java-version: '16'
distribution: 'adopt'
- name: Run gradle tests
uses: gradle/gradle-build-action@v2
with:
arguments: test
β‘οΈ See also: gradle-wrapper-validation.
OCAML actions
ocaml/setup-ocaml to install and configure OCaml.
- name: Use OCaml 4.13.1
uses: ocaml/setup-ocaml@v2
with:
ocaml-compiler: 4.13.1
Node.js actions
actions/setup-node to install and configure Node.
- name: Use Node.js 16.16.0
uses: actions/setup-node@v2
with:
node-version: 16.16.0
- run: npm ci
- run: npm run build --if-present
- run: npm test
Cache build
actions/cache to cache build results.
Static code analysis
GitHub/codeql-action for CodeQL static code analysis.
Code quality analysis
JetBrains/qodana-action for Qodana code quality analysis.
Dependabot
Dependabot is a "bot" that checks your dependencies. If it detects that we can upgrade a dependency, it opens a pull-request with the suggested upgrade. Here is the official tutorial π.
It can also detect vulnerabilities in dependencies and notify developers to upgrade their dependencies.
Here are some dependabot.yml
examples:
version: 2
updates:
- package-ecosystem: "gradle"
directory: "/"
schedule:
interval: "daily"
version: 2
updates:
- package-ecosystem: "npm"
directory: "/"
schedule:
interval: "daily"
time: "13:00"
open-pull-requests-limit: "99"
versioning-strategy: "increase"
It works by analyzing dependencies in the ecosystem file:
-
npm
: package.json -
gradle
: build.gradle -
docker
: Dockerfile -
pip
: requirements.txt - ...
π» To-do π»
Stuff that I found, but never read/used yet.