Compare commits

..
6 Commits
6 changed files with 54 additions and 8 deletions
+13
View File
@@ -1,5 +1,18 @@
# Changelog
## 0.22.1 — 2026-10-20
### Correctif — colonne Terminé vide
- Les issues **fermées dans Gitea** mais suivies par le board
n'apparaissaient pas dans la colonne **Terminé** : la
réconciliation plaçait bien leur ligne locale en `done`, mais
l'affichage du board ne fusionnait que les issues **ouvertes**.
- Le board (page HTML et API JSON) inclut désormais les issues
fermées dont la ligne locale est en `done`, y compris dans la
vue par milestone.
- Test de régression ajouté ; suite complète : 201 tests verts.
## 0.22.0 — 2026-10-14
### Écran de connexion (demande de Bruno)
+1 -1
View File
@@ -95,7 +95,7 @@ from pathlib import Path
BASE_DIR = Path(__file__).resolve().parent.parent
APP_VERSION = "0.22.0"
APP_VERSION = "0.22.1"
def _env_bool(name: str, default: bool) -> bool:
+1 -1
View File
@@ -143,7 +143,7 @@ async def _mcp_session(client: httpx.AsyncClient, url: str, token: str) -> None:
{
"protocolVersion": MCP_PROTOCOL_VERSION,
"capabilities": {},
"clientInfo": {"name": "kanbante", "version": "0.22.0"},
"clientInfo": {"name": "kanbante", "version": "0.22.1"},
},
req_id=1,
)
+25 -5
View File
@@ -832,13 +832,25 @@ async def board(request: Request, owner: str, repo: str, milestone: str = ""):
# A kanban:* label changed outside Kanbante wins over local state.
_adopt_label_columns(full_name, open_issues, get_board_state(full_name))
# Closed issues stay visible while the board tracks them as done
# (reconcile_board_state moved their row). Merging open issues only
# made the "Terminé" column permanently empty.
done_numbers = {
c["issue_number"] for c in get_board_state(full_name).get("done", [])
}
closed_display = [
i
for i in issues
if i.get("state") != "open" and i["number"] in done_numbers
]
# Milestone view: filter the board to one milestone (sprint-style),
# with its deadline and completion progress.
milestones: list[dict] = []
selected_milestone = None
milestone_progress = None
milestone_forecast = None
display_issues = open_issues
display_issues = open_issues + closed_display
try:
milestones = await gitea.get_milestones(owner, repo)
except Exception as exc: # milestones are decoration, never fatal
@@ -851,7 +863,7 @@ async def board(request: Request, owner: str, repo: str, milestone: str = ""):
str(ms.get("id")) == milestone or ms.get("title") == milestone
)
display_issues = [i for i in open_issues if _in_milestone(i)]
display_issues = [i for i in display_issues if _in_milestone(i)]
selected_milestone = next(
(
m for m in milestones
@@ -941,7 +953,16 @@ def _board_columns_for(
for number in changes["closed_numbers"]:
log_event(full_name, number, "closed", to_column="done", source="gitea")
_adopt_label_columns(full_name, open_issues, get_board_state(full_name))
display_issues = open_issues
board_state = get_board_state(full_name)
# Closed issues stay visible while the board tracks them as done
# (reconcile_board_state moved their row). Merging open issues only
# made the "Terminé" column permanently empty.
done_numbers = {c["issue_number"] for c in board_state.get("done", [])}
display_issues = open_issues + [
i
for i in issues
if i.get("state") != "open" and i["number"] in done_numbers
]
if milestone:
def _in_ms(issue: dict) -> bool:
ms = issue.get("milestone") or {}
@@ -949,8 +970,7 @@ def _board_columns_for(
str(ms.get("id")) == milestone or ms.get("title") == milestone
)
display_issues = [i for i in open_issues if _in_ms(i)]
board_state = get_board_state(full_name)
display_issues = [i for i in display_issues if _in_ms(i)]
columns = _merge_issues_with_board(display_issues, board_state)
return columns, display_issues, board_state
+1 -1
View File
@@ -1,6 +1,6 @@
[project]
name = "kanbante"
version = "0.22.0"
version = "0.22.1"
description = "Kanban project manager integrated with Gitea"
requires-python = ">=3.11"
dependencies = [
+13
View File
@@ -39,6 +39,19 @@ def test_board_hides_pull_requests_and_reconciles(client):
assert [c["issue_number"] for c in state["done"]] == [3] # reconciled
def test_board_renders_closed_issue_in_done_column(client):
# Regression: reconcile moved the closed issue's row to "done", but
# the board merged open issues only, so the card never rendered and
# the "Terminé" column stayed empty.
models.move_issue("Projets/demo", 3, "todo") # closed in Gitea
r = client.get("/board/Projets/demo")
assert r.status_code == 200
assert "Ancienne tâche" in r.text
payload = client.get("/api/board/Projets/demo").json()
assert payload["columns"]["done"]["count"] == 1
assert "Ancienne tâche" in payload["columns"]["done"]["html"]
def test_focus_lists_in_progress_across_projects(client):
models.move_issue("Projets/demo", 5, "in_progress")
r = client.get("/focus")