From a1ce5f8a77abaf8b3a9628f9e298c4b9899140cb Mon Sep 17 00:00:00 2001 From: Alec Thomas Date: Tue, 24 Feb 2026 14:02:22 +1100 Subject: [PATCH] fix: use github.com/alecthomas/errors instead of stdlib errors/fmt.Errorf --- .golangci.yml | 18 ++++++++++++++++++ cmd/cachewd/main.go | 9 +++++---- internal/cache/cachetest/soak.go | 2 +- internal/cache/cachetest/suite.go | 2 +- internal/metrics/metrics.go | 10 +++++----- internal/strategy/apiv1.go | 3 ++- internal/strategy/artifactory.go | 7 ++++--- internal/strategy/gomod/cacher.go | 11 ++++++----- internal/strategy/gomod/gomod.go | 7 +++---- internal/strategy/host.go | 5 +++-- 10 files changed, 48 insertions(+), 26 deletions(-) diff --git a/.golangci.yml b/.golangci.yml index fd6d20c..a995456 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -1,3 +1,5 @@ +# yaml-language-server: $schema=https://golangci-lint.run/jsonschema/golangci.v2.jsonschema.json +# # This file is licensed under the terms of the MIT license https://opensource.org/license/mit # Copyright (c) 2021-2025 Marat Reimers @@ -217,6 +219,12 @@ linters: deny: - pkg: log$ desc: Use log/slog instead, see https://go.dev/blog/slog + "errors": + deny: + - pkg: ^errors$ + desc: Use github.com/alecthomas/errors instead + - pkg: ^github.com/pkg/errors$ + desc: Use github.com/alecthomas/errors instead embeddedstructfieldcheck: # Checks that sync.Mutex and sync.RWMutex are not used as embedded fields. @@ -434,6 +442,16 @@ linters: ignore-package-globs: - "github.com/alecthomas/errors" + forbidigo: + exclude-godoc-examples: true + analyze-types: true + forbid: + - pkg: ^fmt$ + pattern: ^fmt\.Errorf$ + msg: "Use github.com/alecthomas/errors.Errorf instead" + - pkg: "^errors$" + msg: "Use github.com/alecthomas/errors instead" + exclusions: # Predefined exclusion rules. # Default: [] diff --git a/cmd/cachewd/main.go b/cmd/cachewd/main.go index 6f3762b..b41814c 100644 --- a/cmd/cachewd/main.go +++ b/cmd/cachewd/main.go @@ -11,6 +11,7 @@ import ( "time" "github.com/alecthomas/chroma/v2/quick" + "github.com/alecthomas/errors" "github.com/alecthomas/hcl/v2" "github.com/alecthomas/kong" "go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp" @@ -149,7 +150,7 @@ func newMux(ctx context.Context, cr *cache.Registry, sr *strategy.Registry, prov }) if err := config.Load(ctx, cr, sr, providersConfigHCL, mux, vars); err != nil { - return nil, fmt.Errorf("load config: %w", err) + return nil, errors.Errorf("load config: %w", err) } return mux, nil @@ -205,7 +206,7 @@ func loadGlobalConfig(ast *hcl.AST) (GlobalConfig, map[string]string, error) { var cfg GlobalConfig schema, err := hcl.Schema(&cfg) if err != nil { - return cfg, nil, fmt.Errorf("global config schema: %w", err) + return cfg, nil, errors.Errorf("global config schema: %w", err) } envars := parseEnvars() config.InjectEnvars(schema, ast, "CACHEW", envars) @@ -220,7 +221,7 @@ func loadGlobalConfig(ast *hcl.AST) (GlobalConfig, map[string]string, error) { }) }) if err := hcl.UnmarshalAST(ast, &cfg, hcl.HydratedImplicitBlocks(true), preserving); err != nil { - return cfg, nil, fmt.Errorf("load global config: %w", err) + return cfg, nil, errors.Errorf("load global config: %w", err) } // Inject state directory as CACHEW_STATE for provider config expansion. @@ -232,7 +233,7 @@ func loadGlobalConfig(ast *hcl.AST) (GlobalConfig, map[string]string, error) { return os.Expand(s, func(key string) string { return envars[key] }) }) if err := hcl.UnmarshalAST(ast, &cfg, hcl.HydratedImplicitBlocks(true), expanding); err != nil { - return cfg, nil, fmt.Errorf("load global config: %w", err) + return cfg, nil, errors.Errorf("load global config: %w", err) } return cfg, envars, nil } diff --git a/internal/cache/cachetest/soak.go b/internal/cache/cachetest/soak.go index 5490060..ef9d247 100644 --- a/internal/cache/cachetest/soak.go +++ b/internal/cache/cachetest/soak.go @@ -4,7 +4,6 @@ import ( "context" "crypto/rand" "crypto/sha256" - "errors" "fmt" "io" mrand "math/rand/v2" @@ -17,6 +16,7 @@ import ( "time" "github.com/alecthomas/assert/v2" + "github.com/alecthomas/errors" "github.com/block/cachew/internal/cache" ) diff --git a/internal/cache/cachetest/suite.go b/internal/cache/cachetest/suite.go index 217e57e..96342f4 100644 --- a/internal/cache/cachetest/suite.go +++ b/internal/cache/cachetest/suite.go @@ -2,7 +2,6 @@ package cachetest import ( "context" - "errors" "io" "net/http" "os" @@ -10,6 +9,7 @@ import ( "time" "github.com/alecthomas/assert/v2" + "github.com/alecthomas/errors" "github.com/block/cachew/internal/cache" ) diff --git a/internal/metrics/metrics.go b/internal/metrics/metrics.go index 37edb95..9d934b0 100644 --- a/internal/metrics/metrics.go +++ b/internal/metrics/metrics.go @@ -2,11 +2,11 @@ package metrics import ( "context" - "errors" "fmt" "net/http" "time" + "github.com/alecthomas/errors" "github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus/promhttp" "go.opentelemetry.io/otel" @@ -61,7 +61,7 @@ func New(ctx context.Context, cfg Config) (*Client, error) { resource.WithHost(), ) if err != nil { - return nil, fmt.Errorf("failed to create resource: %w", err) + return nil, errors.Errorf("failed to create resource: %w", err) } var readers []sdkmetric.Reader @@ -74,7 +74,7 @@ func New(ctx context.Context, cfg Config) (*Client, error) { registry = prometheus.NewRegistry() prometheusExporter, err = prometheusexporter.New(prometheusexporter.WithRegisterer(registry)) if err != nil { - return nil, fmt.Errorf("failed to create Prometheus exporter: %w", err) + return nil, errors.Errorf("failed to create Prometheus exporter: %w", err) } readers = append(readers, prometheusExporter) exporters = append(exporters, "prometheus") @@ -91,7 +91,7 @@ func New(ctx context.Context, cfg Config) (*Client, error) { otlpExporter, err := otlpmetrichttp.New(ctx, opts...) if err != nil { - return nil, fmt.Errorf("failed to create OTLP exporter: %w", err) + return nil, errors.Errorf("failed to create OTLP exporter: %w", err) } // Create periodic reader for OTLP @@ -140,7 +140,7 @@ func (c *Client) Close() error { } if provider, ok := c.provider.(*sdkmetric.MeterProvider); ok { if err := provider.Shutdown(context.Background()); err != nil { - return fmt.Errorf("failed to shutdown meter provider: %w", err) + return errors.Errorf("failed to shutdown meter provider: %w", err) } } return nil diff --git a/internal/strategy/apiv1.go b/internal/strategy/apiv1.go index 1a55dda..353ad6a 100644 --- a/internal/strategy/apiv1.go +++ b/internal/strategy/apiv1.go @@ -3,7 +3,6 @@ package strategy import ( "context" "encoding/json" - "errors" "io" "log/slog" "maps" @@ -11,6 +10,8 @@ import ( "os" "time" + "github.com/alecthomas/errors" + "github.com/block/cachew/internal/cache" "github.com/block/cachew/internal/logging" ) diff --git a/internal/strategy/artifactory.go b/internal/strategy/artifactory.go index 08c105c..fe2efb6 100644 --- a/internal/strategy/artifactory.go +++ b/internal/strategy/artifactory.go @@ -2,13 +2,14 @@ package strategy import ( "context" - "fmt" "log/slog" "net/http" "net/url" "slices" "strings" + "github.com/alecthomas/errors" + "github.com/block/cachew/internal/cache" "github.com/block/cachew/internal/logging" "github.com/block/cachew/internal/strategy/handler" @@ -55,7 +56,7 @@ var _ Strategy = (*Artifactory)(nil) func NewArtifactory(ctx context.Context, config ArtifactoryConfig, cache cache.Cache, mux Mux) (*Artifactory, error) { u, err := url.Parse(config.Target) if err != nil { - return nil, fmt.Errorf("invalid target URL: %w", err) + return nil, errors.Errorf("invalid target URL: %w", err) } a := &Artifactory{ @@ -117,7 +118,7 @@ func (a *Artifactory) transformRequest(r *http.Request) (*http.Request, error) { req, err := http.NewRequestWithContext(r.Context(), http.MethodGet, targetURL.String(), nil) if err != nil { - return nil, fmt.Errorf("failed to create request: %w", err) + return nil, errors.Errorf("failed to create request: %w", err) } // Pass through authentication headers diff --git a/internal/strategy/gomod/cacher.go b/internal/strategy/gomod/cacher.go index 16e91d7..2d79196 100644 --- a/internal/strategy/gomod/cacher.go +++ b/internal/strategy/gomod/cacher.go @@ -2,11 +2,12 @@ package gomod import ( "context" - "fmt" "io" "io/fs" "strings" + "github.com/alecthomas/errors" + "github.com/block/cachew/internal/cache" ) @@ -34,20 +35,20 @@ func (g *goproxyCacher) Put(ctx context.Context, name string, content io.ReadSee wc, err := g.cache.Create(ctx, key, nil, 0) if err != nil { - return fmt.Errorf("create cache entry: %w", err) + return errors.Errorf("create cache entry: %w", err) } defer wc.Close() if _, err := content.Seek(0, io.SeekStart); err != nil { - return fmt.Errorf("seek to start: %w", err) + return errors.Errorf("seek to start: %w", err) } if _, err := io.Copy(wc, content); err != nil { - return fmt.Errorf("write to cache: %w", err) + return errors.Errorf("write to cache: %w", err) } if err := wc.Close(); err != nil { - return fmt.Errorf("close cache entry: %w", err) + return errors.Errorf("close cache entry: %w", err) } return nil diff --git a/internal/strategy/gomod/gomod.go b/internal/strategy/gomod/gomod.go index 08332c6..9a16d88 100644 --- a/internal/strategy/gomod/gomod.go +++ b/internal/strategy/gomod/gomod.go @@ -2,13 +2,12 @@ package gomod import ( "context" - "errors" - "fmt" "log/slog" "net/http" "net/url" "os/exec" + "github.com/alecthomas/errors" "github.com/goproxy/goproxy" "github.com/block/cachew/internal/cache" @@ -48,12 +47,12 @@ func New(ctx context.Context, config Config, cache cache.Cache, mux strategy.Mux parsedURL, err := url.Parse(config.Proxy) if err != nil { - return nil, fmt.Errorf("invalid proxy URL: %w", err) + return nil, errors.Errorf("invalid proxy URL: %w", err) } cloneManager, err := cloneManagerProvider() if err != nil { - return nil, fmt.Errorf("failed to create clone manager: %w", err) + return nil, errors.Errorf("failed to create clone manager: %w", err) } s := &Strategy{ diff --git a/internal/strategy/host.go b/internal/strategy/host.go index afa4f8a..8fa4e09 100644 --- a/internal/strategy/host.go +++ b/internal/strategy/host.go @@ -2,11 +2,12 @@ package strategy import ( "context" - "fmt" "log/slog" "net/http" "net/url" + "github.com/alecthomas/errors" + "github.com/block/cachew/internal/cache" "github.com/block/cachew/internal/logging" "github.com/block/cachew/internal/strategy/handler" @@ -43,7 +44,7 @@ var _ Strategy = (*Host)(nil) func NewHost(ctx context.Context, config HostConfig, cache cache.Cache, mux Mux) (*Host, error) { u, err := url.Parse(config.Target) if err != nil { - return nil, fmt.Errorf("invalid target URL: %w", err) + return nil, errors.Errorf("invalid target URL: %w", err) } prefix := "/" + u.Host + u.EscapedPath() h := &Host{