feat(notify): Telegram Bot notifier — v1.1.0 (closes #22)#23
Merged
Conversation
added 3 commits
April 15, 2026 08:31
Native `type: telegram` notifier using the Bot API sendMessage endpoint. Supports multi-chat delivery (one sequential HTTP call per chat_id), HTML parse_mode by default, 429 Retry-After handling with bounded delay, and codepoint-safe truncation at Telegram's 4096-character limit. Safety: - bot_token stored as SecretString; full endpoint URL (which contains the token) is kept in SecretString and never logged - reqwest errors are sanitized via `.without_url()` before logging - fail-fast on empty chat_ids, empty chat_id elements, unresolved or empty bot_token, invalid body_template - Retry-After clamped to [1s, 60s] to prevent tight loops and adversarial delays Observability: - new `valerter_alerts_truncated_total` Prometheus counter - existing sent/failed/error counters gain `notifier_type="telegram"` Cargo.toml bumped to 1.1.0.
- Extend .gitignore to cover config/prod-*/ so local test variants (e.g. config/prod-test-telegram) cannot be accidentally committed. - Document in CHANGELOG the known limitation that Markdown-flavored template bodies render literally in Telegram's HTML parse_mode, with the body_template workaround. A proper render-pipeline-per- notifier will land in 1.2.
Codecov Report❌ Patch coverage is
📢 Thoughts on this report? Let us know! |
added 2 commits
April 15, 2026 09:27
…aths Patch coverage bumped from 81.65% by adding targeted tests for previously uncovered lines: - src/config/tests.rs: two tests exercising Config::validate() for a Telegram notifier with empty chat_ids (fails) and with populated chat_ids (passes). - src/notify/tests.rs: two registry tests that instantiate a Telegram notifier from config and that verify validation errors propagate through NotifierRegistry::from_config. - src/notify/telegram.rs: three wiremock scenarios covering the 5xx retry path (recovers after one 5xx), the MaxRetriesExceeded path on persistent 5xx, and the Err(reqwest::Error) branch on network failure when the server goes away.
… on CI On CI, wiremock's random-port allocation could recycle a port from a just-dropped server, letting requests from one test land on another test's server. This produced two intermittent failures: - send_network_error_exhausts_retries observed the dropped server's port reused by a live mock and saw Ok(()) instead of a connect error. - send_payload_has_expected_fields saw a second request body leak in from a peer test, tripping the exact-count verification. Fixes: - Mark every send_* wiremock test with #[serial] so they run one at a time. Adds ~3s of total runtime, eliminates the flake. - Replace the drop-server trick in send_network_error_exhausts_retries with a connection to TEST-NET-1 (192.0.2.1, RFC 5737) and a short connect_timeout, guaranteeing ECONNREFUSED / timeout regardless of port reuse.
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.
Summary
Adds a native
type: telegramnotifier to valerter, alongside the existing Mattermost / Webhook / Email notifiers. Resolves issue #22.sendMessageendpoint, one sequential HTTP call perchat_id(Telegram rate-limits at 1 msg/sec/chat so fan-out parallelism would not help).parse_mode: HTMLby default, UTF-8 codepoint-safe truncation at Telegram's 4096 hard limit.Retry-Afterhandling with bounded delay[1s, 60s]and a pool of 3 retries shared with 5xx + network errors.bot_tokenstored asSecretString. Full endpoint URL (which contains the token) is kept inSecretStringand never logged —reqwest::Erroris sanitized via.without_url()before tracing.valerter_alerts_truncated_total{notifier_type}.Validation
_bmad-output/implementation-artifacts/deferred-work.md.Cargo.toml,Cargo.lock, CHANGELOG.Known limitation (documented in CHANGELOG)
Templates have a single
bodyfield shared across notifiers. Markdown-flavored bodies (written for Mattermost) render literally in Telegram's HTML mode. Workaround: overridebody_templateon the Telegram notifier with HTML-friendly Jinja. A render-pipeline-per-notifier abstraction is planned for 1.2.Test plan
cargo fmt --checkcargo clippy --all-targets -- -D warningscargo test— 459 passed, 0 failedcargo build --releasev1.1.0→ release workflow publishes x86_64/aarch64 tarballs +.deb