SourceAnt

Crear un plugin

El sistema de plugins de SourceAnt le permite ampliar la plataforma con integraciones personalizadas, proveedores de autenticación, backends LLM y más.

Resumen

Los plugins son clases de Python que heredan de BasePlugin. Cada plugin declara su tipo, metadatos y hooks de ciclo de vida. El gestor de plugins maneja automáticamente el descubrimiento, la resolución de dependencias y la gestión del ciclo de vida.

Tipos de plugins

Cada plugin debe declarar uno de los siguientes tipos mediante el PluginType enum:

  • INTEGRATION. Integraciones de servicios externos (GitHub, GitLab, etc.)
  • AUTHENTICATION. Proveedores de autenticación (OAuth, SAML, etc.)
  • LLM. Backends de modelos de lenguaje
  • WEBHOOK. Manejadores de webhooks
  • NOTIFICATION. Canales de notificación (Slack, Email, etc.)
  • UTILITY. Utilidades auxiliares

Inicio rápido

Cree un nuevo directorio bajo src/plugins/ con un plugin.py archivo:

src/plugins/
  my_plugin/
    plugin.py
    __init__.py

Aquí hay un plugin mínimo:

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

Metadatos del plugin

La PluginMetadata La dataclass define la identidad y configuración de su plugin:

Campo Tipo Descripción
namestrIdentificador único del plugin
versionstrVersión semántica (por ejemplo, "1.0.0")
descriptionstrDescripción breve
authorstrAutor del plugin
plugin_typePluginTypeUno de los valores del enum de tipo de plugin
dependenciesList[str]Nombres de los plugins de los que depende (predeterminado: [])
config_schemaDictEsquema JSON para la validación de la configuración (predeterminado: None)
enabledboolSi el plugin está activo (predeterminado: True)
priorityintPrioridad de carga, menor = antes (predeterminado: 100)

Hooks del ciclo de vida

Los plugins siguen un ciclo de vida estricto gestionado por el PluginManager:

  1. Descubrimiento. El gestor escanea los directorios de plugins en busca de plugin.py o __init__.py
  2. Carga. Las clases de plugin se importan y se instancian
  3. Registro. Los metadatos se validan y el plugin se registra
  4. Inicialización. _initialize() se llama en orden de dependencias
  5. Arranque. _start() se llama después de que todos los plugins se hayan inicializado
  6. Apagado. _stop() se llama en orden inverso de dependencias
  7. Limpieza. _cleanup() se ejecuta antes de que el plugin se descargue

Sobrescribir _initialize, _start, _stop, y _cleanup en su plugin. Los métodos de la clase base (initialize, start, etc.) gestionan el seguimiento del estado y llaman a sus implementaciones.

Sistema de eventos

Los plugins interactúan con SourceAnt mediante puntos de enganche y suscripciones a eventos.

Puntos de enganche

Registre callbacks para eventos integrados del ciclo de vida:

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,
)

Puntos de enganche disponibles:

  • Ciclo de vida de la aplicación. app_startup, app_shutdown
  • Webhooks. before_webhook_processing, after_webhook_processing
  • Revisiones de código. before_review_generation, after_review_generation, before_review_posting, after_review_posting
  • Autenticación. before_user_authentication, after_user_authentication, before_user_logout, after_user_logout
  • Repositorios. before_repository_authorization, after_repository_authorization, before_webhook_setup, after_webhook_setup
  • Errores. on_error, on_plugin_error

Suscripciones a eventos

Suscríbase a eventos específicos de dominio para un control más granular:

event_hooks.subscribe_to_events(
    plugin_name=self.metadata.name,
    callback=self._handle_event,
    event_types=[
        "pull_request.opened",
        "pull_request.synchronize",
    ],
)

Prioridad de hooks

Controle el orden en que se ejecutan los hooks con HookPriority:

Nivel Valor Caso de uso
HIGHEST0Comprobaciones de seguridad, validación
HIGH25Preprocesamiento, enriquecimiento
NORMAL50Procesamiento estándar (predeterminado)
LOW75Posprocesamiento, registro
LOWEST100Limpieza, analítica

Descubrimiento de plugins

La PluginManager descubre automáticamente los plugins escaneando los directorios registrados. Para que un plugin sea descubierto, debe:

  1. Estar en un subdirectorio de un directorio de plugins registrado
  2. Contener un archivo plugin.py o __init__.py archivo
  3. Exportar una clase que herede de BasePlugin

Se omiten los directorios que empiezan por guion bajo.

Dependencias

Declare las dependencias en sus metadatos para garantizar el orden de carga correcto:

PluginMetadata(
    name="my_plugin",
    version="1.0.0",
    description="Depends on GitHub OAuth",
    author="Your Name",
    plugin_type=PluginType.INTEGRATION,
    dependencies=["github_oauth"],
)

El registro de plugins utiliza la ordenación topológica para resolver el grafo de dependencias. Las dependencias circulares se detectan y provocarán un error en el momento de la carga. El método _initialize de un plugin solo se llama después de que se hayan inicializado todas sus dependencias.

Validación de la configuración

Definir un JSON Schema en config_schema para validar la configuración del plugin en el momento de la carga:

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"],
    },
)

Acceder a los valores de configuración validados en su plugin con self.get_config("webhook_url").