Files
nextcloud-workflow-deck-aut…/DEVELOPMENT.md
T
Patrick Niebeling 7612344726
Build package / xml-lint (push) Successful in 33s
Build package / php-lint (8.5) (push) Successful in 1m48s
Build package / php-lint (8.4) (push) Successful in 1m50s
Build package / unit-tests (push) Successful in 1m52s
Build package / package (push) Successful in 1m38s
Send moved-card notices as Nextcloud notifications too
Each workflow now has a notify channel (mail, notification or both) next
to its recipient mode. Notifications go out per card through
OCP\Notification\IManager, so they show up in the bell and as push on the
mobile and desktop clients. Without the notifications app nothing is sent.
The one-off "workflow disabled" notice is sent as a notification as well.

Existing workflows keep mail (migration Version1004). Bumps to 35.3.0 so
the migration runs.
2026-09-30 12:31:01 +02:00

6.3 KiB

Entwicklung

Informationen für Entwickler und Admins, die tiefer einsteigen. Die Nutzer-Doku steht in der README. Ausführliche Hintergründe zu den Stolperfallen, also warum etwas genau so gebaut ist, stehen in 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 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 ist ein einfacher Job ohne Intervall. Er läuft bei jedem Cron-Durchlauf und ruft WorkflowRunner 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 verschickt über Nextclouds IMailer. Die Empfänger ermittelt DeckIntegrationService::findNotificationRecipients(), die Entscheidungsregel steckt in NotificationPolicy.
  • Nextcloud-Benachrichtigungen: NotificationPusher legt sie über OCP\Notification\IManager an, eine pro Karte, an dieselben Empfänger wie die Mail. Er speichert nur Rohwerte. Den deutschen Text baut Notifier, registriert in Application::register(). Ist die App notifications für einen Empfänger nicht aktiv, wird nichts angelegt. Push aufs Handy übernimmt die Notifications-App selbst.
  • Oberfläche: src/PersonalSettings.vue (Vue 3, @nextcloud/vue 9) spricht über src/api.js mit dem OCS-Controller WorkflowController.

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 (wer)
notify_channel mail, notification oder both (wie)
enabled, last_run aktiv? / letzter Lauf

Migrationen in 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.
  • Version1004… fügt notify_channel hinzu. Bestehende Workflows bekommen mail.

Migrationen laufen nur, wenn die App-Version steigt.

Lokales Setup

Voraussetzungen: PHP 8.4+, Composer, Node.js 24 mit npm.

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

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())
  • Benachrichtigungsweg (NotificationPolicy::sendsMail()/sendsNotification())

Die Deck-Anbindung lässt sich nur auf einer echten Nextcloud-Instanz mit Deck testen:

# 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 <id> --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:

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 <Nextcloud-Major>.<minor>.<patch>. 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.

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:

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:

php occ background-job:delete <id>
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.