How to test and deploy a Django project using Github Actions

Automating your testing and deployment process is crucial for modern web development, ensuring code quality and speeding up delivery. This guide walks you through creating a complete CI/CD pipeline for a Django project using GitHub Actions. You'll learn how to automatically run tests against a PostgreSQL database and securely deploy your application to a server with every code push, streamlining your entire workflow from commit to production.

GitHub Actions workflow

This GitHub Actions workflow .github/workflows/test_and_deploy.yaml automates testing and deployment for a Django project:

name: Test and Deploy

on: [push]

jobs:
  build:
    name: build and test django app
    runs-on: ubuntu-latest
    services:
      postgres:
        image: postgres:12
        env:
          POSTGRES_USER: postgres
          POSTGRES_PASSWORD: postgres
          POSTGRES_DB: testing_db
        ports:
          - 5432:5432
        # health check for making sure the service is up
        options: --health-cmd pg_isready --health-interval 10s --health-timeout 5s --health-retries 5
    steps:
      - name: Check out repo
        uses: actions/checkout@v3
      - name: Set up Python
        uses: actions/setup-python@v4
        with:
          python-version: "3.9"
      - uses: actions/cache@v3
        name: Configure pip caching
        with:
          path: ~/.cache/pip
          key: ${{ runner.os }}-pip-${{ hashFiles('**/requirements.txt') }}
          restore-keys: |
            ${{ runner.os }}-pip-
      - name: Install Python dependencies
        run: |
          python -m pip install -r requirements.txt
      - name: Run Tests
        env:
          USE_SQLITE3_DB: "0"
          USE_SPACES: "0"
          DJANGO_SECRET_KEY: CI_CD_TEST_KEY
          POSTGRES_DB: testing_db
          POSTGRES_HOST: localhost
          POSTGRES_USER: postgres
          POSTGRES_PASSWORD: postgres
          POSTGRES_PORT: 5432
          DEBUG: "0"
          PRODUCTION: "1"
        run: |
          python manage.py test
      - name: Deploy to server, executing remote ssh commands using ssh key
        uses: appleboy/ssh-action@master
        with:
          host: ${{ secrets.MY_SERVER_HOST }}
          username: ${{ secrets.MY_SERVER_USERNAME }}
          key: ${{ secrets.MY_SERVER_KEY }}
          port: ${{ secrets.MY_SERVER_PORT }}
          # fingerprint: ${{ secrets.MY_SERVER_FINGERPRINT }}
          # if a try to run the shell script I get: bash: /home/***/my_server_scripts/myproject/after_deployment.sh: Permission denied
          # /home/${{ secrets.MY_SERVER_USERNAME }}/my_server_scripts/myproject/after_deployment.sh
          script: |
            cd /home/myuser/myproject
            git pull
            source venv/bin/activate
            python -m pip install -r requirements.txt
            python manage.py migrate
            python manage.py collectstatic
Testing Phase
  • PostgreSQL Service: Spins up a temporary PostgreSQL database for testing
  • Python Setup: Configures Python 3.9 and caches pip dependencies for faster runs
  • Environment Variables: Sets up database connection and Django settings for testing
  • Test Execution: Runs Django tests against the PostgreSQL database
Deployment Phase
  • SSH Deployment: Uses SSH with stored secrets to connect to your production server
  • Deployment Script: Executes commands to:
  • Pull latest code from repository
  • Activate virtual environment
  • Install/update Python dependencies
  • Run database migrations
  • Collect static files

Author

Rami Boutassghount

Rami Boutassghount

Hetzner Cloud

Sign up using my referral link and get €20 in Hetzner Cloud credits!

Once you spend €10, I’ll also receive a €10 credit — a win-win!

🌐 Change language