Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
73 changes: 3 additions & 70 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -116,76 +116,6 @@ jobs:
if: '!cancelled()'
run: uv run python manage.py validate_templates

test:
runs-on: ubuntu-latest
env:
DB_ROOT_PASSWORD: "root-password"
DB_PASSWORD: "user-password"
DB_USER: citest
container: python:3.13.12-alpine3.22
services:
db:
image: mariadb:10.11.16-jammy
env:
MARIADB_ROOT_PASSWORD: ${{ env.DB_ROOT_PASSWORD }}
# ensure that user has permissions for test DB to be used by pytest
MARIADB_DATABASE: test_opal
MARIADB_USER: ${{ env.DB_USER }}
MARIADB_PASSWORD: ${{ env.DB_PASSWORD }}

steps:
- name: Install Git
run: |
apk add --no-cache git git-lfs
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false
lfs: true
- name: Install dependencies
run: |
pip install uv
echo "Installed uv version is $(uv --version)"
# install dependencies for mysqlclient
apk add --no-cache build-base mariadb-dev mariadb-client chromium
uv sync --locked
chromium --version
- name: Prepare environment
# set up env file for DB service
# use sample env file
# create additional DBs for legacy DB tests (OpalDB & QuestionnaireDB)
run: |
cp .env.sample .env
sed -i "s/^DATABASE_USER=.*/DATABASE_USER=$DB_USER/" .env
sed -i "s/^DATABASE_PASSWORD=.*/DATABASE_PASSWORD=$DB_PASSWORD/" .env
sed -i "s/^DATABASE_HOST=.*/DATABASE_HOST=db/" .env
# set up legacy DB connection
# reuse the same database as for the other tests to make it easier
sed -i "s/^LEGACY_DATABASE_HOST=.*/LEGACY_DATABASE_HOST=db/" .env
sed -i "s/^LEGACY_DATABASE_PORT=.*/LEGACY_DATABASE_PORT=3306/" .env
sed -i "s/^LEGACY_DATABASE_USER=.*/LEGACY_DATABASE_USER=$DB_USER/" .env
sed -i "s/^LEGACY_DATABASE_PASSWORD=.*/LEGACY_DATABASE_PASSWORD=$DB_PASSWORD/" .env
# generate secret key
SECRET_KEY=$(python -c "import secrets; print(secrets.token_urlsafe())")
sed -i "s/^SECRET_KEY=.*/SECRET_KEY=$SECRET_KEY/" .env
MYSQL_PWD=$DB_ROOT_PASSWORD mariadb -u root -h db --skip-ssl -e "GRANT ALL PRIVILEGES ON \`test_OpalDB\`.* TO \`$DB_USER\`@\`%\`;"
MYSQL_PWD=$DB_ROOT_PASSWORD mariadb -u root -h db --skip-ssl -e "GRANT ALL PRIVILEGES ON \`test_QuestionnaireDB\`.* TO \`$DB_USER\`@\`%\`;"
- name: Run pytest
run: |
uv run pytest --version
# -m "" runs all tests, even the ones marked as slow
uv run coverage run -m pytest -m "" -v --junitxml=test-report.xml
# see: https://github.com/dorny/test-reporter/issues/244
# - name: Publish Test Results
# uses: dorny/test-reporter@v1.9.1
# if: '!cancelled()'
# with:
# name: Tests
# path: ./test-report.xml
# reporter: java-junit
- name: Check coverage
run: |
uv run coverage report


markdownlint:
permissions:
Expand All @@ -195,6 +125,9 @@ jobs:
run-reuse-workflow:
uses: opalmedapps/.github/.github/workflows/reuse.yaml@main

test:
uses: ./.github/workflows/test.yml

build-docs:
runs-on: ubuntu-latest
needs:
Expand Down
127 changes: 127 additions & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
# SPDX-FileCopyrightText: Copyright (C) 2025 Opal Health Informatics Group at the Research Institute of the McGill University Health Centre <john.kildea@mcgill.ca>
#
# SPDX-License-Identifier: AGPL-3.0-or-later
name: test

on:
workflow_call:
workflow_dispatch:

concurrency:
group: ${{ github.workflow }}-test-${{ github.event.pull_request.number || github.sha }}
cancel-in-progress: true

permissions:
contents: read

jobs:
seed:
runs-on: ubuntu-latest
outputs:
seed: ${{ steps.calculate-seed.outputs.seed }}
steps:
- name: Create seed
id: calculate-seed
run: echo "seed=$(python3 -c 'import random; print(random.Random().getrandbits(32));')" >> "$GITHUB_OUTPUT"

