Skip to main content

GitHub Actions for CI-CD Basics

Now that you've mastered Git fundamentals and GitHub workflows, it's time to automate your development process. In this lesson, you'll learn how to use GitHub Actions to automatically build, test, and deploy your code whenever you push changes.

Learning Goals

  • Understand what CI/CD is and why it matters
  • Create your first GitHub Actions workflow
  • Run automated tests on code changes
  • Build and deploy applications automatically
  • Monitor workflow execution and troubleshoot failures

What is CI/CD?

CI/CD stands for Continuous Integration and Continuous Deployment/Delivery. It's a development practice where developers regularly merge code changes into a central repository, after which automated builds and tests run.

Continuous Integration (CI) means automatically building and testing code whenever changes are pushed to the repository. This helps catch bugs early.

Continuous Deployment/Delivery (CD) takes this further by automatically deploying the tested code to production or staging environments.

tip

Think of CI/CD as having an automated assistant that tests your code, builds your application, and deploys it—all without manual intervention!

Your First GitHub Actions Workflow

GitHub Actions uses YAML files in the .github/workflows/ directory to define workflows. Let's create a simple workflow that runs tests whenever code is pushed.

Create a new file in your repository:

.github/workflows/ci.yml
name: CI Pipeline

on:
push:
branches: [ main, develop ]
pull_request:
branches: [ main ]

jobs:
test:
runs-on: ubuntu-latest

steps:
- name: Checkout code
uses: actions/checkout@v4

- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '18'

- name: Install dependencies
run: npm install

- name: Run tests
run: npm test

This workflow:

  • Triggers on pushes to main or develop branches, and on pull requests targeting main
  • Runs on the latest Ubuntu environment
  • Checks out your code, sets up Node.js, installs dependencies, and runs tests

Understanding Workflow Components

Events (on)

Events trigger workflows. Common triggers include:

  • push: Code is pushed to a branch
  • pull_request: A pull request is opened or updated
  • schedule: Run on a schedule (like cron jobs)
  • workflow_dispatch: Manual trigger from GitHub UI

Jobs (jobs)

Jobs are sets of steps that execute on the same runner. Each job runs in its own virtual environment.

Steps (steps)

Steps can either:

  • Run commands (run)
  • Use pre-built actions (uses)

Building and Testing a Real Project

Let's create a more comprehensive workflow for a web application:

.github/workflows/full-ci.yml
name: Full CI/CD Pipeline

on:
push:
branches: [ main ]
pull_request:
branches: [ main ]

jobs:
test:
runs-on: ubuntu-latest

strategy:
matrix:
node-version: [16.x, 18.x, 20.x]

steps:
- uses: actions/checkout@v4

- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v4
with:
node-version: ${{ matrix.node-version }}
cache: 'npm'

- name: Install dependencies
run: npm ci

- name: Run linting
run: npm run lint

- name: Run tests
run: npm test

- name: Run build
run: npm run build

- name: Upload coverage reports
uses: codecov/codecov-action@v3

deploy:
needs: test
runs-on: ubuntu-latest
if: github.ref == 'refs/heads/main'

steps:
- uses: actions/checkout@v4

- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '18'

- name: Install and build
run: |
npm ci
npm run build

- name: Deploy to GitHub Pages
uses: peaceiris/actions-gh-pages@v3
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
publish_dir: ./dist

This workflow:

  • Tests across multiple Node.js versions
  • Runs linting, tests, and build
  • Uploads coverage reports
  • Deploys to GitHub Pages (only from main branch)

Environment Variables and Secrets

Sometimes you need sensitive data (API keys, tokens) in your workflows. Use GitHub Secrets:

.github/workflows/deploy-with-secrets.yml
name: Deploy with Secrets

on:
push:
branches: [ main ]

jobs:
deploy:
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v4

- name: Deploy to production
run: |
echo "Deploying to ${{ secrets.DEPLOY_SERVER }}"
# Use deployment script with secrets
env:
API_KEY: ${{ secrets.PRODUCTION_API_KEY }}
DEPLOY_URL: ${{ secrets.DEPLOYMENT_URL }}
warning

Never hardcode secrets in your workflow files! Always use GitHub Secrets through the repository settings → Secrets and variables → Actions.

Monitoring and Debugging Workflows

You can view workflow execution in the "Actions" tab of your repository. Each run shows:

  • Which jobs ran and their status
  • Execution time for each step
  • Log output for debugging
  • Artifacts created

If a workflow fails, check the logs to see which step failed and why. Common issues include:

  • Missing dependencies
  • Failing tests
  • Incorrect file paths
  • Permission issues

Common Pitfalls

  • Missing triggers: Forgetting to specify when the workflow should run
  • Hardcoded secrets: Accidentally committing API keys or tokens
  • Race conditions: Jobs that depend on each other but aren't properly sequenced
  • Environment differences: Code that works locally but fails in CI due to different environments
  • Long-running jobs: Workflows that timeout due to excessive execution time
  • Incorrect paths: Using relative paths that don't work in the CI environment

Summary

GitHub Actions provides powerful CI/CD capabilities directly in your repository. You learned how to:

  • Create workflow files that trigger on code changes
  • Run automated tests and builds
  • Use matrix strategies for multiple environments
  • Deploy applications automatically
  • Manage secrets securely
  • Monitor and debug workflow execution

CI/CD helps maintain code quality and speeds up development by automating repetitive tasks.

Quiz

GitHub Actions and CI/CD – Quick Check

What does the `on: push: branches: [main]` configuration do?

Question 1/5