GitHub Actions & CI/CD
GitHub Actions automates CI/CD inside GitHub using workflows defined in .github/workflows. Events trigger jobs on runners; jobs run steps that call actions like actions/checkout. Learn events, matrix builds, secrets, caching and artifacts to build production-grade pipelines.
What is this?
GitHub Actions is a CI/CD platform built into GitHub. Workflows are YAML files in .github/workflows that define jobs and steps. They are triggered by events such as push, pull_request or schedule, run on hosted or self-hosted runners, and can build, test, deploy, and report status back to the pull request.
Why do you need it?
- CI/CD lives in the same system as the code, so every push and pull request gets checks automatically.
- Reusable, versioned actions let you compose pipelines from community building blocks.
- Matrix builds run the same job across OSes and versions in parallel.
- Tight integration with PR review: required checks gate merges.
Mental model
An assembly line
A GitHub Actions workflow
An event starts the line; each station (job/step) does one task; parts (artifacts) move along; the QA gate (tests) decides whether the product ships.
How it works
- An event (e.g. push or pull_request) triggers a workflow file in .github/workflows.
- The workflow defines jobs, each of which runs on a runner such as ubuntu-latest.
- Each job runs steps sequentially — either shell commands (run:) or community actions (uses:).
- needs: creates dependencies between jobs, so a deploy job can wait for tests to pass.
- Secrets are injected via secrets.X and never appear in logs; artifacts are uploaded for later steps or downloads.
- The final status is reported on the commit and the pull request as a check.
Anatomy of a GitHub Actions workflow run.
Key commands
git push origin mainPushing to main triggers workflows configured for push events.
gh workflow listList workflows in the repository with the GitHub CLI.
gh run watch <id>Watch a workflow run until it finishes.
gh run view --log-failedShow only the failing steps of the latest run.
gh pr checksShow the status of all checks on a pull request.
Examples
A minimal CI workflow
name: CIon: push: branches: [main] pull_request: jobs: test: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 with: node-version: 20 - run: npm ci - run: npm testThis workflow runs on every push to main and every pull request. It checks out the code, installs Node 20, installs dependencies with npm ci, and runs the test suite. A failure blocks the PR from merging.
In production
- CI: lint, test and build on every pull request, gating merges with required checks.
- CD: deploy to staging on push to main and to production on a release tag.
- Matrix builds verify an app across Node versions and operating systems.
- Scheduled workflows run security scans, dependency updates and database backups.
Best practices
- Pin actions to a tag or commit SHA, never to a floating branch like @main.
- Cache dependency installs with actions/cache to cut run time.
- Store credentials in repository secrets and reference them as secrets.X.
- Use small, focused jobs with needs: dependencies so failures are easy to isolate.
- Reuse logic with composite actions or reusable workflows instead of duplicating YAML.
Common mistakes
- Hardcoding tokens or passwords directly in workflow files.
- Using unpinned action versions (uses: user/action@main), which can change behavior overnight.
- Running untrusted pull request code with access to secrets (forks).
- Building one giant monolith workflow that is impossible to debug or reuse.
Common issues
No such file or directory when reading source filesA step expected the repository to be present but checkout did not run first.
Add - uses: actions/checkout@v4 as the first step of the job.
Problem with this workflow file: 'jobs' must not be emptyYAML syntax error or wrong indentation.
Validate with yamllint or a YAML parser before pushing, and check indentation of jobs/steps.
403 Resource not accessible by integrationA protected branch rejected the push or the job lacks permission.
Open a pull request instead of pushing to the protected branch, or grant the required permissions.
Debugging tips
- gh run view --log-failed to jump straight to the failing step.
- Rerun failed jobs with gh run rerun <id> or the Actions tab.
- Set the repository secret ACTIONS_STEP_DEBUG to true to enable step debug logging.
- Validate workflow YAML locally with yamllint before pushing.
Interview checkpoint
Hands-on lab
- Create a workflow file in .github/workflows
- Trigger CI on push and pull_request
- Add a matrix build across Node versions
- Cache dependencies and inspect run logs
Build a CI Pipeline with GitHub Actions
35 min · advanced
Quick quiz
Where are GitHub Actions workflow files stored?
GitHub Actions workflow files must be named main.yml.
Which action clones the repository into the runner?
Cheat sheet
name:Workflow nameon: [push]Triggering eventsjobs:Top-level job listruns-on: ubuntu-latestRunner imageneeds: [test]Job dependencyuses: actions/checkout@v4Call an actionrun: npm testRun a shell commandsecrets: ${{ secrets.X }}Inject a secret