from pathlib import Path ROOT = Path(__file__).resolve().parents[2] def read(path: str) -> str: return (ROOT / path).read_text(encoding="utf-8") def test_python_ci_lock_is_hashed_linux_311_and_excludes_ai() -> None: for lock_path in ( "backend/requirements-runtime.lock", "backend/requirements-ci.lock", ): lock = read(lock_path) assert "pip-compile with Python 3.11" in lock assert "# geointel-input-sha256: " in lock assert "--generate-hashes" in lock assert "\ntorch==" not in lock assert "\nultralytics==" not in lock def test_lock_generator_uses_pinned_linux_runtime_and_verifies_policy() -> None: generator = read("scripts/generate_python_lock.sh") assert "python:3.11-bookworm@sha256:" in generator assert 'PIP_TOOLS_VERSION="7.5.3"' in generator assert "--extra gis" in generator assert "--extra dev" in generator assert "requirements-runtime.lock" in generator assert "requirements-ci.lock" in generator assert "--generate-hashes" in generator assert "verify_python_lock.py --stamp" in generator def test_ci_runs_complete_release_and_supply_chain_gates() -> None: for workflow_path, context in ( (".github/workflows/release-gates.yml", "github.sha"), (".gitea/workflows/release-gates.yml", "gitea.sha"), ): workflow = read(workflow_path) assert "backend/requirements-ci.lock" in workflow assert "scripts/verify_python_lock.py" in workflow assert "scripts/run_readiness_check.sh" in workflow assert "python -m alembic upgrade head --sql" in workflow assert "docker compose config" in workflow assert "pip-audit==2.10.1" in workflow assert "audit_python_dependencies.sh" in workflow assert "npm audit --audit-level=high" in workflow assert "GEOINTEL_INSTALL_AI=true" in workflow assert "geointel-ci:$RELEASE_SHA-ai" in workflow assert "artifacts/image-id.txt" in workflow assert 'scan_container_image.sh "$IMAGE_ID"' in workflow assert "generate_container_sbom.sh" in workflow assert "scan_container_image.sh" in workflow assert "GEOINTEL_IMAGE_ARCHIVE: artifacts/geointel-image.tar" in workflow assert "Remove temporary image archive" in workflow assert context in workflow assert ( "actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02" in read(".github/workflows/release-gates.yml") ) assert ( "actions/upload-artifact@c6a3b2bd78b3985e4b2f15397fec357f0fd808de" in read(".gitea/workflows/release-gates.yml") ) def test_gitea_production_deploy_depends_on_every_release_gate() -> None: release = read(".gitea/workflows/release-gates.yml") legacy_deploy = ROOT / ".gitea" / "workflows" / "unraid-deploy.yml" assert "pull_request:" in release assert "needs: [quality, dependency-audit, container]" in release assert "gitea.event_name == 'push'" in release assert "gitea.ref == 'refs/heads/main'" in release assert "/opt/gitea-deploy/deploy.py deploy" in release assert not legacy_deploy.exists() assert "workflow_dispatch:" in release def test_release_workflows_pin_third_party_actions_to_reviewed_commits() -> None: shared = ( "actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683", "actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065", "actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020", ) for path in (".gitea/workflows/release-gates.yml", ".github/workflows/release-gates.yml"): workflow = read(path) for action in shared: assert action in workflow assert ( "actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02" in read(".github/workflows/release-gates.yml") ) assert ( "actions/upload-artifact@c6a3b2bd78b3985e4b2f15397fec357f0fd808de" in read(".gitea/workflows/release-gates.yml") ) def test_managed_validation_targets_the_actual_backend_and_frontend_projects() -> None: workflow = read(".gitea/workflows/managed-validation.yml") assert "backend/requirements-ci.lock" in workflow assert "frontend/package-lock.json" in workflow assert "python -m pytest -W error::DeprecationWarning" in workflow assert "cd frontend && npm run test:unit" in workflow assert "python -m ruff check backend scripts tests" in workflow assert "python scripts/verify_repository_layout.py" in workflow assert "[[ -f pyproject.toml" not in workflow def test_scanner_images_are_versioned_and_digest_pinned() -> None: sbom = read("scripts/generate_container_sbom.sh") scan = read("scripts/scan_container_image.sh") assert "anchore/syft:v1.44.0@sha256:" in sbom assert "--user 0:0" in sbom assert 'docker save "$IMAGE_ID"' in sbom assert '"docker-archive:$WORKDIR/$IMAGE_ARCHIVE"' in sbom assert 'SYFT_PARALLELISM=${SYFT_PARALLELISM:-1}' in sbom assert 'GOMEMLIMIT=${SYFT_GOMEMLIMIT:-4GiB}' in sbom assert 'GOGC=${SYFT_GOGC:-25}' in sbom assert "--select-catalogers=-binary" in sbom assert '--volumes-from "$HOSTNAME"' in sbom assert 'ARCHIVE_ID_FILE="${IMAGE_ARCHIVE}.image-id"' in sbom assert "/var/run/docker.sock" not in sbom assert "aquasec/trivy:0.70.0@sha256:" in scan assert "--severity HIGH,CRITICAL" in scan assert "--ignore-unfixed" in scan assert "--timeout 20m" in scan assert "--scanners vuln" in scan assert 'docker save "$IMAGE_ID"' in scan assert '--input "$WORKDIR/$IMAGE_ARCHIVE"' in scan assert '--volumes-from "$HOSTNAME"' in scan assert '--ignorefile "$CONTAINER_IGNORE_FILE"' in scan assert "/var/run/docker.sock" not in scan assert "--skip-files /usr/local/bin/gosu" in scan assert "final filesystem replaces it with the audited setpriv shell wrapper" in scan assert "geointel-container-vulnerabilities.json" in scan def test_readiness_guards_lock_and_supply_chain_entrypoints() -> None: readiness = read("scripts/run_readiness_check.sh") assert "scripts/verify_python_lock.py" in readiness assert "scripts/verify_security_exceptions.py" in readiness for path in ( "scripts/generate_python_lock.sh", "scripts/generate_container_sbom.sh", "scripts/scan_container_image.sh", "scripts/audit_python_dependencies.sh", ): assert f"bash -n {path}" in readiness def test_python_audit_policy_has_no_active_exceptions_and_keeps_full_evidence() -> None: policy = read("security/pip-audit-exceptions.json") audit_script = read("scripts/audit_python_dependencies.sh") assert '"schema_version": 1' in policy assert '"advisories": []' in policy assert "pip-audit-full.json" in audit_script assert "pip-audit-policy.json" in audit_script assert "--ignore-vuln" in audit_script assert "verify_security_exceptions.py" in audit_script def test_release_image_uses_locked_non_ai_dependencies_and_npm_ci() -> None: dockerfile = read("deploy/unraid/Dockerfile.all-in-one") assert "RUN npm ci" in dockerfile assert "COPY backend/requirements-runtime.lock /app/" in dockerfile assert "pip install --no-cache-dir --require-hashes -r requirements-runtime.lock" in dockerfile assert "ARG GEOINTEL_ULTRALYTICS_VERSION=8.4.99" in dockerfile assert '"ultralytics==$GEOINTEL_ULTRALYTICS_VERSION"' in dockerfile assert "ARG GEOINTEL_SETUPTOOLS_VERSION=81.0.0" in dockerfile assert "ARG GEOINTEL_WHEEL_VERSION=0.47.0" in dockerfile assert "COPY deploy/unraid/gosu-setpriv /usr/local/bin/gosu" in dockerfile assert "&& pip check" in dockerfile def test_gosu_compatibility_wrapper_uses_exec_and_setpriv() -> None: wrapper = read("deploy/unraid/gosu-setpriv") readiness = read("scripts/run_readiness_check.sh") assert "exec setpriv" in wrapper assert '--reuid="$target_user"' in wrapper assert '--regid="$target_user"' in wrapper assert "--init-groups" in wrapper assert "bash -n deploy/unraid/gosu-setpriv" in readiness