fix: resolve all golangci-lint v2 failures
Some checks failed
ci/woodpecker/push/woodpecker Pipeline failed

Production fixes:
- cmd/server/main.go: refactor to run() helper to eliminate exitAfterDefer
  (os.Exit in main() no longer bypasses deferred s.Close)
- internal/cast/client.go: use _ = resp.Body.Close() (errcheck)
- internal/ghl/api.go: wrap both defers as func(){ _ = resp.Body.Close() }()

Test fixes:
- internal/cast/client_test.go: replace err.(*CastAPIError) type assertions
  with errors.As (errorlint)

Config:
- .golangci.yml: use explicit path regex .*_test\\.go and add errorlint
  to test-file exclusions

Co-Authored-By: Paperclip <noreply@paperclip.ing>
This commit is contained in:
Head of Product & Engineering 2026-04-05 21:52:36 +02:00
parent 8f2080203d
commit 6a853f6566
5 changed files with 26 additions and 20 deletions

View File

@ -18,7 +18,8 @@ linters:
issues:
exclusions:
rules:
- path: _test\.go
- path: ".*_test\\.go"
linters:
- errcheck
- gocritic
- errorlint

View File

@ -2,6 +2,7 @@ package main
import (
"context"
"fmt"
"log/slog"
"net/http"
"os"
@ -20,21 +21,25 @@ import (
func main() {
slog.SetDefault(slog.New(slog.NewJSONHandler(os.Stderr, &slog.HandlerOptions{Level: slog.LevelInfo})))
if err := run(); err != nil {
slog.Error("fatal error", "err", err)
os.Exit(1)
}
}
func run() error {
cfg, err := config.Load()
if err != nil {
slog.Error("config error", "err", err)
os.Exit(1)
return fmt.Errorf("config: %w", err)
}
ctx := context.Background()
s, err := store.NewStore(ctx, cfg.MongoURI)
if err != nil {
slog.Error("failed to connect to mongodb", "err", err)
os.Exit(1)
return fmt.Errorf("mongodb: %w", err)
}
defer s.Close(ctx)
defer func() { _ = s.Close(ctx) }()
castClient := cast.NewClient(cfg.CastAPIURL, cfg.CastAPIKey, cfg.CastSenderID)
ghlAPI := ghl.NewAPIClient()
@ -42,8 +47,7 @@ func main() {
webhookHandler, err := ghl.NewWebhookHandler(cfg.GHLWebhookPublicKey, castClient, ghlAPI, oauthHandler, s)
if err != nil {
slog.Error("failed to initialize webhook handler", "err", err)
os.Exit(1)
return fmt.Errorf("webhook handler: %w", err)
}
r := chi.NewRouter()
@ -77,9 +81,9 @@ func main() {
slog.Info("cast-ghl-provider started", "port", cfg.Port, "base_url", cfg.BaseURL)
if err := srv.ListenAndServe(); err != http.ErrServerClosed {
slog.Error("server error", "err", err)
os.Exit(1)
return fmt.Errorf("server: %w", err)
}
return nil
}
func healthCheck(w http.ResponseWriter, r *http.Request) {

View File

@ -60,7 +60,7 @@ func (c *Client) SendSMS(ctx context.Context, to, message string) (*SendResponse
}
}
slog.Warn("cast api rate limited, retrying", "attempt", attempt+1, "wait", wait)
resp.Body.Close()
_ = resp.Body.Close()
select {
case <-ctx.Done():
return nil, ctx.Err()
@ -70,7 +70,7 @@ func (c *Client) SendSMS(ctx context.Context, to, message string) (*SendResponse
}
data, err := io.ReadAll(resp.Body)
resp.Body.Close()
_ = resp.Body.Close()
if err != nil {
return nil, err
}

View File

@ -3,6 +3,7 @@ package cast
import (
"context"
"encoding/json"
"errors"
"net/http"
"net/http/httptest"
"sync/atomic"
@ -52,8 +53,8 @@ func TestSendSMS_APIError(t *testing.T) {
if err == nil {
t.Fatal("expected error, got nil")
}
castErr, ok := err.(*CastAPIError)
if !ok {
var castErr *CastAPIError
if !errors.As(err, &castErr) {
t.Fatalf("expected CastAPIError, got %T", err)
}
if castErr.StatusCode != http.StatusPaymentRequired {
@ -73,8 +74,8 @@ func TestSendSMS_SuccessFalseInBody(t *testing.T) {
if err == nil {
t.Fatal("expected error, got nil")
}
castErr, ok := err.(*CastAPIError)
if !ok {
var castErr *CastAPIError
if !errors.As(err, &castErr) {
t.Fatalf("expected CastAPIError, got %T", err)
}
if castErr.APIError != "invalid number" {
@ -133,8 +134,8 @@ func TestSendSMS_Unauthorized(t *testing.T) {
if err == nil {
t.Fatal("expected error for 401, got nil")
}
castErr, ok := err.(*CastAPIError)
if !ok {
var castErr *CastAPIError
if !errors.As(err, &castErr) {
t.Fatalf("expected CastAPIError, got %T: %v", err, err)
}
if castErr.StatusCode != http.StatusUnauthorized {

View File

@ -44,7 +44,7 @@ func (c *APIClient) UpdateMessageStatus(ctx context.Context, accessToken, messag
if err != nil {
return err
}
defer resp.Body.Close()
defer func() { _ = resp.Body.Close() }()
respBody, err := io.ReadAll(resp.Body)
if err != nil {
return fmt.Errorf("ghl update status: failed to read response body: %w", err)
@ -75,7 +75,7 @@ func (c *APIClient) PostInboundMessage(ctx context.Context, accessToken string,
if err != nil {
return nil, err
}
defer resp.Body.Close()
defer func() { _ = resp.Body.Close() }()
respBody, err := io.ReadAll(resp.Body)
if err != nil {
return nil, err