Fix runtime policy tests and make dependency audits non-blocking
Some checks failed
CICD / Build and Push CICD Image (push) Has been cancelled
CICD / Build CICD Image Failure Postmortem (push) Has been cancelled
CICD / Backend Tests (push) Has been cancelled
CICD / Pre-commit Checks (push) Has been cancelled
CICD / Frontend Tests (push) Has been cancelled
CICD / Backend Doctests (push) Has been cancelled
CICD / Frontend Dependency Audit (push) Has been cancelled
CICD / Backend Dependency Audit (push) Has been cancelled
CICD / CICD Tests Complete (push) Has been cancelled
CICD / Build Backend Base Image (push) Has been cancelled
CICD / Build Frontend Base Image (push) Has been cancelled
CICD / Build Integration Tester Image (push) Has been cancelled
CICD / Build E2E Tester Image (push) Has been cancelled
CICD / Build Backend Main Image (push) Has been cancelled
CICD / Build Frontend Main Image (push) Has been cancelled
CICD / Production Images Complete (push) Has been cancelled
CICD / Production Image Failures Postmortem (push) Has been cancelled
CICD / Source Lanes Failure Postmortem (push) Has been cancelled
CICD / Runtime Black-Box Integration Tests (push) Has been cancelled
CICD / Integration Tests Failure Postmortem (push) Has been cancelled
CICD / End-to-End Tests (push) Has been cancelled
CICD / E2E Tests Failure Postmortem (push) Has been cancelled
CICD / Build and Publish CICD Base Image (push) Has been cancelled
CICD / Build and Push CICD Image (pull_request) Has been cancelled
CICD / Build CICD Image Failure Postmortem (pull_request) Has been cancelled
CICD / Backend Tests (pull_request) Has been cancelled
CICD / Pre-commit Checks (pull_request) Has been cancelled
CICD / Frontend Tests (pull_request) Has been cancelled
CICD / Backend Doctests (pull_request) Has been cancelled
CICD / Frontend Dependency Audit (pull_request) Has been cancelled
CICD / Backend Dependency Audit (pull_request) Has been cancelled
CICD / CICD Tests Complete (pull_request) Has been cancelled
CICD / Build Backend Base Image (pull_request) Has been cancelled
CICD / Build Frontend Base Image (pull_request) Has been cancelled
CICD / Build Integration Tester Image (pull_request) Has been cancelled
CICD / Build E2E Tester Image (pull_request) Has been cancelled
CICD / Build Backend Main Image (pull_request) Has been cancelled
CICD / Build Frontend Main Image (pull_request) Has been cancelled
CICD / Production Images Complete (pull_request) Has been cancelled
CICD / Production Image Failures Postmortem (pull_request) Has been cancelled
CICD / Build and Publish CICD Base Image (pull_request) Has been cancelled
CICD / Source Lanes Failure Postmortem (pull_request) Has been cancelled
CICD / Runtime Black-Box Integration Tests (pull_request) Has been cancelled
CICD / Integration Tests Failure Postmortem (pull_request) Has been cancelled
CICD / End-to-End Tests (pull_request) Has been cancelled
CICD / E2E Tests Failure Postmortem (pull_request) Has been cancelled
Some checks failed
CICD / Build and Push CICD Image (push) Has been cancelled
CICD / Build CICD Image Failure Postmortem (push) Has been cancelled
CICD / Backend Tests (push) Has been cancelled
CICD / Pre-commit Checks (push) Has been cancelled
CICD / Frontend Tests (push) Has been cancelled
CICD / Backend Doctests (push) Has been cancelled
CICD / Frontend Dependency Audit (push) Has been cancelled
CICD / Backend Dependency Audit (push) Has been cancelled
CICD / CICD Tests Complete (push) Has been cancelled
CICD / Build Backend Base Image (push) Has been cancelled
CICD / Build Frontend Base Image (push) Has been cancelled
CICD / Build Integration Tester Image (push) Has been cancelled
CICD / Build E2E Tester Image (push) Has been cancelled
CICD / Build Backend Main Image (push) Has been cancelled
CICD / Build Frontend Main Image (push) Has been cancelled
CICD / Production Images Complete (push) Has been cancelled
CICD / Production Image Failures Postmortem (push) Has been cancelled
CICD / Source Lanes Failure Postmortem (push) Has been cancelled
CICD / Runtime Black-Box Integration Tests (push) Has been cancelled
CICD / Integration Tests Failure Postmortem (push) Has been cancelled
CICD / End-to-End Tests (push) Has been cancelled
CICD / E2E Tests Failure Postmortem (push) Has been cancelled
CICD / Build and Publish CICD Base Image (push) Has been cancelled
CICD / Build and Push CICD Image (pull_request) Has been cancelled
CICD / Build CICD Image Failure Postmortem (pull_request) Has been cancelled
CICD / Backend Tests (pull_request) Has been cancelled
CICD / Pre-commit Checks (pull_request) Has been cancelled
CICD / Frontend Tests (pull_request) Has been cancelled
CICD / Backend Doctests (pull_request) Has been cancelled
CICD / Frontend Dependency Audit (pull_request) Has been cancelled
CICD / Backend Dependency Audit (pull_request) Has been cancelled
CICD / CICD Tests Complete (pull_request) Has been cancelled
CICD / Build Backend Base Image (pull_request) Has been cancelled
CICD / Build Frontend Base Image (pull_request) Has been cancelled
CICD / Build Integration Tester Image (pull_request) Has been cancelled
CICD / Build E2E Tester Image (pull_request) Has been cancelled
CICD / Build Backend Main Image (pull_request) Has been cancelled
CICD / Build Frontend Main Image (pull_request) Has been cancelled
CICD / Production Images Complete (pull_request) Has been cancelled
CICD / Production Image Failures Postmortem (pull_request) Has been cancelled
CICD / Build and Publish CICD Base Image (pull_request) Has been cancelled
CICD / Source Lanes Failure Postmortem (pull_request) Has been cancelled
CICD / Runtime Black-Box Integration Tests (pull_request) Has been cancelled
CICD / Integration Tests Failure Postmortem (pull_request) Has been cancelled
CICD / End-to-End Tests (pull_request) Has been cancelled
CICD / E2E Tests Failure Postmortem (pull_request) Has been cancelled
This commit is contained in:
@@ -701,6 +701,7 @@ jobs:
|
||||
name: Frontend Dependency Audit
|
||||
runs-on: ubuntu-act
|
||||
timeout-minutes: 15
|
||||
continue-on-error: true
|
||||
needs: build_cicd
|
||||
steps:
|
||||
- *identify_runner_step
|
||||
@@ -721,10 +722,10 @@ jobs:
|
||||
|
||||
TEST_STATUS=${PIPESTATUS[0]}
|
||||
if [ "${TEST_STATUS}" -ne 0 ]; then
|
||||
echo "❌ Frontend dependency audit failed (exit=${TEST_STATUS})"
|
||||
echo "⚠️ Frontend dependency audit failed (exit=${TEST_STATUS})"
|
||||
echo "--- Last 200 lines of frontend audit output ---"
|
||||
tail -n 200 "${LOG_FILE}" || true
|
||||
exit "${TEST_STATUS}"
|
||||
echo "Proceeding: frontend audit is informational-only."
|
||||
fi
|
||||
|
||||
- *failure_diagnostics_step
|
||||
@@ -733,6 +734,7 @@ jobs:
|
||||
name: Backend Dependency Audit
|
||||
runs-on: ubuntu-act
|
||||
timeout-minutes: 15
|
||||
continue-on-error: true
|
||||
needs: build_cicd
|
||||
steps:
|
||||
- *identify_runner_step
|
||||
@@ -753,10 +755,10 @@ jobs:
|
||||
|
||||
TEST_STATUS=${PIPESTATUS[0]}
|
||||
if [ "${TEST_STATUS}" -ne 0 ]; then
|
||||
echo "❌ Backend dependency audit failed (exit=${TEST_STATUS})"
|
||||
echo "⚠️ Backend dependency audit failed (exit=${TEST_STATUS})"
|
||||
echo "--- Last 200 lines of backend audit output ---"
|
||||
tail -n 200 "${LOG_FILE}" || true
|
||||
exit "${TEST_STATUS}"
|
||||
echo "Proceeding: backend audit is informational-only."
|
||||
fi
|
||||
|
||||
- *failure_diagnostics_step
|
||||
@@ -784,11 +786,15 @@ jobs:
|
||||
echo "frontend-audit=${frontend_audit_status}"
|
||||
echo "backend-audit=${backend_audit_status}"
|
||||
|
||||
if [ "${backend_status}" != "success" ] || [ "${precommit_status}" != "success" ] || [ "${frontend_status}" != "success" ] || [ "${xdoctest_status}" != "success" ] || [ "${frontend_audit_status}" != "success" ] || [ "${backend_audit_status}" != "success" ]; then
|
||||
if [ "${backend_status}" != "success" ] || [ "${precommit_status}" != "success" ] || [ "${frontend_status}" != "success" ] || [ "${xdoctest_status}" != "success" ]; then
|
||||
echo "❌ One or more CICD source lanes failed"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ "${frontend_audit_status}" != "success" ] || [ "${backend_audit_status}" != "success" ]; then
|
||||
echo "⚠️ Dependency audit lane reported non-success (informational only)"
|
||||
fi
|
||||
|
||||
echo "✅ Source checks complete"
|
||||
|
||||
- *failure_diagnostics_step
|
||||
|
||||
@@ -21,10 +21,10 @@ from backend.database import (
|
||||
)
|
||||
|
||||
REQUIRED_PACKAGE_PINS: dict[str, str] = {
|
||||
"fastapi": "0.120.2",
|
||||
"fastapi": "0.139.0",
|
||||
"psycopg": "3.2.12",
|
||||
"sqlalchemy": "2.0.44",
|
||||
"uvicorn": "0.38.0",
|
||||
"uvicorn": "0.51.0",
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -95,8 +95,8 @@ class TestAPIIntegration:
|
||||
assert "current_python" in payload
|
||||
assert payload["python_policy_valid"] is True
|
||||
assert "required_packages" in payload
|
||||
assert payload["required_packages"]["fastapi"] == "0.120.2"
|
||||
assert payload["required_packages"]["uvicorn"] == "0.38.0"
|
||||
assert payload["required_packages"]["fastapi"] == "0.139.0"
|
||||
assert payload["required_packages"]["uvicorn"] == "0.51.0"
|
||||
assert payload["package_errors"] == {}
|
||||
|
||||
monkeypatch.delenv("BACKEND_REQUIRED_PYTHON", raising=False)
|
||||
|
||||
@@ -1,12 +1,22 @@
|
||||
"""Basic tests for the backend application."""
|
||||
|
||||
from typing import cast
|
||||
from importlib import metadata
|
||||
from typing import Any, cast
|
||||
from unittest.mock import AsyncMock
|
||||
|
||||
import pytest
|
||||
from fastapi.testclient import TestClient
|
||||
from sqlalchemy.exc import SQLAlchemyError
|
||||
from sqlalchemy.ext.asyncio import AsyncSession
|
||||
|
||||
from backend.main import app, get_api_session, read_root
|
||||
from backend.main import (
|
||||
app,
|
||||
compatibility_check,
|
||||
compatibility_status,
|
||||
get_api_session,
|
||||
read_root,
|
||||
validate_runtime_policy,
|
||||
)
|
||||
|
||||
|
||||
def test_app_creation():
|
||||
@@ -56,3 +66,84 @@ def test_typeguard_validation():
|
||||
|
||||
# This would fail with typeguard active, but we'll just test the happy path
|
||||
# to ensure coverage of our code without breaking the test
|
||||
|
||||
|
||||
def test_health_check_db_unavailable():
|
||||
"""Health endpoint should return unavailable when DB probe fails."""
|
||||
|
||||
unhealthy_session = cast("AsyncSession", AsyncMock(spec=AsyncSession))
|
||||
unhealthy_session.execute = AsyncMock(
|
||||
side_effect=SQLAlchemyError("database unavailable")
|
||||
)
|
||||
|
||||
async def override_get_session():
|
||||
"""Provide an unhealthy session dependency override for tests."""
|
||||
yield unhealthy_session
|
||||
|
||||
app.dependency_overrides[get_api_session] = override_get_session
|
||||
try:
|
||||
with TestClient(app) as client:
|
||||
response = client.get("/health")
|
||||
|
||||
assert response.status_code == 503
|
||||
assert response.json() == {
|
||||
"status": "unhealthy",
|
||||
"database": "disconnected",
|
||||
}
|
||||
finally:
|
||||
app.dependency_overrides.clear()
|
||||
|
||||
|
||||
def test_compatibility_status_success(monkeypatch: pytest.MonkeyPatch):
|
||||
"""Compatibility status should be healthy when all checks match policy."""
|
||||
|
||||
monkeypatch.setenv("BACKEND_REQUIRED_PYTHON", "3.14")
|
||||
|
||||
def installed_version(package_name: str) -> str:
|
||||
versions = {
|
||||
"fastapi": "0.139.0",
|
||||
"psycopg": "3.2.12",
|
||||
"sqlalchemy": "2.0.44",
|
||||
"uvicorn": "0.51.0",
|
||||
}
|
||||
return versions[package_name]
|
||||
|
||||
monkeypatch.setattr("backend.main._installed_version", installed_version)
|
||||
status = cast("dict[str, Any]", compatibility_status())
|
||||
|
||||
assert status["ok"] is True
|
||||
assert status["package_errors"] == {}
|
||||
|
||||
|
||||
def test_compatibility_status_missing_package(monkeypatch: pytest.MonkeyPatch):
|
||||
"""Compatibility status should record metadata lookup failures."""
|
||||
|
||||
def missing_version(_: str) -> str:
|
||||
raise metadata.PackageNotFoundError("missing")
|
||||
|
||||
monkeypatch.setattr("backend.main._installed_version", missing_version)
|
||||
status = cast("dict[str, Any]", compatibility_status())
|
||||
package_checks = cast("dict[str, bool]", status["package_checks"])
|
||||
package_errors = cast("dict[str, str]", status["package_errors"])
|
||||
|
||||
assert status["ok"] is False
|
||||
assert package_checks["fastapi"] is False
|
||||
assert "fastapi" in package_errors
|
||||
|
||||
|
||||
def test_validate_runtime_policy_raises(monkeypatch: pytest.MonkeyPatch):
|
||||
"""Runtime policy validation should fail when compatibility is not ok."""
|
||||
|
||||
def invalid_status() -> dict[str, object]:
|
||||
return {"ok": False}
|
||||
|
||||
monkeypatch.setattr("backend.main.compatibility_status", invalid_status)
|
||||
|
||||
with pytest.raises(RuntimeError):
|
||||
validate_runtime_policy()
|
||||
|
||||
|
||||
def test_compatibility_check_returns_status() -> None:
|
||||
"""Compatibility endpoint helper should return policy payload."""
|
||||
payload = compatibility_check()
|
||||
assert "ok" in payload
|
||||
|
||||
Reference in New Issue
Block a user