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.
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 aspushto a specific branch or apull_request. - Runner (
runs-on): The machine where the job executes.ubuntu-latestis 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@v4to clone your repository oractions/setup-node@v4to 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.
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
- Dependency Caching: The
cache: 'npm'option inactions/setup-nodesignificantly speeds up the workflow by reusing dependencies from previous runs . - Job Dependencies: The
needskeyword defines the order of execution. For example, thebuildjob only runs if thelintandtestjobs succeed . This prevents wasting time building broken code. - Environment Variables: For services like databases, you can define environment variables. For instance, a
testjob can spin up a PostgreSQL service container and useenvto 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.
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 :
DOCKER_HUB_USERNAME: Your Docker Hub username.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
- Set up GitHub Actions CI/CD pipeline · Issue #176 (Practical YAML examples for CI, E2E, and deploy)
- DevOps: Set up GitHub Actions CI/CD pipeline · Issue #19 (Demonstrates linting, type-checking, and build verification)
- GitHub - kamrun111/GitHubActionTest (A simple, beginner-friendly Python CI/CD example)
- @jamesives/github-pages-deploy-action (Documentation for deploying to GitHub Pages)
- GitHub - CarlosQuintero8/cicdsimulation (Demonstrates a multi-stage pipeline with testing, building, and deployment to GitHub Pages)
- GitHub - anuragstark/Py-app-CI-CD-Pipeline- (Comprehensive guide including Docker and Minikube deployment)
- Automated CI/CD with GitHub Actions, starting from scratch (A walkthrough on incrementally building CI/CD workflows)
- Extend App with GitHub Actions · AccelByte Documentation (Example of deployment triggered by a release event)
- Configure CI/CD for your C++ application · Docker Docs (Demonstrates setting up GitHub Actions with Docker Hub)
- Hello CI World · HSF Training (A basic tutorial for creating and running a first workflow)
— Editorial Team
No comments yet.