Back to Home

How to Set Up CI/CD Pipeline with GitHub Actions – Guide

This comprehensive guide explains how to set up a CI/CD pipeline with GitHub Actions, covering everything from basic workflows to advanced Docker deployments. You'll learn to automate testing, building, and deployment with practical YAML examples, job dependencies, caching strategies, and secure secrets management.

CI/CD Pipeline with GitHub Actions: Complete Setup
Advertisement 728x90

CI/CD Pipeline with GitHub Actions: Complete Setup Guide

CI/CD Pipeline with GitHub Actions: Complete Setup Guide

In modern software development, manually testing code and running deployment scripts after every change is a bottleneck that slows delivery and introduces human error. A CI/CD pipeline automates this entire process, from testing code to deploying it to production. This guide will teach you how to set up ci cd pipeline with github actions, a powerful and integrated automation platform, using practical, real-world YAML examples so you can ship code faster and more reliably.

What You'll Learn

By the end of this guide, you'll understand the core concepts of Continuous Integration and Continuous Deployment (CI/CD) and be able to implement a multi-stage pipeline using GitHub Actions. You'll learn how to write workflows for automated testing, building Docker images, and deploying applications. You'll walk away with working YAML code for testing, building, and deploying your own projects, whether they're Python, Node.js, or containerized applications.

Google AdInline article slot

Understanding GitHub Actions Fundamentals

GitHub Actions is an event-driven automation platform integrated directly into GitHub repositories. It allows you to run automated workflows triggered by events like push, pull_request, or release . At its core, a workflow is defined in a YAML file located in the .github/workflows/ directory and consists of one or more jobs that run in parallel by default, each containing a series of steps .

Core Components

  • Event (on): The trigger that initiates the workflow, such as push to a specific branch or a pull_request .
  • Runner (runs-on): The machine where the job executes. ubuntu-latest is the most common and recommended choice for its performance and wide software availability .
  • Steps: Individual tasks within a job. These can be shell scripts (run) or pre-built Actions (uses) from the GitHub Marketplace .
  • Actions: Reusable units of code, like actions/checkout@v4 to clone your repository or actions/setup-node@v4 to install Node.js .

A Basic Workflow to Get Started

The simplest workflow can be triggered with every push. Create a file at .github/workflows/main.yml to run a basic "Hello World" command .

name: example
on: push
jobs:
  greeting:
    runs-on: ubuntu-latest
    steps:
      - run: echo "Hello, CI/CD World!"

After committing and pushing this file to your repository, you can view the job's output in the "Actions" tab of your GitHub repository.

Google AdInline article slot

Building a Comprehensive CI Pipeline

The "CI" part of a pipeline ensures that code changes are automatically tested and verified before they are merged. This typically involves linting, type-checking, and running unit tests.

The CI Workflow File

Create .github/workflows/ci.yml. This workflow triggers on every push and pull_request to the main branch . The example below demonstrates a complete pipeline for a Node.js project, but the pattern applies to other languages, such as Python with actions/setup-python .

name: CI Pipeline

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

jobs:
  lint:
    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

  test:
    runs-on: ubuntu-latest
    needs: lint
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: '20'
          cache: 'npm'
      - run: npm ci
      - run: npm test

  build:
    runs-on: ubuntu-latest
    needs: [lint, test]
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: '20'
          cache: 'npm'
      - run: npm ci
      - run: npm run build

Key Features Explained

  1. Dependency Caching: The cache: 'npm' option in actions/setup-node significantly speeds up the workflow by reusing dependencies from previous runs .
  2. Job Dependencies: The needs keyword defines the order of execution. For example, the build job only runs if the lint and test jobs succeed . This prevents wasting time building broken code.
  3. Environment Variables: For services like databases, you can define environment variables. For instance, a test job can spin up a PostgreSQL service container and use env to connect to it .

Advanced Scenarios: Containerized and Multi-Environment Deployments

For modern applications, the pipeline often involves building container images and deploying them. The following table outlines common deployment strategies and their triggers.

Google AdInline article slot

Comparison of Deployment Triggers

