alertmanager-gotify-bridge: initial commit with bridge and CI
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
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
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
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()