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.

Sources

— Editorial Team

Advertisement 728x90

Read Next