Print useful error when switch fails outside user control

This commit is contained in:
William Martin 2023-12-04 16:15:49 +01:00
parent dbff555835
commit af8bcd3ed2
4 changed files with 35 additions and 5 deletions

View file

@ -507,7 +507,7 @@ func TestSwitchUserErrorsAndRestoresUserAndInsecureConfigUnderFailure(t *testing
err = authCfg.SwitchUser("github.com", "test-user-1")
// Then it returns an error
require.EqualError(t, err, "no token found for 'test-user-1'")
require.EqualError(t, err, "no token found for test-user-1")
// And restores the previous state
activeUser, err := authCfg.User("github.com")
@ -533,7 +533,7 @@ func TestSwitchUserErrorsAndRestoresUserAndKeyringUnderFailure(t *testing.T) {
err = authCfg.SwitchUser("github.com", "test-user-1")
// Then it returns an error
require.EqualError(t, err, "no token found for 'test-user-1'")
require.EqualError(t, err, "no token found for test-user-1")
// And restores the previous state
activeUser, err := authCfg.User("github.com")

View file

@ -369,7 +369,9 @@ func (c *AuthConfig) SwitchUser(hostname, user string) error {
// to its previous clean state just in case something else tries to make use of the config, or tries
// to write it again.
if previousSource == "keyring" {
err = errors.Join(err, keyring.Set(keyringServiceName(hostname), "", previouslyActiveToken))
if setErr := keyring.Set(keyringServiceName(hostname), "", previouslyActiveToken); setErr != nil {
err = errors.Join(err, setErr)
}
}
if previousSource == "oauth_token" {
@ -442,7 +444,7 @@ func (c *AuthConfig) activateUser(hostname, user string) error {
}
if !tokenSwitched {
return fmt.Errorf("no token found for '%s'", user)
return fmt.Errorf("no token found for %s", user)
}
// Then we'll update the active user for the host

View file

@ -163,11 +163,15 @@ func switchRun(opts *SwitchOptions) error {
return cmdutil.SilentError
}
cs := opts.IO.ColorScheme()
if err := authCfg.SwitchUser(hostname, username); err != nil {
fmt.Fprintf(opts.IO.ErrOut, "%s Failed to switch account for %s to %s\n",
cs.FailureIcon(), hostname, cs.Bold(username))
return err
}
cs := opts.IO.ColorScheme()
fmt.Fprintf(opts.IO.ErrOut, "%s Switched active account for %s to %s\n",
cs.SuccessIcon(), hostname, cs.Bold(username))

View file

@ -3,10 +3,12 @@ package authswitch
import (
"bytes"
"errors"
"fmt"
"io"
"testing"
"github.com/cli/cli/v2/internal/config"
"github.com/cli/cli/v2/internal/keyring"
"github.com/cli/cli/v2/internal/prompter"
"github.com/cli/cli/v2/pkg/cmdutil"
"github.com/cli/cli/v2/pkg/iostreams"
@ -104,6 +106,8 @@ func TestSwitchRun(t *testing.T) {
stderr string
}
userWithMissingToken := "user-that-is-broken-by-the-test"
tests := []struct {
name string
opts SwitchOptions
@ -316,6 +320,22 @@ func TestSwitchRun(t *testing.T) {
stderr: "✓ Switched active account for ghe.io to inactive-user",
},
},
{
name: "when switching fails due to something other than user error, an informative message is printed to explain their new state",
opts: SwitchOptions{
Username: userWithMissingToken,
},
cfgHosts: []hostUsers{
{"github.com", []user{
{userWithMissingToken, "inactive-user-token"},
{"active-user", "active-user-token"},
}},
},
expectedFailure: failedExpectation{
err: fmt.Errorf("no token found for %s", userWithMissingToken),
stderr: fmt.Sprintf("X Failed to switch account for github.com to %s", userWithMissingToken),
},
},
}
for _, tt := range tests {
@ -341,6 +361,10 @@ func TestSwitchRun(t *testing.T) {
user.token, "ssh", true,
)
require.NoError(t, err)
if user.name == userWithMissingToken {
require.NoError(t, keyring.Delete(fmt.Sprintf("gh:%s", hostUsers.host), userWithMissingToken))
}
}
}