Skip to content

Conversation

@glefer
Copy link
Owner

@glefer glefer commented Sep 24, 2025

This pull request introduces webhook support to GitHub Runner Manager.

Key features and changes:

Webhook notifications:

Added support for sending notifications on key runner events (start, stop, error, build, update, etc.).
Supports multiple providers: Slack, Discord, Microsoft Teams, and generic webhooks.
Configurable in runners_config.yaml with options for enabling/disabling, timeout, retry, and per-provider settings.
Events can be filtered per provider.
Configuration examples and documentation:

Updated README.md with detailed instructions and configuration samples for webhooks.
Provided example runners_config.yaml.webhook-example for quick setup.
Added CLI commands to test webhooks without triggering real actions.
Testing and validation:

Includes tests for webhook formatting, sending, and retry logic.
Ensures configuration schema supports new webhook options.

@glefer glefer requested a review from Copilot September 24, 2025 11:09
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This pull request introduces comprehensive webhook support to GitHub Runner Manager, allowing users to receive notifications on key runner events through multiple providers (Slack, Discord, Microsoft Teams, and generic webhooks).

  • Webhook system implementation with configurable providers and event filtering
  • Test commands for validating webhook configurations and templates
  • Full test coverage with mocking to prevent real HTTP requests during testing

Reviewed Changes

Copilot reviewed 18 out of 18 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
tests/services/test_webhook_service.py Comprehensive unit tests for WebhookService covering providers, notifications, payloads, retry logic, and formatters
tests/services/test_notification_service.py Tests for NotificationService integration with webhook functionality and dispatcher behavior
tests/presentation/cli/test_webhook_commands_unit.py Unit tests for webhook CLI commands covering prompt logic, error handling, and result display
tests/presentation/cli/test_webhook_commands.py Integration tests for CLI webhook command invocation
tests/notifications/test_factory_events.py Tests for event factory converting operation results to typed notification events
tests/conftest.py Global test fixtures to mock webhook services and prevent real HTTP requests
src/services/webhook_service.py Core webhook service implementation supporting multiple providers with retry logic and templating
src/services/notification_service.py Refactored notification service using event dispatcher pattern while maintaining backward compatibility
src/services/config_schema.py Extended configuration schema with webhook-specific models and validation
src/presentation/cli/webhook_commands.py CLI commands for testing and debugging webhook configurations
src/presentation/cli/commands.py Integration of webhook testing commands into main CLI application
src/notifications/factory.py Factory utilities for converting Docker operation results to typed notification events
src/notifications/events.py Typed notification event definitions using dataclasses
src/notifications/dispatcher.py Event dispatcher routing notifications to registered channels
src/notifications/channels/webhook.py Webhook channel implementation for the notification system
src/notifications/channels/base.py Base interfaces and registry for notification channels
README.md Updated documentation with webhook configuration examples and usage instructions
.coveragerc Removed coverage configuration file
Comments suppressed due to low confidence (1)

tests/services/test_notification_service.py:1

  • This comment indicates that duplicate code was removed, but it appears to be a leftover comment that should be deleted as it doesn't provide value and may confuse future maintainers.
import types

Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.

Comment on lines 369 to 402
# Patch notification_service
monkeypatch.setattr(
commands,
"notification_service",
types.SimpleNamespace(notify_runner_removed=lambda d: notified.append(d)),
)
# Patch config_service/dummy
monkeypatch.setattr(
commands, "config_service", types.SimpleNamespace(load_config=lambda: None)
)
# Patch docker_service pour retourner deleted et skipped
monkeypatch.setattr(
commands,
"docker_service",
types.SimpleNamespace(
remove_runners=lambda: {
"deleted": [{"id": "x", "name": "foo"}],
"skipped": [{"name": "bar"}],
"errors": [],
}
),
)
# Patch console
monkeypatch.setattr(
commands,
"console",
types.SimpleNamespace(print=lambda *a, **k: printed.append(a[0] if a else "")),
)
# Appel
commands.remove_runners()
# Vérifie notification
assert any(d["runner_id"] == "x" and d["runner_name"] == "foo" for d in notified)
# Vérifie affichage suppression indisponible
assert any("bar n'est pas disponible à la suppression" in s for s in printed)
Copy link

Copilot AI Sep 24, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This test contains duplicated code from lines 329-402. The entire setup (patches for notification_service, config_service, docker_service, and console) and test logic is repeated. This should be refactored to use a helper function or parameterized test to reduce duplication and improve maintainability.

Copilot uses AI. Check for mistakes.
Comment on lines +273 to +294
class DummyConfig:
def __init__(self, enabled=True, providers=None, events=None):
self.webhooks = types.SimpleNamespace(
enabled=enabled,
dict=lambda: {},
model_dump=lambda: {},
)
self.webhooks.dict = lambda: {}
self.webhooks.model_dump = lambda: {}
self.webhooks.enabled = enabled
self.webhooks.slack = types.SimpleNamespace(
enabled=True, events=events or [], templates={}
)


class DummyWebhookService:
def __init__(self, providers=None):
self.providers = providers or {}
self._send_notification = lambda *a, **k: True

def notify(self, event_type, data, provider=None):
return {provider or "slack": True}
Copy link

Copilot AI Sep 24, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The DummyConfig and DummyWebhookService classes are duplicated from the fixture definitions at the top of the file (lines 13-42). This duplication should be removed and the existing fixtures should be used instead to improve maintainability and avoid inconsistencies.

Copilot uses AI. Check for mistakes.
@github-actions
Copy link

Coverage

Coverage Report
FileStmtsMissCoverMissing
__init__.py10100% 
notifications
   dispatcher.py130100% 
   events.py830100% 
   factory.py400100% 
notifications/channels
   base.py110100% 
   webhook.py210100% 
presentation
   __init__.py00100% 
presentation/cli
   __init__.py00100% 
   commands.py1740100% 
   main.py190100% 
   webhook_commands.py940100% 
services
   __init__.py40100% 
   config_schema.py830100% 
   config_service.py200100% 
   docker_logger.py220100% 
   docker_service.py4030100% 
   notification_service.py500100% 
   scheduler_service.py1620100% 
   webhook_service.py1570100% 
TOTAL13570100% 

@glefer glefer merged commit e904783 into main Sep 25, 2025
2 checks passed
@glefer glefer deleted the feat/webhook branch September 25, 2025 05:52
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants