0.28.0 — Émission d'événements vers le journal du service d'agents (Lot 2)
CI / test (push) Successful in 2m1s
CI / test (push) Successful in 2m1s
- app/agent_journal.py : enveloppe ACC-0.2 signée HMAC-SHA256 (clé AGENT_EVENEMENTS_CLE, URL AGENT_EVENEMENTS_URL), envoi en arrière-plan, timeout 2 s, inactif sans clé, échecs avalés - main.py : _emettre_changement_colonne accolée aux log_event de déplacement (interface, étiquettes forge, webhook, réconciliation, PR fusionnée, branche) — kanbante.card.moved pour tout changement de colonne, kanbante.card.review_requested à l'entrée en Révision - config : AGENT_EVENEMENTS_URL/_CLE documentés et lus à l'appel - 247 tests verts (5 nouveaux : signature revérifiable, inactivité sans clé, moved, review_requested, panne du récepteur)
This commit is contained in:
+69
@@ -58,6 +58,7 @@ from app.briefing import (
|
||||
send_ntfy,
|
||||
)
|
||||
from app.capture import ntfy_capture_loop, parse_capture_text
|
||||
from app import agent_journal
|
||||
from app import models
|
||||
from app.models import (
|
||||
KANBAN_COLUMNS,
|
||||
@@ -2020,6 +2021,38 @@ def _merge_issues_with_board(
|
||||
return columns
|
||||
|
||||
|
||||
def _emettre_changement_colonne(
|
||||
full_name: str,
|
||||
number: int,
|
||||
from_column: str | None,
|
||||
to_column: str,
|
||||
source: str,
|
||||
title: str = "",
|
||||
) -> None:
|
||||
"""Émission Lot 2 : refléter un changement de colonne réel dans
|
||||
le journal du service d'agents (contrat ACC-0.2, voir
|
||||
app/agent_journal.py).
|
||||
|
||||
Appelée à côté des log_event qui consignent un déplacement —
|
||||
jamais à leur place. ``kanbante.card.moved`` pour tout
|
||||
changement de colonne, plus ``kanbante.card.review_requested``
|
||||
quand la carte ENTRE en colonne Révision. Au mieux : sans clé
|
||||
configurée, rien ne part ; en cas de panne du service, le
|
||||
déplacement n'est jamais affecté.
|
||||
"""
|
||||
if not to_column or from_column == to_column:
|
||||
return
|
||||
actor = "user" if source == "ui" else f"agent:{source}"
|
||||
ref = f"issue:{full_name}#{number}"
|
||||
label = (title or "").strip() or ref
|
||||
url = f"{get_settings().gitea_url}/{full_name}/issues/{number}"
|
||||
agent_journal.emettre("kanbante.card.moved", ref, label, url, actor=actor)
|
||||
if to_column == "review" and from_column != "review":
|
||||
agent_journal.emettre(
|
||||
"kanbante.card.review_requested", ref, label, url, actor=actor
|
||||
)
|
||||
|
||||
|
||||
def _adopt_label_columns(
|
||||
full_name: str,
|
||||
open_issues: list[dict],
|
||||
@@ -2063,6 +2096,10 @@ def _adopt_label_columns(
|
||||
from_column=current, to_column=target, source="gitea",
|
||||
workspace_id=workspace_id, connection_id=connection_id,
|
||||
)
|
||||
_emettre_changement_colonne(
|
||||
full_name, issue["number"], current, target, "gitea",
|
||||
title=issue.get("title", ""),
|
||||
)
|
||||
placement[issue["number"]] = target
|
||||
|
||||
|
||||
@@ -2392,6 +2429,9 @@ async def board(request: Request, owner: str, repo: str, milestone: str = ""):
|
||||
full_name, number, "closed", to_column="done", source="gitea",
|
||||
workspace_id=ws_id, connection_id=conn_id,
|
||||
)
|
||||
_emettre_changement_colonne(
|
||||
full_name, number, None, "done", "gitea",
|
||||
)
|
||||
|
||||
# A kanban:* label changed outside Kanbante wins over local state.
|
||||
_adopt_label_columns(
|
||||
@@ -2543,6 +2583,9 @@ def _board_columns_for(
|
||||
full_name, number, "closed", to_column="done", source="gitea",
|
||||
workspace_id=workspace_id, connection_id=connection_id,
|
||||
)
|
||||
_emettre_changement_colonne(
|
||||
full_name, number, None, "done", "gitea",
|
||||
)
|
||||
_adopt_label_columns(
|
||||
full_name, open_issues,
|
||||
get_board_state(
|
||||
@@ -4138,6 +4181,11 @@ def _apply_external_transition(
|
||||
from_column="done", to_column=target_column, source="webhook",
|
||||
workspace_id=workspace_id, connection_id=connection_id,
|
||||
)
|
||||
_emettre_changement_colonne(
|
||||
full_name, number,
|
||||
current if event_type == "closed" else "done",
|
||||
target_column, "webhook",
|
||||
)
|
||||
return event_type
|
||||
|
||||
|
||||
@@ -4207,6 +4255,10 @@ async def _apply_pr_merged(
|
||||
to_column="done", source="webhook",
|
||||
workspace_id=workspace_id, connection_id=connection_id,
|
||||
)
|
||||
_emettre_changement_colonne(
|
||||
full_name, number, None, "done", "webhook",
|
||||
title=issue.get("title", ""),
|
||||
)
|
||||
outcome = "closed"
|
||||
results.append(f"#{number}:{outcome}")
|
||||
return results
|
||||
@@ -4823,6 +4875,19 @@ async def api_move(
|
||||
from_column or None, to_column,
|
||||
workspace_id=ws_id, connection_id=conn_id,
|
||||
)
|
||||
# Émission Lot 2 (journal du service d'agents) : le titre
|
||||
# n'est relu que si l'émission est configurée, au mieux.
|
||||
titre_carte = ""
|
||||
if agent_journal.actif():
|
||||
try:
|
||||
detail = await client.get_issue(owner, repo, issue_number)
|
||||
titre_carte = detail.get("title", "")
|
||||
except Exception:
|
||||
titre_carte = ""
|
||||
_emettre_changement_colonne(
|
||||
repo_full_name, issue_number, from_column or None, to_column,
|
||||
"ui", title=titre_carte,
|
||||
)
|
||||
|
||||
result: dict = {"ok": True, "gitea_sync": "skipped"}
|
||||
settings = get_settings()
|
||||
@@ -5156,6 +5221,10 @@ async def api_create_branch(
|
||||
source="branch",
|
||||
workspace_id=ws_id, connection_id=conn_id,
|
||||
)
|
||||
_emettre_changement_colonne(
|
||||
full_name, number, current, "in_progress", "branch",
|
||||
title=issue.get("title", ""),
|
||||
)
|
||||
await _sync_kanban_label(
|
||||
owner, repo, number, "in_progress", client
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user