#!/bin/sh # CI lint: keeps grafana dashboard panel/board descriptions short and free of # meta-commentary — a tooltip answers "what is this number", not "how did we # arrive at this panel" or "what did someone say about it". # # Two checks: length (over MAX_LEN means it became prose, not a short # answer — fix by deleting the editorializing, not trimming words), and # keywords (the operator's name, hardcoded rather than read from config — # the class of mistake is what's caught, not one specific name; and a # tracker tag `#1234`, reusing check-issue-refs.sh's own pattern and its # same known false-positive class, e.g. `PKCS#11` — no `lint:allow` escape # hatch here though, since JSON has no comment syntax to carry the marker; # rephrase to drop the `#digits` shape instead). # # Deliberately NOT a blanket ban on the word "issue": forge/gitea panels # legitimately show issue-tracker counts ("Currently open issues, across # every repo." is exactly the short description this check wants to keep). # The tracker-tag pattern is the part machine-checkable; a prose # meta-reference with no `#N` needs a human reviewer, same as elsewhere. # # Uses `jq` — the right tool for JSON, unlike its zero-dependency siblings # in this directory. This script does NOT nix-shell for it itself: the # caller declares that dependency (see `pre-push` and # `.forgejo/workflows/ci.yml`, the same `nix shell nixpkgs#jq --command sh # ` shape the vale/shellcheck jobs already use for their own # tools), so a leaf script never hides a nix invocation inside itself. # # Emits a CI error annotation per hit, exits 1 if any hit is found. set -eu dashboards_dir="nix/host-modules/swarm-grafana/dashboards" max_len=100 tracker_pattern='#[0-9]{2,5}([^0-9a-zA-Z]|$)' files="$(find "$dashboards_dir" -maxdepth 1 -name '*.json' 2>/dev/null | sort)" if [ -z "$files" ]; then echo 'check-dashboard-descriptions: no dashboard json files found — path moved?' >&2 exit 1 fi violations=0 checked=0 for f in $files; do # One JSON object per description hit: {"title": "...", "description": "..."} # -- recursive `..` walk catches both schema shapes uniformly, since in # both a description always sits beside a sibling title in the same object. while IFS= read -r row; do [ -n "$row" ] || continue title="$(printf '%s' "$row" | jq -r '.title')" desc="$(printf '%s' "$row" | jq -r '.description')" [ -n "$desc" ] || continue checked=$((checked + 1)) len="$(printf '%s' "$desc" | wc -m | tr -d ' ')" if [ "$len" -gt "$max_len" ]; then violations=$((violations + 1)) printf '::error file=%s::panel "%s" description is %s chars (max %s) — shorten it to what the number is, drop the reasoning\n' \ "$f" "$title" "$len" "$max_len" fi if printf '%s' "$desc" | grep -qiE 'mara'; then violations=$((violations + 1)) printf '::error file=%s::panel "%s" description names the operator — describe the metric, not who asked for the panel\n' \ "$f" "$title" fi if printf '%s' "$desc" | grep -qE "$tracker_pattern"; then violations=$((violations + 1)) printf '::error file=%s::panel "%s" description references a tracker issue — write prose that stands on its own\n' \ "$f" "$title" fi done <&2 exit 1 fi if [ "$violations" -gt 0 ]; then printf 'check-dashboard-descriptions: %s violation(s) across %s description(s) checked\n' \ "$violations" "$checked" >&2 exit 1 fi echo "check-dashboard-descriptions: $checked description(s) checked, clean" >&2 exit 0