git-subtree-dir: observability git-subtree-mainline:ae1d9bb534git-subtree-split:19e74af9ca
66 lines
2.4 KiB
YAML
66 lines
2.4 KiB
YAML
name: Validate observability stack
|
|
|
|
# This repo deploys by hand (`docker compose up -d` on beta + the Alloy agent on
|
|
# each node) with no build step, so nothing caught a malformed compose file, a
|
|
# broken dashboard JSON, or an unparseable config until it failed live on the
|
|
# host. This is that missing guard: it parses every YAML/JSON artifact that ships
|
|
# to a node. It does NOT deploy, and deliberately needs no docker CLI (the
|
|
# node:20-bookworm job image doesn't ship one) — a YAML parse catches the real
|
|
# breakage (bad indent / unparseable file) without it.
|
|
#
|
|
# Not validated here: the Alloy config (alloy/config.alloy, an HCL-like format,
|
|
# needs the `alloy` binary) and docker-compose *schema* (unknown-key checks, which
|
|
# would need the docker CLI). Add either if the churn warrants the extra tooling.
|
|
|
|
on:
|
|
push:
|
|
branches: [main]
|
|
pull_request:
|
|
branches: [main]
|
|
|
|
jobs:
|
|
validate:
|
|
runs-on: docker
|
|
steps:
|
|
- uses: actions/checkout@v4
|
|
|
|
- name: Dashboards are valid JSON
|
|
run: |
|
|
set -euo pipefail
|
|
python3 - <<'PY'
|
|
import json, pathlib, sys
|
|
bad = False
|
|
files = sorted(pathlib.Path("grafana/dashboards").glob("*.json"))
|
|
if not files:
|
|
print("no dashboards found"); sys.exit(1)
|
|
for f in files:
|
|
try:
|
|
json.loads(f.read_text()); print("OK", f)
|
|
except Exception as e: # noqa: BLE001
|
|
print("INVALID JSON", f, "-", e); bad = True
|
|
sys.exit(1 if bad else 0)
|
|
PY
|
|
|
|
- name: YAML artifacts parse (compose + loki + grafana provisioning)
|
|
run: |
|
|
set -euo pipefail
|
|
apt-get update -qq && apt-get install -y -qq python3-yaml >/dev/null
|
|
python3 - <<'PY'
|
|
import pathlib, sys
|
|
import yaml
|
|
bad = False
|
|
targets = [
|
|
pathlib.Path("docker-compose.yml"),
|
|
pathlib.Path("alloy/docker-compose.agent.yml"),
|
|
pathlib.Path("loki/config.yml"),
|
|
*sorted(pathlib.Path("grafana/provisioning").rglob("*.yml")),
|
|
]
|
|
for f in targets:
|
|
if not f.exists():
|
|
print("MISSING", f); bad = True; continue
|
|
try:
|
|
yaml.safe_load(f.read_text()); print("OK", f)
|
|
except Exception as e: # noqa: BLE001
|
|
print("INVALID YAML", f, "-", e); bad = True
|
|
sys.exit(1 if bad else 0)
|
|
PY
|