Intro to GitHub Actions (CI/CD)

Reviewed & published by Brayan K

Stop running tests by hand. By the end of this lesson you'll write a workflow YAML file that runs your test suite automatically on every push and pull request — your first taste of continuous integration, built right into GitHub.

Part of the free Git course at LearnCodingFast — hands-on lessons with worked examples and the output they print, plus practice exercises and a quick quiz.

What You'll Learn

1️⃣ Your First Workflow

A workflow is a YAML file in .github/workflows/. This one runs your tests on every push to main and on every pull request. Commit it, push, and the run shows up in the repo's Actions tab.

# .github/workflows/ci.yml
# A workflow is a YAML file in .github/workflows/. This one runs your tests
# automatically every time someone pushes or opens a pull request.

name: CI                       # shown in the Actions tab

on:                            # WHICH events start this workflow
  push:
    branches: [ main ]         # pushes to main
  pull_request:                # and any pull request

jobs:                          # one or more jobs (run in parallel by default)
  test:                        # a job id you choose
    runs-on: ubuntu-latest     # the runner (a fresh virtual machine)
    steps:                     # ordered steps inside the job
      - uses: actions/checkout@v4        # 1) check out your repo onto the runner
      - uses: actions/setup-node@v4      # 2) install Node from the Marketplace
        with:
          node-version: '20'
      - run: npm ci                      # 3) install dependencies
      - run: npm test                    # 4) run the test suite

2️⃣ The Anatomy of a Workflow

Every workflow shares the same skeleton: name, the triggering events under on, and jobs. Each job sets runs-on (the runner) and a list of steps. A step either uses a prebuilt action or runs shell commands.

# The vocabulary, top to bottom:
#
#   name:      a label for the workflow (optional)
#   on:        the EVENTS that trigger it (push, pull_request, schedule, ...)
#   jobs:      a map of jobs; each runs on its own fresh runner
#     <job>:
#       runs-on:  which runner OS/image (ubuntu-latest, windows-latest, ...)
#       steps:    an ordered list; each step is EITHER:
#                   - uses: <action>   pull in a reusable action
#                   - run:  <command>  run shell commands on the runner
#
# 'uses' pulls prebuilt actions (e.g. actions/checkout@v4) from the
# GitHub Marketplace; 'run' executes plain shell commands like npm test.

3️⃣ Testing Across Versions (Matrix)

A matrix runs the same job several times in parallel — once per value you list. It's the standard way to prove your code works on multiple language versions at once, with one small block of YAML.

# A "matrix" runs the SAME job across several versions in parallel — great
# for testing your code on multiple language versions at once.

jobs:
  test:
    runs-on: ubuntu-latest
    strategy:
      matrix:
        node-version: [ 18, 20, 22 ]   # three parallel runs
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: ${{ matrix.node-version }}
      - run: npm ci
      - run: npm test

Your turn. Complete a minimal CI workflow. Fill in the three blanks, then commit it as .github/workflows/ci.yml.

# 🎯 YOUR TURN — replace each ___ then commit this as
# .github/workflows/ci.yml and push to trigger it.

name: CI

___:                           # 👉 the key that lists triggering events
  push:
    branches: [ main ]

jobs:
  test:
    runs-on: ubuntu-latest     # the runner
    steps:
      - ___: actions/checkout@v4   # 👉 the keyword that pulls in an action
      - ___: echo "Running tests"  # 👉 the keyword that runs a shell command

# ✅ Expected: after pushing, the Actions tab shows a "CI" run that checks
#    out your code and prints "Running tests", finishing with a green check.

Common Errors (and the fix)

Pro Tips

📋 Quick Reference

YAML keyPurpose
name:Label shown in the Actions tab
on:Events that trigger the workflow
jobs:One or more jobs to run
runs-on:The runner OS for a job
uses:Pull in a reusable action
run:Execute shell commands

Mini-Challenge: Add CI to a Project

No file given this time — just the plan. Wire up real continuous integration and watch it pass, then fail.

# 🎯 MINI-CHALLENGE: add CI to a project.
# No file given — just the plan. Do it in a real repo on GitHub.
#
# 1. Create the folder .github/workflows/ and a file ci.yml inside it
# 2. Trigger on push to main AND on pull_request
# 3. Use a job on ubuntu-latest with these steps:
#       - actions/checkout@v4
#       - set up your language (e.g. actions/setup-node@v4)
#       - install deps, then run your test command
# 4. Commit, push, and open the Actions tab to watch it run
# 5. Break a test on purpose and confirm the run turns red
#
# ✅ Expected: green check when tests pass, red X (with the failing step
#    highlighted) when they don't.

