Compare commits

...

2 Commits

Author SHA1 Message Date
Peter Steinberger
cf43cafa3d fix: land watch serve client override fix and changelog (#411) (thanks @chrysb)
Some checks failed
ci / test (push) Has been cancelled
ci / worker (push) Has been cancelled
ci / windows (push) Has been cancelled
ci / darwin-cgo-build (push) Has been cancelled
ci / windows-build (push) Has been cancelled
2026-03-07 14:59:04 +00:00
Chrys Bader
f4a1a56165 fix(gmail): preserve --client in watch serve push handler contexts
Ensure gmail watch serve re-applies the selected OAuth client to request-time contexts before creating Gmail services, so push handling does not fall back to client default in multi-client setups.
2026-03-07 14:56:33 +00:00
3 changed files with 67 additions and 1 deletions

View File

@ -15,6 +15,7 @@
- Timezone: embed the IANA timezone database so Windows builds can resolve calendar timezones correctly. (#388) — thanks @visionik.
- Gmail: add a fetch delay in `watch serve` so History API reads don't race message indexing. (#397) — thanks @salmonumbrella.
- Gmail: allow Workspace-managed send-as aliases with empty verification status in `send` and `drafts create`. (#407) — thanks @salmonumbrella.
- Gmail: preserve the selected `--client` during `watch serve` push handling instead of falling back to the default client. (#411) — thanks @chrysb.
- Secrets: respect empty `GOG_KEYRING_PASSWORD` (treat set-to-empty as intentional; avoids headless prompts). (#269) — thanks @zerone0x.
- Calendar: reject ambiguous calendar-name selectors for `calendar events` instead of guessing. (#131) — thanks @salmonumbrella.
- Gmail: `drafts update --quote` now picks a non-draft, non-self message from thread fallback (or errors clearly), avoiding self-quote loops and wrong reply headers. (#394) — thanks @salmonumbrella.

View File

@ -14,6 +14,7 @@ import (
"google.golang.org/api/gmail/v1"
"google.golang.org/api/idtoken"
"github.com/steipete/gogcli/internal/authclient"
"github.com/steipete/gogcli/internal/outfmt"
"github.com/steipete/gogcli/internal/ui"
)
@ -354,12 +355,20 @@ func (c *GmailWatchServeCmd) Run(ctx context.Context, kctx *kong.Context, flags
cfg.MaxBodyBytes = defaultHookMaxBytes
}
selectedClient := strings.TrimSpace(flags.Client)
serviceFactory := func(ctx context.Context, account string) (*gmail.Service, error) {
if selectedClient != "" {
ctx = authclient.WithClient(ctx, selectedClient)
}
return newGmailService(ctx, account)
}
hookClient := &http.Client{Timeout: cfg.HookTimeout}
server := &gmailWatchServer{
cfg: cfg,
store: store,
validator: validator,
newService: newGmailService,
newService: serviceFactory,
hookClient: hookClient,
excludeLabelIDs: stringSet(cfg.ExcludeLabels),
logf: u.Err().Printf,

View File

@ -7,8 +7,10 @@ import (
"testing"
"time"
"google.golang.org/api/gmail/v1"
"google.golang.org/api/idtoken"
"github.com/steipete/gogcli/internal/authclient"
"github.com/steipete/gogcli/internal/ui"
)
@ -312,3 +314,57 @@ func TestGmailWatchServeCmd_SaveHookAndOIDC(t *testing.T) {
t.Fatalf("expected hook saved, got %#v", loaded.Get().Hook)
}
}
func TestGmailWatchServeCmd_PreservesClientOverrideForRequestContexts(t *testing.T) {
origListen := listenAndServe
origNew := newGmailService
t.Cleanup(func() {
listenAndServe = origListen
newGmailService = origNew
})
home := t.TempDir()
t.Setenv("HOME", home)
store, err := newGmailWatchStore("a@b.com")
if err != nil {
t.Fatalf("store: %v", err)
}
updateErr := store.Update(func(s *gmailWatchState) error {
s.Account = "a@b.com"
return nil
})
if updateErr != nil {
t.Fatalf("seed: %v", updateErr)
}
flags := &RootFlags{Account: "a@b.com", Client: "personal"}
var got *gmailWatchServer
listenAndServe = func(srv *http.Server) error {
if gs, ok := srv.Handler.(*gmailWatchServer); ok {
got = gs
}
return nil
}
newGmailService = func(ctx context.Context, _ string) (*gmail.Service, error) {
if client := authclient.ClientOverrideFromContext(ctx); client != "personal" {
t.Fatalf("expected client override personal, got %q", client)
}
return &gmail.Service{}, nil
}
u, err := ui.New(ui.Options{Stdout: io.Discard, Stderr: io.Discard, Color: "never"})
if err != nil {
t.Fatalf("ui.New: %v", err)
}
if execErr := runKong(t, &GmailWatchServeCmd{}, []string{"--port", "9999", "--path", "/hook"}, ui.WithUI(context.Background(), u), flags); execErr != nil {
t.Fatalf("execute: %v", execErr)
}
if got == nil {
t.Fatalf("expected server")
}
if _, callErr := got.newService(context.Background(), "a@b.com"); callErr != nil {
t.Fatalf("newService: %v", callErr)
}
}