Add Helm chart for Matrix Alertmanager receiver
This commit is contained in:
@@ -0,0 +1,86 @@
|
||||
name: Validate, publish and promote Matrix Alertmanager receiver chart
|
||||
|
||||
on:
|
||||
push:
|
||||
pull_request:
|
||||
|
||||
jobs:
|
||||
validate:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- uses: azure/setup-helm@v4
|
||||
with:
|
||||
version: v4.3.0
|
||||
- name: Install chart-test dependency
|
||||
run: |
|
||||
python3 -m venv "${RUNNER_TEMP}/chart-test"
|
||||
"${RUNNER_TEMP}/chart-test/bin/pip" install PyYAML
|
||||
echo "${RUNNER_TEMP}/chart-test/bin" >> "${GITHUB_PATH}"
|
||||
- run: ./test.sh
|
||||
|
||||
publish:
|
||||
if: gitea.event_name == 'push' && gitea.ref == 'refs/heads/main'
|
||||
needs: validate
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- uses: azure/setup-helm@v4
|
||||
with:
|
||||
version: v4.3.0
|
||||
- name: Select immutable chart version
|
||||
run: echo "CHART_VERSION=$(./scripts/chart-version.sh)" >> "${GITHUB_ENV}"
|
||||
- name: Package and publish chart
|
||||
env:
|
||||
PACKAGE_USERNAME: ${{ secrets.PACKAGE_USERNAME }}
|
||||
PACKAGE_TOKEN: ${{ secrets.PACKAGE_TOKEN }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
test -n "${PACKAGE_USERNAME}" && test -n "${PACKAGE_TOKEN}"
|
||||
helm package chart/matrix-alertmanager-receiver \
|
||||
--destination "${RUNNER_TEMP}" \
|
||||
--version "${CHART_VERSION}"
|
||||
curl --fail --silent --show-error \
|
||||
--user "${PACKAGE_USERNAME}:${PACKAGE_TOKEN}" \
|
||||
--request POST \
|
||||
--upload-file "${RUNNER_TEMP}/matrix-alertmanager-receiver-${CHART_VERSION}.tgz" \
|
||||
https://code.brunner.ninja/api/packages/feedc0de/helm/api/charts
|
||||
- name: Check that this is still current main
|
||||
id: current-main
|
||||
env:
|
||||
COMMIT_SHA: ${{ gitea.sha }}
|
||||
run: |
|
||||
git fetch --no-tags origin main
|
||||
if [ "$(git rev-parse FETCH_HEAD)" = "${COMMIT_SHA}" ]; then
|
||||
echo "promote=true" >> "${GITHUB_OUTPUT}"
|
||||
else
|
||||
echo "promote=false" >> "${GITHUB_OUTPUT}"
|
||||
fi
|
||||
- uses: actions/checkout@v4
|
||||
if: steps.current-main.outputs.promote == 'true'
|
||||
with:
|
||||
repository: feedc0de/homelab-gitops
|
||||
ref: main
|
||||
token: ${{ secrets.GITOPS_TOKEN }}
|
||||
path: homelab-gitops
|
||||
- name: Promote chart version
|
||||
if: steps.current-main.outputs.promote == 'true'
|
||||
working-directory: homelab-gitops
|
||||
run: |
|
||||
set -euo pipefail
|
||||
./scripts/update-chart-version.sh matrix-alertmanager-receiver "${CHART_VERSION}"
|
||||
git config user.name feedc0de
|
||||
git config user.email feedc0de@users.noreply.code.brunner.ninja
|
||||
git add bootstrap/matrix-alertmanager-receiver.yaml
|
||||
if git diff --cached --quiet; then exit 0; fi
|
||||
git commit -m "Deploy Matrix receiver chart ${CHART_VERSION}"
|
||||
for attempt in 1 2 3; do
|
||||
if git push origin HEAD:main; then exit 0; fi
|
||||
if [ "${attempt}" = 3 ]; then exit 1; fi
|
||||
git fetch origin main
|
||||
git rebase origin/main
|
||||
done
|
||||
@@ -0,0 +1,25 @@
|
||||
# Matrix Alertmanager receiver Helm chart
|
||||
|
||||
This repository packages the upstream
|
||||
[`metio/matrix-alertmanager-receiver`](https://github.com/metio/matrix-alertmanager-receiver)
|
||||
container as a reusable Helm chart. It does not rebuild or mirror the upstream
|
||||
image. The chart owns the ConfigMap, Deployment, Service, probes, and optional
|
||||
ServiceMonitor. Set the Matrix homeserver, bot ID, room mapping, and existing
|
||||
Secret reference in values; never put an access token in Helm values.
|
||||
|
||||
The image tag defaults to the chart's `appVersion`. The Git tag follows the
|
||||
upstream application release; CI derives package versions with
|
||||
`git describe --tags --long`. A tag release packages without the leading `v`;
|
||||
later chart-only commits append their distance and commit hash.
|
||||
|
||||
For the public chart repository:
|
||||
|
||||
```sh
|
||||
helm repo add brunner.ninja https://brunner.ninja/charts
|
||||
helm repo update brunner.ninja
|
||||
helm search repo brunner.ninja/matrix-alertmanager-receiver
|
||||
```
|
||||
|
||||
For a local install from this checkout, create the referenced Kubernetes
|
||||
Secret first, then run `NAMESPACE=prometheus ./chart/install.sh` with the
|
||||
appropriate values file. Argo CD is the normal deployment path in this cluster.
|
||||
Executable
+18
@@ -0,0 +1,18 @@
|
||||
#!/bin/sh
|
||||
set -eu
|
||||
|
||||
script_dir=$(CDPATH= cd -- "$(dirname -- "$0")" && pwd)
|
||||
repo_dir=$(CDPATH= cd -- "${script_dir}/.." && pwd)
|
||||
namespace=${NAMESPACE:-default}
|
||||
version=${CHART_VERSION:-$(${repo_dir}/scripts/chart-version.sh)}
|
||||
|
||||
helm repo add brunner.ninja https://brunner.ninja/charts --force-update
|
||||
helm repo update brunner.ninja
|
||||
helm upgrade --install matrix-alertmanager-receiver \
|
||||
brunner.ninja/matrix-alertmanager-receiver \
|
||||
--version "${version}" \
|
||||
--namespace "${namespace}" \
|
||||
--create-namespace \
|
||||
--wait \
|
||||
--timeout 10m \
|
||||
"$@"
|
||||
@@ -0,0 +1,6 @@
|
||||
apiVersion: v2
|
||||
name: matrix-alertmanager-receiver
|
||||
description: Matrix webhook receiver for Prometheus Alertmanager
|
||||
type: application
|
||||
version: 0.0.0
|
||||
appVersion: "2026.9.23"
|
||||
@@ -0,0 +1,19 @@
|
||||
{{- define "matrix-alertmanager-receiver.name" -}}
|
||||
{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" -}}
|
||||
{{- end -}}
|
||||
|
||||
{{- define "matrix-alertmanager-receiver.fullname" -}}
|
||||
{{- if .Values.fullnameOverride -}}
|
||||
{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" -}}
|
||||
{{- else -}}
|
||||
{{- printf "%s" (include "matrix-alertmanager-receiver.name" .) | trunc 63 | trimSuffix "-" -}}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
|
||||
{{- define "matrix-alertmanager-receiver.labels" -}}
|
||||
app.kubernetes.io/name: {{ include "matrix-alertmanager-receiver.name" . }}
|
||||
app.kubernetes.io/instance: {{ .Release.Name }}
|
||||
app.kubernetes.io/version: {{ .Chart.AppVersion | quote }}
|
||||
app.kubernetes.io/managed-by: {{ .Release.Service }}
|
||||
helm.sh/chart: {{ printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | quote }}
|
||||
{{- end -}}
|
||||
@@ -0,0 +1,20 @@
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: {{ include "matrix-alertmanager-receiver.fullname" . }}
|
||||
labels:
|
||||
{{- include "matrix-alertmanager-receiver.labels" . | nindent 4 }}
|
||||
data:
|
||||
config.yaml: |
|
||||
http:
|
||||
port: {{ .Values.service.port }}
|
||||
metrics-enabled: true
|
||||
matrix:
|
||||
homeserver-url: {{ required "matrix.homeserverUrl is required" .Values.matrix.homeserverUrl | quote }}
|
||||
user-id: {{ required "matrix.userId is required" .Values.matrix.userId | quote }}
|
||||
access-token: ${MATRIX_ACCESS_TOKEN}
|
||||
room-mapping:
|
||||
{{ toYaml .Values.matrix.roomMapping | indent 8 }}
|
||||
templating:
|
||||
firing-template: {{ .Values.templating.firing | quote }}
|
||||
resolved-template: {{ .Values.templating.resolved | quote }}
|
||||
@@ -0,0 +1,69 @@
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: {{ include "matrix-alertmanager-receiver.fullname" . }}
|
||||
labels:
|
||||
{{- include "matrix-alertmanager-receiver.labels" . | nindent 4 }}
|
||||
spec:
|
||||
replicas: {{ .Values.replicaCount }}
|
||||
strategy:
|
||||
type: RollingUpdate
|
||||
rollingUpdate:
|
||||
maxSurge: 1
|
||||
maxUnavailable: 0
|
||||
selector:
|
||||
matchLabels:
|
||||
app.kubernetes.io/name: {{ include "matrix-alertmanager-receiver.name" . }}
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app.kubernetes.io/name: {{ include "matrix-alertmanager-receiver.name" . }}
|
||||
annotations:
|
||||
checksum/config: {{ include (print $.Template.BasePath "/configmap.yaml") . | sha256sum }}
|
||||
spec:
|
||||
automountServiceAccountToken: false
|
||||
containers:
|
||||
- name: receiver
|
||||
image: "{{ .Values.image.repository }}:{{ default .Chart.AppVersion .Values.image.tag }}"
|
||||
imagePullPolicy: {{ .Values.image.pullPolicy }}
|
||||
args:
|
||||
- --config-path
|
||||
- /etc/matrix-receiver/config.yaml
|
||||
env:
|
||||
- name: MATRIX_ACCESS_TOKEN
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: {{ default (printf "%s-auth" (include "matrix-alertmanager-receiver.fullname" .)) .Values.matrix.accessTokenSecret.name }}
|
||||
key: {{ .Values.matrix.accessTokenSecret.key }}
|
||||
ports:
|
||||
- name: http
|
||||
containerPort: {{ .Values.service.port }}
|
||||
protocol: TCP
|
||||
volumeMounts:
|
||||
- name: config
|
||||
mountPath: /etc/matrix-receiver
|
||||
readOnly: true
|
||||
readinessProbe:
|
||||
httpGet:
|
||||
path: /metrics
|
||||
port: http
|
||||
periodSeconds: 10
|
||||
livenessProbe:
|
||||
httpGet:
|
||||
path: /metrics
|
||||
port: http
|
||||
periodSeconds: 30
|
||||
securityContext:
|
||||
allowPrivilegeEscalation: false
|
||||
readOnlyRootFilesystem: true
|
||||
capabilities:
|
||||
drop:
|
||||
- ALL
|
||||
{{- with .Values.resources }}
|
||||
resources:
|
||||
{{- toYaml . | nindent 12 }}
|
||||
{{- end }}
|
||||
volumes:
|
||||
- name: config
|
||||
configMap:
|
||||
name: {{ include "matrix-alertmanager-receiver.fullname" . }}
|
||||
@@ -0,0 +1,15 @@
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: {{ include "matrix-alertmanager-receiver.fullname" . }}
|
||||
labels:
|
||||
{{- include "matrix-alertmanager-receiver.labels" . | nindent 4 }}
|
||||
spec:
|
||||
type: {{ .Values.service.type }}
|
||||
selector:
|
||||
app.kubernetes.io/name: {{ include "matrix-alertmanager-receiver.name" . }}
|
||||
ports:
|
||||
- name: http
|
||||
port: {{ .Values.service.port }}
|
||||
targetPort: http
|
||||
protocol: TCP
|
||||
@@ -0,0 +1,17 @@
|
||||
{{- if .Values.serviceMonitor.enabled }}
|
||||
apiVersion: monitoring.coreos.com/v1
|
||||
kind: ServiceMonitor
|
||||
metadata:
|
||||
name: {{ include "matrix-alertmanager-receiver.fullname" . }}
|
||||
labels:
|
||||
{{- include "matrix-alertmanager-receiver.labels" . | nindent 4 }}
|
||||
spec:
|
||||
selector:
|
||||
matchLabels:
|
||||
app.kubernetes.io/name: {{ include "matrix-alertmanager-receiver.name" . }}
|
||||
app.kubernetes.io/instance: {{ .Release.Name }}
|
||||
endpoints:
|
||||
- port: http
|
||||
path: /metrics
|
||||
interval: 30s
|
||||
{{- end }}
|
||||
@@ -0,0 +1,28 @@
|
||||
replicaCount: 1
|
||||
|
||||
image:
|
||||
repository: docker.io/metio/matrix-alertmanager-receiver
|
||||
tag: ""
|
||||
pullPolicy: IfNotPresent
|
||||
|
||||
service:
|
||||
type: ClusterIP
|
||||
port: 12345
|
||||
|
||||
matrix:
|
||||
homeserverUrl: https://matrix.example.org
|
||||
userId: "@alertmanager:example.org"
|
||||
roomMapping:
|
||||
cluster: "!room-id:example.org"
|
||||
accessTokenSecret:
|
||||
name: ""
|
||||
key: token
|
||||
|
||||
templating:
|
||||
firing: '<strong>FIRING</strong> {{ .Alert.Labels.alertname }}{{ if .Alert.Labels.namespace }} in {{ .Alert.Labels.namespace }}{{ end }}: {{ if .Alert.Annotations.description }}{{ .Alert.Annotations.description }}{{ else }}{{ .Alert.Annotations.summary }}{{ end }}'
|
||||
resolved: '<strong>RESOLVED</strong> {{ .Alert.Labels.alertname }}{{ if .Alert.Labels.namespace }} in {{ .Alert.Labels.namespace }}{{ end }}'
|
||||
|
||||
resources: {}
|
||||
|
||||
serviceMonitor:
|
||||
enabled: false
|
||||
Executable
+13
@@ -0,0 +1,13 @@
|
||||
#!/bin/sh
|
||||
set -eu
|
||||
|
||||
description=$(git describe --tags --long --match 'v[0-9]*' --dirty)
|
||||
case "$description" in
|
||||
*-dirty) echo 'Refusing to package a dirty tree' >&2; exit 1 ;;
|
||||
esac
|
||||
|
||||
version=${description#v}
|
||||
case "$version" in
|
||||
*-0-g*) version=${version%%-0-g*} ;;
|
||||
esac
|
||||
printf '%s\n' "$version"
|
||||
@@ -0,0 +1,18 @@
|
||||
#!/bin/sh
|
||||
set -eu
|
||||
|
||||
repo_dir=$(CDPATH= cd -- "$(dirname -- "$0")" && pwd)
|
||||
chart_dir=${repo_dir}/chart/matrix-alertmanager-receiver
|
||||
rendered=$(mktemp)
|
||||
trap 'rm -f "$rendered"' EXIT
|
||||
|
||||
sh -n "${repo_dir}/scripts/chart-version.sh"
|
||||
sh -n "${repo_dir}/chart/install.sh"
|
||||
helm lint "${chart_dir}"
|
||||
helm template matrix-alertmanager-receiver "${chart_dir}" \
|
||||
--namespace default \
|
||||
--set matrix.homeserverUrl=https://matrix.example.org \
|
||||
--set matrix.userId='@alertmanager:example.org' \
|
||||
--set matrix.roomMapping.cluster='!room-id:example.org' \
|
||||
--set serviceMonitor.enabled=true > "${rendered}"
|
||||
python3 "${repo_dir}/tests/assert_chart.py" "${chart_dir}" "${rendered}"
|
||||
@@ -0,0 +1,35 @@
|
||||
#!/usr/bin/env python3
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
import yaml
|
||||
|
||||
chart_dir = Path(sys.argv[1])
|
||||
rendered_path = Path(sys.argv[2])
|
||||
chart = yaml.safe_load((chart_dir / "Chart.yaml").read_text())
|
||||
values = yaml.safe_load((chart_dir / "values.yaml").read_text())
|
||||
documents = [doc for doc in yaml.safe_load_all(rendered_path.read_text()) if doc]
|
||||
by_kind = {(doc["kind"], doc["metadata"]["name"]): doc for doc in documents}
|
||||
|
||||
name = "matrix-alertmanager-receiver"
|
||||
deployment = by_kind[("Deployment", name)]
|
||||
service = by_kind[("Service", name)]
|
||||
service_monitor = by_kind[("ServiceMonitor", name)]
|
||||
config = by_kind[("ConfigMap", name)]["data"]["config.yaml"]
|
||||
container = deployment["spec"]["template"]["spec"]["containers"][0]
|
||||
service_port = service["spec"]["ports"][0]
|
||||
app_config = yaml.safe_load(config)
|
||||
|
||||
assert container["image"] == f'{values["image"]["repository"]}:{chart["appVersion"]}'
|
||||
assert deployment["spec"]["replicas"] == 1
|
||||
assert deployment["spec"]["selector"]["matchLabels"] == service["spec"]["selector"]
|
||||
assert deployment["spec"]["selector"]["matchLabels"]["app.kubernetes.io/name"] == chart["name"]
|
||||
assert container["ports"][0]["containerPort"] == service_port["port"]
|
||||
assert service_port["targetPort"] == container["ports"][0]["name"]
|
||||
assert container["readinessProbe"]["httpGet"]["path"] == "/metrics"
|
||||
assert container["livenessProbe"]["httpGet"]["path"] == "/metrics"
|
||||
assert container["env"][0]["valueFrom"]["secretKeyRef"]["key"] == values["matrix"]["accessTokenSecret"]["key"]
|
||||
assert "access-token: ${MATRIX_ACCESS_TOKEN}" in config
|
||||
assert app_config["matrix"]["access-token"] == "${MATRIX_ACCESS_TOKEN}"
|
||||
assert service_monitor["spec"]["endpoints"][0]["port"] == service_port["name"]
|
||||
assert service_monitor["spec"]["endpoints"][0]["path"] == "/metrics"
|
||||
Reference in New Issue
Block a user