#!/usr/bin/env python3 """Suivi quotidien du projet Mon-site-web-photos v4. Utilise gh CLI pour interroger le board GitHub et produit un résumé. À exécuter via cronjob avec no_agent=True. """ import json import subprocess import sys from datetime import datetime, timezone def gh_run(*args: str) -> dict: """Run gh CLI and return parsed JSON.""" result = subprocess.run( ["gh", *args], capture_output=True, text=True, timeout=30, env={**__import__("os").environ, "GH_PROMPT_DISABLED": "1"}, ) if result.returncode != 0: print(f"ERREUR gh {' '.join(args)}: {result.stderr.strip()}", file=sys.stderr) return {} return json.loads(result.stdout) def get_issue_state(number: int) -> dict: """Get issue state and labels.""" return gh_run("issue", "view", str(number), "--json", "number,title,state,labels,updatedAt") def format_daily_report() -> str: """Generate the daily status report.""" board = gh_run("project", "item-list", "2", "--owner", "lolo1580", "--limit", "50", "--format", "json") items = board.get("items", []) if not items: return "⚠️ Impossible de récupérer les données du board." # Collect issue numbers from board items issue_numbers = set() for item in items: content = item.get("content", {}) num = content.get("number") if num: issue_numbers.add(num) # Get details for each issue issues = [] for num in sorted(issue_numbers): detail = get_issue_state(num) if detail and detail.get("number"): # Merge board-level labels (more reliable) board_labels = [] for item in items: if item.get("content", {}).get("number") == num: board_labels = item.get("labels", []) break detail["_board_labels"] = board_labels issues.append(detail) # Categorize bugs = [i for i in issues if "bug" in i.get("_board_labels", [])] features = [i for i in issues if "feature" in i.get("_board_labels", [])] critical = [i for i in issues if "critical" in i.get("_board_labels", [])] high = [i for i in issues if "high" in i.get("_board_labels", [])] open_issues = [i for i in issues if i.get("state") == "OPEN"] closed_issues = [i for i in issues if i.get("state") == "CLOSED"] now = datetime.now(timezone.utc).strftime("%d/%m/%Y %H:%M UTC") lines = [ f"📋 **Suivi quotidien — Mon-site-web-photos v4**", f"_{now}_", "", "---", "", f"### 📊 Résumé", "", f"| Indicateur | Valeur |", f"|------------|--------|", f"| Issues ouvertes | {len(open_issues)} |", f"| Issues fermées | {len(closed_issues)} |", f"| Bugs | {len(bugs)} |", f"| Features | {len(features)} |", f"| 🔴 Critiques | {len(critical)} |", f"| 🟡 Hautes | {len(high)} |", "", ] if critical: lines.append("### 🔴 Bugs critiques") for i in critical: lines.append(f"- **#{i['number']}** {i['title']}") lines.append("") if open_issues: lines.append("### 📌 Issues ouvertes") lines.append("") lines.append("| # | Titre | Type | Priorité |") lines.append("|---|------|------|----------|") for i in open_issues: labels = i.get("_board_labels", []) i_type = "Bug" if "bug" in labels else "Feature" if "feature" in labels else "Autre" priority = "🔴" if "critical" in labels else "🟡" if "high" in labels else "🟢" if "medium" in labels else "⚪" lines.append(f"| #{i['number']} | {i['title'][:55]} | {i_type} | {priority} |") lines.append("") if closed_issues: lines.append("### ✅ Récemment fermés") for i in closed_issues: lines.append(f"- **#{i['number']}** {i['title']}") lines.append("") lines.append("---") lines.append(f"🔗 **Board** : https://github.com/lolo1580/Mon-site-web-photos/projects/2") lines.append(f"📁 **Repo** : https://github.com/lolo1580/Mon-site-web-photos") return "\n".join(lines) if __name__ == "__main__": report = format_daily_report() print(report)