Introduction
Continuous Integration and Continuous Deployment (CI/CD) are essential practices in modern software development. In this guide, I’ll walk you through setting up a complete CI/CD pipeline for a Python project using GitHub Actions.
Why GitHub Actions?
GitHub Actions is a powerful, free (for public repositories) automation platform that integrates seamlessly with your GitHub workflow. Key benefits include:
- Native GitHub integration — no external services needed
- Matrix builds — test across multiple Python versions simultaneously
- Extensive marketplace — pre-built actions for common tasks
- Free for open source — generous free tier for public repos
Basic Workflow Structure
Create a .github/workflows/ci.yml file in your repository:
name: CI Pipeline
on:
push:
branches: [main, develop]
pull_request:
branches: [main]
jobs:
test:
runs-on: ubuntu-latest
strategy:
matrix:
python-version: ['3.10', '3.11', '3.12']
steps:
- uses: actions/checkout@v4
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install -r requirements.txt
pip install pytest pytest-cov flake8
- name: Lint with flake8
run: flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics
- name: Run tests
run: pytest --cov=./ --cov-report=xml
Adding Docker Build
For projects that use Docker, extend your workflow:
build:
needs: test
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Build Docker image
run: docker build -t myapp:${{ github.sha }} .
- name: Run container tests
run: |
docker run --rm myapp:${{ github.sha }} python -m pytest
Deployment Stage
Add automatic deployment to your server or cloud provider:
deploy:
needs: build
runs-on: ubuntu-latest
if: github.ref == 'refs/heads/main'
steps:
- name: Deploy to production
uses: appleboy/ssh-action@v1.0.0
with:
host: ${{ secrets.HOST }}
username: ${{ secrets.USERNAME }}
key: ${{ secrets.SSH_KEY }}
script: |
cd /app
docker-compose pull
docker-compose up -d
Secrets Management
Store sensitive data in GitHub Secrets:
- Go to Repository → Settings → Secrets and variables → Actions
- Add secrets like
SSH_KEY,HOST,USERNAME - Reference in workflow as
${{ secrets.SECRET_NAME }}
Best Practices
- Fail fast — run linting before time-consuming tests
- Cache dependencies — speed up builds with pip caching
- Use matrix builds — ensure compatibility across Python versions
- Separate concerns — use different jobs for test, build, deploy
- Protect main branch — require passing CI before merge
Conclusion
A well-configured CI/CD pipeline saves hours of manual work and catches issues early. Start with basic testing, then gradually add linting, Docker builds, and automated deployment as your project grows.
This workflow is used in my projects like TicketPro and News Bot.
