The current notification system in Semaphore UI is configured exclusively through config.json, supports a limited set of channels (Email, Telegram, Slack, MS Teams), and operates at the global level with minimal per-project customization. This feature redesigns notifications from the ground up to be UI-managed, extensible, and configurable at project and template granularity.
Goal: Define a common NotificationChannel interface in the backend with per-channel implementations, making it possible to add new channels by implementing a single interface.
Design considerations:
nikoksr/notify (Go library supporting 50+ services) or integrating with Apprise as a notification gateway to avoid maintaining per-provider code.Goal: Move notification setup entirely from config.json into the Web UI.
Requirements:
#ops, one for #dev).config.json as a fallback for existing deployments, but mark it as deprecated in docs.Related issues: #3387, #1821, #3588
Goal: Allow users to customize notification message content using templates.
Requirements:
{{ .Task.Name }}, {{ .Task.Status }}, {{ .Task.URL }}, {{ .Project.Name }}, {{ .Template.Name }}, {{ .Task.Duration }}, etc.slack.tmpl, email.tmpl, telegram.tmpl).Goal: Allow users to configure which notification channels are active on a per-project basis through project settings.
Requirements:
Related issues: #3588
Goal: Provide a generic webhook mechanism for integrating with arbitrary external services and CI/CD pipelines.
Requirements:
TASK_START, TASK_SUCCESS, TASK_FAILURE, TASK_CANCEL.Related issues: #1825, #2594, #3066
Goal: Add native support for commonly requested notification platforms.
Channels to add:
| Channel | Protocol | Notes | Issue |
|---|---|---|---|
| Discord | Webhook (similar to Slack) | High demand, straightforward implementation | #2924 |
| Ntfy | HTTP POST to ntfy.sh or self-hosted | Lightweight, push-notification focused | #3383 |
| Google Chat | Incoming webhook | Mostly needs a different payload template; logic similar to Slack | #1148 |
| Rocket.Chat | Incoming webhook | Same HTTP webhook pattern as Slack | #1091 |
| Pushover | HTTP API | Requires user key + application token | #2594 |
Note: If the outbound webhook feature (1.5) is implemented first, several of these could be documented as webhook configurations rather than native implementations.
Goal: Notify when a template recovers from failure — i.e., the first successful run after one or more consecutive failures.
Requirements:
on_failure / on_success / on_change notification modes.Related issues: #3380
Goal: Add a “Disable All Notifications” option on the task template options page.
Current state: Only “Disable Successful Notifications” checkbox exists. Users developing/debugging scripts have no way to suppress failure notifications without disabling the entire channel.
Requirements:
Related issues: #3724
Goal: Include email in the success notification path.
Current state: Email alerts are only sent on task failure. The sendMailAlert() function is not called from the success notification code path, while Telegram, Slack, and MS Teams are.
Fix: Add sendMailAlert() to the success notification handler, gated by the same “Disable Successful Notifications” checkbox.
Related issues: #3503
Goal: Ensure all notification channels receive a fully qualified, clickable task URL.
Current state: Multiple channels produce broken or unclickable links:
web_host prefix after an update, rendering links unclickable (#2097).{{ .Task.URL }} outputs a relative URI path (/project/1/templates/6?t=189) without scheme/host, failing Slack’s URL validation (#2311).Fix: Construct the task URL centrally using web_host configuration, producing a full URL (e.g., https://semaphore.example.com/project/1/templates/6?t=189). All notification templates should use this pre-built URL.
Goal: Resolve multiple SMTP-related bugs that prevent email notifications from working.
Issues to fix:
| Problem | Root Cause | Issue |
|---|---|---|
| Port 465 (implicit TLS/SMTPS) does not work | Semaphore uses STARTTLS, which only works on port 587. Port 465 requires implicit TLS from connection start. | #2201 |
| Auth command sent before TLS handshake | When TLS is off but SMTP auth is configured, the auth command is sent before STARTTLS | #2971 |
| Date header format incorrect | Uses UTC string instead of +0000, causing display/sorting issues in mail clients |
#3542 |
| Office365 port 587 fails | STARTTLS negotiation fails — connection reset when email_secure: true, STARTTLS required when email_secure: false |
#3209 |
Display name in email_sender breaks sending |
Using "Name <email>" format in sender field causes errors |
#2201 |
Goal: Send Telegram notifications to specific group threads (topics) using message_thread_id.
Requirements:
message_thread_id field to the Telegram notification configuration.Goal: Expose top-level fields in the Slack notification payload for Workflow Builder compatibility.
Current state: Slack’s Workflow Builder can only access top-level JSON fields. The current payload nests everything under attachments, which Workflow Builder cannot parse.
Fix: Add title, title_link, text, color, author, version as top-level fields alongside the existing attachments array.
Related issues: #2607
Goal: Allow configuring an HTTP proxy for outbound notification HTTP calls.
Requirements:
alert_proxy_endpoint configuration option (in config.json and/or environment variable).Related issues: #1484
Goal: Gate specific notification channels behind the Pro plan.
Requirements:
Goal: Trigger a notification when a task runs longer than a configurable threshold.
Requirements:
Related issues: #1393
Goal: Maintain a searchable, persistent log of all notification delivery attempts.
Requirements:
Related issues: #3410
Goal: Native integrations with enterprise incident management tools.
Integrations:
Requirements:
Goal: Restrict who can configure notification rules and channels based on organizational roles.
Requirements:
New tables required:
notification_channel — stores channel instances (project_id, type, name, config JSON, created_at, updated_at)notification_rule — links channels to templates/events (template_id, channel_id, on_success, on_failure, on_start, on_recovery)notification_log — audit log entries (Enterprise only) (channel_id, task_id, event_type, status, error, recipient, timestamp)GET/POST /api/project/{id}/notification-channels — list/create channelsPUT/DELETE /api/project/{id}/notification-channels/{channel_id} — update/delete channelPOST /api/project/{id}/notification-channels/{channel_id}/test — send test notificationGET/PUT /api/project/{id}/templates/{id}/notification-rules — get/set template notification rulesGET /api/project/{id}/notification-log — query audit log (Enterprise)