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
226 changes: 119 additions & 107 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,27 +13,65 @@ env:
IMAGE_NAME: maykinmedia/objects-api

jobs:
tests:
strategy:
matrix:
postgres: ['13', '15', '16', '17']
postgis: ['3.2', '3.5']
exclude:
# postgis 3.2 is not compatible with recent postgres versions
- postgres: '17'
postgis: '3.2'
- postgres: '16'
postgis: '3.2'
- postgres: '15'
postgis: '3.2'

name: Run the Django test suite (PG ${{ matrix.postgres }}, postgis ${{ matrix.postgis }})
# tests:
# strategy:
# matrix:
# postgres: ['13', '15', '16', '17']
# postgis: ['3.2', '3.5']
# exclude:
# # postgis 3.2 is not compatible with recent postgres versions
# - postgres: '17'
# postgis: '3.2'
# - postgres: '16'
# postgis: '3.2'
# - postgres: '15'
# postgis: '3.2'

# name: Run the Django test suite (PG ${{ matrix.postgres }}, postgis ${{ matrix.postgis }})

# runs-on: ubuntu-latest

# services:
# postgres:
# image: postgis/postgis:${{ matrix.postgres }}-${{ matrix.postgis }}
# env:
# POSTGRES_HOST_AUTH_METHOD: trust
# ports:
# - 5432:5432
# # needed because the postgres container does not provide a healthcheck
# options: --health-cmd pg_isready --health-interval 10s --health-timeout 5s --health-retries 5

# steps:
# - uses: actions/checkout@v4
# - name: Set up backend environment
# uses: maykinmedia/setup-django-backend@v1.3
# with:
# apt-packages: 'libgdal-dev gdal-bin'
# python-version: '3.11'
# setup-node: true

# - name: Run tests
# run: |
# python src/manage.py collectstatic --noinput --link
# coverage run src/manage.py test src
# env:
# DJANGO_SETTINGS_MODULE: objects.conf.ci
# SECRET_KEY: dummy
# DB_USER: postgres
# DB_PASSWORD: ''

# - name: Publish coverage report
# uses: codecov/codecov-action@v4
# with:
# token: ${{ secrets.CODECOV_TOKEN }}

performance-tests:
name: Run the performance test suite
runs-on: ubuntu-latest

services:
postgres:
image: postgis/postgis:${{ matrix.postgres }}-${{ matrix.postgis }}
image: postgis/postgis:17-3.5
env:
POSTGRES_HOST_AUTH_METHOD: trust
ports:
Expand All @@ -43,107 +81,81 @@ jobs:

steps:
- uses: actions/checkout@v4

- name: Set up backend environment
uses: maykinmedia/setup-django-backend@v1.3
with:
apt-packages: 'libgdal-dev gdal-bin'
python-version: '3.11'
setup-node: true
setup-node: false

- name: Run tests
run: |
python src/manage.py collectstatic --noinput --link
coverage run src/manage.py test src
pytest performance_test/ --benchmark-json output.json
env:
DJANGO_SETTINGS_MODULE: objects.conf.ci
SECRET_KEY: dummy
DB_USER: postgres
DB_PASSWORD: ''

- name: Publish coverage report
uses: codecov/codecov-action@v4
with:
token: ${{ secrets.CODECOV_TOKEN }}

performance-tests:
name: Run the performance test suite
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v4

- name: Bring up docker compose and load data
run: |
docker compose up -d --build || ( docker compose logs >&2 && exit 1; )
until docker compose logs web | grep -q "spawned uWSGI worker"; do
echo "uWSGI not running yet, waiting..."
sleep 3
done
docker compose exec --user root web pip install factory-boy
cat performance_test/create_data.py | docker compose exec -T web src/manage.py shell

- name: Run tests
run: |
pip install -r requirements/ci.txt
pytest performance_test/ --benchmark-json output.json

docs:
runs-on: ubuntu-latest
name: Documentation build

steps:
- uses: actions/checkout@v4
- name: Set up backend environment
uses: maykinmedia/setup-django-backend@v1.3
with:
apt-packages: 'libgdal-dev gdal-bin'
python-version: '3.11'
setup-node: false

- name: Generate environment variable documentation using OAf and check if it was updated
run: |
bin/generate_envvar_docs.sh
changes=$(git diff docs/installation/config.rst)
if [ ! -z "$changes" ]; then
echo $changes
echo "Please update the environment documentation by running \`bin/generate_envvar_docs.sh\`"
exit 1
fi
env:
DJANGO_SETTINGS_MODULE: objects.conf.ci

store-reusable-workflow-vars:
name: create values which can be passed through a reusable workflow
runs-on: ubuntu-latest
outputs:
image-name: ${{ steps.image-name.outputs.image-name }}

steps:
- run: echo "image-name=$IMAGE_NAME" >> $GITHUB_OUTPUT
name: 'Store the docker image name'
id: image-name

open-api-ci:
uses: maykinmedia/open-api-workflows/.github/workflows/ci.yml@v5
needs:
- store-reusable-workflow-vars
with:
main-branch: 'master'
apt-packages: 'libgdal-dev gdal-bin'
run-docs: true
django-settings-module: objects.conf.ci
python-version: '3.11'
docker-image-name: ${{ needs.store-reusable-workflow-vars.outputs.image-name }}

open-api-publish:
uses: maykinmedia/open-api-workflows/.github/workflows/publish.yml@v5
needs:
- store-reusable-workflow-vars
- open-api-ci
- tests
with:
docker-image-name: ${{ needs.store-reusable-workflow-vars.outputs.image-name }}
repository-owner: 'maykinmedia'
secrets:
docker-username: ${{ secrets.DOCKER_USERNAME }}
docker-token: ${{ secrets.DOCKER_TOKEN }}
DEBUG: False

