ci: add dashboard-description lint
Checks every grafana dashboard panel/board description against a length cap and a small keyword list (operator name, tracker-tag references) so the descriptions just shortened don't regress. Wired into both CI and pre-push, same as the other content lints.
This commit is contained in:
parent
8b8a322369
commit
a7e7ccd7df
3 changed files with 109 additions and 0 deletions
90
scripts/check-dashboard-descriptions.sh
Executable file
90
scripts/check-dashboard-descriptions.sh
Executable file
|
|
@ -0,0 +1,90 @@
|
|||
#!/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
|
||||
# <this file>` 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 <<EOF
|
||||
$(jq -c '[.. | objects | select(has("title") and has("description"))] | .[]' "$f")
|
||||
EOF
|
||||
done
|
||||
|
||||
if [ "$checked" -eq 0 ]; then
|
||||
echo 'check-dashboard-descriptions: found zero title+description pairs — extractor or tree changed' >&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
|
||||
|
|
@ -31,5 +31,13 @@ if ! sh "$repo_root/scripts/check-attribution-trailers.sh"; then
|
|||
exit 1
|
||||
fi
|
||||
|
||||
echo "pre-push: running dashboard-description lint..." >&2
|
||||
# jq isn't a project dependency elsewhere in this repo, so the check script
|
||||
# assumes nothing about the caller's PATH — nix-shell it here instead.
|
||||
if ! nix shell nixpkgs#jq --command sh "$repo_root/scripts/check-dashboard-descriptions.sh"; then
|
||||
echo "pre-push: dashboard-description lint FAILED — fix before pushing" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "pre-push: lints passed ✓" >&2
|
||||
exit 0
|
||||
|
|
|
|||
Loading…
Reference in a new issue