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.

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).

Merge request reports

Loading
Loading