# usage of pytest-split and matrix strategy based on:
# https://github.com/jerry-git/pytest-split-gh-actions-demo/blob/master/.github/workflows/test.yml
pytest:
runs-on: ubuntu-latest
needs: seed
strategy:
fail-fast: false
matrix:
group: [1, 2, 3, 4]
env:
DB_ROOT_PASSWORD: "root-password"
DB_PASSWORD: "user-password"
DB_USER: citest
SEED: ${{ needs.seed.outputs.seed }}
container: python:3.13.12-alpine3.22
services:
db:
image: mariadb:10.11.16-jammy
env:
MARIADB_ROOT_PASSWORD: ${{ env.DB_ROOT_PASSWORD }}
# ensure that user has permissions for test DB to be used by pytest
MARIADB_DATABASE: test_opal
MARIADB_USER: ${{ env.DB_USER }}
MARIADB_PASSWORD: ${{ env.DB_PASSWORD }}

steps:
- name: Install Git
run: |
apk add --no-cache git git-lfs
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false
lfs: true
- name: Install dependencies
run: |
pip install uv
echo "Installed uv version is $(uv --version)"
# install dependencies for mysqlclient
apk add --no-cache build-base mariadb-dev mariadb-client chromium
uv sync --locked
- name: Prepare environment
# set up env file for DB service
# use sample env file
# create additional DBs for legacy DB tests (OpalDB & QuestionnaireDB)
run: |
cp .env.sample .env
sed -i "s/^DATABASE_USER=.*/DATABASE_USER=$DB_USER/" .env
sed -i "s/^DATABASE_PASSWORD=.*/DATABASE_PASSWORD=$DB_PASSWORD/" .env
sed -i "s/^DATABASE_HOST=.*/DATABASE_HOST=db/" .env
# set up legacy DB connection
# reuse the same database as for the other tests to make it easier
sed -i "s/^LEGACY_DATABASE_HOST=.*/LEGACY_DATABASE_HOST=db/" .env
sed -i "s/^LEGACY_DATABASE_PORT=.*/LEGACY_DATABASE_PORT=3306/" .env
sed -i "s/^LEGACY_DATABASE_USER=.*/LEGACY_DATABASE_USER=$DB_USER/" .env
sed -i "s/^LEGACY_DATABASE_PASSWORD=.*/LEGACY_DATABASE_PASSWORD=$DB_PASSWORD/" .env
# generate secret key
SECRET_KEY=$(python -c "import secrets; print(secrets.token_urlsafe())")
sed -i "s/^SECRET_KEY=.*/SECRET_KEY=$SECRET_KEY/" .env
MYSQL_PWD=$DB_ROOT_PASSWORD mariadb -u root -h db --skip-ssl -e "GRANT ALL PRIVILEGES ON \`test_OpalDB\`.* TO \`$DB_USER\`@\`%\`;"
MYSQL_PWD=$DB_ROOT_PASSWORD mariadb -u root -h db --skip-ssl -e "GRANT ALL PRIVILEGES ON \`test_QuestionnaireDB\`.* TO \`$DB_USER\`@\`%\`;"
- name: Run pytest
# use pytest-cov to disable coverage fail
# use the same seed for each group
run: |
uv run pytest --version
# -m "" runs all tests, even the ones marked as slow
uv run pytest --cov --cov-fail-under=0 --cov-report= --randomly-seed="$SEED" --splitting-algorithm=least_duration --splits 4 --group ${{ matrix.group }} -m ""
pwd
- name: Upload coverage
uses: actions/upload-artifact@v7.0.0
with:
name: coverage-${{ matrix.group }}
path: .coverage
include-hidden-files: true
if-no-files-found: error

coverage:
needs: pytest
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false
- uses: astral-sh/setup-uv@5a095e7a2014a4212f075830d4f7277575a9d098 # v7.3.1
id: setup-uv
with:
# renovate: datasource=pypi dependency=uv
version: "0.10.7"
- name: Install dependencies
run: uv sync --locked --only-dev
- name: Download coverage reports
uses: actions/download-artifact@v8.0.0
- name: Check coverage
run: |
pwd
ls -la coverage-*
ls -la opal/
uv run coverage combine coverage*/.coverage*
ls -la
uv run coverage report
2 changes: 2 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -70,10 +70,12 @@ dev = [
"pandas-stubs==3.0.0.260204",
"prek==0.3.4",
"pytest==9.0.2",
"pytest-cov==7.0.0",
"pytest-django==4.11.1",
"pytest-mock==3.15.1",
"pytest-randomly==4.0.1",
"pytest-socket==0.7.0",
"pytest-split==0.11.0",
"pytest-sugar==1.1.1",
"ruff==0.15.4",
"types-beautifulsoup4==4.12.0.20250516",
Expand Down
4 changes: 4 additions & 0 deletions renovate.json5
Original file line number Diff line number Diff line change
Expand Up @@ -101,5 +101,9 @@
"matchPackageNames": ["/uv-pre-commit|uv$/"],
"groupName": "uv",
},
// Group upload and download artifact actions
{
"matchPackageNames": ["actions/upload-artifact", "actions/download-artifact"],
},
],
}
30 changes: 30 additions & 0 deletions uv.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading