[arch-question] CI-Guard für Close-Keyword-Convention in Merge-Commits #406

Closed
opened 2026-05-25 11:41:38 +02:00 by pm-bot · 1 comment
Collaborator

Kontext

Wir hatten bereits vier dokumentierte Convention-Fallen in den letzten 6 Tagen, wo PRs gemerged wurden ohne Closes #N / Fixes #N im Merge-Commit-Title:

  • 2026-05-20: #347, #348, #349 (App-Shell-Bugs) — Issues blieben 5 Tage als "offen" geführt obwohl in Prod
  • 2026-05-25: #398 (Gitea-Release-Step) — Issue blieb beim v0.4.5-Cut noch offen
  • State-Reconciler zeigt zusätzlich: #178, #175, #253, #366 alle in derselben Falle

Folge: Milestone-Counts stimmen nicht, Velocity-Statistik verzerrt, Status-Reports erzeugen Diskrepanzen zwischen PM und Dev-Team (siehe gestriges GF-Gespräch). Manuelles PM-Housekeeping wird zur Dauerlast.

Die PM-Convention liegt in der Memory (convention_commit_close_keywords.md), aber Memory-Awareness allein reicht nicht — Devs (Mensch UND arch-bot) übersehen es konsequent.

Konkrete Entscheidung die gebraucht wird

Ein CI-Guard der PRs blockt, deren Merge keinen Closes #N / Fixes #N Reference enthält — wenn dieser PR ein Issue erledigt (Issue-Nummer im Branch-Namen oder PR-Title).

Optionen die PM sieht

A) Pre-Merge-Hook in Drone/Woodpecker: Step in der PR-Pipeline der den PR-Title oder die Commits prüft. Failt wenn (Issue-Ref im PR-Title) AND (kein Close-Keyword in PR-Body/-Title). Vorteil: Self-hosted, kein externes Tool.

B) Gitea Server-side Hook: Repo-Settings → require Close-Keyword via pre-receive hook. Aggressiver (blockt schon push), aber Gitea-API für solche Hooks ist in 1.22 limitiert.

C) PR-Template + Linter: .gitea/pull_request_template.md mit „Closes #" Vorgabe + ein Lint-Step der den ausgefüllten Wert verifiziert. Sanftere Variante — Dev bekommt Erinnerung statt Wand.

D) Reine PM-Reconciler-Strategie: Kein CI-Guard, stattdessen Reconciler im PM-Workflow (siehe state-reconciler.py). Macht das Problem sichtbar, fixt es aber nicht vorher.

Constraints

  • Drone aktuell, Migration zu Woodpecker laut server-stack#17 — Lösung sollte beide tragen
  • Soll nicht legitime PRs blocken die kein Issue schließen (z.B. reine Refactor-PRs, Doc-PRs) — der Guard muss nur greifen wenn Issue-Referenz erkennbar ist
  • Bot-Account (arch-bot) wird via API mergen können — Hook muss bei API-Merges auch greifen
  • Anti-Bypass: kein Sonderzugang für admin-mrrm (sonst landen Convention-Fallen wie heute wieder durchs Loch)

Optionen mit PM-Empfehlung

Empfehlung: A + C kombiniert.

  • A als Hard-Guard (PR kann nicht gemerged werden)
  • C als UX-Schicht (PR-Template macht es leicht richtig zu machen)
  • D (Reconciler) als Fallback-Audit-Tool

Aber Tech-Call beim Architekten: welche Variante ist in Drone/Woodpecker am robustesten implementierbar? Gibt es vielleicht ein fertiges Plugin (plugins/labels o.ä.)?

Dringlichkeit

Mittel. Nicht produktions-kritisch, aber jeden Tag erzeugt es zusätzliches PM-Housekeeping und potentielle Status-Diskrepanzen. Antwort gerne bis 2026-06-07.

Folge-Aktion sobald entschieden

PM eröffnet ein neues Implementierungs-Ticket im v0.5-Milestone (Infra-Block) basierend auf der gewählten Variante.

## Kontext Wir hatten bereits **vier dokumentierte Convention-Fallen** in den letzten 6 Tagen, wo PRs gemerged wurden ohne `Closes #N` / `Fixes #N` im Merge-Commit-Title: - 2026-05-20: #347, #348, #349 (App-Shell-Bugs) — Issues blieben 5 Tage als "offen" geführt obwohl in Prod - 2026-05-25: #398 (Gitea-Release-Step) — Issue blieb beim v0.4.5-Cut noch offen - State-Reconciler zeigt zusätzlich: #178, #175, #253, #366 alle in derselben Falle Folge: Milestone-Counts stimmen nicht, Velocity-Statistik verzerrt, Status-Reports erzeugen Diskrepanzen zwischen PM und Dev-Team (siehe gestriges GF-Gespräch). Manuelles PM-Housekeeping wird zur Dauerlast. Die PM-Convention liegt in der Memory (`convention_commit_close_keywords.md`), aber Memory-Awareness allein reicht nicht — Devs (Mensch UND arch-bot) übersehen es konsequent. ## Konkrete Entscheidung die gebraucht wird Ein **CI-Guard** der PRs blockt, deren Merge keinen `Closes #N` / `Fixes #N` Reference enthält — wenn dieser PR ein Issue erledigt (Issue-Nummer im Branch-Namen oder PR-Title). ## Optionen die PM sieht **A) Pre-Merge-Hook in Drone/Woodpecker:** Step in der PR-Pipeline der den PR-Title oder die Commits prüft. Failt wenn (Issue-Ref im PR-Title) AND (kein Close-Keyword in PR-Body/-Title). Vorteil: Self-hosted, kein externes Tool. **B) Gitea Server-side Hook:** Repo-Settings → require Close-Keyword via pre-receive hook. Aggressiver (blockt schon push), aber Gitea-API für solche Hooks ist in 1.22 limitiert. **C) PR-Template + Linter:** `.gitea/pull_request_template.md` mit „Closes #" Vorgabe + ein Lint-Step der den ausgefüllten Wert verifiziert. Sanftere Variante — Dev bekommt Erinnerung statt Wand. **D) Reine PM-Reconciler-Strategie:** Kein CI-Guard, stattdessen Reconciler im PM-Workflow (siehe state-reconciler.py). Macht das Problem sichtbar, fixt es aber nicht *vorher*. ## Constraints - Drone aktuell, Migration zu Woodpecker laut server-stack#17 — Lösung sollte beide tragen - Soll nicht legitime PRs blocken die kein Issue schließen (z.B. reine Refactor-PRs, Doc-PRs) — der Guard muss nur greifen wenn Issue-Referenz erkennbar ist - Bot-Account (arch-bot) wird via API mergen können — Hook muss bei API-Merges auch greifen - Anti-Bypass: kein Sonderzugang für admin-mrrm (sonst landen Convention-Fallen wie heute wieder durchs Loch) ## Optionen mit PM-Empfehlung Empfehlung: **A + C kombiniert**. - A als Hard-Guard (PR kann nicht gemerged werden) - C als UX-Schicht (PR-Template macht es leicht richtig zu machen) - D (Reconciler) als Fallback-Audit-Tool Aber Tech-Call beim Architekten: welche Variante ist in Drone/Woodpecker am robustesten implementierbar? Gibt es vielleicht ein fertiges Plugin (`plugins/labels` o.ä.)? ## Dringlichkeit Mittel. Nicht produktions-kritisch, aber jeden Tag erzeugt es zusätzliches PM-Housekeeping und potentielle Status-Diskrepanzen. Antwort gerne bis 2026-06-07. ## Folge-Aktion sobald entschieden PM eröffnet ein neues Implementierungs-Ticket im v0.5-Milestone (Infra-Block) basierend auf der gewählten Variante.
Author
Collaborator

Implementiert via #434 / PR #435 (gemerged). Lösung: Empfehlung A+C — Drone-Step pr-convention-check als Hard-Guard + bestehendes PR-Template als UX-Schicht. Self-Test grün (der PR selbst nutzt den Check via Fixes #434).

Manueller Folge-Schritt fehlt noch (nur Repo-Admin): Gitea Repo-Settings → Branch Protection auf main:

  • "Status checks must pass" → continuous-integration/drone/pr required
  • "Apply to administrators" toggle

Ohne diesen Toggle bleibt der Bypass via direkten Merge bei rotem Build möglich.

Implementiert via #434 / PR #435 (gemerged). Lösung: Empfehlung A+C — Drone-Step `pr-convention-check` als Hard-Guard + bestehendes PR-Template als UX-Schicht. Self-Test grün (der PR selbst nutzt den Check via `Fixes #434`). **Manueller Folge-Schritt fehlt noch** (nur Repo-Admin): Gitea Repo-Settings → Branch Protection auf `main`: - "Status checks must pass" → `continuous-integration/drone/pr` required - "Apply to administrators" toggle Ohne diesen Toggle bleibt der Bypass via direkten Merge bei rotem Build möglich.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
admin-mrrm/mrrmlabapp#406
No description provided.