alertmanager-gotify-bridge: initial commit with bridge and CI
Some checks failed
ci/woodpecker/tag/woodpecker Pipeline failed

This commit is contained in:
Oleks
2026-03-16 17:26:06 +02:00
commit 4c7dcd9279
3 changed files with 115 additions and 0 deletions

24
.woodpecker.yaml Normal file
View File

@@ -0,0 +1,24 @@
labels:
arch: amd64
when:
- event: tag
ref: "refs/tags/v*"
steps:
- name: build-and-push
image: git.oleks.space/oleks/nix-ci:latest
environment:
REGISTRY_TOKEN:
from_secret: registry_token
commands:
- echo "$REGISTRY_TOKEN" | docker login git.oleks.space -u oleks --password-stdin
- docker buildx create --name amd64 --driver remote "tcp://buildkit-rootless-amd64.infra.svc.cluster.local:1234"
- TAG=$(echo "$CI_COMMIT_TAG" | sed 's/^v//')
- IMAGE="git.oleks.space/oleks/alertmanager-gotify-bridge"
- echo "Building $IMAGE:$TAG"
- docker buildx build --builder amd64 --platform linux/amd64 --tag "$IMAGE:$TAG" --tag "$IMAGE:latest" --push .
backend_options:
kubernetes:
nodeSelector:
kubernetes.io/hostname: howard2404

5
Dockerfile Normal file
View File

@@ -0,0 +1,5 @@
FROM python:3.12-alpine
COPY bridge.py /app/bridge.py
WORKDIR /app
EXPOSE 8080
CMD ["python", "bridge.py"]

86
bridge.py Normal file
View File

@@ -0,0 +1,86 @@
#!/usr/bin/env python3
"""Alertmanager webhook receiver that forwards alerts to Gotify."""
import json
import os
import sys
from http.server import HTTPServer, BaseHTTPRequestHandler
from urllib.request import Request, urlopen
from urllib.error import URLError
GOTIFY_URL = os.environ["GOTIFY_URL"]
DISASTER_TOKEN = os.environ["DISASTER_TOKEN"]
WARNING_TOKEN = os.environ["WARNING_TOKEN"]
DISASTER_PRIORITY = int(os.environ.get("DISASTER_PRIORITY", "8"))
WARNING_PRIORITY = int(os.environ.get("WARNING_PRIORITY", "4"))
SEVERITY_MAP = {
"critical": (DISASTER_TOKEN, DISASTER_PRIORITY),
"warning": (WARNING_TOKEN, WARNING_PRIORITY),
}
def send_gotify(token, title, message, priority):
data = json.dumps({
"title": title,
"message": message,
"priority": priority,
}).encode()
req = Request(
f"{GOTIFY_URL}/message?token={token}",
data=data,
headers={"Content-Type": "application/json"},
)
try:
urlopen(req)
except URLError as e:
print(f"ERROR sending to Gotify: {e}", file=sys.stderr)
class Handler(BaseHTTPRequestHandler):
def do_POST(self):
try:
length = int(self.headers.get("Content-Length", 0))
body = json.loads(self.rfile.read(length))
except (json.JSONDecodeError, ValueError) as e:
self.send_response(400)
self.end_headers()
self.wfile.write(f"Bad request: {e}".encode())
return
for alert in body.get("alerts", []):
severity = alert.get("labels", {}).get("severity", "warning")
token, priority = SEVERITY_MAP.get(severity, SEVERITY_MAP["warning"])
status = alert.get("status", "firing")
alertname = alert.get("labels", {}).get("alertname", "Unknown")
summary = alert.get("annotations", {}).get("summary", "")
prefix = "RESOLVED" if status == "resolved" else "FIRING"
title = f"[{prefix}] {alertname}"
message = summary or f"{alertname} is {status}"
send_gotify(token, title, message, priority)
print(f"Forwarded: {title} -> severity={severity} priority={priority}")
self.send_response(200)
self.end_headers()
self.wfile.write(b"ok")
def do_GET(self):
if self.path == "/health":
self.send_response(200)
self.end_headers()
self.wfile.write(b"ok")
return
self.send_response(404)
self.end_headers()
def log_message(self, format, *args):
print(format % args)
if __name__ == "__main__":
port = int(os.environ.get("PORT", "8080"))
server = HTTPServer(("0.0.0.0", port), Handler)
print(f"Bridge listening on :{port}")
server.serve_forever()