Files
gitea-dashboard/docs/plans/v1.1.0-plan.md
2026-03-11 04:30:07 +01:00

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 / -r pour filtrer par nom(s) de repo (inclusion)
  • Option CLI --exclude / -x pour 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

  1. Sans options, comportement identique a v1.0.0 :

    $ gitea-dashboard
    # Affiche tous les repos (aucun changement)
    
  2. Filtrage par inclusion :

    $ gitea-dashboard --repo dashboard --repo infra
    # Affiche uniquement les repos dont le nom contient "dashboard" ou "infra"
    
  3. Filtrage par exclusion :

    $ gitea-dashboard --exclude fork --exclude test
    # Affiche tous les repos sauf ceux dont le nom contient "fork" ou "test"
    
  4. Combinaison inclusion + exclusion :

    $ gitea-dashboard --repo projet -x old
    # Inclut les repos contenant "projet", puis exclut ceux contenant "old"
    
  5. Insensibilite a la casse :

    $ gitea-dashboard --repo Dashboard
    # Match "gitea-dashboard", "Dashboard-test", etc.
    
  6. 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 : retourne Namespace(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 bar fonctionne comme les formes longues
  • test_main_passes_filters_to_collect_all : verifie que collect_all est appele avec les bons include/exclude
  • test_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-chaine
  • test_collect_all_include_multiple : filtre par plusieurs sous-chaines (OR)
  • test_collect_all_exclude_single : exclut par une sous-chaine
  • test_collect_all_include_and_exclude : inclusion puis exclusion
  • test_collect_all_case_insensitive : "Dashboard" matche "gitea-dashboard"
  • test_collect_all_no_match : retourne une liste vide si aucun repo ne correspond
  • test_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-dashboard sans 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