Add external alerting via Webhook, Slack, and PagerDuty notification adapters#230
Merged
Conversation
…adapters
Introduces a Foundation.Notifications subsystem that dispatches deployment
lifecycle events to configured external channels. Delivery is fully async
(Task.Supervisor) so no caller is ever blocked.
Three adapters are provided out of the box:
- Foundation.Notifications.Webhook — generic HTTP POST with a JSON body
- Foundation.Notifications.Slack — Slack Incoming Webhook with per-event
mrkdwn formatting and emoji
- Foundation.Notifications.PagerDuty — PagerDuty Events API v2 with automatic
severity mapping per event type
Six events are instrumented across the system:
- :crash_restart (Deployer.Monitor.Application)
- :deployment_started (Deployer.Monitor.Application)
- :deployment_complete (Deployer.HotUpgrade.Application)
- :watchdog_threshold_exceeded (Sentinel.Watchdog)
- :certificate_renewed (Foundation.Certificates.Manager)
- :certificate_failed (Foundation.Certificates.Manager)
Channels are configured in deployex.yaml under a top-level `notifications:`
list. Each entry specifies an adapter, a URL, an enabled flag, an event
subscription list, and an optional adapter-specific `options:` map (e.g.
routing_key for PagerDuty, username/icon_emoji for Slack).
Foundation.Application gains Foundation.Finch and Foundation.TaskSupervisor
to support outgoing HTTP and async dispatch without depending on Deployer's
supervision tree.
Replaces the Task.Supervisor dispatch model with a proper OTP supervision
tree. Each entry in the notifications: YAML list now gets its own
Foundation.Notifications.Worker GenServer, managed by
Foundation.Notifications.Supervisor.
Key design changes:
- Foundation.Notifications.notify/2 broadcasts to a per-event PubSub topic
("deployex::notifications::<event>") instead of reading app env and
spawning tasks on every call.
- Each Worker subscribes at init only to the topics matching its events
list, so PubSub routing handles delivery without any filtering in
handle_info. Disabled workers subscribe to nothing and are never invoked.
- Foundation.Notifications.topic/1 (was topic/0) takes the event atom and
returns the corresponding topic string.
- Task.Supervisor removed from Foundation.Application; replaced by
Foundation.Notifications.Supervisor.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Introduces a Foundation.Notifications subsystem that dispatches deployment lifecycle events to configured external channels. Delivery is fully async (Task.Supervisor) so no caller is ever blocked.
Three adapters are provided out of the box:
mrkdwn formatting and emoji
severity mapping per event type
Six events are instrumented across the system:
Channels are configured in deployex.yaml under a top-level
notifications:list. Each entry specifies an adapter, a URL, an enabled flag, an event subscription list, and an optional adapter-specificoptions:map (e.g. routing_key for PagerDuty, username/icon_emoji for Slack).Foundation.Application gains Foundation.Finch and Foundation.TaskSupervisor to support outgoing HTTP and async dispatch without depending on Deployer's supervision tree.
Co-Authored-By: Claude Sonnet 4.6 noreply@anthropic.com