Skip to main content

GitHub Actions and Workflow Basics

GitHub Actions is a CI/CD (Continuous Integration/Continuous Delivery) platform that allows you to automate your software development workflows directly within your GitHub repository.

Overview​

With GitHub Actions, you can automate building, testing, and deploying your code. You can trigger workflows based on events on GitHub, such as the creation of a pull request or an issue.

Key Concepts​

Here are the key terms for understanding GitHub Actions.

1. Workflow​

A configurable automated process that runs one or more jobs. It is defined as a YAML file and stored in the .github/workflows directory of your repository.

2. Event​

A specific activity that triggers a workflow run.

  • push: When code is pushed
  • pull_request: When a pull request is created or updated
  • schedule: Scheduled execution
  • workflow_dispatch: Manual execution

3. Job​

A set of steps that execute on the same runner. By default, multiple jobs run in parallel, but you can also define dependencies to run them sequentially.

4. Step​

An individual action or shell command executed within a job. Steps in the same job can share data.

5. Action​

The smallest unit of reusable command that can be used in a workflow. You can create your own or use actions published in the GitHub Marketplace.

6. Runner​

The server where the workflow runs. You can use GitHub-hosted runners (Ubuntu, Windows, macOS) or self-hosted runners that you host yourself.

Workflow File Structure​

The basic structure of a Workflow file is as follows.

.github/workflows/example.yml
name: CI Example

# Definition of events that trigger the workflow
on:
push:
branches: [ "main" ]
pull_request:
branches: [ "main" ]

# Definition of jobs to run
jobs:
build-and-test:
runs-on: ubuntu-latest

steps:
# Checkout repository code
- name: Checkout code
uses: actions/checkout@v4

# Setup Node.js
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'npm'

# Install dependencies
- name: Install dependencies
run: npm ci

# Run tests
- name: Run tests
run: npm test

# Run build
- name: Build
run: npm run build

Practical Usage Examples​

Testing on Multiple OSs (Matrix Strategy)​

If you want to run tests in different environments, strategy.matrix is useful.

jobs:
test:
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [ubuntu-latest, windows-latest, macos-latest]
node-version: [18.x, 20.x]

steps:
- uses: actions/checkout@v4
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v4
with:
node-version: ${{ matrix.node-version }}
- run: npm ci
- run: npm test

Saving Artifacts (Artifacts)​

Use actions/upload-artifact to save build artifacts or logs so they can be downloaded after the workflow completes.

- name: Build
run: npm run build

- name: Upload build artifacts
uses: actions/upload-artifact@v4
with:
name: dist-files
path: dist/

Best Practices​

  1. Pin Action Versions: When using third-party actions, specify a version tag (e.g., @v4) or commit hash to prevent unexpected changes.
  2. Manage Secrets: Store sensitive information like API keys and passwords in Settings > Secrets and variables of the repository and reference them like ${{ secrets.MY_SECRET }}.
  3. Leverage Caching: Use actions/cache or the cache feature of setup-node to reduce dependency installation time.
  4. Suppress Unnecessary Runs: Use path filtering (paths-ignore) to skip CI for documentation changes, etc., to save resources.
on:
push:
paths-ignore:
- 'docs/**'
- '*.md'