🎉 Lesson Complete!

Practice quiz

What is GitHub Actions?

  • A code editor
  • A merge strategy
  • GitHub's built-in CI/CD system that runs workflows on events
  • A branch type

Answer: GitHub's built-in CI/CD system that runs workflows on events. GitHub Actions automates building, testing, and deploying code in response to repository events.

Where must workflow files live in your repo?

  • In .github/workflows/
  • In the repo root
  • In .git/hooks/
  • In /actions/

Answer: In .github/workflows/. Workflow YAML files go in the .github/workflows/ directory of your repository.

What format are workflow files written in?

  • JSON
  • TOML
  • XML
  • YAML

Answer: YAML. GitHub Actions workflows are YAML files (.yml or .yaml).

What does the top-level 'on:' key define?

  • The operating system
  • The events that trigger the workflow (e.g. push, pull_request)
  • The output
  • The owner

Answer: The events that trigger the workflow (e.g. push, pull_request). 'on' lists the events — like push or pull_request — that start the workflow.

What is a 'job' in a workflow?

  • A set of steps that run on one runner machine
  • A single command
  • A commit
  • A secret

Answer: A set of steps that run on one runner machine. A job groups steps that execute together on a runner; jobs can run in parallel by default.

What does 'runs-on: ubuntu-latest' specify?

  • The programming language
  • The branch
  • The runner (virtual machine) the job executes on
  • The schedule

Answer: The runner (virtual machine) the job executes on. runs-on chooses the runner OS/image, such as ubuntu-latest, for that job.

What does the 'uses:' keyword in a step do?

  • Runs a shell command
  • Pulls in a reusable action (e.g. actions/checkout@v4)
  • Sets an environment variable
  • Declares a job

Answer: Pulls in a reusable action (e.g. actions/checkout@v4). 'uses' references a prebuilt action from the Marketplace or a repo, like actions/checkout.

What does the 'run:' keyword do in a step?

  • Imports an action
  • Triggers the workflow
  • Creates a job
  • Executes shell commands on the runner

Answer: Executes shell commands on the runner. 'run' executes shell commands directly, e.g. run: npm test.

Why is actions/checkout usually the first step?

  • It deploys the app
  • It checks out your repository code onto the runner so later steps can use it
  • It installs Node
  • It opens a PR

Answer: It checks out your repository code onto the runner so later steps can use it. The runner starts empty, so actions/checkout fetches your code before tests can run.

Where do you find reusable, prebuilt actions?

  • The Issues tab
  • The Wiki
  • The GitHub Marketplace
  • The Releases page

Answer: The GitHub Marketplace. The GitHub Marketplace hosts thousands of prebuilt actions you reference with 'uses'.

Continue this course

Frequently asked questions

What is CI/CD, and how does GitHub Actions fit in?

CI (continuous integration) means automatically building and testing every change so problems surface immediately; CD (continuous delivery/deployment) extends that to automatically releasing or deploying. GitHub Actions is GitHub's built-in automation system for both: you describe workflows in YAML, and GitHub runs them on its servers whenever chosen events occur, like a push or a pull request.

Where do workflow files go and what format are they?

They live in the .github/workflows/ directory at the root of your repository, and they're written in YAML (.yml or .yaml). You can have many workflow files; GitHub reads them all. Each defines a name, the events that trigger it (on:), and one or more jobs with steps.

What's the difference between 'uses' and 'run' in a step?

A step does exactly one of the two. 'uses' pulls in a reusable, prebuilt action — for example uses: actions/checkout@v4 to fetch your code, or a Marketplace action to set up a language. 'run' executes shell commands directly on the runner, like run: npm test. You'll typically combine a few 'uses' steps for setup with 'run' steps for your own commands.

Why is actions/checkout almost always the first step?

Each job runs on a fresh, empty runner (a virtual machine) that doesn't have your code yet. actions/checkout clones your repository onto that runner so the following steps — installing dependencies, running tests — actually have something to work with. Forget it, and your build commands fail because the files aren't there.

What is the GitHub Marketplace?

It's a catalog of thousands of reusable actions published by GitHub and the community. Instead of scripting common tasks yourself, you reference one with 'uses', like actions/setup-node@v4 to install Node or actions/upload-artifact to save build output. Pin to a version tag (the @v4 part) so your workflow stays stable when the action updates.