CI/CD integration with django tests

July 31, 2025 (5mo 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