Nik Afiq 39b7d6d4b4
All checks were successful
CI / changes (push) Successful in 19s
CI / test (push) Successful in 31s
CI / build-ai-gateway (push) Successful in 1m8s
CI / build-ha-gateway (push) Successful in 1m19s
CI / build-discord-bot (push) Successful in 59s
CI / build-alexa-bridge (push) Successful in 1m8s
CI / build-alert-bridge (push) Successful in 1m17s
CI / build-tts-gateway (push) Successful in 1m10s
CI / build-tts-sidecar (push) Has been skipped
CI / build-tts-model (push) Has been skipped
feat: add alert-bridge service for external cronjob -> Discord alerts
New standalone service that receives authenticated HTTP POSTs (e.g. from a
cronjob elsewhere on the home network) and posts them to a Discord channel
via an Incoming Webhook. Fire-and-forget, no dependency on discord-bot's bot
session at all - mirrors alexa-bridge's precedent of a small bridge service
with its own HTTP listener and auth rather than adding an inbound edge to an
existing internal service.

Wires alert-bridge into go.work, CI (changes filter, test job, new
build-alert-bridge job), and the other five Dockerfiles' COPY lines.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-01 22:45:18 +09:00

49 lines
1.5 KiB
Go

package config
import (
"errors"
"os"
)
// Config holds runtime configuration for the alert-bridge process.
type Config struct {
HTTPPort string // HTTP_PORT, default "8080"
APIKey string // API_KEY — required bearer token callers must present in Authorization: Bearer <key>
DiscordWebhookURL string // DISCORD_WEBHOOK_URL — required, the target channel's Discord Incoming Webhook URL
MentionUserID string // MENTION_USER_ID — optional Discord user ID; when set, level=error alerts mention this user
OTELEndpoint string
LogLevel string
LogFormat string
}
// Load reads alert-bridge configuration from environment variables.
func Load() (*Config, error) {
apiKey := os.Getenv("API_KEY")
if apiKey == "" {
return nil, errors.New("API_KEY is required but not set")
}
webhookURL := os.Getenv("DISCORD_WEBHOOK_URL")
if webhookURL == "" {
return nil, errors.New("DISCORD_WEBHOOK_URL is required but not set")
}
return &Config{
HTTPPort: getenvDefault("HTTP_PORT", "8080"),
APIKey: apiKey,
DiscordWebhookURL: webhookURL,
MentionUserID: os.Getenv("MENTION_USER_ID"),
OTELEndpoint: os.Getenv("OTEL_ENDPOINT"),
LogLevel: getenvDefault("LOG_LEVEL", "info"),
LogFormat: getenvDefault("LOG_FORMAT", "json"),
}, nil
}
// getenvDefault keeps config loading concise for optional variables with defaults.
func getenvDefault(key, fallback string) string {
if v := os.Getenv(key); v != "" {
return v
}
return fallback
}