test_backend.sh 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119
  1. #!/bin/sh
  2. cd backend
  3. { ruff check && ruff format --check; } || exit 1
  4. # Type check against the pinned environment (see CONTRIBUTING.md). The venv is
  5. # rebuilt whenever the lock changes, so it holds what CI installs (on Python
  6. # 3.11 exactly; newer Pythons add a few unpinned backports). Created here on
  7. # first use when Python 3.11 is available (through uv, or as python3.11).
  8. if [ ! -d ../.typecheck-venv ]; then
  9. if command -v uv >/dev/null 2>&1; then
  10. echo "Creating .typecheck-venv (Python 3.11, uv)"
  11. uv venv -q --seed --python 3.11 ../.typecheck-venv || exit 1
  12. elif command -v python3.11 >/dev/null 2>&1; then
  13. echo "Creating .typecheck-venv (python3.11)"
  14. python3.11 -m venv ../.typecheck-venv || exit 1
  15. fi
  16. fi
  17. if [ -d ../.typecheck-venv ]; then
  18. (
  19. cd .. || exit 1
  20. lock_hash=$( (sha256sum requirements-typecheck.lock 2>/dev/null || shasum -a 256 requirements-typecheck.lock) | cut -d' ' -f1)
  21. if [ -z "$lock_hash" ]; then
  22. echo "Type check: neither sha256sum nor shasum is available."
  23. exit 1
  24. fi
  25. if ! .typecheck-venv/bin/python -c '' 2>/dev/null; then
  26. echo "Type check: the python in .typecheck-venv no longer runs (interpreter removed or upgraded); delete .typecheck-venv and recreate it (see CONTRIBUTING.md)."
  27. exit 1
  28. fi
  29. if [ ! -x .typecheck-venv/bin/basedpyright ] || [ "$(cat .typecheck-venv/.lock-hash 2>/dev/null)" != "$lock_hash" ]; then
  30. echo "Rebuilding .typecheck-venv from requirements-typecheck.lock"
  31. # Rebuild from the interpreter the venv was created from (pyvenv.cfg
  32. # "home"), not a fully resolved path, so a stable link stays stable.
  33. py="$(sed -n 's/^home *= *//p' .typecheck-venv/pyvenv.cfg)/python3"
  34. "$py" -m venv --clear .typecheck-venv || exit 1
  35. .typecheck-venv/bin/pip install -q -r requirements-typecheck.lock || exit 1
  36. echo "$lock_hash" > .typecheck-venv/.lock-hash
  37. fi
  38. if ! out=$(.typecheck-venv/bin/pip install --dry-run -r requirements.txt 2>&1); then
  39. echo "$out"
  40. echo "pip could not resolve requirements.txt against .typecheck-venv."
  41. exit 1
  42. fi
  43. if echo "$out" | grep '^Would install'; then
  44. echo "requirements-typecheck.lock is missing packages from requirements.txt; regenerate it (see requirements-typecheck.txt)."
  45. exit 1
  46. fi
  47. .typecheck-venv/bin/basedpyright --pythonpath .typecheck-venv/bin/python
  48. ) || exit 1
  49. else
  50. echo "Skipping the type check: no .typecheck-venv and no Python 3.11 to create it (see CONTRIBUTING.md)."
  51. fi
  52. # PostgreSQL upgrade check, as CI runs it, in a throwaway container. Needs
  53. # Docker and the release tags.
  54. if ! command -v docker >/dev/null 2>&1 || ! docker info >/dev/null 2>&1; then
  55. echo "Skipping the PostgreSQL upgrade check: Docker is not available."
  56. elif [ -z "$(git tag --list v0.2.3)" ]; then
  57. echo "Skipping the PostgreSQL upgrade check: no release tags in this clone (git fetch --tags)."
  58. else
  59. (
  60. cd .. || exit 1
  61. name="bambuddy-pg-check-$$"
  62. port=$(venv/bin/python -c 'import socket; s = socket.socket(); s.bind(("127.0.0.1", 0)); print(s.getsockname()[1])') || exit 1
  63. docker run -d --rm --name "$name" --tmpfs /var/lib/postgresql/data -e POSTGRES_PASSWORD=check \
  64. -p "127.0.0.1:$port:5432" postgres:16-alpine >/dev/null || exit 1
  65. # dash runs no EXIT trap when interrupted, so remove the container on a
  66. # signal too (and then exit as interrupted).
  67. trap 'docker rm -f "$name" >/dev/null 2>&1' EXIT
  68. trap 'docker rm -f "$name" >/dev/null 2>&1; exit 130' INT TERM
  69. ready=0
  70. for _ in $(seq 60); do
  71. if docker exec "$name" pg_isready -U postgres -h 127.0.0.1 >/dev/null 2>&1; then ready=1; break; fi
  72. sleep 1
  73. done
  74. if [ "$ready" != 1 ]; then
  75. echo "PostgreSQL upgrade check: the container did not become ready."
  76. exit 1
  77. fi
  78. venv/bin/python scripts/check_postgres_upgrade.py --url "postgresql://postgres:check@127.0.0.1:$port/postgres"
  79. ) || exit 1
  80. fi
  81. if [ "$1" = "--full" ]; then
  82. ../venv/bin/python3 -m pytest tests/ -v -n 30 || exit 1
  83. else
  84. ../venv/bin/python3 -m pytest tests/ -v -n 30 --ignore=tests/unit/services/test_bambu_ftp.py || exit 1
  85. fi
  86. # The same tests on PostgreSQL, in a throwaway container (--full only: about
  87. # three minutes). Tests of SQLite-only behaviour are skipped there.
  88. if [ "$1" != "--full" ]; then
  89. echo "Skipping the tests on PostgreSQL (run with --full)."
  90. elif ! command -v docker >/dev/null 2>&1 || ! docker info >/dev/null 2>&1; then
  91. echo "Skipping the tests on PostgreSQL: Docker is not available."
  92. else
  93. (
  94. name="bambuddy-pg-tests-$$"
  95. port=$(../venv/bin/python -c 'import socket; s = socket.socket(); s.bind(("127.0.0.1", 0)); print(s.getsockname()[1])') || exit 1
  96. # One database pair per test worker, each with its own connection pool.
  97. docker run -d --rm --name "$name" --tmpfs /var/lib/postgresql/data -e POSTGRES_PASSWORD=tests \
  98. -p "127.0.0.1:$port:5432" postgres:16-alpine \
  99. -c max_connections=2000 -c fsync=off -c synchronous_commit=off -c full_page_writes=off >/dev/null || exit 1
  100. trap 'docker rm -f "$name" >/dev/null 2>&1' EXIT
  101. trap 'docker rm -f "$name" >/dev/null 2>&1; exit 130' INT TERM
  102. ready=0
  103. for _ in $(seq 60); do
  104. if docker exec "$name" pg_isready -U postgres -h 127.0.0.1 >/dev/null 2>&1; then ready=1; break; fi
  105. sleep 1
  106. done
  107. if [ "$ready" != 1 ]; then
  108. echo "Tests on PostgreSQL: the container did not become ready."
  109. exit 1
  110. fi
  111. TEST_POSTGRES_URL="postgresql+asyncpg://postgres:tests@127.0.0.1:$port/postgres" \
  112. ../venv/bin/python3 -m pytest tests/ -v -n 30
  113. ) || exit 1
  114. fi