$ matvix90.blog

> A minimal command-line inspired blog

CI/CD Django Deployment with GitHub Actions

$ cat 2025-12-07.txt
deploy devops django github

Automating your Django deployment with CI/CD eliminates manual errors and speeds up your release process. In this guide, I'll show you how to set up a complete GitHub Actions pipeline that tests, builds, and deploys your Django application automatically.

Why CI/CD for Django?

Continuous Integration and Deployment provides:

  • Automated testing - Catch bugs before they reach production
  • Consistent deployments - Same process every time
  • Faster releases - Deploy with a single git push
  • Quality assurance - Automated code checks and formatting

Architecture Overview

Our pipeline follows a three-stage workflow:

Job 1: Test & Quality Checks
    ├── Run Django tests
    ├── Check code with Ruff
    └── Verify dependencies
        ↓
Job 2: Deploy to Remote Server
    ├── SSH into server
    ├── Pull latest code
    ├── Build containers
    └── Restart services
        ↓
Job 3: Deployment Notification
    └── Confirm successful deployment

Django Project Structure

A typical Django project using pyproject.toml looks like this:

[project]
name = "myproject"
version = "1.0.0"
description = "Django application with Docker deployment"
requires-python = ">=3.11"
dependencies = [
    "django>=5.0",
    "gunicorn>=21.2.0",
    "psycopg2-binary>=2.9.9",
    "python-dotenv>=1.0.0",
]

[project.optional-dependencies]
dev = [
    "ruff>=0.1.0",
    "pytest>=7.4.0",
    "pytest-django>=4.7.0",
]

[tool.ruff]
line-length = 88
target-version = "py311"

[tool.ruff.lint]
select = ["E", "F", "I", "N", "W"]
ignore = ["E501"]

GitHub Actions Workflow

Create .github/workflows/deploy.yml in your repository:

name: Django CI/CD Pipeline

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

jobs:
  test:
    name: Test & Quality Checks
    runs-on: ubuntu-latest

    steps:
      - name: Checkout code
        uses: actions/checkout@v4

      - name: Set up Python
        uses: actions/setup-python@v5
        with:
          python-version: '3.11'

      - name: Install dependencies
        run: |
          python -m pip install --upgrade pip
          pip install -e .[dev]

      - name: Run Ruff linter
        run: |
          ruff check .

      - name: Run Ruff formatter
        run: |
          ruff format --check .

      - name: Run Django tests
        run: |
          python manage.py test
        env:
          DJANGO_SETTINGS_MODULE: myproject.settings
          SECRET_KEY: test-secret-key-for-ci
          DATABASE_URL: sqlite:///db.sqlite3

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

    steps:
      - name: Deploy to server
        uses: appleboy/ssh-action@v1.0.0
        with:
          host: ${{ secrets.SERVER_IP }}
          username: ${{ secrets.SERVER_USER }}
          key: ${{ secrets.SSH_PRIVATE_KEY }}
          script: |
            cd /home/${{ secrets.SERVER_USER }}/myproject
            git pull origin main
            docker compose down
            docker compose up --build -d
            docker compose exec -T web python manage.py migrate
            docker compose exec -T web python manage.py collectstatic --noinput

  notify:
    name: Deployment Notification
    runs-on: ubuntu-latest
    needs: deploy
    if: always()

    steps:
      - name: Notify deployment status
        run: |
          if [ "${{ needs.deploy.result }}" == "success" ]; then
            echo "✅ Deployment to ${{ secrets.DOMAIN }} successful!"
          else
            echo "❌ Deployment failed!"
            exit 1
          fi

Configure GitHub Secrets

GitHub Secrets store sensitive information securely for your workflows.

Generate SSH Key Pair

Create a dedicated SSH key for GitHub Actions:

# On your local machine
ssh-keygen -t ed25519 -C "github-actions" -f ~/.ssh/github_actions

Add Public Key to Remote Server

Copy the public key to your server:

# On Linux - Display public key
cat ~/.ssh/github_actions.pub

# On Windows - Display public key
notepad ~/.ssh/github_actions.pub

# Copy the entire output (starts with "ssh-ed25519")

Add it to your remote server:

# On the REMOTE server
echo "PASTE_PUBLIC_KEY_HERE" >> ~/.ssh/authorized_keys

# Verify permissions
chmod 600 ~/.ssh/authorized_keys
chmod 700 ~/.ssh

Add Secrets to GitHub

Navigate to: GitHub → Repository → Settings → Secrets and variables → Actions → New repository secret

Add these secrets:

Secret Name Value Description
SERVER_IP 203.0.113.42 Your remote server IP address
SERVER_USER deploy SSH username on server
SSH_PRIVATE_KEY -----BEGIN OPENSSH... Full private key content
DOMAIN example.com Your production domain

Getting the private key:

# On Linux
cat ~/.ssh/github_actions

# On Windows
notepad ~/.ssh/github_actions

Copy the entire content including the -----BEGIN and -----END lines.

Pre-Deployment Checklist

Before pushing to production, run these checks in your development environment.

Run Tests Locally

Ensure all tests pass:

python manage.py test

Check Code Quality

Lint and format your code:

# Lint and auto-fix issues
ruff check --fix .

# Format code
ruff format .

Verify Django Configuration

Run Django's deployment checks:

# Apply migrations
python manage.py migrate

# Check for deployment issues
python manage.py check --deploy

Triggering Deployments

Once configured, deployments are automatic:

# Make your changes
git add .
git commit -m "feat: add new feature"

# Push to main branch (triggers CI/CD)
git push origin main

The pipeline will:
1. Run tests and quality checks
2. Deploy to your server if tests pass
3. Notify you of the deployment status

Monitoring Deployments

View your workflow runs:

  1. Go to your GitHub repository
  2. Click the Actions tab
  3. Select your workflow run
  4. View logs for each job

Check deployment on your server:

# View running containers
docker compose ps

# Check application logs
docker compose logs -f web

# Verify deployment
curl https://your-domain.com

Key Takeaways

GitHub Actions automates your entire deployment pipeline, from testing to production, with every git push to the main branch.

CI/CD best practices:

  1. ✓ Always run tests before deployment
  2. ✓ Use dedicated SSH keys for automation
  3. ✓ Store secrets securely in GitHub
  4. ✓ Test locally before pushing
  5. ✓ Monitor deployment logs
  6. ✓ Keep your workflow file versioned

Your Django application now deploys automatically with confidence! 🚀