Fix unconditional maintenance emails; add jsonl structured logging across Maintenance/
- Maintenance/maintenance and Maintenance/edge_maintenance (run daily via
cron, despite the "weekly" naming) were emailing the full run log on
every single run, success or not, because every step was guarded with
`|| true` and never reported failure anywhere. Added a run_step helper
that tracks real failures and wires them into sdp_set_status/
sdp_set_error; the end-of-run email now only fires when something
actually failed (subject changed to "... FAILED" to make that obvious).
- Every other script in Maintenance/ (39 Python scripts + create_p4_filelist.sh
+ email.sh; sdputils.py excluded as a pure library with no __main__) now
emits the same jsonl structured-logging record as the cron scripts in
common/bin, via sdp_structured_log.py's run() context manager (auto-emits
success/failure on exit, sys.exit(N), or unhandled exception) or, for the
two shell scripts, sdp_structured_log.sh's sdp_log_init (auto ERR/EXIT
trap coverage).
- remove_empty_pending_changes.py: the initial pending-changes listing
failure path did a bare `return` (swallowed by the auto-emit machinery,
since a normal return maps to exit code 0/success); now returns 1, and
per-change delete failures inside the loop also flip the overall exit
code, so a partially-failed run is correctly logged as a failure instead
of a silent success.
- pymail.py: usage() called a bare sys.exit() (exit code 0) for both the
-h/help path AND real bad-invocation paths (missing required args,
getopt errors) - meaning a bad invocation reported success both to the
OS and to the structured log. usage() now takes an explicit code
(default 0, preserving -h's exit-0 convention); the two real error call
sites pass a nonzero code.