Créer un plugin
Le système de plugins de SourceAnt vous permet d'étendre la plateforme avec des intégrations personnalisées, des fournisseurs d'authentification, des backends LLM et bien plus encore.
Vue d'ensemble
Les plugins sont des classes Python qui héritent de BasePlugin. Chaque plugin déclare son type, ses métadonnées et ses hooks de cycle de vie. Le gestionnaire de plugins gère automatiquement la découverte, la résolution des dépendances et le cycle de vie.
Types de plugins
Chaque plugin doit déclarer l'un des types suivants via l' PluginType :
- INTEGRATION. Intégrations de services externes (GitHub, GitLab, etc.)
- AUTHENTICATION. Fournisseurs d'authentification (OAuth, SAML, etc.)
- LLM. Backends de modèles de langage
- WEBHOOK. Gestionnaires de webhooks
- NOTIFICATION. Canaux de notification (Slack, Email, etc.)
- UTILITY. Utilitaires
Démarrage rapide
Créez un nouveau répertoire sous src/plugins/ avec un fichier plugin.py :
src/plugins/
my_plugin/
plugin.py
__init__.py Voici un plugin minimal :
from src.core.plugins import BasePlugin, PluginMetadata, PluginType
class MyPlugin(BasePlugin):
@property
def metadata(self) -> PluginMetadata:
return PluginMetadata(
name="my_plugin",
version="1.0.0",
description="A custom plugin",
author="Your Name",
plugin_type=PluginType.UTILITY,
)
async def _initialize(self) -> None:
# One-time setup: register routes, connect to services
pass
async def _start(self) -> None:
# Called after all plugins are initialized
pass
async def _stop(self) -> None:
# Graceful shutdown
pass
async def _cleanup(self) -> None:
# Final cleanup before unload
pass Métadonnées du plugin
Le PluginMetadata La dataclass définit l'identité et la configuration de votre plugin :
| Champ | Type | Description |
|---|---|---|
name | str | Identifiant unique du plugin |
version | str | Version sémantique (par ex., "1.0.0") |
description | str | Brève description |
author | str | Auteur du plugin |
plugin_type | PluginType | L'une des valeurs de l'énumération des types de plugins |
dependencies | List[str] | Noms des plugins dont celui-ci dépend (par défaut : []) |
config_schema | Dict | Schéma JSON pour la validation de la configuration (par défaut : None) |
enabled | bool | Indique si le plugin est actif (par défaut : True) |
priority | int | Priorité de chargement, plus bas = plus tôt (par défaut : 100) |
Hooks de cycle de vie
Les plugins suivent un cycle de vie strict géré par le PluginManager:
- Découverte. Le gestionnaire analyse les répertoires de plugins à la recherche de
plugin.pyou__init__.py - Chargement. Les classes de plugins sont importées et instanciées
- Enregistrement. Les métadonnées sont validées et le plugin est enregistré
- Initialisation.
_initialize()est appelée dans l'ordre des dépendances - Démarrage.
_start()est appelée après l'initialisation de tous les plugins - Arrêt.
_stop()est appelée dans l'ordre inverse des dépendances - Nettoyage.
_cleanup()s'exécute avant le déchargement du plugin
Surcharge _initialize, _start, _stop, et _cleanup dans votre plugin. Les méthodes de la classe de base (initialize, start, etc.) gèrent le suivi de l'état et appellent vos implémentations.
Système d'événements
Les plugins interagissent avec SourceAnt via des points de hook et des abonnements aux événements.
Points de hook
Enregistrez des callbacks pour les événements de cycle de vie intégrés :
from src.core.plugins import event_hooks, HookPriority
# In your _initialize method:
event_hooks.register_hook(
hook_name="before_review_generation",
callback=self._on_before_review,
plugin_name=self.metadata.name,
priority=HookPriority.NORMAL,
) Points de hook disponibles :
- Cycle de vie de l'application.
app_startup,app_shutdown - Webhooks.
before_webhook_processing,after_webhook_processing - Revues de code.
before_review_generation,after_review_generation,before_review_posting,after_review_posting - Authentification.
before_user_authentication,after_user_authentication,before_user_logout,after_user_logout - Dépôts.
before_repository_authorization,after_repository_authorization,before_webhook_setup,after_webhook_setup - Erreurs.
on_error,on_plugin_error
Abonnements aux événements
Abonnez-vous à des événements spécifiques au domaine pour un contrôle plus granulaire :
event_hooks.subscribe_to_events(
plugin_name=self.metadata.name,
callback=self._handle_event,
event_types=[
"pull_request.opened",
"pull_request.synchronize",
],
) Priorité des hooks
Contrôlez l'ordre d'exécution des hooks avec HookPriority:
| Niveau | Valeur | Cas d'usage |
|---|---|---|
HIGHEST | 0 | Vérifications de sécurité, validation |
HIGH | 25 | Pré-traitement, enrichissement |
NORMAL | 50 | Traitement standard (par défaut) |
LOW | 75 | Post-traitement, journalisation |
LOWEST | 100 | Nettoyage, analyses |
Découverte des plugins
Le PluginManager découvre automatiquement les plugins en analysant les répertoires enregistrés. Pour qu'un plugin soit découvert, il doit :
- Se trouver dans un sous-répertoire d'un répertoire de plugins enregistré
- Contenir soit un
plugin.pyou__init__.pyfichier - Exporter une classe qui hérite de
BasePlugin
Les répertoires commençant par un underscore sont ignorés.
Dépendances
Déclarez les dépendances dans vos métadonnées pour garantir le bon ordre de chargement :
PluginMetadata(
name="my_plugin",
version="1.0.0",
description="Depends on GitHub OAuth",
author="Your Name",
plugin_type=PluginType.INTEGRATION,
dependencies=["github_oauth"],
) Le registre de plugins utilise un tri topologique pour résoudre le graphe de dépendances. Les dépendances circulaires sont détectées et entraîneront une erreur au moment du chargement. La méthode _initialize d'un plugin n'est appelée qu'après l'initialisation de toutes ses dépendances.
Validation de la configuration
Définir un schéma JSON dans config_schema pour valider la configuration du plugin au moment du chargement :
PluginMetadata(
name="my_notifier",
version="1.0.0",
description="Slack notifications",
author="Your Name",
plugin_type=PluginType.NOTIFICATION,
config_schema={
"type": "object",
"properties": {
"webhook_url": {"type": "string"},
"channel": {"type": "string"},
},
"required": ["webhook_url"],
},
) Accéder aux valeurs de configuration validées dans votre plugin avec self.get_config("webhook_url").