Progressionsgraph verbessert #54
|
|
@ -11,14 +11,17 @@ on:
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
# Pytest im laufenden backend-Container; ACCESS_LAYER + TRAINING_PLANNING Integration gegen dieselbe PostgreSQL wie Deploy (Schema via Container-Start migriert).
|
# Pytest im laufenden backend-Container; ACCESS_LAYER + TRAINING_PLANNING Integration gegen dieselbe PostgreSQL wie Deploy (Schema via Container-Start migriert).
|
||||||
|
# Nicht bei push auf develop/main: Deploy läuft parallel → Container oft im Restart (siehe workflow_run nach Deploy).
|
||||||
pytest-backend:
|
pytest-backend:
|
||||||
if: ${{ github.event_name != 'workflow_run' || github.event.workflow_run.conclusion == 'success' }}
|
if: ${{ (github.event_name == 'workflow_run' && github.event.workflow_run.conclusion == 'success') || github.event_name == 'pull_request' }}
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- name: Backend pytest im deployten Container
|
- name: Backend pytest im deployten Container
|
||||||
run: |
|
run: |
|
||||||
|
set -e
|
||||||
EVENT_NAME="${{ github.event_name }}"
|
EVENT_NAME="${{ github.event_name }}"
|
||||||
REF_NAME="${{ github.ref_name }}"
|
REF_NAME="${{ github.ref_name }}"
|
||||||
|
BASE_REF="${{ github.base_ref }}"
|
||||||
RUN_WORKFLOW="${{ github.event.workflow_run.name }}"
|
RUN_WORKFLOW="${{ github.event.workflow_run.name }}"
|
||||||
APP_DIR="/home/lars/docker/shinkan"
|
APP_DIR="/home/lars/docker/shinkan"
|
||||||
COMPOSE_FILE="docker-compose.yml"
|
COMPOSE_FILE="docker-compose.yml"
|
||||||
|
|
@ -28,12 +31,27 @@ jobs:
|
||||||
APP_DIR="/home/lars/docker/shinkan-dev"
|
APP_DIR="/home/lars/docker/shinkan-dev"
|
||||||
COMPOSE_FILE="docker-compose.dev-env.yml"
|
COMPOSE_FILE="docker-compose.dev-env.yml"
|
||||||
fi
|
fi
|
||||||
elif [ "$REF_NAME" = "develop" ]; then
|
elif [ "$REF_NAME" = "develop" ] || [ "$BASE_REF" = "develop" ]; then
|
||||||
APP_DIR="/home/lars/docker/shinkan-dev"
|
APP_DIR="/home/lars/docker/shinkan-dev"
|
||||||
COMPOSE_FILE="docker-compose.dev-env.yml"
|
COMPOSE_FILE="docker-compose.dev-env.yml"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
cd "$APP_DIR"
|
cd "$APP_DIR"
|
||||||
|
echo "Warte auf stabilen backend-Container …"
|
||||||
|
for i in $(seq 1 60); do
|
||||||
|
if docker compose -f "$COMPOSE_FILE" exec -T backend true 2>/dev/null; then
|
||||||
|
echo "Backend bereit (Versuch $i)"
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
if [ "$i" -eq 60 ]; then
|
||||||
|
echo "Timeout: backend-Container nicht bereit"
|
||||||
|
docker compose -f "$COMPOSE_FILE" ps || true
|
||||||
|
docker compose -f "$COMPOSE_FILE" logs backend --tail 80 || true
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
sleep 5
|
||||||
|
done
|
||||||
|
|
||||||
docker compose -f "$COMPOSE_FILE" exec -T backend sh -lc "
|
docker compose -f "$COMPOSE_FILE" exec -T backend sh -lc "
|
||||||
pip install -r /app/requirements-dev.txt &&
|
pip install -r /app/requirements-dev.txt &&
|
||||||
cd /app &&
|
cd /app &&
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,7 @@ import re
|
||||||
from typing import Optional, Tuple
|
from typing import Optional, Tuple
|
||||||
|
|
||||||
from account_lifecycle import resolve_account_state
|
from account_lifecycle import resolve_account_state
|
||||||
from club_tenancy import is_platform_admin, memberships_with_roles
|
from club_tenancy import memberships_with_roles
|
||||||
|
|
||||||
# Öffentlich ohne Session
|
# Öffentlich ohne Session
|
||||||
PUBLIC_API_PREFIXES = (
|
PUBLIC_API_PREFIXES = (
|
||||||
|
|
@ -46,9 +46,21 @@ _PROFILE_MUTATION_RE = re.compile(r"^/api/profiles/(\d+)$")
|
||||||
|
|
||||||
|
|
||||||
def api_onboarding_gate_enabled() -> bool:
|
def api_onboarding_gate_enabled() -> bool:
|
||||||
|
"""Produktions-Gate aktiv (ACCOUNT_GATE_API_ENFORCE=0 zum Abschalten)."""
|
||||||
return os.getenv("ACCOUNT_GATE_API_ENFORCE", "1").strip() == "1"
|
return os.getenv("ACCOUNT_GATE_API_ENFORCE", "1").strip() == "1"
|
||||||
|
|
||||||
|
|
||||||
|
def _middleware_db_lookup_enabled() -> bool:
|
||||||
|
"""
|
||||||
|
Middleware-Session-Lookup nur mit echter DB (nicht in pytest TestClient ohne Postgres).
|
||||||
|
"""
|
||||||
|
if os.getenv("SKIP_DB_MIGRATE", "").strip().lower() in ("1", "true", "yes"):
|
||||||
|
return False
|
||||||
|
if os.getenv("PYTEST_CURRENT_TEST"):
|
||||||
|
return False
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
def normalize_api_path(path: str) -> str:
|
def normalize_api_path(path: str) -> str:
|
||||||
p = (path or "").split("?", 1)[0].strip()
|
p = (path or "").split("?", 1)[0].strip()
|
||||||
if not p.startswith("/"):
|
if not p.startswith("/"):
|
||||||
|
|
@ -133,7 +145,7 @@ def evaluate_request_gate(token: Optional[str], path: str, method: str) -> Tuple
|
||||||
Vollständige Prüfung inkl. Session-Lookup.
|
Vollständige Prüfung inkl. Session-Lookup.
|
||||||
Returns: allowed, reason, account_state (für Logging)
|
Returns: allowed, reason, account_state (für Logging)
|
||||||
"""
|
"""
|
||||||
if not api_onboarding_gate_enabled():
|
if not api_onboarding_gate_enabled() or not _middleware_db_lookup_enabled():
|
||||||
return True, None, None
|
return True, None, None
|
||||||
|
|
||||||
p = normalize_api_path(path)
|
p = normalize_api_path(path)
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user