GitHub Actions is the most popular CI/CD platform in 2026 — built into GitHub, with a huge marketplace of pre-made actions. This guide builds a complete pipeline from testing to deployment, entirely in YAML files in your repo.
📋 Table of Contents
How GitHub Actions Works
Workflows live in .github/workflows/*.yml. Each workflow triggers on events (push, pull request, schedule) and contains jobs that run on runners (GitHub-hosted VMs). Jobs contain steps — either shell commands or reusable actions.
Basic CI Workflow
# .github/workflows/ci.yml
name: CI
on:
push:
branches: [main, develop]
pull_request:
branches: [main]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'npm'
- run: npm ci
- run: npm run lint
- run: npm test
- run: npm run build
Matrix Builds (Test Multiple Versions)
jobs:
test:
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [ubuntu-latest, windows-latest, macos-latest]
node: [18, 20, 22]
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: ${{ matrix.node }}
- run: npm ci
- run: npm test
# Runs 9 combinations (3 OS x 3 Node versions) in parallel
Caching Dependencies
steps:
- uses: actions/checkout@v4
# setup-node has built-in caching
- uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'npm' # caches ~/.npm automatically
# Or cache manually for other tools
- uses: actions/cache@v4
with:
path: |
~/.cache/pip
.venv
key: ${{ runner.os }}-pip-${{ hashFiles('requirements.txt') }}
Building and Pushing Docker Images
name: Build and Push
on:
push:
branches: [main]
jobs:
docker:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- uses: docker/build-push-action@v6
with:
context: .
push: true
tags: |
ghcr.io/${{ github.repository }}:latest
ghcr.io/${{ github.repository }}:${{ github.sha }}
cache-from: type=gha
cache-to: type=gha,mode=max
Deployment with Environments and Approvals
jobs:
deploy:
runs-on: ubuntu-latest
needs: [test] # only deploy if tests pass
environment:
name: production # can require manual approval in repo settings
url: https://example.com
steps:
- uses: actions/checkout@v4
- name: Deploy via SSH
uses: appleboy/ssh-action@v1
with:
host: ${{ secrets.PROD_HOST }}
username: ${{ secrets.DEPLOY_USER }}
key: ${{ secrets.SSH_PRIVATE_KEY }}
script: |
cd /app
docker compose pull
docker compose up -d
Managing Secrets
Store secrets in repo Settings, then Secrets and variables, then Actions. Reference them as ${{ secrets.NAME }}. They’re masked in logs and never exposed. Use environment-specific secrets for staging vs production.
steps:
- run: ./deploy.sh
env:
API_KEY: ${{ secrets.API_KEY }}
DATABASE_URL: ${{ secrets.DATABASE_URL }}
Reusable Workflows and Composite Actions
# Call a reusable workflow to avoid duplication
jobs:
call-shared:
uses: ./.github/workflows/shared-test.yml
with:
node-version: '20'
secrets: inherit
# shared-test.yml declares:
# on:
# workflow_call:
# inputs:
# node-version:
# type: string
Optimization Tips
- Use
needs:to control job order and run independent jobs in parallel - Cache dependencies — the biggest speedup for most pipelines
- Cancel outdated runs:
concurrency: { group: ${{ github.ref }}, cancel-in-progress: true } - Use path filters: only run workflows when relevant files change
- Pin action versions (
@v4) for stability and security
Frequently Asked Questions
Q: GitHub Actions vs GitLab CI vs Jenkins?
A: GitHub Actions if your code is on GitHub — deep integration and a huge marketplace. GitLab CI for GitLab-hosted code. Jenkins for maximum control/self-hosting or complex enterprise needs. Actions is the easiest for GitHub projects.
Q: Is GitHub Actions free?
A: Public repos get unlimited free minutes. Private repos get a monthly free allotment, then pay per minute. For most small projects and open source, it’s effectively free.
Q: How do I speed up slow workflows?
A: Cache dependencies (biggest win), run jobs in parallel with needs:, use path filters to skip irrelevant runs, and cancel outdated runs with concurrency groups. Profile which steps are slowest first.
Q: How do I require approval before production deploys?
A: Use GitHub Environments with required reviewers. Configure the production environment in repo settings to require manual approval — the deploy job pauses until an approved reviewer confirms.
Q: Can I run workflows on a schedule?
A: Yes — use on: schedule: - cron: '0 0 * * *' for scheduled runs (nightly builds, cleanup jobs, periodic checks). Cron syntax controls timing.
Conclusion
GitHub Actions makes CI/CD accessible with everything defined in YAML in your repo. This guide covers the essentials — CI workflows with matrix builds, dependency caching, Docker image building, and deployment with environment approvals. The huge marketplace of pre-built actions means you rarely write things from scratch. Start with a simple test workflow, add build and deploy jobs incrementally, cache aggressively for speed, and use environments to gate production deployments. It’s the fastest path to professional CI/CD for GitHub-hosted projects.
📚 You might also like
🔗 Share this article




✍️ Leave a Comment