Tests: every local run and every plugin suite migrates Postulo's 231 migrations before its first test #1144
Labels
No labels
accessibility
authentication
breaking change
bug
documentation
enhancement
interface
internationalisation
observability
performance
security
tier
1
tier
2
tier
3
tier/4
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set
Reference
Postulo/postulo#1144
Loading…
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
What exists today
src/postulo/*/migrationshold 231 migration files, 57 of them withRunPython.src/postulo/config/settings/test.py:13uses in-memory SQLite, so pytest-django's--reuse-dbhas nothing to keep and every process migrates from zero.Measured with
uv run pytest tests/test_career_preview.py -q -p no:cacheprovider -p no:xdist --durations=5(one test, Windows, other agents running): setup 55.89 s, call 2.50 s, total 58.72 s. The same with--no-migrations: setup 2.14 s, total 5.11 s. So about 54 s of a one-test run is migrations on this machine; #1033 measured 32-35 s per process on the CI host.Plugin suites:
postulo-dav,-imap,-apprise,-paperless,-helloworld,-templatesandtiagoagueda/postulo-francetravaileach have atests/settings.pythat importspostulo.config.settings.basewith in-memory SQLite (postulo-dav/tests/settings.py:16), and runuv run pytestin one process (postulo-dav/.forgejo/workflows/ci.yml:84). Each run therefore migrates all of core before its first test, which for a small plugin suite is most of the test step.#1033 item 3 (and order-of-work item 9) covers the core CI angle: per-worker migration on CI, a file-backed database copied per worker (3b), or squashing (3c). It does not mention local runs or the plugin suites, which are the new part here.
What would change
django_db_setupoverride, written once in core and published throughpostulo.plugins.testing(#229's published test helpers) so plugin repos use the same one: whenPOSTULO_TEST_DB_CACHEis set (or by default outside CI), migrate a file-backed SQLite once, store it under a cache directory named by a hash of every migration file of the installed apps, and on later runs restore it into the in-memory connection with SQLite's backup API (sqlite3.Connection.backup, standard library) instead of migrating. A change to any migration changes the hash and the next run migrates afresh.actions/cachekeyed on the hash of the core version inuv.lock, so a plugin run migrates only when its core pin moves.tests/test_migration_*.py) need the graph and keep it either way.--no-migrationsis not the fix: the 57RunPythonmigrations seed rows some tests rely on, and it would stop testing the plugin's own migrations.What it saves or protects
medium: measured locally, one one-test file takes 58.7 s of which 53.7 s is building the test database by migration and 2.1 s without; that cost is paid on every local
pytestof a single file, and once per CI run of each of the eight plugin repos that test against coreAccessibility
none
Decided by the maintainer (2026-10-31)
cached migrated test database keyed by migration hash, in core, exposed through postulo.plugins.testing; core CI unchanged until #1033 decides
Decisions
postulo.plugins.testing, so seven plugin repos gain it with their next repin (#1090) instead of seven copies.Found by the efficiency and reliability audit of 2026-10-30 (finding T1; index postulo/postulo#1108). Checked against
mainatdaee30b15(2026-10-30).