All checks were successful
Deploy Development / deploy (push) Successful in 38s
Test Suite / pytest-backend (push) Successful in 37s
Test Suite / lint-backend (push) Successful in 0s
Test Suite / build-frontend (push) Successful in 13s
Test Suite / k6 /health Baseline (push) Successful in 33s
Test Suite / playwright-tests (push) Successful in 1m8s
- Enhanced the pytest workflow in `.gitea/workflows/test.yml` to include `TRAINING_PLANNING_INTEGRATION` for improved testing against the PostgreSQL database. - Updated `pytest.ini` to clarify integration marker usage, specifying both `ACCESS_LAYER_INTEGRATION` and `TRAINING_PLANNING_INTEGRATION`. - Revised documentation in `test_training_planning_sections_integration.py` to provide clearer activation instructions for local and CI environments.
299 lines
11 KiB
YAML
299 lines
11 KiB
YAML
name: Test Suite
|
|
|
|
on:
|
|
push:
|
|
branches: [main, develop]
|
|
pull_request:
|
|
branches: [main, develop]
|
|
workflow_run:
|
|
workflows: ["Deploy Development", "Deploy Production"]
|
|
types: [completed]
|
|
|
|
jobs:
|
|
# Pytest im laufenden backend-Container; ACCESS_LAYER + TRAINING_PLANNING Integration gegen dieselbe PostgreSQL wie Deploy (Schema via Container-Start migriert).
|
|
pytest-backend:
|
|
if: ${{ github.event_name != 'workflow_run' || github.event.workflow_run.conclusion == 'success' }}
|
|
runs-on: ubuntu-latest
|
|
steps:
|
|
- name: Backend pytest im deployten Container
|
|
run: |
|
|
EVENT_NAME="${{ github.event_name }}"
|
|
REF_NAME="${{ github.ref_name }}"
|
|
RUN_WORKFLOW="${{ github.event.workflow_run.name }}"
|
|
APP_DIR="/home/lars/docker/shinkan"
|
|
COMPOSE_FILE="docker-compose.yml"
|
|
|
|
if [ "$EVENT_NAME" = "workflow_run" ]; then
|
|
if [ "$RUN_WORKFLOW" = "Deploy Development" ]; then
|
|
APP_DIR="/home/lars/docker/shinkan-dev"
|
|
COMPOSE_FILE="docker-compose.dev-env.yml"
|
|
fi
|
|
elif [ "$REF_NAME" = "develop" ]; then
|
|
APP_DIR="/home/lars/docker/shinkan-dev"
|
|
COMPOSE_FILE="docker-compose.dev-env.yml"
|
|
fi
|
|
|
|
cd "$APP_DIR"
|
|
docker compose -f "$COMPOSE_FILE" exec -T backend sh -lc "
|
|
pip install -r /app/requirements-dev.txt &&
|
|
cd /app &&
|
|
ACCESS_LAYER_STRICT=1 python scripts/check_access_layer_hints.py &&
|
|
python scripts/security_release_checks.py &&
|
|
ACCESS_LAYER_INTEGRATION=1 TRAINING_PLANNING_INTEGRATION=1 SKIP_DB_MIGRATE=1 python -m pytest tests -m 'not slow' -ra -vv --tb=short
|
|
"
|
|
|
|
lint-backend:
|
|
if: ${{ github.event_name != 'workflow_run' || github.event.workflow_run.conclusion == 'success' }}
|
|
runs-on: ubuntu-latest
|
|
steps:
|
|
- name: Check backend syntax
|
|
run: |
|
|
EVENT_NAME="${{ github.event_name }}"
|
|
REF_NAME="${{ github.ref_name }}"
|
|
RUN_WORKFLOW="${{ github.event.workflow_run.name }}"
|
|
APP_DIR="/home/lars/docker/shinkan"
|
|
|
|
if [ "$EVENT_NAME" = "workflow_run" ]; then
|
|
if [ "$RUN_WORKFLOW" = "Deploy Development" ]; then
|
|
APP_DIR="/home/lars/docker/shinkan-dev"
|
|
fi
|
|
elif [ "$REF_NAME" = "develop" ]; then
|
|
APP_DIR="/home/lars/docker/shinkan-dev"
|
|
fi
|
|
|
|
python3 -m py_compile "$APP_DIR/backend/main.py"
|
|
echo "✓ Backend syntax OK"
|
|
|
|
build-frontend:
|
|
if: ${{ github.event_name != 'workflow_run' || github.event.workflow_run.conclusion == 'success' }}
|
|
runs-on: ubuntu-latest
|
|
steps:
|
|
- name: Build frontend
|
|
run: |
|
|
EVENT_NAME="${{ github.event_name }}"
|
|
REF_NAME="${{ github.ref_name }}"
|
|
RUN_WORKFLOW="${{ github.event.workflow_run.name }}"
|
|
APP_DIR="/home/lars/docker/shinkan"
|
|
|
|
if [ "$EVENT_NAME" = "workflow_run" ]; then
|
|
if [ "$RUN_WORKFLOW" = "Deploy Development" ]; then
|
|
APP_DIR="/home/lars/docker/shinkan-dev"
|
|
fi
|
|
elif [ "$REF_NAME" = "develop" ]; then
|
|
APP_DIR="/home/lars/docker/shinkan-dev"
|
|
fi
|
|
|
|
cd "$APP_DIR/frontend"
|
|
npm install
|
|
npm run build
|
|
echo "✓ Frontend build OK"
|
|
|
|
# Phase-0 Lastsmoke: nur k6 — eigener Job (kein Node/Playwright), klare CI-Zuordnung.
|
|
k6-health-baseline:
|
|
name: k6 /health Baseline
|
|
if: ${{ github.event_name != 'workflow_run' || github.event.workflow_run.conclusion == 'success' }}
|
|
runs-on: ubuntu-latest
|
|
env:
|
|
E2E_TARGET_URL: https://dev.shinkan.jinkendo.de
|
|
steps:
|
|
- name: Checkout repository
|
|
uses: actions/checkout@v4
|
|
|
|
- name: E2E-Ziel wählen (Dev über Proxy vs. Production)
|
|
id: e2e
|
|
run: |
|
|
EVENT="${{ github.event_name }}"
|
|
WF_NAME="${{ github.event.workflow_run.name }}"
|
|
DEV_BASE="${{ env.E2E_TARGET_URL }}"
|
|
if [ "$EVENT" = "workflow_run" ] && [ "$WF_NAME" = "Deploy Production" ]; then
|
|
echo "mode=prod" >> $GITHUB_OUTPUT
|
|
echo "base_url=https://shinkan.jinkendo.de" >> $GITHUB_OUTPUT
|
|
echo "→ k6 gegen Prod-Basis."
|
|
else
|
|
echo "mode=dev" >> $GITHUB_OUTPUT
|
|
echo "base_url=${DEV_BASE}" >> $GITHUB_OUTPUT
|
|
echo "→ k6 gegen Dev (${DEV_BASE})."
|
|
fi
|
|
|
|
- name: Dev /health abwarten
|
|
if: ${{ steps.e2e.outputs.mode == 'dev' }}
|
|
run: |
|
|
BASE="${{ steps.e2e.outputs.base_url }}"
|
|
echo "Warte auf $BASE/health …"
|
|
for i in $(seq 1 90); do
|
|
if curl -sf "$BASE/health" >/dev/null 2>&1; then
|
|
echo "Health OK (Versuch $i)"
|
|
exit 0
|
|
fi
|
|
sleep 2
|
|
done
|
|
echo "Timeout: Dev /health nicht erreichbar — Deploy / DNS / Firewall prüfen."
|
|
curl -v "$BASE/health" || true
|
|
exit 1
|
|
|
|
- name: Prod /health abwarten
|
|
if: ${{ steps.e2e.outputs.mode == 'prod' }}
|
|
run: |
|
|
BASE="${{ steps.e2e.outputs.base_url }}"
|
|
echo "Warte auf $BASE/health …"
|
|
for i in $(seq 1 60); do
|
|
if curl -sf "$BASE/health" >/dev/null 2>&1; then
|
|
echo "Health OK (Versuch $i)"
|
|
exit 0
|
|
fi
|
|
sleep 5
|
|
done
|
|
echo "Timeout: Prod /health nicht erreichbar"
|
|
curl -v "$BASE/health" || true
|
|
exit 1
|
|
|
|
- name: Install k6
|
|
run: |
|
|
set -e
|
|
K6_VER="v0.55.0"
|
|
ARCH=$(uname -m)
|
|
case "$ARCH" in
|
|
x86_64) K6_ARCH=amd64 ;;
|
|
aarch64|arm64) K6_ARCH=arm64 ;;
|
|
*) echo "k6: unbekannte Architektur: $ARCH"; exit 1 ;;
|
|
esac
|
|
echo "Installing k6 ${K6_VER} linux-${K6_ARCH}"
|
|
curl -sSL "https://github.com/grafana/k6/releases/download/${K6_VER}/k6-${K6_VER}-linux-${K6_ARCH}.tar.gz" -o /tmp/k6.tgz
|
|
tar -xzf /tmp/k6.tgz -C /tmp
|
|
sudo mv "/tmp/k6-${K6_VER}-linux-${K6_ARCH}/k6" /usr/local/bin/k6
|
|
k6 version
|
|
|
|
- name: k6 Health-Baseline (parallele /health)
|
|
env:
|
|
BASE_URL: ${{ steps.e2e.outputs.base_url }}
|
|
run: |
|
|
set -e
|
|
echo "k6 gegen BASE_URL=$BASE_URL"
|
|
k6 run scripts/load/k6-health-baseline.js
|
|
echo "✓ k6 Health-Baseline passed"
|
|
|
|
playwright-tests:
|
|
if: ${{ github.event_name != 'workflow_run' || github.event.workflow_run.conclusion == 'success' }}
|
|
runs-on: ubuntu-latest
|
|
# Kein zusätzlicher docker-compose im Job: keine zweiten Container/Host-Ports.
|
|
# Dev: Tests gegen bereits deployte URL (HTTPS, Reverse-Proxy). Prod: gleicher Ablauf.
|
|
env:
|
|
# Öffentliche Dev-Basis — muss ALLOWED_ORIGINS / Nginx entsprechen; bei anderer Domain Workflow anpassen.
|
|
E2E_TARGET_URL: https://dev.shinkan.jinkendo.de
|
|
steps:
|
|
- name: Checkout repository
|
|
uses: actions/checkout@v4
|
|
|
|
- name: Setup Node.js
|
|
uses: actions/setup-node@v4
|
|
with:
|
|
node-version: '20'
|
|
|
|
- name: E2E-Ziel wählen (Dev über Proxy vs. Production)
|
|
id: e2e
|
|
run: |
|
|
EVENT="${{ github.event_name }}"
|
|
WF_NAME="${{ github.event.workflow_run.name }}"
|
|
DEV_BASE="${{ env.E2E_TARGET_URL }}"
|
|
if [ "$EVENT" = "workflow_run" ] && [ "$WF_NAME" = "Deploy Production" ]; then
|
|
echo "mode=prod" >> $GITHUB_OUTPUT
|
|
echo "base_url=https://shinkan.jinkendo.de" >> $GITHUB_OUTPUT
|
|
echo "→ Prod. Secrets: E2E_PROD_TEST_EMAIL / E2E_PROD_TEST_PASSWORD."
|
|
else
|
|
echo "mode=dev" >> $GITHUB_OUTPUT
|
|
echo "base_url=${DEV_BASE}" >> $GITHUB_OUTPUT
|
|
echo "→ Deployte Dev-Umgebung (${DEV_BASE}). Secrets: E2E_DEV_TEST_EMAIL / E2E_DEV_TEST_PASSWORD."
|
|
fi
|
|
|
|
- name: Dev /health abwarten
|
|
if: ${{ steps.e2e.outputs.mode == 'dev' }}
|
|
run: |
|
|
BASE="${{ steps.e2e.outputs.base_url }}"
|
|
echo "Warte auf $BASE/health …"
|
|
for i in $(seq 1 90); do
|
|
if curl -sf "$BASE/health" >/dev/null 2>&1; then
|
|
echo "Health OK (Versuch $i)"
|
|
exit 0
|
|
fi
|
|
sleep 2
|
|
done
|
|
echo "Timeout: Dev /health nicht erreichbar — Deploy / DNS / Firewall prüfen."
|
|
curl -v "$BASE/health" || true
|
|
exit 1
|
|
|
|
- name: Prod /health abwarten
|
|
if: ${{ steps.e2e.outputs.mode == 'prod' }}
|
|
run: |
|
|
BASE="${{ steps.e2e.outputs.base_url }}"
|
|
echo "Warte auf $BASE/health …"
|
|
for i in $(seq 1 60); do
|
|
if curl -sf "$BASE/health" >/dev/null 2>&1; then
|
|
echo "Health OK (Versuch $i)"
|
|
exit 0
|
|
fi
|
|
sleep 5
|
|
done
|
|
echo "Timeout: Prod /health nicht erreichbar"
|
|
curl -v "$BASE/health" || true
|
|
exit 1
|
|
|
|
- name: Testnutzer registrieren (Dev, nur wenn möglich)
|
|
if: ${{ steps.e2e.outputs.mode == 'dev' }}
|
|
env:
|
|
E2E_DEV_TEST_EMAIL: ${{ secrets.E2E_DEV_TEST_EMAIL }}
|
|
E2E_DEV_TEST_PASSWORD: ${{ secrets.E2E_DEV_TEST_PASSWORD }}
|
|
run: |
|
|
BASE="${{ steps.e2e.outputs.base_url }}"
|
|
if [ -z "$E2E_DEV_TEST_EMAIL" ] || [ -z "$E2E_DEV_TEST_PASSWORD" ]; then
|
|
echo "(Registrierung übersprungen — Secrets E2E_DEV_* nicht gesetzt.)"
|
|
exit 0
|
|
fi
|
|
curl -sf -X POST "$BASE/api/auth/register" \
|
|
-H "Content-Type: application/json" \
|
|
-d "{\"email\":\"${E2E_DEV_TEST_EMAIL}\",\"password\":\"${E2E_DEV_TEST_PASSWORD}\",\"name\":\"Playwright CI\"}" \
|
|
|| echo "(Register evtl. schon erfolgt oder Limits — Login-Test gilt trotzdem.)"
|
|
|
|
- name: Install Playwright
|
|
run: |
|
|
npm ci || npm install
|
|
npx playwright install --with-deps chromium
|
|
|
|
- name: Run Playwright tests
|
|
env:
|
|
E2E_DEV_TEST_EMAIL: ${{ secrets.E2E_DEV_TEST_EMAIL }}
|
|
E2E_DEV_TEST_PASSWORD: ${{ secrets.E2E_DEV_TEST_PASSWORD }}
|
|
run: |
|
|
set -e
|
|
MODE="${{ steps.e2e.outputs.mode }}"
|
|
BASE_URL="${{ steps.e2e.outputs.base_url }}"
|
|
export PLAYWRIGHT_BASE_URL="$BASE_URL"
|
|
|
|
if [ "$MODE" = "prod" ]; then
|
|
export TEST_EMAIL="${{ secrets.E2E_PROD_TEST_EMAIL }}"
|
|
export TEST_PASSWORD="${{ secrets.E2E_PROD_TEST_PASSWORD }}"
|
|
if [ -z "$TEST_EMAIL" ] || [ -z "$TEST_PASSWORD" ]; then
|
|
echo "Fehler: E2E_PROD_TEST_EMAIL und E2E_PROD_TEST_PASSWORD setzen."
|
|
exit 1
|
|
fi
|
|
else
|
|
export TEST_EMAIL="$E2E_DEV_TEST_EMAIL"
|
|
export TEST_PASSWORD="$E2E_DEV_TEST_PASSWORD"
|
|
if [ -z "$TEST_EMAIL" ] || [ -z "$TEST_PASSWORD" ]; then
|
|
echo "Fehler: E2E_DEV_TEST_EMAIL und E2E_DEV_TEST_PASSWORD setzen (Playwright soll gegen Dev einloggen)."
|
|
exit 1
|
|
fi
|
|
fi
|
|
|
|
mkdir -p screenshots
|
|
npx playwright test
|
|
echo "✓ Playwright tests passed"
|
|
|
|
- name: Upload test screenshots
|
|
if: failure()
|
|
# v4 ist auf Gitea (GHES-kompatibles Actions-Backend) oft nicht verfügbar
|
|
uses: actions/upload-artifact@v3
|
|
with:
|
|
name: playwright-screenshots
|
|
path: screenshots/
|
|
retention-days: 7
|