From d54f9b58ea68b70bf5960dac37a93a4232e169e5 Mon Sep 17 00:00:00 2001 From: daharoni Date: Mon, 11 May 2026 18:26:20 +0200 Subject: [PATCH] push_to_wiki: surface the MW login `reason` and `details` on failure MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The current login error handler prints only `result` (always the generic bucket "Failed" / "Aborted" / etc.), throwing away the `reason` field that MediaWiki includes with non-Success responses. That makes auth failures undiagnosable from CI logs without re-running. Surface `reason` and the optional `details` field. Neither contains the password or any other secret — they're MW's human-readable error strings like "Incorrect password", "User is locked", "Bot password has been revoked", or IP-restriction messages. Motivated by the recent post-merge sync of #14 failing with bare `Login failed: Failed` — the same secrets had succeeded 5 minutes earlier for #13's sync, so the actual reason matters for triage. Co-Authored-By: Claude Opus 4.7 (1M context) --- scripts/push_to_wiki.py | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/scripts/push_to_wiki.py b/scripts/push_to_wiki.py index e80a477..6c14e9d 100644 --- a/scripts/push_to_wiki.py +++ b/scripts/push_to_wiki.py @@ -66,9 +66,18 @@ def login(self, username, password): "format": "json", }, ) - result = resp.json()["login"]["result"] + login_obj = resp.json().get("login", {}) + result = login_obj.get("result") if result != "Success": - print(f"Login failed: {result}", file=sys.stderr) + # MW returns a `reason` field on Failed/Aborted responses that + # explains the actual cause (wrong password, account locked, IP + # restriction, bot password deleted, etc.). Surface it so CI + # failures are diagnosable from the logs without re-running. + # The `details` field carries additional context when present. + reason = login_obj.get("reason", "(no reason returned)") + details = login_obj.get("details") + extra = f" — {details}" if details else "" + print(f"Login failed: {result} — {reason}{extra}", file=sys.stderr) sys.exit(1) def get_csrf_token(self):