Add Telegram receiver as default Alertmanager route #41

Merged
forgejo_admin merged 1 commit from 40-add-telegram-alertmanager-receiver into main 2026-03-14 14:13:55 +00:00

Summary

Adds a Telegram receiver to Alertmanager and makes it the default route when configured. The bot token is injected via set_sensitive (matching the existing Slack pattern) so it never appears in state or plan output. Also reduces repeat_interval from 12h to 4h for faster re-notification.

Changes

  • terraform/main.tf: Added telegram receiver with telegram_configs (send_resolved: true, parse_mode: HTML) to the receivers concat list. Changed default route receiver to "telegram" when telegram_bot_token is set (falls back to "default" otherwise). Added dynamic set_sensitive block for telegram_bot_token with computed receiver index (accounts for optional Slack receiver). Changed repeat_interval from 12h to 4h.
  • terraform/variables.tf: Added telegram_bot_token (string, sensitive, default "") and telegram_chat_id (number, default 0) variables.

Test Plan

  • tofu fmt -- passes (no changes)
  • tofu validate -- cannot run in worktree (no cached providers), but HCL syntax is valid per tofu fmt -check
  • Deploy with telegram_bot_token and telegram_chat_id set, verify Alertmanager config shows telegram as default receiver
  • Deploy with only telegram_bot_token="" to verify fallback to "default" receiver
  • Verify existing Slack receiver is unchanged when both are configured

Review Checklist

  • tofu fmt passes
  • tofu validate attempted (provider cache unavailable in worktree)
  • Sensitive values use set_sensitive dynamic block, not yamlencode
  • Existing Slack receiver and default null receiver unchanged
  • Variables have descriptions, types, and defaults
  • PR includes Closes #40

tofu plan

Cannot run tofu plan in worktree (no provider cache / state). Plan should be run from the main checkout before apply.

## Summary Adds a Telegram receiver to Alertmanager and makes it the default route when configured. The bot token is injected via `set_sensitive` (matching the existing Slack pattern) so it never appears in state or plan output. Also reduces `repeat_interval` from 12h to 4h for faster re-notification. ## Changes - **terraform/main.tf**: Added `telegram` receiver with `telegram_configs` (send_resolved: true, parse_mode: HTML) to the receivers concat list. Changed default route receiver to `"telegram"` when `telegram_bot_token` is set (falls back to `"default"` otherwise). Added dynamic `set_sensitive` block for `telegram_bot_token` with computed receiver index (accounts for optional Slack receiver). Changed `repeat_interval` from `12h` to `4h`. - **terraform/variables.tf**: Added `telegram_bot_token` (string, sensitive, default `""`) and `telegram_chat_id` (number, default `0`) variables. ## Test Plan - `tofu fmt` -- passes (no changes) - `tofu validate` -- cannot run in worktree (no cached providers), but HCL syntax is valid per `tofu fmt -check` - Deploy with `telegram_bot_token` and `telegram_chat_id` set, verify Alertmanager config shows telegram as default receiver - Deploy with only `telegram_bot_token=""` to verify fallback to `"default"` receiver - Verify existing Slack receiver is unchanged when both are configured ## Review Checklist - [x] `tofu fmt` passes - [x] `tofu validate` attempted (provider cache unavailable in worktree) - [x] Sensitive values use `set_sensitive` dynamic block, not yamlencode - [x] Existing Slack receiver and default null receiver unchanged - [x] Variables have descriptions, types, and defaults - [x] PR includes `Closes #40` ## Related - Closes #40 ## tofu plan Cannot run `tofu plan` in worktree (no provider cache / state). Plan should be run from the main checkout before apply.
- Add telegram receiver with telegram_configs (send_resolved, HTML parse_mode)
- Change default route from "default" to "telegram" when token is set
- Inject telegram_bot_token via set_sensitive dynamic block (same pattern as Slack)
- Add telegram_bot_token (sensitive) and telegram_chat_id variables
- Reduce repeat_interval from 12h to 4h

Closes #40

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Author
Owner

Self-Review

Verdict: LGTM -- no issues found.

Checked

  • telegram_bot_token injected via set_sensitive dynamic block -- matches the existing Slack pattern exactly. Token never appears in yamlencode or plan output.
  • telegram_chat_id (non-sensitive number) correctly placed in yamlencode block.
  • Receiver index in set_sensitive path uses ${var.slack_webhook_url != "" ? 2 : 1} -- correctly accounts for the concat order (default=0, slack=1 when present, telegram shifts accordingly).
  • Default route conditionally switches to "telegram" only when telegram_bot_token is set; falls back to "default" otherwise.
  • Existing default null receiver and conditional slack receiver are completely unchanged.
  • repeat_interval changed from 12h to 4h as specified.
  • tofu fmt -check passes with no changes needed.
  • Both new variables have descriptions, types, and defaults.
  • telegram_configs includes send_resolved: true and parse_mode: "HTML" as required.
## Self-Review **Verdict: LGTM -- no issues found.** ### Checked - `telegram_bot_token` injected via `set_sensitive` dynamic block -- matches the existing Slack pattern exactly. Token never appears in yamlencode or plan output. - `telegram_chat_id` (non-sensitive number) correctly placed in yamlencode block. - Receiver index in `set_sensitive` path uses `${var.slack_webhook_url != "" ? 2 : 1}` -- correctly accounts for the concat order (default=0, slack=1 when present, telegram shifts accordingly). - Default route conditionally switches to `"telegram"` only when `telegram_bot_token` is set; falls back to `"default"` otherwise. - Existing `default` null receiver and conditional `slack` receiver are completely unchanged. - `repeat_interval` changed from `12h` to `4h` as specified. - `tofu fmt -check` passes with no changes needed. - Both new variables have descriptions, types, and defaults. - `telegram_configs` includes `send_resolved: true` and `parse_mode: "HTML"` as required.
Author
Owner

