fix(checks): stop process_check.sh emitting invalid JSON, and mint one kind
Some checks failed
ci / build-test (push) Has been cancelled
ci / docker-build (push) Has been cancelled
ci / web (push) Has been cancelled
Desktop App / Build Linux (amd64) (push) Has been cancelled
Desktop App / Attach to Release (push) Has been cancelled

`systemctl is-active` prints the state AND exits non-zero when a unit is not
active, so `... || echo unknown` appended a second line: STATE became
"inactive\nunknown" and the script emitted a raw newline inside a JSON string.
The scheduler rejected all 14 process checks with "invalid character '\n' in
string literal".

Latent since the script was written — process checks never actually ran,
because checkdefaults wrote an `args` config the ssh-script checker ignored.
Passing args through finally executed them and exposed it.

- head -1 keeps the state, and the fallback only fires on empty output.
- Quotes are stripped from both the unit name and the state; either would
  break the hand-built JSON just as thoroughly.
- signalKind is now the constant "process" rather than "$SERVICE". Emitting
  the service name minted a distinct signal kind per service (kind=paperless,
  kind=qbit, …) — nothing an approval_rule can match, and it makes "how many
  process checks are failing?" unanswerable.

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
2026-07-28 14:41:56 +02:00
parent 42751623ea
commit 50e899e5ee

View File

@@ -13,10 +13,24 @@ if ! command -v systemctl >/dev/null 2>&1; then
exit 0 exit 0
fi fi
STATE=$(systemctl is-active "$SERVICE" 2>/dev/null || echo "unknown") # `systemctl is-active` PRINTS the state and exits non-zero when the unit is
# not active, so `... || echo unknown` appended a second line and produced
# "paperless is inactive\nunknown" — a raw newline inside a JSON string, which
# the scheduler rejected as invalid output. head -1 keeps the first line and
# the fallback only fires when there was no output at all.
STATE=$(systemctl is-active "$SERVICE" 2>/dev/null | head -1 || true)
[ -z "$STATE" ] && STATE="unknown"
# Belt and braces: a unit name or state containing a quote would break the
# hand-built JSON below just as thoroughly.
STATE=${STATE//\"/}
SAFE_SERVICE=${SERVICE//\"/}
if [ "$STATE" = "active" ]; then if [ "$STATE" = "active" ]; then
echo "{\"health\":\"healthy\"}" echo "{\"health\":\"healthy\"}"
else else
echo "{\"health\":\"degraded\",\"signalKind\":\"$SERVICE\",\"evidence\":\"$SERVICE is $STATE\"}" # signalKind is a taxonomy, not a per-service label. Emitting "$SERVICE"
# here minted a distinct signal kind for every service (kind=paperless,
# kind=qbit, …), which no approval_rule can match and which makes
# "how many process checks are failing?" unanswerable.
echo "{\"health\":\"degraded\",\"signalKind\":\"process\",\"evidence\":\"$SAFE_SERVICE is $STATE\"}"
fi fi