87 lines
3.0 KiB
Python
87 lines
3.0 KiB
Python
"""Tests für das Upload-Paket (scripts/build_deploy_zip.py).
|
|
|
|
Prüft, dass das Paket vollständig ist, keine Geheimnisse oder Caches enthält, nur
|
|
„/“ als Pfadtrenner nutzt und nach dem Entpacken wie auf cPanel startet.
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
import importlib.util
|
|
import os
|
|
import subprocess
|
|
import sys
|
|
import zipfile
|
|
from pathlib import Path
|
|
from types import ModuleType
|
|
|
|
from app.config import PROJECT_ROOT
|
|
|
|
|
|
def _load_builder() -> ModuleType:
|
|
spec = importlib.util.spec_from_file_location(
|
|
"build_deploy_zip", PROJECT_ROOT / "scripts" / "build_deploy_zip.py"
|
|
)
|
|
assert spec is not None and spec.loader is not None
|
|
module = importlib.util.module_from_spec(spec)
|
|
spec.loader.exec_module(module)
|
|
return module
|
|
|
|
|
|
def test_zip_contains_everything_the_server_needs(tmp_path: Path) -> None:
|
|
target = tmp_path / "paket.zip"
|
|
names = _load_builder().build_zip(target)
|
|
with zipfile.ZipFile(target) as archive:
|
|
archived = set(archive.namelist())
|
|
assert archived == set(names)
|
|
for required in (
|
|
"passenger_wsgi.py",
|
|
"requirements.txt",
|
|
"app/__init__.py",
|
|
"app/templates/index.html",
|
|
"app/static/js/main.js",
|
|
"app/static/js/lib/phaser.min.js",
|
|
"app/static/assets/sprites/president.svg",
|
|
):
|
|
assert required in archived, required
|
|
|
|
|
|
def test_zip_has_no_secrets_caches_or_backslashes(tmp_path: Path) -> None:
|
|
target = tmp_path / "paket.zip"
|
|
names = _load_builder().build_zip(target)
|
|
assert all("\\" not in name for name in names)
|
|
assert not any(name == ".env" or name.startswith("instance/") for name in names)
|
|
assert not any("__pycache__" in name or name.endswith(".pyc") for name in names)
|
|
assert not any(name.startswith(("tests/", "node_modules/", ".venv/")) for name in names)
|
|
|
|
|
|
def test_unpacked_zip_starts_like_on_cpanel(tmp_path: Path) -> None:
|
|
"""Das entpackte Paket allein reicht: passenger_wsgi importiert die App und liefert Seiten."""
|
|
target = tmp_path / "paket.zip"
|
|
_load_builder().build_zip(target)
|
|
deploy_root = tmp_path / "glory_defense"
|
|
with zipfile.ZipFile(target) as archive:
|
|
archive.extractall(deploy_root)
|
|
|
|
env = {k: v for k, v in os.environ.items() if not k.startswith(("GLORY_", "SECRET_KEY"))}
|
|
env["SECRET_KEY"] = "deploy-test"
|
|
script = (
|
|
"import runpy\n"
|
|
f"app = runpy.run_path({str(deploy_root / 'passenger_wsgi.py')!r})['application']\n"
|
|
"c = app.test_client()\n"
|
|
"print(c.get('/').status_code, c.get('/static/js/lib/phaser.min.js').status_code,"
|
|
" c.get('/api/highscores').status_code)\n"
|
|
)
|
|
result = subprocess.run(
|
|
[sys.executable, "-c", script],
|
|
cwd=tmp_path,
|
|
env=env,
|
|
capture_output=True,
|
|
text=True,
|
|
timeout=60,
|
|
check=False,
|
|
)
|
|
assert result.returncode == 0, result.stderr
|
|
assert result.stdout.strip() == "200 200 200"
|
|
# Datenbank entsteht im entpackten Projekt, nicht im Arbeitsverzeichnis.
|
|
assert (deploy_root / "instance" / "glory_defense.sqlite3").exists()
|