You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

7.8 KiB

🏗 Architecture du Migration Tool

Vue d'ensemble

Le Migration Tool a été conçu selon les principes de développement suivants :

  • Single Responsibility Principle (SRP) : Chaque classe a une responsabilité unique
  • Open/Closed Principle : Ouvert à l'extension, fermé à la modification
  • Dependency Inversion : Dépendance sur des abstractions, pas des implémentations
  • Extensibilité : Facilité d'ajout de nouveaux providers

Structure du projet

GiteaToGithubMigrator/
├── providers/                   # Providers pour différents services Git
│   ├── __init__.py
│   ├── base.py                 # Classes abstraites et modèles
│   ├── factory.py              # Factory pour créer les providers
│   ├── source/                 # Providers source (Gitea, GitLab, etc.)
│   │   ├── __init__.py
│   │   ├── gitea.py
│   │   └── gitlab.py
│   └── destination/            # Providers destination (GitHub, GitLab, etc.)
│       ├── __init__.py
│       ├── github.py
│       └── gitlab.py
├── core/                       # Logique métier centrale
│   ├── __init__.py
│   ├── config.py              # Gestion de la configuration
│   └── migration_engine.py    # Moteur de migration
├── ui/                        # Interface utilisateur
│   ├── __init__.py
│   └── interactive_selector.py
├── main.py                    # Point d'entrée principal
└── run.sh                     # Script de lancement

Responsabilités des modules

🔧 Providers (providers/)

Base (providers/base.py)

  • Repository : Modèle de données unifié pour tous les providers
  • SourceProvider : Interface abstraite pour les providers source
  • DestinationProvider : Interface abstraite pour les providers destination
  • Exceptions : Exceptions spécialisées pour la gestion d'erreurs

Factory (providers/factory.py)

  • Création dynamique des instances de providers
  • Enregistrement de nouveaux providers
  • Validation des types de providers disponibles

Source Providers (providers/source/)

  • Gitea : Implémentation pour Gitea
  • GitLab : Implémentation pour GitLab (exemple d'extensibilité)

Destination Providers (providers/destination/)

  • GitHub : Implémentation pour GitHub
  • GitLab : Implémentation pour GitLab (exemple d'extensibilité)

⚙ Core (core/)

Configuration (core/config.py)

  • Gestion centralisée de la configuration
  • Support multi-providers via variables d'environnement
  • Validation des paramètres de configuration

Migration Engine (core/migration_engine.py)

  • Orchestration du processus de migration
  • Gestion des repositories temporaires
  • Exécution des commandes Git
  • Logging et rapport de progression

🎨 UI (ui/)

Interactive Selector (ui/interactive_selector.py)

  • Interface interactive pour la sélection de repositories
  • Navigation au clavier
  • Système de renommage
  • Affichage paginated

Extensibilité

Ajouter un nouveau provider source

  1. Créer le fichier : providers/source/mon_provider.py
from typing import List, Optional
from ..base import SourceProvider, Repository, ProviderError, ConfigurationError

class MonProviderSourceProvider(SourceProvider):
    def _validate_config(self) -> None:
        # Valider la configuration spécifique
        pass
    
    def get_user_repositories(self) -> List[Repository]:
        # Récupérer les repos de l'utilisateur
        pass
    
    def get_accessible_repositories(self) -> List[Repository]:
        # Récupérer tous les repos accessibles
        pass
    
    def get_repository_info(self, owner: str, name: str) -> Optional[Repository]:
        # Récupérer les infos d'un repo spécifique
        pass
    
    def get_authenticated_clone_url(self, repository: Repository) -> str:
        # Générer l'URL de clone authentifiée
        pass
  1. Enregistrer le provider dans providers/factory.py :
from .source.mon_provider import MonProviderSourceProvider

class ProviderFactory:
    _source_providers: Dict[str, Type[SourceProvider]] = {
        'gitea': GiteaSourceProvider,
        'gitlab': GitLabSourceProvider,
        'mon_provider': MonProviderSourceProvider,  # Nouveau provider
    }
  1. Ajouter la configuration dans core/config.py :
def _load_source_config(self) -> Dict[str, Any]:
    if self.source_provider == 'mon_provider':
        return {
            'url': os.getenv('MON_PROVIDER_URL'),
            'token': os.getenv('MON_PROVIDER_TOKEN'),
            'username': os.getenv('MON_PROVIDER_USERNAME')
        }
    # ... autres providers

Ajouter un nouveau provider destination

Le processus est identique, mais dans providers/destination/.

Patterns utilisés

1. Abstract Factory Pattern

  • ProviderFactory crée des instances de providers
  • Permet d'ajouter de nouveaux providers sans modifier le code existant

2. Strategy Pattern

  • Les providers implémentent des stratégies différentes pour accéder aux APIs
  • Le moteur de migration utilise ces stratégies de manière transparente

3. Template Method Pattern

  • SourceProvider et DestinationProvider définissent le squelette des opérations
  • Les implémentations concrètes remplissent les détails spécifiques

4. Dependency Injection

  • Les providers sont injectés dans MigrationEngine
  • Facilite les tests et la flexibilité

Configuration

Variables d'environnement

# Provider source
SOURCE_PROVIDER=gitea|gitlab
GITEA_URL=https://gitea.example.com
GITEA_TOKEN=your_token
GITEA_USERNAME=your_username

# Provider destination
DESTINATION_PROVIDER=github|gitlab
GITHUB_TOKEN=your_token
GITHUB_USERNAME=your_username

Extensibilité de la configuration

Pour ajouter un nouveau provider, il suffit d'ajouter les variables correspondantes et de modifier MigrationConfig.

Tests

Structure recommandée

tests/
├── unit/
│   ├── providers/
│   │   ├── test_gitea_provider.py
│   │   └── test_github_provider.py
│   ├── core/
│   │   └── test_migration_engine.py
│   └── ui/
│       └── test_interactive_selector.py
├── integration/
│   └── test_full_migration.py
└── fixtures/
    └── sample_repositories.json

Exemples de tests

# Test d'un provider
def test_gitea_provider_validates_config():
    config = {'url': 'https://gitea.com', 'token': 'token', 'username': 'user'}
    provider = GiteaSourceProvider(config)
    assert provider.base_url == 'https://gitea.com'

# Test du moteur de migration
def test_migration_engine_handles_errors():
    source = Mock(spec=SourceProvider)
    dest = Mock(spec=DestinationProvider)
    engine = MigrationEngine(source, dest)
    # Test error handling...

Bonnes pratiques

1. Gestion d'erreurs

  • Exceptions spécialisées pour chaque type d'erreur
  • Logging approprié à chaque niveau
  • Gestion gracieuse des échecs

2. Documentation

  • Docstrings pour toutes les méthodes publiques
  • Type hints pour la clarté du code
  • README et documentation d'architecture

3. Sécurité

  • Tokens jamais loggés
  • Nettoyage des repositories temporaires
  • Validation des entrées utilisateur

4. Performance

  • Pagination pour les listes de repositories
  • Parallélisation possible des migrations
  • Gestion efficace de la mémoire

Évolutions futures

Fonctionnalités potentielles

  • Migration incrémentale (seulement les changements)
  • Support des webhooks
  • Interface web
  • API REST
  • Migration de métadonnées (issues, pull requests)

Nouveaux providers

  • Bitbucket
  • Azure DevOps
  • Sourcehut
  • Codeberg

L'architecture actuelle permet d'ajouter facilement ces fonctionnalités sans restructuration majeure.