📑 Table of Contents
GitHub Actions is a CI/CD (Continuous Integration / Continuous Delivery) platform integrated directly into GitHub. This article walks you through building a CI/CD pipeline in 30 minutes, step by step.
If you have a GitHub repository, you can start CI/CD at no additional cost. Public repos get unlimited build time; private repos get 2,000 minutes/month free.
1. What is GitHub Actions?
GitHub Actions automates the process of "testing, building, and deploying code when you push."
Key Terminology
- Workflow: The entire automation process, defined in YAML
- Job: An execution unit within a workflow — can run in parallel or sequentially
- Step: An individual command or Action within a job
- Action: A reusable component, shared via the Marketplace
- Runner: The server that executes workflows
2. Workflow Basics
Workflows are placed as YAML files in the .github/workflows/ directory.
# .github/workflows/ci.yml
name: CI Pipeline
# Trigger: on push or PR to main
on:
push:
branches: [ main ]
pull_request:
branches: [ main ]
jobs:
test:
runs-on: ubuntu-latest
strategy:
matrix:
node-version: [18, 20, 22]
steps:
# 1. Checkout code
- uses: actions/checkout@v4
# 2. Set up Node.js
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v4
with:
node-version: ${{ matrix.node-version }}
cache: 'npm'
# 3. Install dependencies
- run: npm ci
# 4. Run lint
- run: npm run lint
# 5. Run tests
- run: npm test
# 6. Verify build
- run: npm run build
Using strategy.matrix enables parallel testing across multiple Node.js versions — invaluable for ensuring compatibility.
3. Implementing Test Automation
A practical workflow that runs tests automatically when a PR is created and comments results on the PR.
# .github/workflows/test-report.yml
name: Test with Coverage Report
on:
pull_request:
branches: [ main ]
jobs:
test-coverage:
runs-on: ubuntu-latest
permissions:
pull-requests: write
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 20
cache: 'npm'
- run: npm ci
- run: npm test -- --coverage --coverageReporters=text
# Comment coverage on PR
- name: Comment Coverage on PR
if: github.event_name == 'pull_request'
uses: actions/github-script@v7
with:
script: |
const fs = require('fs');
const coverage = '✅ Tests passed!';
github.rest.issues.createComment({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
body: coverage
})
4. Setting Up Auto-Deploy
A workflow that auto-deploys to production when code is merged to main.
# .github/workflows/deploy.yml
name: Deploy to Production
on:
push:
branches: [ main ]
jobs:
deploy:
runs-on: ubuntu-latest
needs: test
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 20
cache: 'npm'
- run: npm ci
- run: npm run build
# Deploy to GitHub Pages
- name: Deploy to GitHub Pages
uses: peaceiris/actions-gh-pages@v4
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
publish_dir: ./dist
# Notification
- name: Notify on Success
if: success()
run: |
echo "✅ Deploy complete!"
5. Practical Tips
Speed Up with Caching
# npm dependency caching (automatic)
- uses: actions/setup-node@v4
with:
node-version: 20
cache: 'npm' # This alone enables caching
Managing Secrets
Store API keys and passwords in GitHub Secrets for safe access from workflows.
- Go to Settings → Secrets and variables → Actions
- Click "New repository secret"
- Enter name and value, then save
- Reference in workflows with
${{ secrets.SECRET_NAME }}
Never print secrets to logs. GitHub Actions masks them automatically, but they can leak through indirect means like Base64 encoding.
Summary
With GitHub Actions, you can build the following CI/CD pipeline in 30 minutes:
- On PR creation: Auto-test + coverage report
- On merge: Auto-build + auto-deploy
- On error: Slack/email notification
Start small and expand your workflows gradually.