Skip to content

Commit 7c35747

Browse files
committed
fix(auth): use singleton pattern for keyring store
Avoid multiple macOS Keychain prompts per process by caching the opened keyring store with sync.Once. Adds ResetDefaultStore() for test isolation.
1 parent 5d09086 commit 7c35747

1 file changed

Lines changed: 24 additions & 5 deletions

File tree

internal/auth/keyring.go

Lines changed: 24 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import (
77
"os"
88
"runtime"
99
"strings"
10+
"sync"
1011
"time"
1112

1213
"github.com/99designs/keyring"
@@ -50,6 +51,13 @@ var (
5051
keyringOpenFunc = keyring.Open
5152
)
5253

54+
// Singleton store to avoid multiple keychain prompts per process.
55+
var (
56+
defaultStore Store
57+
defaultStoreOnce sync.Once
58+
defaultStoreErr error
59+
)
60+
5361
const keyringOpenTimeout = 5 * time.Second
5462

5563
func openKeyring() (keyring.Keyring, error) {
@@ -157,12 +165,23 @@ func openKeyringWithTimeout(cfg keyring.Config, timeout time.Duration) (keyring.
157165
}
158166

159167
func OpenDefault() (Store, error) {
160-
ring, err := openKeyringFunc()
161-
if err != nil {
162-
return nil, err
163-
}
168+
defaultStoreOnce.Do(func() {
169+
ring, err := openKeyringFunc()
170+
if err != nil {
171+
defaultStoreErr = err
172+
return
173+
}
174+
defaultStore = &KeyringStore{ring: ring}
175+
})
176+
177+
return defaultStore, defaultStoreErr
178+
}
164179

165-
return &KeyringStore{ring: ring}, nil
180+
// ResetDefaultStore resets the singleton store for testing.
181+
func ResetDefaultStore() {
182+
defaultStoreOnce = sync.Once{}
183+
defaultStore = nil
184+
defaultStoreErr = nil
166185
}
167186

168187
type storedToken struct {

0 commit comments

Comments
 (0)