Skip to content

Django Testing CI #2337

Django Testing CI

Django Testing CI #2337

# Github Actions workflow that runs the test suite on the master branch
# every night, as well as tests new pull requests.
name: Django Testing CI
on:
schedule: # Run every night at 3 AM
- cron: '0 10 * * *' # 10 AM UTC = 3 AM PST
push: # Run when pushes are made on the master and develop branch
branches: [ "master", "develop" ]
pull_request: # Runs when pull request to develop or master is opened,
# reopened, or updated with a new commit.
branches: [ "master", "develop" ]
env:
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true
jobs:
# ─── Coverage strategy ───────────────────────────────────────────────────────
#
# Each test job writes its coverage data to a unique coverage-<shard> file,
# then uploads it as an artifact. The `report` job downloads all five files,
# runs `coverage combine`, and generates the combined HTML + XML report.
#
# Shared setup (checkout, Python, venv, settings) lives in the composite
# action at .github/actions/coldfront-setup. Each job still declares its
# own Postgres service because services cannot be defined in composite actions.
#
# Coverage is written to the default .coverage file (no --data-file flag),
# then renamed to coverage-<shard> (no leading dot) immediately after the run.
# Each job runs on an isolated runner so there is no cross-job collision.
#
# ─────────────────────────────────────────────────────────────────────────────
test-pytest:
runs-on: ubuntu-22.04
permissions:
contents: read
services:
postgres:
image: postgres:15.2-alpine3.17
env:
POSTGRES_DB: cf_brc_db
POSTGRES_PASSWORD: test
POSTGRES_PORT: 5432
POSTGRES_USER: test
ports:
- 5432:5432
options: >-
--health-cmd pg_isready
--health-interval 2s
--health-timeout 3s
--health-retries 15
steps:
- uses: actions/checkout@v4
- uses: ./.github/actions/coldfront-setup
- name: Run pytest unit tests
run: |
source ~/venv/bin/activate
export django_secret_key=`openssl rand -base64 64`
coverage run -m pytest coldfront/ -m unit
- name: Run pytest component tests
run: |
source ~/venv/bin/activate
export django_secret_key=`openssl rand -base64 64`
coverage run --append -m pytest coldfront/ -m component
- name: Rename coverage data
if: always()
run: mv .coverage coverage-pytest || true
- name: Upload pytest coverage data
uses: actions/upload-artifact@v4
with:
name: coverage-data-pytest
path: coverage-pytest
if: always()
# ─── Django: core.project views ──────────────────────────────────────────────
# ~143 test methods — view tests only.
test-django-project-views:
runs-on: ubuntu-22.04
permissions:
contents: read
services:
postgres:
image: postgres:15.2-alpine3.17
env:
POSTGRES_DB: cf_brc_db
POSTGRES_PASSWORD: test
POSTGRES_PORT: 5432
POSTGRES_USER: test
ports:
- 5432:5432
options: >-
--health-cmd pg_isready
--health-interval 2s
--health-timeout 3s
--health-retries 15
steps:
- uses: actions/checkout@v4
- uses: ./.github/actions/coldfront-setup
- name: Run Django tests (core.project - views)
run: |
source ~/venv/bin/activate
export django_secret_key=`openssl rand -base64 64`
python manage.py migrate
coverage run manage.py test \
--timing \
--testrunner=coldfront.tests.timing_runner.TimingTestRunner \
coldfront.core.project.tests.test_views
- name: Rename coverage data
if: always()
run: mv .coverage coverage-django-project-views || true
- name: Upload Django project views coverage data
uses: actions/upload-artifact@v4
with:
name: coverage-data-django-project-views
path: coverage-django-project-views
if: always()
# ─── Django: core.project non-views ──────────────────────────────────────────
# ~151 test methods — commands, forms, and utils.
test-django-project-other:
runs-on: ubuntu-22.04
permissions:
contents: read
services:
postgres:
image: postgres:15.2-alpine3.17
env:
POSTGRES_DB: cf_brc_db
POSTGRES_PASSWORD: test
POSTGRES_PORT: 5432
POSTGRES_USER: test
ports:
- 5432:5432
options: >-
--health-cmd pg_isready
--health-interval 2s
--health-timeout 3s
--health-retries 15
steps:
- uses: actions/checkout@v4
- uses: ./.github/actions/coldfront-setup
- name: Run Django tests (core.project - commands, forms, utils)
run: |
source ~/venv/bin/activate
export django_secret_key=`openssl rand -base64 64`
python manage.py migrate
coverage run manage.py test \
--timing \
--testrunner=coldfront.tests.timing_runner.TimingTestRunner \
coldfront.core.project.tests.test_commands \
coldfront.core.project.tests.test_forms \
coldfront.core.project.tests.test_utils
- name: Rename coverage data
if: always()
run: mv .coverage coverage-django-project-other || true
- name: Upload Django project other coverage data
uses: actions/upload-artifact@v4
with:
name: coverage-data-django-project-other
path: coverage-django-project-other
if: always()
# ─── Django: api.* ───────────────────────────────────────────────────────────
# ~229 test methods across allocation, billing, project, statistics, user apps.
test-django-api:
runs-on: ubuntu-22.04
permissions:
contents: read
services:
postgres:
image: postgres:15.2-alpine3.17
env:
POSTGRES_DB: cf_brc_db
POSTGRES_PASSWORD: test
POSTGRES_PORT: 5432
POSTGRES_USER: test
ports:
- 5432:5432
options: >-
--health-cmd pg_isready
--health-interval 2s
--health-timeout 3s
--health-retries 15
steps:
- uses: actions/checkout@v4
- uses: ./.github/actions/coldfront-setup
- name: Run Django tests (api)
run: |
source ~/venv/bin/activate
export django_secret_key=`openssl rand -base64 64`
python manage.py migrate
coverage run manage.py test \
--timing \
--testrunner=coldfront.tests.timing_runner.TimingTestRunner \
coldfront.api
- name: Rename coverage data
if: always()
run: mv .coverage coverage-django-api || true
- name: Upload Django API coverage data
uses: actions/upload-artifact@v4
with:
name: coverage-data-django-api
path: coverage-django-api
if: always()
# ─── Django: remaining core.* + plugins.* ────────────────────────────────────
# ~284 test methods: core.allocation, billing, user, utils, statistics,
# account, socialaccount, research_output, publication, and plugins.
test-django-core:
runs-on: ubuntu-22.04
permissions:
contents: read
services:
postgres:
image: postgres:15.2-alpine3.17
env:
POSTGRES_DB: cf_brc_db
POSTGRES_PASSWORD: test
POSTGRES_PORT: 5432
POSTGRES_USER: test
ports:
- 5432:5432
options: >-
--health-cmd pg_isready
--health-interval 2s
--health-timeout 3s
--health-retries 15
steps:
- uses: actions/checkout@v4
- uses: ./.github/actions/coldfront-setup
- name: Run Django tests (core except project, plugins)
run: |
source ~/venv/bin/activate
export django_secret_key=`openssl rand -base64 64`
python manage.py migrate
coverage run manage.py test \
--timing \
--testrunner=coldfront.tests.timing_runner.TimingTestRunner \
coldfront.core.account \
coldfront.core.allocation \
coldfront.core.billing \
coldfront.core.publication \
coldfront.core.research_output \
coldfront.core.socialaccount \
coldfront.core.statistics \
coldfront.core.user \
coldfront.core.utils \
coldfront.plugins
- name: Rename coverage data
if: always()
run: mv .coverage coverage-django-core || true
- name: Upload Django core coverage data
uses: actions/upload-artifact@v4
with:
name: coverage-data-django-core
path: coverage-django-core
if: always()
# ─── Report ──────────────────────────────────────────────────────────────────
# Runs after all five test jobs (even if one fails) to combine coverage data,
# post the PR comment, and upload the combined report artifact.
report:
needs: [test-pytest, test-django-project-views, test-django-project-other, test-django-api, test-django-core]
if: always()
runs-on: ubuntu-22.04
permissions:
contents: write # required to push python-coverage-comment-action-data branch
pull-requests: write # required to post coverage comment
steps:
- uses: actions/checkout@v4
- uses: ./.github/actions/coldfront-setup
- name: Download all coverage data
uses: actions/download-artifact@v4
with:
pattern: coverage-data-*
merge-multiple: true
path: coverage-data
- name: Generate combined coverage report
run: |
source ~/venv/bin/activate
coverage combine coverage-data/coverage-*
coverage html
coverage xml -o coverage-combined.xml
coverage report --fail-under=50
- name: Post coverage comment on PR
uses: py-cov-action/python-coverage-comment-action@v3
with:
GITHUB_TOKEN: ${{ github.token }}
- name: Upload coverage reports
uses: actions/upload-artifact@v4
with:
name: coverage-reports
path: |
coverage-*.xml
htmlcov/
retention-days: 7
if: always()