PR #41 Review

BLOCKERS

None. The implementation is correct and well-structured.

NITS

  1. No validation on telegram_chat_id -- When telegram_bot_token is set but telegram_chat_id is left at default 0, Alertmanager will create a telegram receiver with an invalid chat ID, which could cause delivery errors at runtime. Consider adding a validation block similar to harbor/minio passwords, or gating the telegram receiver on both telegram_bot_token != "" AND telegram_chat_id != 0. Low severity since the user must consciously set both values.

  2. Missing tofu plan output -- PR conventions require tofu plan for Terraform changes. The PR explains this is a worktree limitation (no cached providers/state). Acceptable given the constraint, but the plan should be run from the main checkout before apply.

SOP COMPLIANCE

  • Branch named after issue (40-add-telegram-alertmanager-receiver -> issue #40)
  • PR body follows template (Summary, Changes, Test Plan, Related sections present)
  • Related section references Closes #40
  • No secrets committed (bot token injected via set_sensitive, not yamlencode)
  • No .env files or credentials in the diff
  • No unnecessary file changes (2 files, tightly scoped)
  • tofu fmt compliance confirmed per PR checklist

Review Details

Security (PASS): The telegram_bot_token is correctly handled via dynamic "set_sensitive" block (line 311-318 of main.tf), exactly matching the existing Slack webhook pattern. The token never enters yamlencode and will not appear in plan/state output.

Receiver index calculation (PASS): The concat() ordering is [default, slack?, telegram?], making the index receivers[1] when Slack is absent and receivers[2] when Slack is present. The expression var.slack_webhook_url != "" ? 2 : 1 correctly maps to this.

Default route conditional (PASS): var.telegram_bot_token != "" ? "telegram" : "default" correctly falls back to the null receiver when Telegram is not configured. When both Slack and Telegram are configured, Telegram becomes the default route while Slack handles severity-matched alerts via its sub-route.

Existing receivers unchanged (PASS): The "default" null receiver and "slack" conditional receiver are structurally identical to the pre-PR state. The only change in that block is the trailing comma on ] : [], to accommodate the new concat() segment.

repeat_interval change (PASS): 12h to 4h is intentional per the PR description. Reasonable for a platform with active alerting.

Variable definitions (PASS): telegram_bot_token is string, sensitive = true, default "". telegram_chat_id is number, default 0. Both have descriptions. Types and defaults are appropriate.

VERDICT: APPROVED

## PR #41 Review ### BLOCKERS None. The implementation is correct and well-structured. ### NITS 1. **No validation on `telegram_chat_id`** -- When `telegram_bot_token` is set but `telegram_chat_id` is left at default `0`, Alertmanager will create a telegram receiver with an invalid chat ID, which could cause delivery errors at runtime. Consider adding a validation block similar to harbor/minio passwords, or gating the telegram receiver on both `telegram_bot_token != ""` AND `telegram_chat_id != 0`. Low severity since the user must consciously set both values. 2. **Missing `tofu plan` output** -- PR conventions require `tofu plan` for Terraform changes. The PR explains this is a worktree limitation (no cached providers/state). Acceptable given the constraint, but the plan should be run from the main checkout before apply. ### SOP COMPLIANCE - [x] Branch named after issue (`40-add-telegram-alertmanager-receiver` -> issue #40) - [x] PR body follows template (Summary, Changes, Test Plan, Related sections present) - [x] Related section references `Closes #40` - [x] No secrets committed (bot token injected via `set_sensitive`, not `yamlencode`) - [x] No .env files or credentials in the diff - [x] No unnecessary file changes (2 files, tightly scoped) - [x] `tofu fmt` compliance confirmed per PR checklist ### Review Details **Security (PASS)**: The `telegram_bot_token` is correctly handled via `dynamic "set_sensitive"` block (line 311-318 of `main.tf`), exactly matching the existing Slack webhook pattern. The token never enters `yamlencode` and will not appear in plan/state output. **Receiver index calculation (PASS)**: The `concat()` ordering is `[default, slack?, telegram?]`, making the index `receivers[1]` when Slack is absent and `receivers[2]` when Slack is present. The expression `var.slack_webhook_url != "" ? 2 : 1` correctly maps to this. **Default route conditional (PASS)**: `var.telegram_bot_token != "" ? "telegram" : "default"` correctly falls back to the null receiver when Telegram is not configured. When both Slack and Telegram are configured, Telegram becomes the default route while Slack handles severity-matched alerts via its sub-route. **Existing receivers unchanged (PASS)**: The `"default"` null receiver and `"slack"` conditional receiver are structurally identical to the pre-PR state. The only change in that block is the trailing comma on `] : [],` to accommodate the new `concat()` segment. **`repeat_interval` change (PASS)**: `12h` to `4h` is intentional per the PR description. Reasonable for a platform with active alerting. **Variable definitions (PASS)**: `telegram_bot_token` is `string`, `sensitive = true`, default `""`. `telegram_chat_id` is `number`, default `0`. Both have descriptions. Types and defaults are appropriate. ### VERDICT: APPROVED
forgejo_admin deleted branch 40-add-telegram-alertmanager-receiver 2026-03-14 14:13:55 +00:00
Sign in to join this conversation.
No description provided.