9.5 KiB
Plan de version v1.1.0 — gitea-dashboard
Objectif
Permettre a l'utilisateur de filtrer l'affichage du dashboard par nom de repo (inclusion et exclusion), via des options CLI. Premiere evolution fonctionnelle du dashboard.
Track
Minor : 6 -> 7 -> 8 -> 9 -> 10 -> 11 -> (12) -> 13
Budget de scope
| Critere | Valeur |
|---|---|
| Max fichiers par phase | 4 |
| Total fichiers estimes | 6 (3 modules modifies + 3 fichiers de tests modifies) |
Inclus
- Option CLI
--repo/-rpour filtrer par nom(s) de repo (inclusion) - Option CLI
--exclude/-xpour exclure des repos par nom - Filtrage par sous-chaine (match partiel, insensible a la casse)
- Filtrage applicable aux deux options (cumulable :
--repo X --exclude Y) - Ajout d'argparse pour le parsing des options CLI
- Tests unitaires du filtrage et tests d'integration CLI
Exclus
- Filtrage par owner/organisation (hors scope, pas de demande)
- Filtrage par regex (sous-chaine suffit pour v1.1.0)
- Filtrage par labels, activite ou date
- Tri des resultats (differe)
- Options
--format,--sort(differees) - Parallelisation des appels API (ADR-003, differee)
Differe (v1.2+)
- Filtrage par owner/organisation
- Option
--sort(par nom, issues, date de release) - Cache des reponses API
- Option
--format(json, csv)
Etapes skippees
| Etape | Nom | Raison |
|---|---|---|
| 1 | Discovery | Projet existant, discovery v1.0.0 suffisante |
| 2 | Project creation | Projet existant |
| 3 | Specs | Minor — specs couvertes par l'issue #5 et ce plan |
| 4 | Research | Pas de technologie nouvelle (argparse est stdlib) |
| 5 | Roadmap | Minor — roadmap existante, issue #5 deja creee |
| 12 | Deploy | Outil CLI local, pas de deploiement serveur |
Phase 1 : Parsing CLI et logique de filtrage
Goal : Ajouter les options --repo et --exclude a la CLI et implementer la logique de filtrage dans le collecteur.
Issues Gitea : fixes #5
Fichiers
| Action | Fichier | Modifications | Cross-references |
|---|---|---|---|
| Modify | src/gitea_dashboard/cli.py |
Ajouter argparse, options --repo/-r et --exclude/-x, passer les filtres a collect_all() |
collector.py (passe les filtres) |
| Modify | src/gitea_dashboard/collector.py |
Ajouter parametres include et exclude a collect_all(), logique de filtrage |
cli.py (appele avec filtres), client.py (inchange) |
| Modify | tests/test_cli.py |
Tests argparse, passage des filtres, combinaison d'options | cli.py |
| Modify | tests/test_collector.py |
Tests du filtrage : inclusion, exclusion, combinaison, casse, sous-chaine | collector.py |
Interfaces
cli.py (modifications)
import argparse
def parse_args(argv: list[str] | None = None) -> argparse.Namespace:
"""Parse les arguments CLI.
Options:
--repo / -r : noms de repos a inclure (repeatable)
--exclude / -x : noms de repos a exclure (repeatable)
Returns:
Namespace avec .repo (list[str] | None) et .exclude (list[str] | None)
"""
def main(argv: list[str] | None = None) -> None:
"""Point d'entree principal.
Modification : accepte argv pour testabilite.
Appelle parse_args(), puis passe include/exclude a collect_all().
"""
Pourquoi parse_args separe de main : testabilite. On peut tester le parsing seul sans mocker l'environnement complet.
Pourquoi argv en parametre de main : permet aux tests d'injecter des arguments sans patcher sys.argv.
collector.py (modifications)
def collect_all(
client: GiteaClient,
include: list[str] | None = None,
exclude: list[str] | None = None,
) -> list[RepoData]:
"""Collecte les donnees des repos, avec filtrage optionnel.
Args:
client: Client API Gitea.
include: Si fourni, ne garde que les repos dont le nom contient
au moins une des sous-chaines (insensible a la casse).
exclude: Si fourni, exclut les repos dont le nom contient
au moins une des sous-chaines (insensible a la casse).
Ordre d'application : include d'abord (si present), puis exclude.
Si include est None ou vide, tous les repos sont inclus avant l'etape exclude.
"""
Pourquoi le filtrage est dans collector.py et non cli.py : le collecteur est responsable de "quels repos collecter". Cela evite de polluer le CLI avec de la logique metier et garde la testabilite (on teste le filtrage sans mocker argparse).
Pourquoi le filtrage est post-fetch (apres get_repos()) et non pre-fetch : l'API Gitea /user/repos ne supporte pas de filtre par nom cote serveur. On doit recuperer tous les repos puis filtrer localement.
Comportement attendu
-
Sans options, comportement identique a v1.0.0 :
$ gitea-dashboard # Affiche tous les repos (aucun changement) -
Filtrage par inclusion :
$ gitea-dashboard --repo dashboard --repo infra # Affiche uniquement les repos dont le nom contient "dashboard" ou "infra" -
Filtrage par exclusion :
$ gitea-dashboard --exclude fork --exclude test # Affiche tous les repos sauf ceux dont le nom contient "fork" ou "test" -
Combinaison inclusion + exclusion :
$ gitea-dashboard --repo projet -x old # Inclut les repos contenant "projet", puis exclut ceux contenant "old" -
Insensibilite a la casse :
$ gitea-dashboard --repo Dashboard # Match "gitea-dashboard", "Dashboard-test", etc. -
Aucun repo ne correspond :
$ gitea-dashboard --repo inexistant # Affiche "Aucun repo trouve." (comportement existant de render_dashboard)
Tests
test_cli.py (ajouts)
test_parse_args_no_options: retourneNamespace(repo=None, exclude=None)test_parse_args_single_repo:--repo foo->Namespace(repo=["foo"], ...)test_parse_args_multiple_repo:--repo foo --repo bar->Namespace(repo=["foo", "bar"], ...)test_parse_args_short_flags:-r foo -x barfonctionne comme les formes longuestest_main_passes_filters_to_collect_all: verifie quecollect_allest appele avec les bonsinclude/excludetest_main_no_filters_passes_none: sans options,collect_all(client, include=None, exclude=None)
test_collector.py (ajouts)
test_collect_all_no_filter: comportement identique a v1.0.0 (retrocompatibilite)test_collect_all_include_single: filtre par une sous-chainetest_collect_all_include_multiple: filtre par plusieurs sous-chaines (OR)test_collect_all_exclude_single: exclut par une sous-chainetest_collect_all_include_and_exclude: inclusion puis exclusiontest_collect_all_case_insensitive: "Dashboard" matche "gitea-dashboard"test_collect_all_no_match: retourne une liste vide si aucun repo ne correspondtest_collect_all_exclude_all: retourne une liste vide si tout est exclu
Livrable
La commande gitea-dashboard --repo X -x Y filtre l'affichage. Sans options, le comportement est identique a v1.0.0. Tous les tests passent (existants + nouveaux).
Phase 2 : Smoke test et documentation
Goal : Valider le filtrage sur l'instance reelle et mettre a jour la documentation.
Dependances : phase 1 terminee, acces a l'instance Gitea (192.168.0.106:3000)
Composants cles :
- Test E2E manuel :
gitea-dashboard --repo dashboard,gitea-dashboard -x fork, combinaison - Verification de la retrocompatibilite :
gitea-dashboardsans options - Mise a jour de README.md (section usage avec les nouvelles options)
- Mise a jour de CHANGELOG.md (section Added pour v1.1.0)
- Mise a jour de
--help(automatique via argparse)
Architecture des modules (impact)
Le changement est minimal et respecte l'architecture existante (ADR-002) :
| Module | Impact | Detail |
|---|---|---|
cli.py |
Modifie | Ajout argparse + passage des filtres |
collector.py |
Modifie | Nouveaux parametres include/exclude dans collect_all() |
client.py |
Inchange | Aucun impact (le filtrage est local, pas API) |
display.py |
Inchange | Recoit toujours list[RepoData], ne sait pas si c'est filtre |
Pas de nouveau module. La signature de collect_all() est modifiee avec des parametres optionnels : retrocompatible (les parametres ont des valeurs par defaut None).
Risques d'audit
| Zone | Risque | Severite estimee |
|---|---|---|
cli.py — argparse |
Interaction entre argv et sys.argv : s'assurer que parse_args(None) delegue bien a sys.argv |
minor |
collector.py — filtrage |
Match partiel trop agressif (ex: --repo a matche tous les repos contenant "a") |
minor |
collector.py — ordre include/exclude |
L'ordre d'application doit etre documente et teste | minor |
cli.py — retrocompatibilite |
Entry point main() ne doit pas casser si appele sans arguments |
major |
Issues Gitea rattachees
| Issue | Titre | Phase |
|---|---|---|
| #5 | Ajouter le filtrage par repo | Phase 1 |
Dependances
| Dependance | Type | Version |
|---|---|---|
| Python | Runtime | >= 3.10 |
| argparse | Stdlib | inclus dans Python |
| requests | Librairie | >= 2.31 (inchange) |
| rich | Librairie | >= 13.0 (inchange) |
| pytest | Dev | >= 7.0 (inchange) |
| ruff | Dev | >= 0.4 (inchange) |
| Instance Gitea | Service externe | 192.168.0.106:3000 |