Tie workflows to the board owner instead of their creator
Build package / php-lint (8.4) (push) Successful in 2m22s
Build package / php-lint (8.5) (push) Successful in 57s
Build package / xml-lint (push) Successful in 18s
Build package / unit-tests (push) Successful in 1m5s
Build package / package (push) Successful in 1m21s

A workflow now belongs to whoever owns its board. The settings page
lists, edits and deletes workflows by board ownership alone, using
Deck's BoardMapper::findAllByOwner(), a single owner query that never
returns shared boards and carries no frozen uid. A transferred board's
workflows therefore show up for the new owner immediately.

The background job still needs one user to run as and mail, so it
looks up the board owner before every run and stores it in user_id
when it changed. Archived boards stay listed so their workflows keep
a name, but are no longer offered or accepted as a target.
This commit is contained in:
Patrick Niebeling committed 2026-09-30 09:38:11 +02:00
1 parent ada16cb101
commit e84123654e
6 files changed
+185 -72

No files matched your search

+51
View File
@@ -55,7 +55,9 @@ class WorkflowRunner {
}
$byUser = [];
$owners = [];
foreach ($workflows as $workflow) {
$this->followBoardOwner($workflow, $owners);
$byUser[$workflow->getUserId()][] = $workflow;
}
@@ -78,6 +80,55 @@ class WorkflowRunner {
}
}
/**
* A workflow belongs to its board's owner, not to whoever created it: if
* Deck transferred the board, the workflow moves along to the new owner —
* it then runs as them, and they get its mails.
*
* Only a known owner rewrites `user_id`. A board that is gone keeps its
* last owner, so findBrokenTarget() can disable the workflow and mail
* them; a Deck error keeps it too, and the run just goes ahead as before.
*
* @param array<int, ?string> $owners per-run cache, board id => owner
*/
private function followBoardOwner(Workflow $workflow, array &$owners): void {
$boardId = $workflow->getBoardId();
if (!array_key_exists($boardId, $owners)) {
try {
$owners[$boardId] = $this->deckService->findBoardOwner($boardId);
} catch (Throwable $e) {
$this->logger->warning('Could not determine the owner of board {board}: ' . $e->getMessage(), [
'app' => 'workflow_deck_automation',
'board' => $boardId,
]);
$owners[$boardId] = null;
}
}
$owner = $owners[$boardId];
if ($owner === null || $owner === $workflow->getUserId()) {
return;
}
$this->logger->info('Workflow {id} follows board {board} to its new owner {owner}.', [
'app' => 'workflow_deck_automation',
'id' => $workflow->getId(),
'board' => $boardId,
'owner' => $owner,
]);
$workflow->setUserId($owner);
try {
$this->workflowMapper->update($workflow);
} catch (Throwable $e) {
// Not persisted, but this run still goes to the right user; the
// next one tries again.
$this->logger->warning('Could not store the new owner of workflow {id}: ' . $e->getMessage(), [
'app' => 'workflow_deck_automation',
'id' => $workflow->getId(),
]);
}
}
/**
* @param Workflow[] $workflows
*/