# Entwicklung Informationen für Entwickler und Admins, die tiefer einsteigen. Die Nutzer-Doku steht in der [README](README.md). Ausführliche Hintergründe zu den Stolperfallen, also warum etwas genau so gebaut ist, stehen in [CLAUDE.md](CLAUDE.md). ## Aufbau - **Keine HTTP/OCS-Aufrufe gegen Deck.** Lesen (Boards, Stapel, Karten, Board-Mitglieder) und das Verschieben laufen ausschließlich über Decks interne PHP-Klassen im selben Prozess. Sämtlicher Deck-Zugriff ist in [`lib/Service/DeckIntegrationService.php`](lib/Service/DeckIntegrationService.php) gebündelt. - `OCA\Deck\*` ist keine stabile öffentliche API. Jeder Zugriff ist deshalb abgesichert: `class_exists()`-Checks, Prüfung ob Deck aktiviert ist, try/catch mit Logging. - Nach größeren Deck-Updates lohnt sich ein Blick ins Nextcloud-Log. - **Hintergrundjob:** [`RunWorkflowsJob`](lib/BackgroundJob/RunWorkflowsJob.php) ist ein einfacher `Job` ohne Intervall. Er läuft bei jedem Cron-Durchlauf und ruft [`WorkflowRunner`](lib/Service/WorkflowRunner.php) auf. - **Rechte-Kontext:** Der Runner arbeitet die Workflows nach Eigentümer gruppiert ab und setzt Deck jeweils auf diesen Nutzer, per `DeckIntegrationService::beginUserContext()`. Decks Berechtigungsprüfungen lesen nämlich nicht die Session, sondern eine pro Prozess festgelegte Nutzer-ID. - **E-Mail:** [`NotificationMailer`](lib/Service/NotificationMailer.php) verschickt über Nextclouds `IMailer`. Die Empfänger ermittelt `DeckIntegrationService::findNotificationRecipients()`, die Entscheidungsregel steckt in [`NotificationPolicy`](lib/Service/NotificationPolicy.php). - **Oberfläche:** [`src/PersonalSettings.vue`](src/PersonalSettings.vue) (Vue 3, `@nextcloud/vue` 9) spricht über [`src/api.js`](src/api.js) mit dem OCS-Controller [`WorkflowController`](lib/Controller/WorkflowController.php). ## Datenmodell Die Tabelle `wfda_workflows` enthält eine Zeile pro Workflow: | Spalte | Bedeutung | | --- | --- | | `board_id`, `source_stack_id`, `target_stack_id` | Deck-IDs | | `user_id` | Board-Eigentümer, in dessen Namen der Job läuft. Wird bei jedem Lauf aus Deck aktualisiert. | | `notify_mode` | `off`, `owner` oder `board` | | `enabled`, `last_run` | aktiv? / letzter Lauf | Migrationen in [`lib/Migration/`](lib/Migration/): - `Version1000…` legt die Tabelle an. - `Version1001…` entfernt die früheren Filter-Spalten. - `Version1002…` und `Version1003…` ersetzen `notify_email` durch `notify_mode`. Ein gesetztes Häkchen wird dabei zu `owner`. Migrationen laufen nur, wenn die App-Version steigt. ## Lokales Setup Voraussetzungen: PHP 8.4+, Composer, Node.js 24 mit npm. ```bash composer install npm install # nicht `npm ci`: Lockfiles werden bewusst nicht committet npm run build # Produktions-Build npm run watch # Entwicklung mit automatischem Rebuild ``` ## Tests und Linting ```bash composer run lint # php -l über lib/ und tests/ composer run cs:check # nextcloud/coding-standard (cs:fix korrigiert) composer run test:unit # PHPUnit ``` Die Unit-Tests decken nur reine Logik ab, ohne Deck-Installation: - Fälligkeitsprüfung (`WorkflowRunner::isOverdue()`) - Empfängerregel (`NotificationPolicy::shouldNotify()`) Die Deck-Anbindung lässt sich nur auf einer echten Nextcloud-Instanz mit Deck testen: ```bash # Job-ID und letzten Lauf anzeigen php occ background-job:list --class 'OCA\WorkflowDeckAutomation\BackgroundJob\RunWorkflowsJob' # Sofort ausführen, ohne auf Cron zu warten php occ background-job:execute --force-execute ``` ## Build, CI und Release `make appstore` erzeugt `build/artifacts/appstore/workflow_deck_automation.tar.gz`. Die einzige Pipeline ist [`.gitea/workflows/build-main.yml`](.gitea/workflows/build-main.yml): | Job | Zweck | | --- | --- | | `php-lint` | `php -l` mit PHP 8.4 und 8.5 | | `xml-lint` | prüft `appinfo/info.xml` gegen das Appstore-Schema | | `unit-tests` | PHPUnit | | `package` | Frontend-Build und `make appstore`. Läuft nur, wenn die Checks grün sind. | Das Paket wird als Release veröffentlicht: - Bei jedem Push auf `main` als Pre-Release **`latest-main`**, das jedes Mal neu erzeugt wird. - Bei einem `v*`-Tag als reguläres Release. - Bei Pull Requests wird nur gebaut, nicht veröffentlicht. **Versionen** folgen dem Schema `..`. Die unterstützte Nextcloud-Version steht in `appinfo/info.xml`. Ablauf für ein Release: 1. Version in `appinfo/info.xml` und `package.json` gleich anheben. 2. Auf `main` pushen und warten, bis die Pipeline grün ist. 3. `git tag -a vX.Y.Z -m "…" && git push origin vX.Y.Z`. Einzelheiten, etwa zum Verschieben eines Tags nach einem fehlgeschlagenen Build, stehen in [CLAUDE.md](CLAUDE.md). ## Fehlersuche: Der Job läuft nur nachts oder gar nicht Nextcloud überspringt „nicht zeitkritische“ Jobs außerhalb des Wartungsfensters (`maintenance_window_start` in der `config.php`). Bis einschließlich v0.1.0 war dieser Job als nicht zeitkritisch markiert. Diese Markierung bleibt in der Spalte `oc_jobs.time_sensitive` stehen, auch nach App-Updates. Symptom: Der Job läuft nur im 4-Stunden-Wartungsfenster, oder `occ background-job:list` zeigt als letzten Lauf `1970-01-01`. Einmalig korrigieren: ```sql UPDATE oc_jobs SET time_sensitive = 0 WHERE class = 'OCA\\WorkflowDeckAutomation\\BackgroundJob\\RunWorkflowsJob'; ``` Oder ohne Datenbankzugriff den Job löschen und durch Aus- und Einschalten der App neu registrieren: ```bash php occ background-job:delete php occ app:disable workflow_deck_automation php occ app:enable workflow_deck_automation ``` Die frühere `config.php`-Option `workflow_deck_automation.interval` (bis v0.1.0) wird ignoriert und kann entfernt werden.