Add Argo CD Helm chart release
Validate and publish mktxp chart / publish (push) Successful in 3s
Validate and publish mktxp chart / validate (push) Successful in 2s
Validate and publish mktxp chart / promote (push) Successful in 2s

This commit is contained in:
2026-10-19 08:43:32 +02:00
commit d3efe6d34c
10 changed files with 307 additions and 0 deletions
+105
View File
@@ -0,0 +1,105 @@
name: Validate and publish mktxp chart
on:
push:
pull_request:
jobs:
validate:
runs-on: linux_amd64
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Install Helm
run: |
curl --fail --silent --show-error --location --output "${RUNNER_TEMP}/helm.tar.gz" https://get.helm.sh/helm-v4.2.2-linux-amd64.tar.gz
tar -xzf "${RUNNER_TEMP}/helm.tar.gz" -C "${RUNNER_TEMP}" linux-amd64/helm
mv "${RUNNER_TEMP}/linux-amd64/helm" "${RUNNER_TEMP}/helm"
chmod 0700 "${RUNNER_TEMP}/helm"
echo "${RUNNER_TEMP}" >> "$GITHUB_PATH"
- run: ./test.sh
publish:
if: gitea.event_name == 'push' && gitea.ref == 'refs/heads/main'
needs: validate
runs-on: linux_amd64
outputs:
chart_version: ${{ steps.chart.outputs.version }}
source_sha: ${{ gitea.sha }}
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Install Helm
run: |
curl --fail --silent --show-error --location --output "${RUNNER_TEMP}/helm.tar.gz" https://get.helm.sh/helm-v4.2.2-linux-amd64.tar.gz
tar -xzf "${RUNNER_TEMP}/helm.tar.gz" -C "${RUNNER_TEMP}" linux-amd64/helm
mv "${RUNNER_TEMP}/linux-amd64/helm" "${RUNNER_TEMP}/helm"
chmod 0700 "${RUNNER_TEMP}/helm"
echo "${RUNNER_TEMP}" >> "$GITHUB_PATH"
- id: chart
name: Derive chart version
env:
COMMIT_SHA: ${{ gitea.sha }}
run: |
set -euo pipefail
git fetch --tags origin main
test "$(git rev-parse origin/main)" = "$COMMIT_SHA"
description=$(git describe --tags --long --match 'v[0-9]*' --dirty)
case "$description" in *-dirty) echo 'Refusing dirty chart tree' >&2; exit 1 ;; esac
version=${description#v}
case "$version" in *-0-g*) version=${version%%-0-g*} ;; esac
echo "version=${version}" >> "$GITHUB_OUTPUT"
- name: Package and publish
env:
PACKAGE_USERNAME: ${{ secrets.PACKAGE_USERNAME }}
PACKAGE_TOKEN: ${{ secrets.PACKAGE_TOKEN }}
CHART_VERSION: ${{ steps.chart.outputs.version }}
run: |
set -euo pipefail
test -n "$PACKAGE_USERNAME" && test -n "$PACKAGE_TOKEN"
helm lint chart
./test.sh
helm package chart --version "$CHART_VERSION" --destination "$RUNNER_TEMP"
curl --fail --silent --show-error --user "${PACKAGE_USERNAME}:${PACKAGE_TOKEN}" \
--request POST --upload-file "${RUNNER_TEMP}/mktxp-${CHART_VERSION}.tgz" \
https://code.brunner.ninja/api/packages/feedc0de/helm/api/charts
promote:
if: gitea.event_name == 'push' && gitea.ref == 'refs/heads/main'
needs: publish
runs-on: linux_amd64
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Promote GitOps chart version
env:
GITOPS_TOKEN: ${{ secrets.GITOPS_TOKEN }}
CHART_VERSION: ${{ needs.publish.outputs.chart_version }}
COMMIT_SHA: ${{ gitea.sha }}
run: |
set -euo pipefail
test -n "$GITOPS_TOKEN"
git fetch origin main
test "$(git rev-parse origin/main)" = "$COMMIT_SHA"
auth=$(printf 'feedc0de:%s' "$GITOPS_TOKEN" | base64 | tr -d '\n')
git -c "http.extraheader=AUTHORIZATION: basic ${auth}" clone --depth=1 \
https://code.brunner.ninja/feedc0de/homelab-gitops.git "$RUNNER_TEMP/gitops"
unset auth
cd "$RUNNER_TEMP/gitops"
gitops_auth=$(printf 'feedc0de:%s' "$GITOPS_TOKEN" | base64 | tr -d '\n')
unset GITOPS_TOKEN
git config user.name feedc0de
git config user.email feedc0de@users.noreply.code.brunner.ninja
sed -i -E "0,/targetRevision: [^ ]+/s//targetRevision: ${CHART_VERSION}/" bootstrap/mktxp.yaml
if git diff --quiet; then exit 0; fi
git add bootstrap/mktxp.yaml
git commit -m "Deploy mktxp chart ${CHART_VERSION}"
for attempt in 1 2 3; do
if git -c "http.extraheader=AUTHORIZATION: basic ${gitops_auth}" push origin HEAD:main; then exit 0; fi
git -c "http.extraheader=AUTHORIZATION: basic ${gitops_auth}" fetch origin main
git rebase origin/main
done
exit 1
+20
View File
@@ -0,0 +1,20 @@
# mktxp Helm chart
Maintained adapter chart for the public `ghcr.io/akpw/mktxp` image. It deploys
one exporter, exposes its metrics Service, and can optionally create a
Prometheus Operator `ServiceMonitor`.
The chart references an existing Secret containing the mktxp configuration; it
never stores MikroTik credentials. For this homelab, Argo CD consumes the chart
and [cluster values](https://code.brunner.ninja/feedc0de/homelab-gitops/src/branch/main/apps/mktxp).
Install on another cluster after creating the `mktxp-credentials` Secret:
```sh
helm repo add brunner.ninja https://brunner.ninja/charts
helm repo update brunner.ninja
helm upgrade --install mktxp brunner.ninja/mktxp \
--namespace default --create-namespace --wait --timeout 5m
```
Chart tags version this adapter; `appVersion` selects the upstream image.
+6
View File
@@ -0,0 +1,6 @@
apiVersion: v2
name: mktxp
description: Helm chart for the MikroTik mktxp Prometheus exporter
type: application
version: 0.1.0
appVersion: "2.1.0"
+41
View File
@@ -0,0 +1,41 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: mktxp-exporter
labels:
app: mktxp-exporter
app.kubernetes.io/name: mktxp
app.kubernetes.io/instance: {{ .Release.Name }}
spec:
replicas: {{ .Values.replicaCount }}
selector:
matchLabels:
app: mktxp-exporter
template:
metadata:
labels:
app: mktxp-exporter
app.kubernetes.io/name: mktxp
app.kubernetes.io/instance: {{ .Release.Name }}
spec:
automountServiceAccountToken: false
containers:
- name: mktxp
image: {{ printf "%s:%s" .Values.image.repository .Chart.AppVersion | quote }}
imagePullPolicy: {{ .Values.image.pullPolicy }}
command: ["mktxp"]
args: ["--cfg-dir", "/mktxp_config", "export"]
ports:
- name: metrics
containerPort: {{ .Values.service.port }}
protocol: TCP
resources:
{{- toYaml .Values.resources | nindent 12 }}
volumeMounts:
- name: mktxp-credentials
mountPath: /mktxp_config
readOnly: true
volumes:
- name: mktxp-credentials
secret:
secretName: {{ .Values.existingConfigSecret | quote }}
+16
View File
@@ -0,0 +1,16 @@
apiVersion: v1
kind: Service
metadata:
name: mktxp-exporter
labels:
app: mktxp-exporter
app.kubernetes.io/name: mktxp
app.kubernetes.io/instance: {{ .Release.Name }}
spec:
selector:
app: mktxp-exporter
ports:
- name: metrics
port: {{ .Values.service.port }}
targetPort: metrics
protocol: TCP
+31
View File
@@ -0,0 +1,31 @@
{{- if .Values.serviceMonitor.enabled }}
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
name: mktxp-exporter
labels:
app.kubernetes.io/name: mktxp
app.kubernetes.io/instance: {{ .Release.Name }}
{{- with .Values.serviceMonitor.labels }}
{{- toYaml . | nindent 4 }}
{{- end }}
spec:
selector:
matchLabels:
app: mktxp-exporter
namespaceSelector:
matchNames:
- {{ .Release.Namespace }}
endpoints:
- port: metrics
path: /metrics
interval: {{ .Values.serviceMonitor.interval }}
scrapeTimeout: {{ .Values.serviceMonitor.scrapeTimeout }}
honorLabels: true
relabelings:
- regex: 'pod|container|instance|endpoint|namespace|service'
action: labeldrop
metricRelabelings:
- regex: 'instance|pod|container'
action: labeldrop
{{- end }}
+32
View File
@@ -0,0 +1,32 @@
{
"$schema": "https://json-schema.org/draft-07/schema#",
"type": "object",
"required": ["image", "existingConfigSecret", "serviceMonitor"],
"properties": {
"replicaCount": {"type": "integer", "minimum": 1},
"image": {
"type": "object",
"required": ["repository", "pullPolicy"],
"properties": {
"repository": {"type": "string", "minLength": 1},
"pullPolicy": {"type": "string", "enum": ["Always", "IfNotPresent", "Never"]}
},
"additionalProperties": false
},
"existingConfigSecret": {"type": "string", "minLength": 1},
"service": {"type": "object"},
"serviceMonitor": {
"type": "object",
"required": ["enabled", "labels"],
"properties": {
"enabled": {"type": "boolean"},
"labels": {"type": "object"},
"interval": {"type": "string"},
"scrapeTimeout": {"type": "string"}
},
"additionalProperties": true
},
"resources": {"type": "object"}
},
"additionalProperties": true
}
+21
View File
@@ -0,0 +1,21 @@
replicaCount: 1
image:
repository: ghcr.io/akpw/mktxp
pullPolicy: IfNotPresent
existingConfigSecret: mktxp-credentials
service:
port: 49090
serviceMonitor:
enabled: false
labels: {}
interval: 30s
scrapeTimeout: 20s
resources:
limits:
cpu: 500m
memory: 512Mi
Executable
+16
View File
@@ -0,0 +1,16 @@
#!/bin/sh
set -eu
release=${RELEASE_NAME:-mktxp}
namespace=${NAMESPACE:-default}
helm repo add brunner.ninja https://brunner.ninja/charts --force-update
helm repo update brunner.ninja
if [ -n "${VALUES_FILE:-}" ]; then
helm upgrade --install "$release" brunner.ninja/mktxp \
--namespace "$namespace" --create-namespace \
--values "$VALUES_FILE" --wait --timeout 5m
else
helm upgrade --install "$release" brunner.ninja/mktxp \
--namespace "$namespace" --create-namespace --wait --timeout 5m
fi
Executable
+19
View File
@@ -0,0 +1,19 @@
#!/bin/sh
set -eu
chart_dir=$(CDPATH= cd -- "$(dirname -- "$0")/chart" && pwd)
workdir=$(mktemp -d)
trap 'rm -rf "$workdir"' EXIT
helm lint "$chart_dir"
helm template mktxp "$chart_dir" --namespace default >"$workdir/default.yaml"
helm template mktxp "$chart_dir" --namespace default \
--set serviceMonitor.enabled=true \
--set serviceMonitor.labels.release=prometheus >"$workdir/monitor.yaml"
grep -q 'name: mktxp-exporter' "$workdir/default.yaml"
grep -q 'secretName: "mktxp-credentials"' "$workdir/default.yaml"
grep -q 'kind: ServiceMonitor' "$workdir/monitor.yaml"
app_version=$(sed -n 's/^appVersion: *"\{0,1\}\([^" ]*\).*/\1/p' "$chart_dir/Chart.yaml")
image_repository=$(sed -n 's/^ repository: *//p' "$chart_dir/values.yaml")
grep -Fq "${image_repository}:${app_version}" "$workdir/default.yaml"