Use GitHub action as CI for django

Use GitHub action as CI for django

When we develop a Django application, we need to test it before deploying it to production. We can use GitHub action as CI (Continuous Integration) to automate the testing process. This post explains how to set up GitHub action as CI for Django.

Django settings file

The settings file should have configuration for database:

1
2
3
4
5
6
7
8
9
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME': 'journalapp',
'USER': 'root',
'HOST':'127.0.0.1',
'PORT':'3306',
}
}

Note:

  • Django create a test database for testing. The name is “test_” + database name. For example, if the database name is “journalapp”, the test database name is “test_journalapp”.
  • It’s better to use root user here. Otherwise, it may have permission error when running tests.

Docker file

When we use GitHub action as CI, we need to create a Docker file to build the image and create environment for testing. Here is an example of a Docker file:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
services:
db:
image: mysql:8.2
container_name: db
restart: always
environment:
MYSQL_ALLOW_EMPTY_PASSWORD: "true"
MYSQL_USER: test
MYSQL_PASSWORD: test
ports:
- "3306:3306"
volumes:
- ./db:/var/lib/mysql
healthcheck:
test: ["CMD", "mysqladmin", "ping", "-h", "localhost"]
interval: 10s
timeout: 5s
retries: 3

Note: We shouldn’t create test_journalapp database in the MySQL container. Django will create it automatically.

GitHub action

Create a .github/workflows folder in the root directory of the project. Then create a django.yml file in this folder:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
name: Django CI

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

jobs:
build:

runs-on: ubuntu-latest
strategy:
max-parallel: 4
matrix:
python-version: ["3.10", "3.11"]

steps:
- uses: actions/checkout@v3
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v3
with:
python-version: ${{ matrix.python-version }}
- name: Install Dependencies
run: |
python -m pip install --upgrade pip
pip install -r requirements.txt

- name: Build docker
run: docker-compose build

- name: run docker
run: docker-compose up -d
timeout-minutes: 10

- name: Wait for MySQL
run: |
for i in {1..10}; do
if docker exec db mysqladmin ping -hlocalhost --silent; then
break
fi
echo "Waiting for MySQL..."
sleep 10
done

- name: Run Tests
run: |
python manage.py test

Note: After running docker, we should wait for MySQL to be ready before running tests. Otherwise, we will have error: MySQLdb.OperationalError: (2013, “Lost connection to MySQL server at ‘reading initial communication packet’, system error: 0”).

Comments