diff --git a/.gitea/workflows/ci.yaml b/.gitea/workflows/ci.yaml new file mode 100644 index 0000000..6241a27 --- /dev/null +++ b/.gitea/workflows/ci.yaml @@ -0,0 +1,148 @@ +# Gitea Actions CI Pipeline +# BreakPilot Lehrer +# +# Services: +# Go: school-service +# Python: klausur-service, backend-lehrer, agent-core +# Node.js: website, admin-lehrer, studio-v2 + +name: CI + +on: + push: + branches: [main, develop] + pull_request: + branches: [main, develop] + +jobs: + # ======================================== + # Lint (nur bei PRs) + # ======================================== + + go-lint: + runs-on: ubuntu-latest + if: github.event_name == 'pull_request' + container: golangci/golangci-lint:v1.55-alpine + steps: + - uses: actions/checkout@v4 + - name: Lint school-service + run: | + if [ -d "school-service" ]; then + cd school-service && golangci-lint run --timeout 5m ./... + fi + + python-lint: + runs-on: ubuntu-latest + if: github.event_name == 'pull_request' + container: python:3.12-slim + steps: + - uses: actions/checkout@v4 + - name: Lint Python services + run: | + pip install --quiet ruff + for svc in backend-lehrer agent-core; do + if [ -d "$svc" ]; then + echo "=== Linting $svc ===" + ruff check "$svc/" --output-format=github || true + fi + done + if [ -d "klausur-service/backend" ]; then + echo "=== Linting klausur-service ===" + ruff check klausur-service/backend/ --output-format=github || true + fi + + nodejs-lint: + runs-on: ubuntu-latest + if: github.event_name == 'pull_request' + container: node:20-alpine + steps: + - uses: actions/checkout@v4 + - name: Lint Node.js services + run: | + for svc in website admin-lehrer studio-v2; do + if [ -d "$svc" ]; then + echo "=== Linting $svc ===" + cd "$svc" + npm ci --silent 2>/dev/null || npm install --silent + npx next lint || true + cd .. + fi + done + + # ======================================== + # Unit Tests + # ======================================== + + test-go-school: + runs-on: ubuntu-latest + container: golang:1.23-alpine + env: + CGO_ENABLED: "0" + steps: + - uses: actions/checkout@v4 + - name: Test school-service + run: | + apk add --no-cache jq bash + if [ ! -d "school-service" ]; then + echo "WARNUNG: school-service nicht gefunden" + exit 0 + fi + cd school-service + go test -v -coverprofile=coverage.out ./... 2>&1 + COVERAGE=$(go tool cover -func=coverage.out 2>/dev/null | tail -1 | awk '{print $3}' || echo "0%") + echo "Coverage: $COVERAGE" + + test-python-klausur: + runs-on: ubuntu-latest + container: python:3.12-slim + env: + CI: "true" + steps: + - uses: actions/checkout@v4 + - name: Test klausur-service + run: | + if [ ! -d "klausur-service/backend" ]; then + echo "WARNUNG: klausur-service/backend nicht gefunden" + exit 0 + fi + cd klausur-service/backend + export PYTHONPATH="$(pwd):${PYTHONPATH:-}" + pip install --quiet --no-cache-dir -r requirements.txt 2>/dev/null || true + pip install --quiet --no-cache-dir fastapi uvicorn pytest pytest-asyncio + python -m pytest tests/ -v --tb=short + + test-python-agent-core: + runs-on: ubuntu-latest + container: python:3.12-slim + env: + CI: "true" + steps: + - uses: actions/checkout@v4 + - name: Test agent-core + run: | + if [ ! -d "agent-core" ]; then + echo "WARNUNG: agent-core nicht gefunden" + exit 0 + fi + # Symlink fuer Python import (Verzeichnis agent-core -> agent_core) + ln -sf agent-core agent_core + export PYTHONPATH="$(pwd):${PYTHONPATH:-}" + cd agent-core + pip install --quiet --no-cache-dir -r requirements.txt 2>/dev/null || true + pip install --quiet --no-cache-dir pytest pytest-asyncio + python -m pytest tests/ -v --tb=short + + test-nodejs-website: + runs-on: ubuntu-latest + container: node:20-alpine + steps: + - uses: actions/checkout@v4 + - name: Test website + run: | + if [ ! -d "website" ]; then + echo "WARNUNG: website nicht gefunden" + exit 0 + fi + cd website + npm ci --silent 2>/dev/null || npm install --silent + npx jest --passWithNoTests || true