CI/CD integration with django tests

July 31, 2025 (10d ago)

metadata: DevOps, django, github

CI/CD

basically there are some things which I learned today while enhancing my frontpage application regarding running tests

To use github actions you need to have a folder named .github and inside that folder a workflows folder

.github
	workflows
		tests.yml
		tests2.yml
		...

and inside the workflows you have your custom yml files which will run after each commit (if they are the certain branch that the test.yml is configured to run on)

Meta of a yml file

first you give name to the specific action using

name: Django CI Check

Then you define the scope of your action

on:
  push:
    branches: ["*"]
  pull_request:
    branches: ["*"]

in this case it will be configured and run on all the branches

After that you define the respective jobs and subjobs

jobs:
	subjob1:
		....
	subjob2:
		....
	subjob3:
		....

Meta Learning for jobs

there are few meta for a specific job:

  • runs-on which is described as the OS used to run the specific action (usually ubuntu-latest)

  • needs: (any previous subjob this particular sub job needs) (Optional)

  • steps: inside steps there are some syntax name: Name of action uses: actions/setup-python@v4 => (there are different types of in-built github-actions functions that are triggered by using uses parameter)

    run: | (commands go here) python manage.py tests

Example django-ci.yml file

name: Django CI Check
on:
  push:
    branches: ["*"]
  pull_request:
    branches: ["*"]
jobs:
  lint:
    runs-on: ubuntu-latest
    steps:
      - name: Check out code
        uses: actions/checkout@v3
      - name: Set up Python
        uses: actions/setup-python@v4
        with:
          python-version: '3.11'
      - name: Install dependencies for linting
        run: |
          python -m pip install --upgrade pip
          pip install -r requirements.txt
          pip install flake8
      - name: Run flake8
        run: |
          flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics
          flake8 . --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics
  migrate:
    runs-on: ubuntu-latest
    needs: lint
    steps:
      - name: Check out code
        uses: actions/checkout@v3
      - name: Set up Python
        uses: actions/setup-python@v4
        with:
          python-version: '3.11'
      - name: Install dependencies for migration
        run: |
          python -m pip install --upgrade pip
          pip install -r requirements.txt
      - name: Run migrations
        run: |
          python manage.py makemigrations --noinput
          python manage.py migrate --noinput
  test:
    runs-on: ubuntu-latest
    needs: migrate
    steps:
      - name: Check out code
        uses: actions/checkout@v3
      - name: Set up Python
        uses: actions/setup-python@v4
        with:
          python-version: '3.11'
      - name: Install dependencies for testing
        run: |
          python -m pip install --upgrade pip
          pip install -r requirements.txt
          pip install coverage
      - name: Run tests with coverage
        env:
          DJANGO_SECRET_KEY: "dummy-test-secret"
        run: |
          coverage run manage.py test
          coverage report --fail-under=80
          coverage xml
      - name: Upload coverage to GitHub summary
        if: always()
        run: |
          echo "## Coverage Report" >> $GITHUB_STEP_SUMMARY
          coverage report >> $GITHUB_STEP_SUMMARY
  • This file configure and download the linting package along with required project libraries from requirements.txt
  • then it migrates the database and run tests
  • after that it uploads test report to github summary

⚠️: This yml file structure is actually unnecessary because it it a redundant script I used to demonstrate different subjobs in action, you can use all the subjobs instances here together inside a single job for faster workflow

Gradient background
CI/CD integration with django tests