diff --git a/.husky/pre-push b/.husky/pre-push index 0496f4df..56493c4e 100755 --- a/.husky/pre-push +++ b/.husky/pre-push @@ -1,29 +1,31 @@ #!/bin/sh +# ⚠️ SECURITY GATE – KEIN BYPASS ERLAUBT +# git push --no-verify ist verboten (ssot_agent_policy.md §2.2). +# Fehlschlagende Tests müssen behoben werden, nicht umgangen. echo "🔍 Starte Qualitäts-Checks vor dem Push..." -# 1. Schnelle Tests mit Coverage ausführen -# Hinweis: Falls Tests zu lange dauern, können Sie diese Hook mit: -# git push --no-verify -# umgehen (nicht empfohlen!) +# 1. Schnelle Tests ausführen (Quality Gate – blockierend) echo "⏳ Starte npm run test:fast..." -LOG_LEVEL=warn npx vitest run --exclude tests/server/load-suite.test.ts --exclude tests/integration/serial-flow.test.ts -if [ $? -ne 0 ]; then +if LOG_LEVEL=warn npx vitest run --exclude tests/server/load-suite.test.ts --exclude tests/integration/serial-flow.test.ts; then + echo "✅ Alle Tests bestanden" +else echo "❌ Fehler: Die schnellen Tests sind fehlgeschlagen!" - echo "💡 Tipp: Um den Hook zu überspringen, verwende: git push --no-verify" + echo " → Tests reparieren, dann erneut pushen." exit 1 fi # 2. SonarQube Integration (optional - nur wenn Token gesetzt) if [ -n "$SONAR_TOKEN" ]; then echo "📡 Starte SonarQube Scan..." - sonar-scanner -Dsonar.token=$SONAR_TOKEN -Dsonar.qualitygate.wait=false - if [ $? -ne 0 ]; then + # Wrap in if-condition to prevent sh -e from exiting on scanner failure (non-blocking) + if sonar-scanner -Dsonar.token="$SONAR_TOKEN" -Dsonar.qualitygate.wait=false; then + echo "✅ SonarQube Scan abgeschlossen" + else echo "⚠️ Warnung: SonarQube Scan fehlgeschlagen (nicht blockierend)" - # Nicht mit exit 1 abbrechen - SonarQube Fehler sollten Push nicht blockieren fi else - echo "💡 Tipp: Um SonarQube zu aktivieren, setzen Sie: export SONAR_TOKEN=\"\"" + echo "ℹ️ Kein SONAR_TOKEN gesetzt — SonarQube Scan übersprungen" fi echo "✅ Pre-Push Checks abgeschlossen. Push wird fortgesetzt..." \ No newline at end of file diff --git a/README.md b/README.md index 62f8292a..648a6ab1 100644 --- a/README.md +++ b/README.md @@ -135,17 +135,16 @@ docker run --rm -p 3000:3000 \ unosim-server:latest ``` -Or with Docker Compose: +Or with Docker Compose (backend only): ```bash docker compose up --build ``` -This will now start the UnoSim backend plus two SonarQube services: +This will start the UnoSim backend only. Sandbox execution remains dynamic and uses the Docker socket at runtime. -- `sonarqube` at `http://localhost:9000` -- `mcp-sonarqube` at `http://localhost:9001` +If you need SonarQube, run it separately in its own stack or service; the UnoSim compose file does not include SonarQube or MCP. -The full application runs inside a container with `arduino-cli` pre-installed and is available at `http://localhost:3000`. +The application runs inside a container and is available at `http://localhost:3000`. For sandboxed sketch execution, the server container must use a temp directory that is bind-mounted from the host at the same absolute path. The provided Compose file does this via `UNOSIM_SHARED_TEMP_DIR=/Users/to/Documents/TT_Web/UnoSim/temp` and `./temp:/Users/to/Documents/TT_Web/UnoSim/temp`. diff --git a/docker-compose.yml b/docker-compose.yml index 491a13ce..726b12dd 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,5 +1,6 @@ services: - + # Minimal backend-only stack. Sandbox containers are created dynamically + # by the UnoSim backend via the Docker socket and are not persistent services. unosim-backend: build: context: . diff --git a/run-tests.sh b/run-tests.sh index 84499ce2..79bb6c32 100755 --- a/run-tests.sh +++ b/run-tests.sh @@ -6,7 +6,7 @@ # Konfiguration LOG_FILE="run-tests_output.log" -TOTAL_STEPS=8 +TOTAL_STEPS=7 STEP=0 SERVER_PID="" @@ -15,10 +15,12 @@ export LOG_LEVEL=1 export NODE_ENV=test # Docker-Konfiguration (überschreibbar per Umgebungsvariable) -DOCKER_HOST="${DOCKER_HOST:-unix:///$(echo $HOME)/.docker/run/docker.sock}" -DOCKER_IMAGE="unosim:latest" +# unix:// + absolute path = 3 slashes total; $HOME already starts with / +DOCKER_HOST="${DOCKER_HOST:-unix://${HOME}/.docker/run/docker.sock}" DOCKER_SANDBOX_IMAGE="${DOCKER_SANDBOX_IMAGE:-unosim-sandbox:latest}" -export DOCKER_HOST DOCKER_SANDBOX_IMAGE +# Temp-Verzeichnis unter /Users/… damit Docker Desktop es per default mounten kann +UNOSIM_SHARED_TEMP_DIR="${UNOSIM_SHARED_TEMP_DIR:-$(pwd)/temp}" +export DOCKER_HOST DOCKER_SANDBOX_IMAGE UNOSIM_SHARED_TEMP_DIR # Farben & Icons G="\033[32m"; Y="\033[33m"; R="\033[31m"; C="\033[36m"; B="\033[1m"; D="\033[2m"; RS="\033[0m" @@ -31,10 +33,10 @@ cleanup() { if [ -n "$SERVER_PID" ]; then kill "$SERVER_PID" 2>/dev/null fi - # Docker-Container aufräumen: alle laufenden unosim-Container stoppen und entfernen + # Sandbox-Container aufräumen (ephemeral, aus unosim-sandbox:latest entstanden) if docker info > /dev/null 2>&1; then local containers - containers=$(docker ps -aq --filter "ancestor=$DOCKER_IMAGE" 2>/dev/null) + containers=$(docker ps -aq --filter "ancestor=$DOCKER_SANDBOX_IMAGE" 2>/dev/null) if [ -n "$containers" ]; then echo "$containers" | xargs docker stop --time 5 > /dev/null 2>&1 || true echo "$containers" | xargs docker rm -f > /dev/null 2>&1 || true @@ -115,10 +117,10 @@ run_task "Statische Analyse" "npm run check" run_task "Unit-Tests" "NODE_OPTIONS='--no-warnings' npm run test:fast -- --reporter=default --maxConcurrency=2" parse_test_results "Tests.*passed" -# 4+5. Docker Image Build & Docker-Tests (optional, wenn Docker verfügbar) +# 3+4. Sandbox Image Build & Docker-Tests (optional, wenn Docker verfügbar) +# HINWEIS: unosim-server:latest wird von docker compose gebaut, nicht hier. +# Nur das Sandbox-Image wird benötigt und nur wenn es noch nicht existiert. if docker info > /dev/null 2>&1; then - run_task "Docker Image Build" "docker build -t $DOCKER_IMAGE ." - # Sandbox Image nur bauen wenn es noch nicht existiert if ! docker image inspect "$DOCKER_SANDBOX_IMAGE" > /dev/null 2>&1; then run_task "Sandbox Image Build" "docker build -f Dockerfile.sandbox -t $DOCKER_SANDBOX_IMAGE ." @@ -140,7 +142,7 @@ if docker info > /dev/null 2>&1; then tests/server/services/serial-backpressure.test.ts" parse_test_results "Tests.*passed" else - echo -e " ${WARN} Docker nicht verfügbar – Docker-Tests werden übersprungen (Steps 4+5)" + echo -e " ${WARN} Docker nicht verfügbar – Docker-Tests werden übersprungen (Steps 3+4)" STEP=$((STEP+2)) fi @@ -153,7 +155,7 @@ export PORT=3000 # Server startet im Hintergrund (NODE_ENV=development für Vite-Snapshots) # FORCE_DOCKER + DOCKER_SANDBOX_IMAGE werden gesetzt, wenn Docker verfügbar ist (s. oben) if docker info > /dev/null 2>&1; then - FORCE_DOCKER=1 DOCKER_SANDBOX_IMAGE=$DOCKER_SANDBOX_IMAGE NODE_ENV=development npm run dev >> "$LOG_FILE" 2>&1 & + FORCE_DOCKER=1 DOCKER_SANDBOX_IMAGE=$DOCKER_SANDBOX_IMAGE UNOSIM_SHARED_TEMP_DIR=$UNOSIM_SHARED_TEMP_DIR NODE_ENV=development npm run dev >> "$LOG_FILE" 2>&1 & else NODE_ENV=development npm run dev >> "$LOG_FILE" 2>&1 & fi diff --git a/ssot/ssot_agent_policy.md b/ssot/ssot_agent_policy.md index 7ce7c23b..9356fc91 100644 --- a/ssot/ssot_agent_policy.md +++ b/ssot/ssot_agent_policy.md @@ -14,6 +14,7 @@ 2.2 Test-Integrität: - Kompletter lokaler Test-Lauf (unit, integration, e2e) vor jedem Push. +- **`git push --no-verify` ist VERBOTEN** – der pre-push Hook ist ein nicht umgehbares Security Gate. - Bestehende Tests sind unantastbare Spezifikationen (Immutability). - Test-Anpassungen erfordern technische Begründung und explizite User-Genehmigung. @@ -32,7 +33,7 @@ ## 4. Checkliste für jeden Agenten-Durchlauf - [ ] Working-Branch genutzt? - [ ] State/DOM-Bindung korrekt (Sichtbarkeit/Klassen)? -- [ ] Alle 826 Tests lokal ohne unautorisierte Änderungen bestanden? +- [ ] Alle Tests lokal ohne unautorisierte Änderungen bestanden? - [ ] User-Intent gewahrt? - [ ] Numerische/DOM Evidenzen dokumentiert?