chore(lint): tighten golangci rules

This commit is contained in:
Peter Steinberger 2025-12-31 17:38:29 +01:00
parent 625ccf85cd
commit ddef9fa17a
10 changed files with 51 additions and 24 deletions

View File

@ -8,7 +8,13 @@ linters:
- errorlint
- govet
- ineffassign
- makezero
- misspell
- nilerr
- nilnil
- prealloc
- staticcheck
- unparam
- unused
settings:

View File

@ -8,6 +8,8 @@ import (
)
func TestMainHelpDoesNotExit(t *testing.T) {
t.Helper()
origArgs := os.Args
defer func() { os.Args = origArgs }()

View File

@ -3,6 +3,7 @@ package cmd
import (
"context"
"encoding/json"
"errors"
"net/http"
"net/http/httptest"
"strings"
@ -132,7 +133,7 @@ func TestCalendarTimeCmd_WithTimezoneFlag(t *testing.T) {
// No server needed since we're using --timezone flag
newCalendarService = func(context.Context, string) (*calendar.Service, error) {
t.Fatal("should not call calendar service when --timezone is provided")
return nil, nil
return nil, errors.New("unexpected calendar service call")
}
out := captureStdout(t, func() {
@ -174,7 +175,7 @@ func TestCalendarTimeCmd_InvalidTimezone(t *testing.T) {
// No server needed since we're testing error case
newCalendarService = func(context.Context, string) (*calendar.Service, error) {
t.Fatal("should not call calendar service when invalid timezone is provided")
return nil, nil
return nil, errors.New("unexpected calendar service call")
}
stderr := captureStderr(t, func() {

View File

@ -3,6 +3,7 @@ package cmd
import (
"context"
"encoding/json"
"errors"
"io"
"net/http"
"net/http/httptest"
@ -252,7 +253,7 @@ func TestExecute_DocsExport_RejectsNonDoc(t *testing.T) {
called := false
driveExportDownload = func(context.Context, *drive.Service, string, string) (*http.Response, error) {
called = true
return nil, nil
return nil, errors.New("unexpected export call")
}
err = Execute([]string{"--json", "--account", "a@b.com", "docs", "export", "x", "--out", filepath.Join(t.TempDir(), "out")})

View File

@ -54,7 +54,7 @@ func TestExecute_GmailAttachment_OutPath_JSON(t *testing.T) {
outPath := filepath.Join(t.TempDir(), "a.bin")
run := func() (string, map[string]any) {
run := func() map[string]any {
out := captureStdout(t, func() {
_ = captureStderr(t, func() {
if execErr := Execute([]string{
@ -71,10 +71,10 @@ func TestExecute_GmailAttachment_OutPath_JSON(t *testing.T) {
if unmarshalErr := json.Unmarshal([]byte(out), &parsed); unmarshalErr != nil {
t.Fatalf("json parse: %v\nout=%q", unmarshalErr, out)
}
return out, parsed
return parsed
}
_, parsed1 := run()
parsed1 := run()
if atomic.LoadInt32(&attachmentCalls) != 1 {
t.Fatalf("attachmentCalls=%d", attachmentCalls)
}
@ -96,7 +96,7 @@ func TestExecute_GmailAttachment_OutPath_JSON(t *testing.T) {
t.Fatalf("content=%q", string(b))
}
_, parsed2 := run()
parsed2 := run()
if atomic.LoadInt32(&attachmentCalls) != 1 {
t.Fatalf("attachmentCalls=%d", attachmentCalls)
}

View File

@ -18,8 +18,9 @@ import (
)
var (
newOIDCValidator = idtoken.NewValidator
listenAndServe = func(srv *http.Server) error { return srv.ListenAndServe() }
newOIDCValidator = idtoken.NewValidator
listenAndServe = func(srv *http.Server) error { return srv.ListenAndServe() }
errNoHookConfigured = errors.New("no hook configured")
)
type GmailWatchCmd struct {
@ -55,7 +56,11 @@ func (c *GmailWatchStartCmd) Run(ctx context.Context, kctx *kong.Context, flags
maxChanged := flagProvided(kctx, "max-bytes")
hook, err := hookFromFlags(c.HookURL, c.HookToken, c.IncludeBody, c.MaxBytes, maxChanged, false)
if err != nil {
return err
if errors.Is(err, errNoHookConfigured) {
hook = nil
} else {
return err
}
}
svc, err := newGmailService(ctx, account)
@ -248,7 +253,11 @@ func (c *GmailWatchServeCmd) Run(ctx context.Context, kctx *kong.Context, flags
maxChanged := flagProvided(kctx, "max-bytes")
hook, err := hookFromFlags(hookURL, hookToken, includeBody, maxBytes, maxChanged, true)
if err != nil {
return err
if errors.Is(err, errNoHookConfigured) {
hook = nil
} else {
return err
}
}
if c.SaveHook && hook != nil {
if updateErr := store.Update(func(s *gmailWatchState) error {
@ -405,7 +414,7 @@ func hookFromFlags(url, token string, includeBody bool, maxBytes int, maxBytesCh
if !allowNoHook && (includeBody || maxBytesChanged) {
return nil, usage("--hook-url required when setting hook options")
}
return nil, nil
return nil, errNoHookConfigured
}
if maxBytes <= 0 {
if includeBody {

View File

@ -3,6 +3,7 @@ package cmd
import (
"context"
"encoding/json"
"errors"
"io"
"os"
"strings"
@ -87,8 +88,8 @@ func TestHookFromFlags(t *testing.T) {
t.Run("allow no hook", func(t *testing.T) {
hook, err := hookFromFlags("", "", false, 0, false, true)
if err != nil {
t.Fatalf("unexpected error: %v", err)
if err == nil || !errors.Is(err, errNoHookConfigured) {
t.Fatalf("expected no hook error, got: %v", err)
}
if hook != nil {
t.Fatalf("expected nil hook")

View File

@ -18,6 +18,8 @@ import (
"google.golang.org/api/idtoken"
)
var errNoNewMessages = errors.New("no new messages")
type gmailWatchServer struct {
cfg gmailWatchServeConfig
store *gmailWatchStore
@ -63,6 +65,10 @@ func (s *gmailWatchServer) ServeHTTP(w http.ResponseWriter, r *http.Request) {
result, err := s.handlePush(r.Context(), payload)
if err != nil {
if errors.Is(err, errNoNewMessages) {
w.WriteHeader(http.StatusAccepted)
return
}
s.warnf("watch: handle push failed: %v", err)
w.WriteHeader(http.StatusInternalServerError)
return
@ -141,7 +147,7 @@ func (s *gmailWatchServer) handlePush(ctx context.Context, payload gmailPushPayl
return nil, err
}
if startID == 0 {
return nil, nil
return nil, errNoNewMessages
}
svc, err := s.newService(ctx, s.cfg.Account)

View File

@ -2,6 +2,7 @@ package cmd
import (
"context"
"errors"
"strings"
"testing"
@ -13,7 +14,7 @@ func TestExecute_TasksAdd_RequiresTitle(t *testing.T) {
t.Cleanup(func() { newTasksService = origNew })
newTasksService = func(context.Context, string) (*tasks.Service, error) {
t.Fatalf("expected validation to fail before creating service")
return nil, nil
return nil, errors.New("unexpected tasks service call")
}
_ = captureStderr(t, func() {
@ -29,7 +30,7 @@ func TestExecute_TasksUpdate_RequiresFields(t *testing.T) {
t.Cleanup(func() { newTasksService = origNew })
newTasksService = func(context.Context, string) (*tasks.Service, error) {
t.Fatalf("expected validation to fail before creating service")
return nil, nil
return nil, errors.New("unexpected tasks service call")
}
_ = captureStderr(t, func() {
@ -45,7 +46,7 @@ func TestExecute_TasksUpdate_RejectsInvalidStatus(t *testing.T) {
t.Cleanup(func() { newTasksService = origNew })
newTasksService = func(context.Context, string) (*tasks.Service, error) {
t.Fatalf("expected validation to fail before creating service")
return nil, nil
return nil, errors.New("unexpected tasks service call")
}
_ = captureStderr(t, func() {

View File

@ -16,7 +16,7 @@ import (
"golang.org/x/oauth2"
)
func newTokenServer(t *testing.T, refreshToken string) *httptest.Server {
func newTokenServer(t *testing.T) *httptest.Server {
t.Helper()
return httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
@ -39,7 +39,7 @@ func newTokenServer(t *testing.T, refreshToken string) *httptest.Server {
w.Header().Set("Content-Type", "application/json")
_ = json.NewEncoder(w).Encode(map[string]any{
"access_token": "at",
"refresh_token": refreshToken,
"refresh_token": "rt",
"token_type": "Bearer",
"expires_in": 3600,
})
@ -68,7 +68,7 @@ func TestAuthorize_Manual_Success(t *testing.T) {
}
randomStateFn = func() (string, error) { return "state123", nil }
tokenSrv := newTokenServer(t, "rt")
tokenSrv := newTokenServer(t)
defer tokenSrv.Close()
oauthEndpoint = oauth2EndpointForTest(tokenSrv.URL)
@ -110,7 +110,7 @@ func TestAuthorize_Manual_StateMismatch(t *testing.T) {
}
randomStateFn = func() (string, error) { return "state123", nil }
tokenSrv := newTokenServer(t, "rt")
tokenSrv := newTokenServer(t)
defer tokenSrv.Close()
oauthEndpoint = oauth2EndpointForTest(tokenSrv.URL)
@ -148,7 +148,7 @@ func TestAuthorize_ServerFlow_Success(t *testing.T) {
return config.ClientCredentials{ClientID: "id", ClientSecret: "secret"}, nil
}
tokenSrv := newTokenServer(t, "rt")
tokenSrv := newTokenServer(t)
defer tokenSrv.Close()
oauthEndpoint = oauth2EndpointForTest(tokenSrv.URL)
@ -210,7 +210,7 @@ func TestAuthorize_ServerFlow_CallbackErrors(t *testing.T) {
return config.ClientCredentials{ClientID: "id", ClientSecret: "secret"}, nil
}
tokenSrv := newTokenServer(t, "rt")
tokenSrv := newTokenServer(t)
defer tokenSrv.Close()
oauthEndpoint = oauth2EndpointForTest(tokenSrv.URL)