# docs:
# runs-on: ubuntu-latest
# name: Documentation build

# steps:
# - uses: actions/checkout@v4
# - name: Set up backend environment
# uses: maykinmedia/setup-django-backend@v1.3
# with:
# apt-packages: 'libgdal-dev gdal-bin'
# python-version: '3.11'
# setup-node: false

# - name: Generate environment variable documentation using OAf and check if it was updated
# run: |
# bin/generate_envvar_docs.sh
# changes=$(git diff docs/installation/config.rst)
# if [ ! -z "$changes" ]; then
# echo $changes
# echo "Please update the environment documentation by running \`bin/generate_envvar_docs.sh\`"
# exit 1
# fi
# env:
# DJANGO_SETTINGS_MODULE: objects.conf.ci

# store-reusable-workflow-vars:
# name: create values which can be passed through a reusable workflow
# runs-on: ubuntu-latest
# outputs:
# image-name: ${{ steps.image-name.outputs.image-name }}

# steps:
# - run: echo "image-name=$IMAGE_NAME" >> $GITHUB_OUTPUT
# name: 'Store the docker image name'
# id: image-name

# open-api-ci:
# uses: maykinmedia/open-api-workflows/.github/workflows/ci.yml@v5
# needs:
# - store-reusable-workflow-vars
# with:
# main-branch: 'master'
# apt-packages: 'libgdal-dev gdal-bin'
# run-docs: true
# django-settings-module: objects.conf.ci
# python-version: '3.11'
# docker-image-name: ${{ needs.store-reusable-workflow-vars.outputs.image-name }}

# open-api-publish:
# uses: maykinmedia/open-api-workflows/.github/workflows/publish.yml@v5
# needs:
# - store-reusable-workflow-vars
# - open-api-ci
# - tests
# with:
# docker-image-name: ${{ needs.store-reusable-workflow-vars.outputs.image-name }}
# repository-owner: 'maykinmedia'
# secrets:
# docker-username: ${{ secrets.DOCKER_USERNAME }}
# docker-token: ${{ secrets.DOCKER_TOKEN }}
22 changes: 22 additions & 0 deletions performance_test/conftest.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
import pytest

from objects.core.tests.factories import ObjectRecordFactory, ObjectTypeFactory
from objects.token.tests.factories import TokenAuthFactory


@pytest.fixture
def benchmark_assertions(benchmark):
Expand All @@ -11,3 +14,22 @@ def wrapper(**kwargs):
), f"{name} {getattr(stats, name)}s exceeded {value}s"

return wrapper


@pytest.fixture(scope="session")
def setup(django_db_setup, django_db_blocker):
with django_db_blocker.unblock():
object_type = ObjectTypeFactory.create(
service__api_root="http://localhost:8001/api/v2/",
uuid="f1220670-8ab7-44f1-a318-bd0782e97662",
)

TokenAuthFactory(token="secret", is_superuser=True)

ObjectRecordFactory.create_batch(
5000,
object__object_type=object_type,
start_at="2020-01-01",
version=1,
data={"kiemjaar": "1234"},
)
6 changes: 3 additions & 3 deletions performance_test/test_objects_list.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
import pytest
import requests
from furl import furl

BASE_URL = furl("http://localhost:8000/api/v2/")
AUTH_HEADERS = {"Authorization": "Token secret"}


@pytest.mark.django_db
@pytest.mark.benchmark(max_time=60, min_rounds=5)
def test_objects_api_list(benchmark, benchmark_assertions):
def test_objects_api_list(benchmark, benchmark_assertions, client, setup):
"""
Regression test for maykinmedia/objects-api#538
"""
Expand All @@ -19,7 +19,7 @@ def test_objects_api_list(benchmark, benchmark_assertions):
}

def make_request():
return requests.get((BASE_URL / "objects").set(params), headers=AUTH_HEADERS)
return client.get((BASE_URL / "objects").set(params), headers=AUTH_HEADERS)

result = benchmark(make_request)

Expand Down
3 changes: 3 additions & 0 deletions requirements/ci.txt
Original file line number Diff line number Diff line change
Expand Up @@ -589,8 +589,11 @@ pytest==8.3.3
# via
# -r requirements/test-tools.in
# pytest-benchmark
# pytest-django
pytest-benchmark==5.1.0
# via -r requirements/test-tools.in
pytest-django==4.10.0
# via -r requirements/test-tools.in
python-dateutil==2.9.0.post0
# via
# -c requirements/base.txt
Expand Down
5 changes: 5 additions & 0 deletions requirements/dev.txt
Original file line number Diff line number Diff line change
Expand Up @@ -717,10 +717,15 @@ pytest==8.3.3
# -c requirements/ci.txt
# -r requirements/ci.txt
# pytest-benchmark
# pytest-django
pytest-benchmark==5.1.0
# via
# -c requirements/ci.txt
# -r requirements/ci.txt
pytest-django==4.10.0
# via
# -c requirements/ci.txt
# -r requirements/ci.txt
python-dateutil==2.9.0.post0
# via
# -c requirements/ci.txt
Expand Down
1 change: 1 addition & 0 deletions requirements/test-tools.in
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
codecov
pytest
pytest-benchmark
pytest-django
coverage < 5.0
django-webtest
factory-boy
Expand Down
4 changes: 4 additions & 0 deletions setup.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,7 @@ skip_glob = **/migrations/**
known_django=django
known_first_party=objects
sections=FUTURE,STDLIB,DJANGO,THIRDPARTY,FIRSTPARTY,LOCALFOLDER

[tool:pytest]
DJANGO_SETTINGS_MODULE = objects.conf.ci
pythonpath = . src
Loading