CI/CD Pipelines Explained with GitHub Actions

DevOps2026-09-12TryQuickToolBox

You just pushed a commit and now you're manually running tests, building the app, and uploading files to a server. It works, but it's slow, error-prone, and doesn't scale. That's where CI/CD pipelines come in.

In this guide, we'll break down CI/CD concepts and show you how to build a real pipeline with GitHub Actions. By the end, you'll understand how to automate testing, building, and deployment for any project.

What is CI/CD?

CI (Continuous Integration) is the practice of automatically testing and merging code changes into a shared branch. Every push triggers a build and test run, catching integration issues early.

CD (Continuous Delivery/Deployment) extends CI by automatically preparing (and optionally deploying) your application to production. Continuous Delivery means the code is always ready to deploy; Continuous Deployment means it deploys automatically.

Together, CI/CD forms a pipeline: a series of automated steps that take your code from commit to production.

Why use GitHub Actions for CI/CD?

GitHub Actions is a CI/CD platform built into GitHub. It's free for public repositories and offers generous minutes for private ones. Key benefits:

Core concepts of GitHub Actions

Before writing your first workflow, understand these terms:

Term Description
Workflow An automated process defined in a YAML file under .github/workflows/.
Event A trigger that starts a workflow (e.g., push, pull_request).
Job A set of steps that run on the same runner. Jobs run in parallel by default.
Step A single task within a job. Can run a command or use an action.
Action A reusable unit of code (e.g., actions/checkout) that you can include in a step.
Runner A virtual machine that executes jobs (Ubuntu, Windows, macOS).

Building your first CI pipeline

Let's create a basic CI workflow for a Node.js project. It will run tests on every push and pull request to the main branch.

Create .github/workflows/ci.yml:

name: CI

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

jobs:
  test:
    runs-on: ubuntu-latest

    strategy:
      matrix:
        node-version: [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 }}
    - run: npm ci
    - run: npm test

This workflow:

  1. Triggers on pushes and PRs to main.
  2. Runs a job called test on the latest Ubuntu runner.
  3. Uses a matrix to test against Node.js 18 and 20.
  4. Checks out the code, sets up Node, installs dependencies, and runs tests.

Push this file and watch the Actions tab. You'll see two parallel jobs (one per Node version). If any test fails, the workflow fails and GitHub notifies you.

Adding continuous deployment

CI is great, but CD is where automation shines. Let's extend the workflow to deploy to a server after tests pass on the main branch.

We'll add a deploy job that depends on test and runs only on pushes to main.

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

    steps:
    - uses: actions/checkout@v4
    - name: Deploy to server
      uses: appleboy/ssh-action@v1.0.0
      with:
        host: ${{ secrets.SSH_HOST }}
        username: ${{ secrets.SSH_USER }}
        key: ${{ secrets.SSH_KEY }}
        script: |
          cd /var/www/myapp
          git pull origin main
          npm ci --production
          pm2 restart myapp

Key points:

This pattern works for many deployment targets: SSH, Docker registries, cloud platforms (AWS, Vercel, Netlify), or Kubernetes.

Best practices for CI/CD with GitHub Actions

Debugging failed workflows

When a workflow fails, GitHub shows logs for each step. Common issues include:

You can also enable debug logging by setting repository secrets ACTIONS_STEP_DEBUG to true.

FAQ

What's the difference between CI and CD?

CI automates testing and integration of code changes. CD automates the delivery or deployment of those changes to an environment. CI ensures code quality; CD ensures it reaches users quickly and reliably.

Is GitHub Actions free?

GitHub Actions is free for public repositories. For private repositories, you get a monthly allowance of free minutes (e.g., 2,000 minutes for Free accounts) and pay for additional usage. Self-hosted runners are also an option.

Can I use GitHub Actions for non-GitHub projects?

Yes, GitHub Actions can run any command-line tools. You can use it to build and deploy projects hosted elsewhere, as long as the code is on GitHub or you use actions to fetch it.

Ready to streamline your CI/CD? Start by automating your tests with GitHub Actions. For a quick way to analyze deployment logs, try our Nginx Log Analyzer to spot errors and performance issues after each deploy.