feat(tasks): Aufgabe als Git-Issue anlegen, Zustand wandert mit
Die Zuordnung stand im Schema laengst – sourceIssue, sourceUrl und sourceRepositoryId samt Eindeutigkeit je Repository, gefuellt von der Uebernahme aus Issues seit v0.9.0. Es fehlte die Gegenrichtung. Ein Knopf im Aufgabendialog legt das Issue an; Nummer und Adresse landen in denselben Feldern, der Dublettenschutz gilt also fuer beide Wege. In den Rumpf kommt ein Rueckverweis auf das Projekt. Ausdruecklich per Knopf und nie nebenbei: was in ein fremdes System geschrieben wird, soll jemand gewollt haben. Ist die Aufgabe erst verknuepft, wandert der Zustand allerdings mit – erledigt schliesst das Issue, ein Zurueckziehen oeffnet es wieder. Fehlertolerant: ein nicht erreichbares Git-System darf das Abhaken nicht verhindern. Die Zustaende passen nicht aufeinander, und das bleibt so. Nebula kennt vier, ein Issue zwei; nach aussen geht nur die Grenze um ERLEDIGT. Ein Rundlauf verliert damit IN ARBEIT und BLOCKIERT. Labels waeren die Alternative, wuerden aber den Issue-Tracker mit Zustaenden fuellen, die dort niemand pflegt. Kein Widerspruch zu "keine eigenen Git-Operationen": Issues laufen ueber die HTTP-API der Provider. Dafuer gibt es jetzt sendJson neben getJson – durch dieselbe SSRF-Schleuse, aber ohne Umleitungen zu folgen. Ein 307 auf eine interne Adresse naehme den Rumpf und den Token im Header mit. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -10,6 +10,7 @@ import {
|
||||
refreshDerivedProgress,
|
||||
spawnRecurrence,
|
||||
} from "@/lib/tasks";
|
||||
import { issueShouldBeOpen, mirrorStatusToIssue } from "@/lib/tasks/issues";
|
||||
import { formatZodError, taskUpdateSchema } from "@/lib/validation";
|
||||
|
||||
export const dynamic = "force-dynamic";
|
||||
@@ -74,6 +75,23 @@ export async function PATCH(request: Request, { params }: Params) {
|
||||
|
||||
await refreshDerivedProgress(existing.projectId);
|
||||
|
||||
/**
|
||||
* Haengt die Aufgabe an einem Issue, wandert der Zustand mit: erledigt
|
||||
* schliesst es, ein Zurueckziehen oeffnet es wieder. Nur die Grenze um
|
||||
* ERLEDIGT geht nach draussen – mehr kennt ein Issue nicht.
|
||||
*
|
||||
* Fehlertolerant und ohne den Aufrufer warten zu lassen, was schiefgehen
|
||||
* kann: ein nicht erreichbares Git-System darf das Abhaken nicht
|
||||
* verhindern. Beim naechsten Wechsel wird es erneut versucht.
|
||||
*/
|
||||
if (update.status !== undefined) {
|
||||
const vorher = issueShouldBeOpen(existing.status);
|
||||
const nachher = issueShouldBeOpen(update.status as TaskStatus);
|
||||
if (vorher !== nachher) {
|
||||
await mirrorStatusToIssue(id, update.status as TaskStatus);
|
||||
}
|
||||
}
|
||||
|
||||
// Nur der Spaltenwechsel kommt in den Verlauf. Ein umbenannter Titel oder
|
||||
// ein neues Label sind zu kleinteilig, um die Geschichte des Projekts zu
|
||||
// erzaehlen – und beim Ziehen im Brett ist der Wechsel die eigentliche Tat.
|
||||
|
||||
Reference in New Issue
Block a user