Files
xiaoxia-saas/tests/unit/test_release_scripts.py
T
Xiaoxia AI 631328ea7c
CI/CD Pipeline / Validate Code Quality And Tests (push) Has been cancelled
Deploy / Deploy Staging (push) Has been cancelled
Deploy / Deploy Production (push) Has been cancelled
fix(deploy): require prebuilt web artifact for production
2026-06-22 09:34:27 +08:00

119 lines
5.0 KiB
Python

from pathlib import Path
def test_restore_postgres_plan_is_non_destructive():
script = Path("scripts/restore_postgres_plan.sh").read_text(encoding="utf-8")
executable_prefix = script.split("cat <<EOF", 1)[0]
assert "pg_restore" in script
assert "This script intentionally does not execute restore automatically." in script
assert "pg_restore" not in executable_prefix
def test_gitea_production_deploy_uses_production_ports():
workflow = Path(".gitea/workflows/deploy.yml").read_text(encoding="utf-8")
production_section = workflow.split("deploy-production:", 1)[1]
assert "WEB_PORT=3001" not in production_section
assert "http://127.0.0.1:8001/health" in production_section
assert "http://127.0.0.1:8000/health" not in production_section
def test_deploy_production_uses_production_infra_and_project():
script = Path("infra/docker/deploy-production.sh").read_text(encoding="utf-8")
assert 'HOST_PREFIX="${HOST_PREFIX-/host}"' in script
assert "apps/web/dist/index.html" in script
assert "Production deploy must not build frontend assets on the server" in script
assert "WEB_DOCKERFILE=infra/docker/web-artifact.Dockerfile" in script
assert "xiaoxia-postgres-production" in script
assert "xiaoxia-redis-production" in script
assert "xiaoxia-postgres\n" not in script
assert "xiaoxia-redis\n" not in script
assert "COMPOSE_PROJECT_NAME=xiaoxia-production-app" in script
assert "--env-file \"$ENV_FILE\"" in script
assert "python /app/scripts/validate_release_env.py --from-environ --strict-external" in script
assert "alembic upgrade head" in script
def test_production_infra_uses_separate_containers_and_ports():
compose = Path("infra/docker/infra-production.yml").read_text(encoding="utf-8")
assert "name: xiaoxia-production" in compose
assert "container_name: xiaoxia-postgres-production" in compose
assert "container_name: xiaoxia-redis-production" in compose
assert "${POSTGRES_PORT:-5433}:5432" in compose
assert "${REDIS_PORT:-6380}:6379" in compose
assert "postgres_data:" not in compose
assert "redis_data:" not in compose
def test_init_production_env_is_non_deploying_and_separated():
script = Path("scripts/init_production_env.sh").read_text(encoding="utf-8")
assert "APP_ENV=production" in script
assert "ENVIRONMENT=production" in script
assert "xiaoxia-postgres-production" in script
assert "xiaoxia-redis-production" in script
assert "GENERATED_FILES_HOST_DIR=$GENERATED_DIR" in script
assert "ENABLE_EMAIL_DELIVERY=false" in script
assert "docker compose" not in script
assert "docker run" not in script
def test_staging_deploy_supports_host_prefix_and_web_build():
script = Path("infra/docker/deploy-staging.sh").read_text(encoding="utf-8")
assert 'HOST_PREFIX="${HOST_PREFIX-/host}"' in script
assert 'ROOT_DIR="$HOST_PREFIX/var/lib/xiaoxia-saas-staging/repo"' in script
assert 'ENV_FILE="$HOST_PREFIX/var/lib/xiaoxia-saas-staging/.env"' in script
assert '"$HOST_PREFIX/var/lib/xiaoxia-saas-staging/generated"' in script
assert "docker compose build --pull=false web" in script
def test_deploy_scripts_build_web_image_explicitly():
staging_script = Path("infra/docker/deploy-staging.sh").read_text(encoding="utf-8")
production_script = Path("infra/docker/deploy-production.sh").read_text(encoding="utf-8")
compose = Path("infra/docker/compose.yml").read_text(encoding="utf-8")
assert "docker compose build --pull=false web" in staging_script
assert "docker compose --env-file \"$ENV_FILE\" build --pull=false web" in production_script
assert "dockerfile: ${WEB_DOCKERFILE:-infra/docker/web.Dockerfile}" in compose
def test_web_artifact_dockerfile_does_not_build_frontend_on_server():
dockerfile = Path("infra/docker/web-artifact.Dockerfile").read_text(encoding="utf-8")
assert "COPY apps/web/dist ./" in dockerfile
assert "npm" not in dockerfile
assert "node" not in dockerfile.lower()
def test_release_artifact_script_builds_web_before_packaging():
script = Path("scripts/package_release_artifact.sh").read_text(encoding="utf-8")
assert "npm ci" in script
assert "npm run build" in script
assert "--exclude=apps/web/node_modules" in script
def test_web_dockerfile_uses_reachable_base_image_mirror():
dockerfile = Path("infra/docker/web.Dockerfile").read_text(encoding="utf-8")
assert "FROM docker.m.daocloud.io/library/node:20 AS builder" in dockerfile
assert "npm ci" in dockerfile
assert "COPY apps/web/package.json apps/web/package-lock.json" in dockerfile
assert "FROM docker.m.daocloud.io/library/nginx:alpine AS runner" in dockerfile
assert "FROM node:20" not in dockerfile
assert "FROM nginx:alpine" not in dockerfile
def test_backup_postgres_writes_manifest_and_version():
script = Path("scripts/backup_postgres.sh").read_text(encoding="utf-8")
assert "pg_dump" in script
assert "alembic_version.txt" in script
assert "manifest.txt" in script
assert "test -s" not in script
assert 'if [ ! -s "$DUMP_PATH" ]' in script