Strategy Deployment Triggers Best For
Branch-Based push to main Continuous deployment of the latest development code .
Tag-Based push of a new tag (e.g., v1.0.0) Releasing stable, versioned software to production .
Release-Based release published on GitHub Official product releases that also generate release notes .

Example: Deploying a Docker Container with a CI/CD Workflow

This comprehensive example demonstrates a pipeline that tests a Python application, builds a Docker image, and pushes it to a registry . It uses a series of official Docker Actions for a secure, high-performance build.

Create .github/workflows/deploy.yml:

name: Complete CI/CD Pipeline

on:
  push:
    branches: [ main ]
  release:
    types: [published]

env:
  DOCKER_HUB_USERNAME: ${{ secrets.DOCKER_HUB_USERNAME }}
  DOCKER_HUB_TOKEN: ${{ secrets.DOCKER_HUB_TOKEN }}
  IMAGE_NAME: my-app

jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-python@v4
        with:
          python-version: '3.9'
      - run: pip install -r requirements.txt
      - run: pytest

  build-and-push:
    runs-on: ubuntu-latest
    needs: test
    if: github.event_name == 'push' || github.event_name == 'release'
    steps:
      - uses: actions/checkout@v4
      - name: Set up Docker Buildx
        uses: docker/setup-buildx-action@v3
      - name: Login to Docker Hub
        uses: docker/login-action@v3
        with:
          username: ${{ env.DOCKER_HUB_USERNAME }}
          password: ${{ env.DOCKER_HUB_TOKEN }}
      - name: Extract metadata
        id: meta
        uses: docker/metadata-action@v5
        with:
          images: ${{ env.DOCKER_HUB_USERNAME }}/${{ env.IMAGE_NAME }}
          tags: |
            type=ref,event=branch
            type=semver,pattern={{version}}
            type=raw,value=latest,enable={{is_default_branch}}
      - name: Build and push
        uses: docker/build-push-action@v5
        with:
          context: .
          push: true
          tags: ${{ steps.meta.outputs.tags }}
          labels: ${{ steps.meta.outputs.labels }}
          cache-from: type=gha
          cache-to: type=gha,mode=max

  deploy:
    runs-on: ubuntu-latest
    needs: build-and-push
    if: github.event_name == 'release'
    steps:
      - name: Execute Deployment Script
        run: |
          echo "Deploying image ${{ env.DOCKER_HUB_USERNAME }}/${{ env.IMAGE_NAME }}:${{ github.event.release.tag_name }}"

Important: Secrets Management

For the workflow above to work, you must store your credentials securely in your GitHub repository. Navigate to Settings > Secrets and variables > Actions and add the following secrets :

  1. DOCKER_HUB_USERNAME: Your Docker Hub username.
  2. DOCKER_HUB_TOKEN: A Docker Hub Personal Access Token with read/write permissions.

⚠️ Security Warning: Never hardcode passwords, tokens, or other sensitive data directly in your YAML files. Always use GitHub secrets, which are encrypted and only accessible during workflow runs.

Frequently Asked Questions

What are the first steps to set up a CI/CD pipeline with GitHub Actions?

To get started, create a .github/workflows directory in your repository. Inside, create a YAML file (e.g., ci.yml) and define your name, on (trigger events like push), and jobs (the tasks to run). Commit and push this file to start your first automated workflow .

Can I use GitHub Actions to run tests on pull requests?

Yes, testing on pull requests is a core use case. By setting the on trigger to pull_request for the main branch, the workflow will automatically run on every new pull request, ensuring code quality before merging .

How do I build and push a Docker image with a GitHub Actions workflow?

You can use official composite actions like docker/login-action, docker/setup-buildx-action, and docker/build-push-action. This simplifies the process, automatically handles authentication, and enables features like build caching and multi-platform builds .

Is it possible to deploy to GitHub Pages using GitHub Actions?

Yes. You can use the JamesIves/github-pages-deploy-action community action. You configure it with the folder containing your built site, and it handles the git operations to commit and push the changes to the gh-pages branch .

What's the difference between a push and release event trigger?

A push event triggers the workflow whenever code is pushed to a specified branch. A release event triggers when a GitHub Release is published. push is typically used for CI and staging deployments, while release is often used for deploying to production .

Sources

— Editorial Team

Advertisement 728x90

Read Next