# Integrationsplan: Metabase & Teamup → DokuWiki (All-Inkl) ## 1. Zielbild Automatisierter Ablauf jeden **1. des Monats um 03:00 Uhr**: 1. Gitea Action startet ein Shell-Skript auf *Hobbybackend1*. 2. Skript erzeugt: - einen **Metabase-PDF-Export** einer Registerkarte (Dashboard/Frage), - **zwei Teamup-Kalenderübersichten** als Bilder (jeweils eine Woche, über Datum definiert). 3. Skript überträgt PDF/Bilder per SSH/SCP auf den **All-Inkl-Server** ins DokuWiki-Dateisystem. 4. Skript erzeugt oder aktualisiert eine **DokuWiki-Seite für das Monatsmeeting**, welche die neuen Dateien referenziert. --- ## Verantwortlichkeiten - Owner / Betrieb: `it@hobbyhimmel.de` (Ansprechpartner für Ausfälle, Secrets & Deploy) - Maintainer (Skripte / Runner): Hobbybackend1-Admin (Repository-Owner) - DokuWiki-Admin: Wiki-Administrator (z. B. für API-Zugriff und Namespace-Setup) Hinweis: Für dieses Hobbyprojekt genügt eine schlanke Aufgabenverteilung — Owner ist primärer Kontakt für Störungen. ## 2. Architektur & Datenfluss - **Gitea (Repository + Actions)** - Enthält: - Shell-Skript(e) - ggf. Hilfsskripte (z. B. Node/Puppeteer-Renderer) - GitHub-/Gitea-Action Workflow - **Trigger:** `schedule` → monatlich. - **Hobbybackend1 (Docker-Host)** - Stack: `metabase` - Container: `metabase-metabase-1` - Führt das Shell-Skript aus (über Gitea Action Runner). - Headless-Browser (z. B. **Puppeteer / Playwright** in Docker oder lokal installiert) rendert: - Metabase-Registerkarte export siehe https://www.metabase.com/docs/latest/api - Teamup-Ansichten export siehe https://apidocs.teamup.com/docs/api/ - **All-Inkl-Server (DokuWiki)** - Per SSH erreichbar. - Skript überträgt Dateien (`scp`/`rsync`) nach `data/media/...`. - Skript erzeugt/aktualisiert `data/pages/...` mit DokuWiki-Seite für das entsprechende Monatsmeeting. --- ## 3. Voraussetzungen ### 3.1. Infrastruktur 1. **Gitea** - Repository für das Skript (z. B. `hobbyhimmel/teammeeting-dokuwiki`). - Gitea Action Runner auf *Hobbybackend1* konfiguriert. 2. **Hobbybackend1** - Zugriff auf Metabase-Container `metabase-metabase-1`. - Node.js + Puppeteer/Playwright **oder** ein Docker-Image, das URLs per Headless-Browser in PDF/PNG rendert. - Netzwerkzugriff auf: - Metabase-URL (intern, z. B. `http://metabase-metabase-1:3000` oder über Hostname). - Teamup-URLs. 3. **All-Inkl / DokuWiki** - SSH-Zugang: User + SSH-Key (passwortlos aus Skript verwendbar). - Kenntnis der DokuWiki-Verzeichnisse (typischerweise): - Seiten: `.../data/pages/...` - Medien: `.../data/media/...` - Namespace für Meetings, z. B. `:teammeetings:folien:`. ### 3.2. Gitea-Secrets In Gitea als **Repository-Secrets** hinterlegen (Bezeichnungen Beispiel): - **Metabase** - `METABASE_URL` – Basis-URL (intern von Hobbybackend1 aus erreichbar). - `METABASE_USER` – Benutzer für Login. - `METABASE_PASSWORD` – Passwort oder API-Key (je nach Login-Strategie). - Optional: `METABASE_DASHBOARD_ID` oder `METABASE_CARD_ID`. - **Teamup** - `TEAMUP_BASE_URL` – Basis-URL zum Kalender (inkl. Calendar-Key). - Optional: `TEAMUP_API_KEY` – falls API genutzt wird. - **DokuWiki / All-Inkl** - `ALLINKL_SSH_HOST` – z. B. `sshXXX.all-inkl.com`. - `ALLINKL_SSH_USER` – SSH-User. - `ALLINKL_USER` – All-Inkl-User. - `ALLINKL_SSH_KEY` – privater SSH-Key (optional; häufig nicht nötig, wenn die DokuWiki-API verwendet wird). Wenn verwendet: als secret file oder String in Kombination mit `ssh-agent`. - `ALLINKL_BASE_PATH` – Pfad zum DokuWiki, z. B. `/www/htdocs//wiki.neu.hobbyhimmel.de/data`. - `ALLINKL_MEETING_NAMESPACE` – z. B. `teammeetings/folien` (Dateipfade ohne Doppelpunkt). - Optional (bei API-Nutzung): `DOKUWIKI_API_URL` und `DOKUWIKI_API_TOKEN` (empfohlen statt direktem Dateizugriff) - **Allgemein** - `TZ` – Zeitzone (z. B. `Europe/Berlin`), falls im Skript nötig. Hinweis zur Secret-Handhabung: - Für lokale Tests nutze eine `.env`-Datei (niemals einchecken). Beispiele stehen im Repo in einer `.env.example` (nur Platzhalter). - In Gitea die Secrets als Repository-Secrets anlegen. Verwende `DOKUWIKI_API_TOKEN` falls die API genutzt wird; `ALLINKL_SSH_KEY` wird nur beim Fallback über SSH benötigt. --- ## 4. Shell-Skript-Design ### 4.1. Hauptaufgaben des Skripts 1. **Datum & Kontext bestimmen** - Ausführungsdatum ist immer der **1. des Monats**. - Skript ermittelt: - `YEAR` – aktuelles Jahr. - `MONTH` – aktueller Monat (ggf. auch vorheriger Monat, je nach Reporting-Logik). - Generiert z. B. einen Identifier `MEETING_ID="${YEAR}-${MONTH}"`. 2. **Export Metabase** - Aufruf eines Hilfsskripts (z. B. `render_metabase.sh` oder Node-Skript): - Parameter: Dashboard-ID / Card-ID, Dateiname, ggf. Filter (z. B. Zeitraum). - Ausgabe: `metabase-report-${MEETING_ID}.???` im lokalen Arbeitsverzeichnis. 3. **Export Teamup → Kalenderbilder** - Definition der **zwei Wochen**, die exportiert werden sollen: - Es werden immer die ersten zwei Wochen des aktuellen Monats genommen. - Für jede Woche: - URL zu Teamup generieren (inkl. `startDate`, `endDate` oder ähnlichen Parametern). - Ausgabe: `teamup-week1-${MEETING_ID}.png`, `teamup-week2-${MEETING_ID}.png`. 4. **Transfer zum All-Inkl-Server** - Medienpfad bestimmen, z. B.: `MEDIA_DIR="${ALLINKL_BASE_PATH}/data/media/${TEAM_MEETING_NAMESPACE}"` - Falls nicht existent: per `ssh` Ordner anlegen. - Dateien per `scp` oder `rsync -e ssh` kopieren: - `metabase-report-${MEETING_ID}.pdf` - `teamup-week1-${MEETING_ID}.png` - `teamup-week2-${MEETING_ID}.png`. 5. **DokuWiki-Seite erzeugen/aktualisieren** - Seitenpfad bestimmen, z. B.: `PAGE_FILE="${WIKI_BASE_PATH}/data/pages/${WIKI_MEETING_NAMESPACE}/${MEETING_ID}.txt"` - Per `ssh` Remote-Here-Doc schreiben: Empfehlung: Wenn möglich die DokuWiki-API (`DOKUWIKI_API_URL` + `DOKUWIKI_API_TOKEN`) verwenden, statt direkt auf `data/pages` zu schreiben. API-Aufrufe sind robuster gegenüber Dateirechten/Ownership auf All-Inkl. Beispiel (API, einfaches PUT via curl an ein Plugin / XML-RPC-Endpoint - anpassen je nach Wiki-Setup): ```bash curl -sS -X POST "${DOKUWIKI_API_URL}" \ -H "Authorization: Bearer ${DOKUWIKI_API_TOKEN}" \ -F "id=${WIKI_MEETING_NAMESPACE}:${MEETING_ID}" \ -F "text=$(cat newpage.txt)" ``` Fallback (wenn API nicht möglich): per SSH/Here-Doc wie bisher. Achte hier auf korrekte Ownership/Encoding beim Schreiben nach `data/pages`. Platzhalter `` und `` werden im Shell-Skript vor dem Upload ersetzt. ### 4.2. Schnittstellen zum Headless-Browser - Generische Hilfsfunktionen, z. B.: ```bash render_metabase_pdf() { local url="$1" # z. B. "$METABASE_URL/dashboard/${METABASE_DASHBOARD_ID}?date=${MEETING_ID}" local outfile="$2" node scripts/render_pdf.js "$url" "$outfile" } render_url_to_png() { local url="$1" local outfile="$2" node scripts/render_png.js "$url" "$outfile" } ``` - `render_pdf.js` / `render_png.js` verwenden Puppeteer/Playwright, loggen sich ggf. bei Metabase ein und erzeugen die Dateien. --- ## 5. Gitea Action: Workflow-Definition ### 5.1. Workflow-Datei `.gitea/workflows/monthly-report.yml` ```yaml name: Monthly Metabase & Teamup Export on: schedule: - cron: '0 2 1 * *' workflow_dispatch: jobs: export-and-upload: runs-on: hobbybackend1 # Label des Act-Runners steps: - name: Checkout repository uses: actions/checkout@v4 - name: Setup Node.js uses: actions/setup-node@v4 with: node-version: '20' - name: Install dependencies run: | npm ci - name: Run export script env: METABASE_URL: ${{ secrets.METABASE_URL }} METABASE_USER: ${{ secrets.METABASE_USER }} METABASE_PASSWORD: ${{ secrets.METABASE_PASSWORD }} METABASE_DASHBOARD_ID: ${{ secrets.METABASE_DASHBOARD_ID }} TEAMUP_BASE_URL: ${{ secrets.TEAMUP_BASE_URL }} TEAMUP_API_KEY: ${{ secrets.TEAMUP_API_KEY }} WIKI_SSH_HOST: ${{ secrets.WIKI_SSH_HOST }} WIKI_SSH_USER: ${{ secrets.WIKI_SSH_USER }} WIKI_SSH_KEY: ${{ secrets.WIKI_SSH_KEY }} WIKI_BASE_PATH: ${{ secrets.WIKI_BASE_PATH }} WIKI_MEETING_NAMESPACE: ${{ secrets.WIKI_MEETING_NAMESPACE }} TZ: Europe/Berlin run: | mkdir -p ~/.ssh echo "$WIKI_SSH_KEY" > ~/.ssh/id_rsa chmod 600 ~/.ssh/id_rsa ssh-keyscan "$WIKI_SSH_HOST" >> ~/.ssh/known_hosts ./scripts/monthly_export.sh ``` > **Hinweis zur Zeit:** > - Gitea/Aktions-Cron läuft typischerweise in UTC. > - Wenn du 03:00 Uhr **Europe/Berlin** willst, musst du den `cron`-Wert ggf. anpassen (Sommer-/Winterzeit beachten). Beispiel oben `0 2 1 * *` wäre 03:00 MEZ, aber 04:00 MESZ – hier vorher genau prüfen. --- ## 6. Teamup: Wochenansichten als Bild ### 6.1. URL-Strategie - Teamup erlaubt üblicherweise Links mit Datumsparametern, z. B.: - `?view=week&date=YYYY-MM-DD` für eine Wochenansicht. - Das Skript berechnet: - `WEEK1_DATE` – ISO-Datum (Montag der ersten gewünschten Woche). - `WEEK2_DATE` – ISO-Datum (Montag der zweiten gewünschten Woche). - Für jede Woche wird eine URL gebaut: ```bash TEAMUP_URL_WEEK1="${TEAMUP_BASE_URL}?view=week&date=${WEEK1_DATE}" TEAMUP_URL_WEEK2="${TEAMUP_BASE_URL}?view=week&date=${WEEK2_DATE}" ``` ### 6.2. Rendering - Aufruf z. B.: ```bash render_url_to_png "$TEAMUP_URL_WEEK1" "teamup-week1-${MEETING_ID}.png" render_url_to_png "$TEAMUP_URL_WEEK2" "teamup-week2-${MEETING_ID}.png" ``` - Im Headless-Browser-Skript wird: 1. Seite geladen. 2. Auf ausreichende Ladezeit gewartet. 3. `page.screenshot({ path: outfile, fullPage: true })` ausgeführt. --- ## 7. Test- & Rollout-Plan 1. **Lokaler Test des Headless-Browsers** - Auf Hobbybackend1 die Node-Skripte (`render_pdf.js` / `render_png.js`) mit Test-URLs ausprobieren. - verifizieren, dass Metabase-Login und Teamup-Laden funktionieren. 2. **SSH/Dateipfade testen** - Manuell per `ssh` und `scp` eine Test-PDF und Test-PNG ins DokuWiki `data/media` übertragen. - testweise eine Seite unter `data/pages` anlegen und im Browser prüfen. 3. **Shell-Skript `monthly_export.sh` lokal laufen lassen** - Mit Test-Umgebungsvariablen (ohne Gitea) ausführen. - Prüfen, ob alle Schritte durchlaufen und Dateien in DokuWiki korrekt landen. 4. **Gitea Action mit `workflow_dispatch`** - Workflow manuell starten, Log-Ausgaben prüfen. - Validieren, dass der Action Runner auf Hobbybackend1 das Skript erfolgreich ausführt. 5. **Schedule aktiv beobachten** - Nach dem ersten echten Lauf (1. des Monats) kontrollieren: - Sind PDF/Bilder generiert? - Ist die neue DokuWiki-Seite da und korrekt verlinkt? 6. **Feinjustierung** - Falls nötig: Cron-Zeit, Dateinamen, Seitentemplate, Wochenlogik (z. B. „nächste + übernächste Woche“) anpassen. --- ## Akzeptanzkriterien - Metabase-PDF existiert unter `${MEDIA_DIR}/metabase-report-${MEETING_ID}.pdf` und Dateigröße > 50 KB. - Zwei Teamup-PNGs existieren unter `${MEDIA_DIR}` und sind in der erzeugten DokuWiki-Seite verlinkt. - DokuWiki-Seite `${WIKI_MEETING_NAMESPACE}:${MEETING_ID}` ist im Wiki sichtbar und referenziert die Medien. - Action-Log zeigt Exit-Code 0; bei Fehlern wird ein Fehler-Log-Eintrag erzeugt und an `it@hobbyhimmel.de` gemeldet (oder als Issue im Repo dokumentiert). Diese Kriterien sind bewusst minimal gehalten und reichen für den Hobbybetrieb eines Vereins aus. ## 8. Erweiterungen (optional) - Mehrere Metabase-Registerkarten / Dashboards pro Meeting. - Automatische Verlinkung aus einer Übersichtsseite (z. B. `:teammeetings:start`) auf die neuen Monatsseiten. - Fehlerreport per Mail oder in DokuWiki-Logseite, wenn Exports fehlschlagen. - Optionale Parameter, um das Skript für „ad hoc Exports“ außerhalb des Monatslaufes zu nutzen (z. B. `./monthly_export.sh 2025-03`). --- ## Umsetzung: Lokaler Testplan (Metabase, Teamup, DokuWiki) Ziel: Die drei beteiligten APIs lokal auf deinem PC (Windows, `cmd.exe`) testen und verifizieren, dass: - ein Metabase-Export erzeugt werden kann, - Teamup-Daten (oder Screenshots der Wochenansicht) erzeugt werden können, - eine DokuWiki-Seite erstellt/aktualisiert und Medien eingebunden werden können. Hinweis: Lege lokal eine `.env`-Datei an (niemals einchecken). Nutze eine `.env.example` im Repo mit Platzhaltern. Basic-Prüfwerkzeuge (lokal installieren/prüfen): - `curl` (Windows 10+ meist vorhanden), - `jq` (hilfreich für JSON-Auswertung), - `node` + `npm` (falls du Puppeteer/Playwright oder Node-Renderer nutzen willst), - optional `wkhtmltopdf`/Headless Chrome für Rendering. 1) Metabase — lokaler API-Test Zweck: Authentifizieren und einen PDF- oder JSON-Export eines Dashboards/Cards abrufen. Vorgehen: - Voraussetzungen: Metabase ist von deinem PC aus erreichbar (z. B. via VPN oder Port-Forwarding auf `http://localhost:3000`). - Env-Variablen (Beispiel in `.env`): - `METABASE_URL=http://localhost:3000` - `METABASE_USER=...` - `METABASE_PASSWORD=...` - `METABASE_CARD_ID=123` (oder `METABASE_DASHBOARD_ID`) Schritte (vereinfachtes Beispiel): 1. Auth (Session-Token) anfordern — Beispiel (ersetze Platzhalter): ```cmd curl -s -X POST "%METABASE_URL%/api/session" -H "Content-Type: application/json" -d "{\"username\": \"%METABASE_USER%\", \"password\": \"%METABASE_PASSWORD%\"}" ``` 2. Export anfragen (Beispiel: PDF-Export eines Cards/Dashboards). Je nach Metabase-Version kann der Pfad variieren. Beispiel-Form (Platzhalter): ```cmd curl -s -X POST "%METABASE_URL%/api/card/%METABASE_CARD_ID%/query/pdf" -H "Content-Type: application/json" -H "X-Metabase-Session: " --output metabase-report.pdf ``` Validierung: - Datei `metabase-report.pdf` existiert und ist > 50 KB. - Öffne die Datei lokal im PDF-Viewer und prüfe, ob Daten sichtbar sind. Troubleshooting: - Auth schlägt fehl → Credentials prüfen, ggf. IP-Restrictions. - Endpoint nicht vorhanden → Metabase-Dokumentation zur API-Version prüfen (Session-API / Export-Endpoints variieren). 2) Teamup — lokaler API-Test Zweck: Kalenderdaten per API abrufen oder Wochenansicht via Headless-Browser rendern. Vorgehen: - Env-Variablen: - `TEAMUP_CALENDAR_BASE=https://api.teamup.com` - `TEAMUP_CALENDAR_KEY=dein_calendar_key` (oder `TEAMUP_PUBLIC_URL` für Web-Rendering) - Optional: `TEAMUP_API_KEY=...` falls benötigt API-Request (Events im Zeitraum abrufen) — Beispiel: ```cmd curl -s -H "Teamup-Token: %TEAMUP_API_KEY%" "%TEAMUP_CALENDAR_BASE%/v2/calendars/%TEAMUP_CALENDAR_KEY%/events?startDate=2025-11-01&endDate=2025-11-14" | jq '.' ``` Alternativ (wenn du die Web-Ansicht als Bild willst): - Öffne die Wochen-URL (z. B. `%TEAMUP_PUBLIC_URL%?view=week&date=YYYY-MM-DD`) mit einem Headless-Renderer (Puppeteer) und erstelle `teamup-week1.png`. Validierung: - API: JSON-Antwort mit Events (Array) und HTTP 200. - Screenshot: `teamup-week1.png` ist vorhanden und lesbar. Troubleshooting: - 403/401 → API-Key oder Zugriff prüfen. - Keine Events → Zeitraum / Kalenderkey kontrollieren. 3) DokuWiki — lokaler API-Test (empfohlen: API) oder SSH-Fallback Zweck: Eine Testseite erzeugen und Medien verlinken, um Upload & Sichtbarkeit zu prüfen. Vorgehen (API-Variante, wenn `DOKUWIKI_API_URL` + `DOKUWIKI_API_TOKEN` vorhanden): - Env-Variablen: - `DOKUWIKI_API_URL=https://wiki.example.com/lib/exe/rest.php/bin/actions` (Beispiel – passe an) - `DOKUWIKI_API_TOKEN=...` - `WIKI_MEETING_NAMESPACE=teammeetings` - `MEETING_ID=2025-11` Beispiel (allgemeines curl-Pattern; Plugin/Endpoint anpassen): ```cmd set /p PAGE_TEXT=< newpage.txt curl -s -X POST "%DOKUWIKI_API_URL%" -H "Authorization: Bearer %DOKUWIKI_API_TOKEN%" -F "id=%WIKI_MEETING_NAMESPACE%:%MEETING_ID%" -F "text=%PAGE_TEXT%" ``` Wenn keine API verfügbar ist (SSH-Fallback): - Upload der Medien per `scp` oder `rsync -e ssh` in `${ALLINKL_BASE_PATH}/data/media/...` und Schreiben der Seite per SSH-Here-Doc (wie im Plan beschrieben). Validierung: - Nach API-Request: die Seite im Browser öffnen (z. B. `https://wiki.example.com/doku.php?do=show&id=%WIKI_MEETING_NAMESPACE%:%MEETING_ID%`) → HTTP 200 und sichtbarer Inhalt. - Medien sind im Wiki sichtbar und korrekt verlinkt. Troubleshooting: - API 401/403 → Token prüfen / Plugin aktivieren. - SSH-Fallback: Dateirechte und Ownership prüfen (All-Inkl kann hier beschränken). 4) `.env.example` — minimale Variablen (Beispiel zum Anlegen) ``` # Metabase METABASE_URL= METABASE_USER= METABASE_PASSWORD= METABASE_CARD_ID= # Teamup TEAMUP_CALENDAR_BASE= TEAMUP_CALENDAR_KEY= TEAMUP_API_KEY= # DokuWiki (API bevorzugt) DOKUWIKI_API_URL= DOKUWIKI_API_TOKEN= WIKI_MEETING_NAMESPACE=teammeetings # Fallback/SSH (nur falls nötig) ALLINKL_SSH_HOST= ALLINKL_SSH_USER= ALLINKL_BASE_PATH= # TZ TZ=Europe/Berlin ``` 5) Ablauf für lokale Durchführung (kurz) 1. `.env` aus `.env.example` anlegen und mit echten (lokal gültigen) Werten füllen. 2. Prüfe Tools: `curl --version`, `node --version` (falls Renderer benötigt), `jq --version`. 3. Metabase-Test ausführen (Auth → Export → Datei prüfen). 4. Teamup-Test ausführen (API → JSON prüfen oder Screenshot erzeugen). 5. DokuWiki-Test ausführen (API → Seite prüfen). Falls API nicht vorhanden, teste SSH-Fallback. 6. Wenn alle drei Tests grün sind, kannst du `monthly_export.sh` lokal im Dry-Run-Mode ausführen und anschließend per Gitea-Action in den Runner überführen. 6) Minimal gewünschte Ergebnisse (zum Abhaken) - [ ] Metabase PDF lokal erzeugt und geprüft - [ ] Teamup-Daten/API oder Screenshots erzeugt und geprüft - [ ] DokuWiki-Seite erstellt/aktualisiert und Medien referenziert Wenn du möchtest, erstelle ich als nächstes eine `.env.example`-Datei im Repo und ein sehr kleines Shell-Skript-Skeleton (`./scripts/test_apis.sh`) mit den obenstehenden curl-Beispielen (ohne Secrets). Sag kurz Bescheid, ob ich das anlegen soll.