fix(config): name the keyring in credential write failures
Description
A failed keyring write returned the backend's error verbatim. On macOS
zalando/go-keyring shells out to /usr/bin/security, so the error is a
bare exit code with nothing identifying the keyring, the host, or the key:
ERROR Failed to set "token": exit status 161.This is reachable whenever the keychain is locked, access is denied, or a
sandbox denies writes to ~/Library/Keychains — in that last case the
underlying failure is
SecKeychainItemCreateFromContent (<default>): UNIX[Operation not permitted],
none of which reaches the user.
The read path in GetWithSource already wraps its keyring errors:
return "", "keyring", fmt.Errorf("failed to read %q from the operating system keyring for host %q: %w", key, hostname, err)This makes the write path symmetric. The upstream exit code stays opaque —
that's a go-keyring limitation — but the message now names the failing
subsystem, the host, and the key.
Related Issues
Found while investigating #8262 (closed) (sandboxed glab usage). Not a fix for
that issue and does not resolve it; the opaque error is independent of
sandboxing.
How has this been tested?
New test Test_Set_SurfacesKeyringWriteError uses the existing
keyring.MockInitWithError seam (as Test_GetWithSource_SurfacesKeyringReadError
does) and asserts the error names the keyring, host, and key, preserves
the underlying cause, and does not echo the credential.
Verified the test is not vacuous: reverting the wrap fails it with
"exit status 161" does not contain "keyring".
Full internal/config suite and golangci-lint clean; pre-push suite
passed (3,860 tests).