Viel neues

This commit is contained in:
Sven Steinert
2026-04-30 12:06:00 +02:00
parent 118809bfae
commit fce31ebcd7
1274 changed files with 181255 additions and 0 deletions

460
qa-tool/README.MD Normal file
View File

@@ -0,0 +1,460 @@
# oByte QA TestprotokollTool (Full README)
**Stand:** 2025-09-04
**Stack:** PHP 8.3 ( Apache ), JS (Vanilla), MariaDB, Docker & Compose, Portainer
Dieses Repository enthält ein vollwertiges QATool mit Login (OIDC), GitLabTemplateLoader, DocBeePosting, PDFErzeugung im Browser und persistenter Speicherung (DB + PDFAblage). Diese README basiert ausschließlich auf dem mitgelieferten Projektstand.
---
## Inhaltsverzeichnis
1. [Überblick](#überblick)
2. [Architektur & Verzeichnisstruktur](#architektur--verzeichnisstruktur)
3. [Funktionen](#funktionen)
4. [UIBedienung (Kurzüberblick)](#ui-bedienung-kurzüberblick)
5. [Datenmodell (DB)](#datenmodell-db)
6. [APIEndpunkte](#api-endpunkte)
7. [Konfiguration per Umgebungsvariablen (.env)](#konfiguration-per-umgebungsvariablen-env)
8. [Lokale Entwicklung](#lokale-entwicklung)
9. [Deployment mit Docker Compose](#deployment-mit-docker-compose)
10. [Deployment mit Portainer (Stack)](#deployment-mit-portainer-stack)
11. [GitLabVorlagen](#gitlab-vorlagen)
12. [DocBeeIntegration](#docbee-integration)
13. [PDFExport](#pdf-export)
14. [Troubleshooting](#troubleshooting)
15. [Sicherheitshinweise](#sicherheitshinweise)
16. [Lizenz / Nutzung](#lizenz--nutzung)
---
## Überblick
- **Ziel:** Manuelle QATestläufe effizient vorbereiten, durchführen und revisionssicher exportieren.
- **Workflow:** Vorlage laden → Metadaten eintragen (inkl. **OLMNummer**) → Schritte bearbeiten (Gruppen, Status, Evidenzen) → **Exportieren (DocBee, DB, PDF)**.
- **Login:** OpenID Connect (konfigurierbar), optional **bypassbar** über `AUTH_DISABLED=true` für lokale Tests.
- **Persistenz:** Reports (Metadaten & Steps) in MariaDB, PDFs serverseitig abgelegt.
- **Integrationen:** GitLab (YAMLVorlagen), DocBee (Login + NotizErzeugung via REST).
---
## Architektur & Verzeichnisstruktur
```
o-byte-qa-tool/
├─ compose/
│ ├─ Dockerfile # PHP 8.3 + Apache, Composer
│ └─ docker-compose.yml # app, mariadb, schema-loader, phpmyadmin, fix-pdf-perms
└─ htdocs/ # Webroot
├─ index.php # App-Entry, Token-Bootstrap für DocBee, UI
├─ app.js # UI-Logik, Exporte, DocBee-Push, GitLab-Loader
├─ style.css # Styles
├─ api/
│ ├─ export.php # Report+Steps in DB speichern, PDF entgegennehmen
│ ├─ echo.php # einfache Echo-Route (Debug)
│ └─ health.php # HealthCheck (DB/PDFPfad)
├─ config/config.php # ENVKonfiguration (OIDC, DocBee, DB, APP_BASE_URL, …)
├─ login.php # OIDCStart
├─ callback.php # OIDCCallback, SessionBootstrap
├─ logout.php # Session reset (OLM beibehalten)
├─ logo.png / logo_light.png
├─ favicon.ico
├─ vendor/ # Composer (z.B. jumbojett/openid-connect-php, phpseclib, …)
└─ oidc/ # phpseclib Assets (lokal eingebunden)
```
---
## Funktionen
### Vorlagen & Schritte
- **Vorlagen laden**: YAML/JSON (lokal per Datei **oder** aus **GitLab**Repo/Pfad/Ref).
- **Gruppen**: Gruppenzeilen, ein-/ausklappbar; Schritte via DragHandle verschiebbar (innerhalb und zwischen Gruppen).
- **Automatische NeuNummerierung** der Steps bei Änderungen/Verschieben.
- **Pflichtschritte** (📌) werden geprüft Export blockiert, wenn offen.
- **Gruppenstatus setzen** auf *pass/fail/skip/blocked*, inkl. **Warnung** bei Überschreiben bestehender Stati.
- **Kommentare & Evidenzen** (Freitext + URL).
### Metadaten
- **Module**, **ModulVersion**, **PBXVersion**, **Tester** (aus Session), **DocBeeTicketURL**, **OLMNummer** (`olm_nummer`).
### Exporte
- **Exportieren (DocBee, DB, PDF)** per **einem** Button:
1. DocBeeNotiz erstellen (falls Token vorhanden) → TicketURL ggf. aktualisiert.
2. **PDF** im Browser generieren (jsPDF+AutoTable).
3. **/api/export.php**: JSON (Run) + PDF (multipart) an Server → DBSpeicherung + PDFAblage.
4. Server sendet `report_id` und `pdf_path` zurück.
- **Lauf speichern / laden** als JSON (Zwischenspeichern/Weiterarbeiten).
- **Template als YAML exportieren** (inkl. `olm_nummer`, Gruppen & Steps).
> Hinweis: Dedizierte Buttons für CSV/MD/PDF wurden in dieser Version **konsolidiert** CSV/MDFunktionen existieren noch im Code, UIseitig aber nicht exponiert.
---
## UIBedienung (Kurzüberblick)
- **GitLab Vorlage**: Dropdown befüllen (`GitLab: …` Tag zeigt Status), Datei wählen → Vorlage wird geladen.
- **Metadaten**: Felder ausfüllen (**OLMNummer** nicht vergessen).
- **Steps**: `+ Step` / `+ Gruppe`, per Griff `⋮⋮` ziehen, Status setzen, Kommentare/Evidenzen pflegen.
- **Exportieren (DocBee, DB, PDF)**: Startet kompletten LaufExport. Ergebnisdialog zeigt Ticket/PDFPfad/ReportID.
---
## Datenmodell (DB)
Beim Export werden folgende Tabellen (idempotent) angelegt/aktualisiert:
**reports**
- `id` BIGINT (PK)
- `created_at` TIMESTAMP (Default `CURRENT_TIMESTAMP`)
- `module` VARCHAR(255)
- `module_version` VARCHAR(100)
- `pbx_version` VARCHAR(100)
- `olm_nummer` VARCHAR(100)
- `tester` VARCHAR(255)
- `docbee_url` TEXT
- `summary` VARCHAR(255)  → z.B. `12/15 pass, 2 fail, 1 skip`
- `pdf_path` TEXT
**steps**
- `id` BIGINT (PK)
- `report_id` BIGINT (FK → reports.id, ON DELETE CASCADE)
- `step_index` INT
- `step_id` VARCHAR(50)
- `title` TEXT
- `expected` TEXT
- `status` ENUM('pass','fail','skip','na','')
- `comment` TEXT
- `evidence` TEXT
- `group_title` VARCHAR(255)
- `group_index` INT
Der **schemaloader** Service in `docker-compose.yml` erstellt die Tabellen automatisch beim ersten Start.
---
## APIEndpunkte
- `GET /api/health.php`
- Prüft PDO / MariaDBErreichbarkeit, Schreibrechte des PDFOrdners.
- `POST /api/export.php` (multipart/form-data)
- **Felder:**
- `run` JSON mit Metadaten (`module`, `module_version`, `pbx_version`, `olm_nummer`, `tester`, `docbee_url`, `ts`, `steps`[…])
- `pdf` erzeugte PDFDatei (optional; Export läuft auch ohne PDF durch)
- **Antwort:** `{{"ok":true,"report_id":<int>,"pdf_path":"…","summary":"…"}}`
- `POST /api/echo.php`
- Debug/Echo.
---
## Konfiguration per Umgebungsvariablen (.env)
Beispiel **.env** (für Compose/Portainer):
```env
# App
APP_PORT=8009
APP_BASE_URL=http://localhost:8009
AUTH_DISABLED=false # true = Login-BYPASS (nur lokal verwenden)
# OpenID Connect (Login)
OIDC_PROVIDER=https://auth.o-byte.com/realms/o-byte.com
OIDC_CLIENT=qa-tool
OIDC_SECRET=<client-secret>
# MariaDB
DB_HOST=mariadb
DB_PORT=3306
DB_NAME=qa_tool
DB_USER=qa
DB_PASS=change_me
DB_ROOT_PASS=change_me_root
# Persistenz
PDF_STORAGE_DIR=/var/reports
# DocBee
DOCBEE_BASEURL=https://obyte.docbee.com
DOCBEE_USER=OBYTE/service
DOCBEE_PASS=<password>
DOCBEE_TIME=1440 # Minuten Token-Gültigkeit
# GitLab Templates
GITLAB_HOST=https://git.steinert.cc
GITLAB_PROJECT_ID=qa/templates # oder numerische ID
GITLAB_REF=main
GITLAB_PATH=templates
GITLAB_TOKEN= # optional (PRIVATE-TOKEN)
# Container-User (Dateirechte)
APP_UID=0
APP_GID=0
# phpMyAdmin Port (optional)
PHPMYADMIN_PORT=8010
```
> **Wichtig:** Keine Secrets in Repos commiten. Für Produktion Token/Passwörter über PortainerUI/Secrets setzen.
---
## Lokale Entwicklung
1. **ComposerAbhängigkeiten** sind bereits im Repo (`vendor/`). Falls nötig:
```bash
cd htdocs && composer install
```
2. **PHPBuiltin** (nur für schnellen Test, ohne DB/PDFAblage):
```bash
php -S 127.0.0.1:8009 -t htdocs
```
3. **LoginBypass** lokal aktivieren:
```bash
export AUTH_DISABLED=true
```
4. Browser: `http://127.0.0.1:8009`
---
## Deployment mit Docker Compose
Im Ordner `compose/` befindet sich ein funktionsfähiges Setup mit:
- **app** (Apache+PHP 8.3), bindmountet `htdocs` und nutzt `PDF_STORAGE_DIR` Volume
- **mariadb** (11.x)
- **schema-loader** (initialisiert Tabellen)
- **phpmyadmin** (optional)
- **fix-pdf-perms** (setzt 0777 auf PDFVolume)
**Starten:**
```bash
cd compose
cp ../.env .env # eigene Werte setzen
docker compose up -d
```
**Zugriff:** `http://<host>:${APP_PORT:-8009}`
**phpMyAdmin:** `http://<host>:${PHPMYADMIN_PORT:-8010}`
---
## Deployment mit Portainer (Stack)
1. **Stack → Add Stack**
2. **Environment Vars** nach obiger `.env` setzen (oder Datei hochladen).
3. **Compose** verwenden (aus `compose/docker-compose.yml`), z.B.:
```yaml
version: "3.8"
services:
app:
image: thecodingmachine/php:8.3-v4-apache
user: "${APP_UID:-0}:${APP_GID:-0}"
ports:
- "${APP_PORT:-8009}:80"
environment:
PHP_EXTENSION_PDO_MYSQL: "1"
APP_BASE_URL: ${APP_BASE_URL}
AUTH_DISABLED: ${AUTH_DISABLED}
DB_HOST: ${DB_HOST}
DB_PORT: ${DB_PORT}
DB_NAME: ${DB_NAME}
DB_USER: ${DB_USER}
DB_PASS: ${DB_PASS}
PDF_STORAGE_DIR: ${PDF_STORAGE_DIR}
OIDC_PROVIDER: ${OIDC_PROVIDER}
OIDC_CLIENT: ${OIDC_CLIENT}
OIDC_SECRET: ${OIDC_SECRET}
DOCBEE_BASEURL: ${DOCBEE_BASEURL}
DOCBEE_USER: ${DOCBEE_USER}
DOCBEE_PASS: ${DOCBEE_PASS}
DOCBEE_TIME: ${DOCBEE_TIME}
GITLAB_HOST: ${GITLAB_HOST}
GITLAB_PROJECT_ID: ${GITLAB_PROJECT_ID}
GITLAB_REF: ${GITLAB_REF}
GITLAB_PATH: ${GITLAB_PATH}
GITLAB_TOKEN: ${GITLAB_TOKEN}
volumes:
- ${APP_HTDOCS_HOST:-/opt/qa-tool/htdocs}:/var/www/html
- pdf_storage:/var/reports
depends_on:
mariadb:
condition: service_healthy
fix-pdf-perms:
condition: service_completed_successfully
restart: unless-stopped
mariadb:
image: mariadb:11
environment:
MYSQL_DATABASE: ${DB_NAME}
MYSQL_USER: ${DB_USER}
MYSQL_PASSWORD: ${DB_PASS}
MYSQL_ROOT_PASSWORD: ${DB_ROOT_PASS}
volumes:
- db_data:/var/lib/mysql
healthcheck:
test: ["CMD", "mariadb-admin", "ping", "-h", "127.0.0.1", "-p${DB_PASS}"]
interval: 10s
timeout: 5s
retries: 30
start_period: 20s
restart: unless-stopped
schema-loader:
image: mariadb:11
depends_on:
mariadb:
condition: service_healthy
environment:
DB_HOST: ${DB_HOST}
DB_PORT: ${DB_PORT}
DB_NAME: ${DB_NAME}
DB_USER: ${DB_USER}
DB_PASS: ${DB_PASS}
command: >
sh -lc "
echo 'Waiting for DB…'; sleep 3;
mysql -h $DB_HOST -P $DB_PORT -u$DB_USER -p$DB_PASS $DB_NAME <<SQL
CREATE TABLE IF NOT EXISTS reports (
id BIGINT AUTO_INCREMENT PRIMARY KEY,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
module VARCHAR(255),
module_version VARCHAR(100),
pbx_version VARCHAR(100),
olm_nummer VARCHAR(100),
tester VARCHAR(255),
docbee_url TEXT,
summary VARCHAR(255),
pdf_path TEXT
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
CREATE TABLE IF NOT EXISTS steps (
id BIGINT AUTO_INCREMENT PRIMARY KEY,
report_id BIGINT NOT NULL,
step_index INT,
step_id VARCHAR(50),
title TEXT,
expected TEXT,
status ENUM('pass','fail','skip','na','') DEFAULT '',
comment TEXT,
evidence TEXT,
group_title VARCHAR(255),
group_index INT,
CONSTRAINT fk_steps_report FOREIGN KEY (report_id) REFERENCES reports(id) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
SQL
"
restart: "no"
fix-pdf-perms:
image: busybox:1.36
volumes:
- pdf_storage:/target
command: |
sh -lc '
set +e
mkdir -p /target
chmod -R 0777 /target 2>/dev/null || true
chown -R 0:0 /target 2>/dev/null || true
exit 0
'
restart: "no"
phpmyadmin:
image: phpmyadmin:5
ports:
- "${PHPMYADMIN_PORT:-8010}:80"
environment:
PMA_HOST: mariadb
PMA_USER: ${DB_USER}
PMA_PASSWORD: ${DB_PASS}
depends_on:
mariadb:
condition: service_healthy
restart: unless-stopped
volumes:
db_data:
pdf_storage:
```
4. **Deploy Stack** → öffnen: `http://<host>:${APP_PORT}`.
---
## GitLabVorlagen
- Konfiguration via ENV (`GITLAB_HOST`, `GITLAB_PROJECT_ID`, `GITLAB_REF`, `GITLAB_PATH`, `GITLAB_TOKEN`).
- UI lädt per GitLab API die Liste der YAMLDateien aus `GITLAB_PATH` (nur `.yaml`/`.yml`).
- Parser akzeptiert **YAML** und **JSON** (Fallback).
---
## DocBeeIntegration
- Beim Laden von `index.php` wird via `DOCBEE_BASEURL/restApi/login` ein Token geholt und **clientseitig** als `window.DOCBEE_TOKEN` bereitgestellt.
- Exportablauf:
1. **postToDocBee** erstellt eine Notiz im angegebenen **Ticket** (aus `DocBee TicketURL`).
2. Bei Erfolg wird die URL im Lauf aktualisiert.
3. Danach erfolgt ServerExport (DB + optional PDF).
**Erforderliche ENV:** `DOCBEE_BASEURL`, `DOCBEE_USER`, `DOCBEE_PASS`, `DOCBEE_TIME` (Minuten).
---
## PDFExport
- Erzeugung **im Browser** via **jsPDF** + **AutoTable** (CDNFallbacks vorhanden).
- **Logo** `logo_light.png` wird proportional (max 26×12 mm) **rechtsbündig** im Kopf platziert.
- Fallback: Falls Libraries fehlen, wird ein TextPDF erzeugt.
- Server speichert PDFs in `PDF_STORAGE_DIR` (Default `/var/reports`).
---
## YAMLVorlage (Beispiel inkl. OLM)
```yaml
name: "Modul XYZ BasisTests"
module: "Modul XYZ"
module_version: "1.2.3"
pbx_version: "8.1"
olm_nummer: "OLM-12345"
steps:
- type: "group"
title: "Telefonie Basis"
- type: "step"
id: "s1"
title: "Anruf initiieren"
expected: "Ruf wird erfolgreich aufgebaut"
required: true
- type: "step"
id: "s2"
title: "Rufumleitung"
expected: "Ruf wird korrekt umgeleitet"
required: false
```
---
## Troubleshooting
- **LoginLoop / 401:** OIDCKonfiguration prüfen (`OIDC_PROVIDER`, RedirectURL `/callback.php`). Lokal ggf. `AUTH_DISABLED=true`.
- **DocBee 401/403:** `DOCBEE_USER/DOCBEE_PASS/DOCBEE_BASEURL/DOCBEE_TIME` prüfen.
- **DBFehler (PDO not loaded):** Image/Extension prüfen (`PHP_EXTENSION_PDO_MYSQL=1` gesetzt? Compose).
- **Keine Schreibrechte PDF:** Volume/`fix-pdf-perms` prüfen; `PDF_STORAGE_DIR` existiert/schreibbar? `/api/health.php` ansehen.
- **GitLabListe leer:** Pfad/Ref/Token prüfen; nur `.yaml/.yml` werden angezeigt.
- **Export blockiert:** Pflichtschritte haben keinen Status (📌).
---
## Sicherheitshinweise
- **AUTH_DISABLED** ausschließlich in Dev/Stage verwenden.
- DocBeeToken wird **clientseitig** verwendet nur in internen Netzen nutzen oder alternative ServerProxyVariante vorsehen.
- Secrets per PortainerSecrets/ENV setzen, nicht im Repo.
- DBBackups/Retention für `reports`/`steps` einplanen; PDFAblage regelmäßig bereinigen/archivieren.
---
## Lizenz / Nutzung
Interne Nutzung innerhalb oByte / Kundenprojekten. Anpassungen willkommen.