GitHub action is a CI/CD tool integrated within GitHub repositories that can run different kinds of jobs (building, testing, deployment). Store workflow files in .github/workflows
inside the repository, which will be triggered based on specified conditions.
This post covers GitHub actions basics, from specifying the workflow name to configuring different jobs.
Name
Specify the name of the workflow with the name
field.
# .github/workflows/config.yml
name: CI/CD pipeline
Running
on
field specifies when the workflow should be running.
Automatically
The following configuration runs on every push to a specific branch.
# .github/workflows/config.yml
on:
push:
branches:
- main
The following configuration runs on every push to every branch.
# .github/workflows/config.yml
on:
push:
branches:
- '*'
Cron jobs
The following configuration runs at a specified interval (e.g., every hour).
# .github/workflows/config.yml
on:
schedule:
- cron: '0 * * * *'
Manual triggers
The following configuration enables manual triggering. Trigger it on the Actions tab by selecting the workflow and clicking the Run workflow button.
Use a manual trigger to upload apps to the Google Play console or update the GitHub profile Readme.
# .github/workflows/config.yml
on:
workflow_dispatch:
Environment variables
Specify with the env
field. Set repository secrets in Settings → Secrets and variables → Actions page.
# .github/workflows/config.yml
env:
API_KEY: ${{ secrets.API_KEY }}
Jobs
Specify the job name with the name
field. Otherwise, the workflow will use the jobs item as the job name.
Every job can have a separate working directory in case you have multiple subdirectories, and you want to run a different job in a different subdirectory so you can specify it within the defaults field
jobs:
job-name:
defaults:
run:
working-directory: directory-name
Every job should have a runs-on
field specified for the machine, which will be running on (e.g., ubuntu-latest
) or container
field with set Docker image (e.g., node:20.9.0-alpine3.17
)
You can specify multiple tasks inside one job. Every task can have the following fields
-
name
- task name -
uses
- GitHub action path from GitHub Marketplace -
with
- parameters for the specified GitHub action -
run
- bash commands -
env
- environment variables
# .github/workflows/config.yml
jobs:
build:
name: Custom build job
runs-on: ubuntu-latest
# container: node:20.9.0-alpine3.17
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Configure Node.js
uses: actions/setup-node@v4
with:
node-version: 20
- name: Install and build
run: |
npm ci
npm run build
Use the needs
field for running jobs sequentially. It specifies a job that has to be finished before starting the next one. Otherwise, jobs will run in parallel.
# .github/workflows/config.yml
jobs:
build:
# ...
deploy:
name: Custom deploy job
runs-on: ubuntu-latest
needs: build
steps:
- name: Deploy
run: |
npm run deploy
Every job can run multiple times with different versions using a matrix strategy (e.g., Node versions 18 and 20 or multiple OS versions inside an array of objects).
# .github/workflows/config.yml
jobs:
build:
name: Custom build job
strategy:
matrix:
node-version: [18, 20]
os:
[
{ name: 'linux', image: 'ubuntu-latest' },
{ name: 'windows', image: 'windows-latest' },
{ name: 'macos', image: 'macos-latest' }
]
runs-on: ${{ matrix.os.image }}
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Configure Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v4
with:
node-version: ${{ matrix.node-version }}
- name: Install and build
run: |
npm ci
npm run build
Every job can provision databases for e2e tests with a services
field like Postgres in the following example.
# .github/workflows/config.yml
jobs:
build:
name: Custom build job
runs-on: ubuntu-latest
strategy:
matrix:
database-name:
- test-db
database-user:
- username
database-password:
- password
database-host:
- postgres
database-port:
- 5432
services:
postgres:
image: postgres:latest
env:
POSTGRES_DB: ${{ matrix.database-name }}
POSTGRES_USER: ${{ matrix.database-user }}
POSTGRES_PASSWORD: ${{ matrix.database-password }}
ports:
- ${{ matrix.database-port }}:${{ matrix.database-port }}
# Set health checks to wait until postgres has started
options: --health-cmd pg_isready
--health-interval 10s
--health-timeout 5s
--health-retries 5
steps:
# ...
- run: npm run test:e2e
env:
DATABASE_URL: postgres://${{ matrix.database-user }}:${{ matrix.database-password }}@${{ matrix.database-host }}:${{ matrix.database-port }}/${{ matrix.database-name }}
Passing artifacts between jobs can be done with uploading (actions/upload-artifact
) and downloading (actions/download-artifact
) actions.
# .github/workflows/config.yml
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Configure Node.js
uses: actions/setup-node@v4
with:
node-version: 20
- name: Install and build
run: |
npm ci
npm run build
- name: Upload artifact
uses: actions/upload-artifact@v3
with:
name: artifact
path: public
deploy:
needs: build
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Download artifact
uses: actions/download-artifact@v3
with:
name: artifact
# ...
Running locally
You can use act to run GitHub actions locally.
Install it and run it with the following commands.
curl -s https://raw.githubusercontent.com/nektos/act/master/install.sh | sudo bash
cp ./bin/act /usr/local/bin/act
act
Top comments (0)