This lesson on GitHub Actions Basics is hands-on and example-driven. You will be able to design and implement automated CI/CD workflows using GitHub Actions YAML syntax. You can configure jobs to run across multiple environments in parallel and optimize execution speed using dependency caching.
What You'll Be Able To Do
- Configure automated workflows triggered by repository events like push or pull request.
- Define job steps utilizing marketplace actions and executing shell commands.
- Implement dependency caching to minimize build times and bandwidth usage.
- Utilize the matrix strategy to test code compatibility across various OS and environment versions.
- Structure the YAML configuration file correctly within the required repository path.
Detailed Concept Walkthrough
1. Workflow Architecture and Components
GitHub Actions workflows automate tasks based on repository events, defined by a YAML file that specifies triggers, jobs, and steps. The system requires the YAML file to be located in a specific directory for recognition.
- Mechanism: A workflow is initiated by a defined trigger (
on:), such as apushorpull_request, specified in the YAML configuration. - Execution Flow: The workflow executes one or more jobs, where each job runs on a specified runner (e.g.,
ubuntu-latest). - Syntax Rule: The configuration file must reside in the
.github/workflows/directory of the repository root to be recognized by GitHub. - Under the Hood: Jobs are composed of sequential steps, which can be shell commands (
run:) or reusable marketplace actions (uses:likecheckout).
name: CI Build
on: [push, pull_request] # Triggers on push or PR
jobs:
build:
runs-on: ubuntu-latest # Specifies the runner OS
steps:
- uses: actions/checkout@v4 # Clones the repo
- run: npm install
- run: npm test
Key Takeaway: Workflows are YAML files in
.github/workflows/that map triggers to jobs running on specific runners.
2. Accelerating CI with Caching
Caching stores frequently downloaded dependencies (like npm packages) between workflow runs, drastically reducing build times by avoiding repetitive network downloads.
- Mechanism: The
cacheaction attempts to restore dependencies based on a uniquekeyderived from environment variables and lock files. - Under the Hood: If the key matches a previous run, the cache is restored; otherwise, dependencies are downloaded, and a new cache entry is saved upon job completion.
- Best Practice: The cache
keymust be constructed using a hash of the dependency lock file (package-lock.json) to ensure accurate invalidation and rebuilding. - Performance: Effective caching can reduce typical dependency installation times from minutes to seconds, speeding up feedback loops.
- name: Cache Node Modules
uses: actions/cache@v4
with:
path: ~/.npm # Directory to cache
key: ${{ runner.os }}-node-${{ hashFiles('package-lock.json') }} # Key based on OS and lock file hash
Key Takeaway: Use the
cacheaction with a key based on the lock file hash to ensure fast, accurate dependency restoration.
3. Matrix Strategy for Compatibility
The matrix strategy allows a single job definition to execute simultaneously across multiple combinations of environment variables, ensuring broad compatibility testing.
- Mechanism: The
strategy: matrixblock defines lists of variables, such asnode-versionorostypes. - Execution Flow: GitHub Actions generates a separate, parallel job for every possible combination of the defined variables.
- Syntax Rule: Variables defined in the matrix are accessed within the job steps using the
${{ matrix.<variable_name> }}context. - Best Practice: Use matrix builds for testing against multiple runtime versions (e.g., Node 18, 20, 22) and different operating systems (Ubuntu, Windows) simultaneously.
jobs:
test:
strategy:
matrix:
os: [ubuntu-latest, windows-latest]
node-version: [18, 20]
runs-on: ${{ matrix.os }}
steps:
- uses: actions/setup-node@v4
with:
node-version: ${{ matrix.node-version }}
Key Takeaway: Matrix builds enable parallel, comprehensive compatibility testing by generating jobs for every variable combination.
Topics Covered in GitHub Actions Basics
- CI Pain Points (0:00 - 1:11) — Continuous Integration solves manual testing and inconsistent environment issues by providing consistent, fast feedback.
- Workflow Architecture (1:11 - 3:12) — Workflows require YAML configuration in the .github/workflows/ path and consist of triggers, runners, and jobs.
- Basic CI Syntax (3:13 - 5:06) — The core YAML structure defines the trigger, the runner OS, and sequential steps using actions and shell commands.
- File Location Demo (5:06 - 5:57) — A live demonstration shows the required .github/workflows/CI.yaml file structure in a repository.
- Dependency Caching (5:58 - 8:14) — Implementing the cache action significantly reduces build time by storing and restoring dependencies based on a key.
- Matrix Builds (8:15 - 9:12) — The strategy: matrix feature enables running the same job simultaneously across multiple environment combinations for compatibility testing.
Git Cheat Sheet
-
.github/workflows/— Required directory for workflow YAML filesmkdir -p .github/workflows -
on: [push, pull_request]— Defines the events that trigger the workflow executionon: [push, pull_request] -
runs-on: ubuntu-latest— Specifies the operating system environment for the jobruns-on: ubuntu-latest -
actions/checkout@v4— Marketplace action to clone the repository code- uses: actions/checkout@v4 -
actions/cache@v4— Action used to save and restore dependencies between runs- uses: actions/cache@v4 -
${{ hashFiles('file') }}— Generates a unique key based on the content of a filekey: ${{ runner.os }}-${{ hashFiles('package-lock.json') }}
Comparison Table
| Runner Type | GitHub Hosted | Self-Hosted |
|---|---|---|
| Environment | Managed by GitHub | Managed by User |
| Cost/Limits | Free minutes limit applies | No minute limit, user pays infra |
| Setup | Instant, specified by runs-on | Requires setup and maintenance |
| Use Case | Standard CI/CD, public projects | Specific hardware/OS needs, cost control |
Common Pitfalls
- Mistake: Workflow YAML is placed in the repository root. Avoid: Always place workflow files inside the .github/workflows/ directory.
- Mistake: Using a static cache key that never changes. Avoid: Use hashFiles() on lock files to ensure cache invalidation when dependencies update.
- Mistake: Forgetting to use actions/checkout before running commands. Avoid: The first step in almost every job must be - uses: actions/checkout@v4.
- Mistake: Running expensive jobs on ubuntu-latest for private repos. Avoid: Monitor usage and optimize job frequency to stay within free minute limits.
FAQs
- How does GitHub know where to find my workflow? GitHub automatically scans the .github/workflows/ directory in the repository root for any YAML files to register as workflows.
- What happens if my cache key doesn't match? If the key doesn't match, the cache is missed, dependencies are downloaded normally, and a new cache entry is saved at the end of the job.
- Are GitHub-hosted runners free? They offer a free minute quota (e.g., 2,000 minutes for public projects); exceeding this limit, especially in private repos, incurs costs.
- Why use a matrix build instead of separate jobs? Matrix builds ensure parallel execution and comprehensive coverage with less YAML duplication than defining separate jobs for every environment combination.