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'