fix: resolve all linting and formatting issues

- Fix error return value checks (errcheck)
- Fix unused parameters by using underscore prefix
- Add missing package comments to all packages
- Fix context key type issue in middleware (use typed contextKey)
- Replace deprecated trace.NewNoopTracerProvider with noop.NewTracerProvider
- Fix embedded field selector in database client
- Remove trailing whitespace
- Remove revive linter (as requested) to avoid stuttering warnings for public API interfaces

All linting and formatting checks now pass.
This commit is contained in:
2025-11-05 20:48:59 +01:00
parent 926f3f927e
commit 52d48590ae
21 changed files with 57 additions and 68 deletions

View File

@@ -13,21 +13,11 @@ linters:
- errcheck - errcheck
- govet - govet
- staticcheck - staticcheck
- revive
- gosec - gosec
disable: disable:
- gocritic # Can be enabled later for stricter checks - gocritic # Can be enabled later for stricter checks
linters-settings: linters-settings:
revive:
rules:
- name: exported
severity: warning
arguments:
- checkPrivateReceivers
# Disable stuttering check - interface names like ConfigProvider are acceptable
- name: package-comments
severity: warning
gosec: gosec:
severity: medium severity: medium
errcheck: errcheck:
@@ -43,10 +33,6 @@ issues:
linters: linters:
- errcheck - errcheck
- gosec - gosec
# ConfigProvider stuttering is acceptable - it's a common pattern for interfaces
- path: pkg/config/config\.go
linters:
- revive
output: output:
print-issued-lines: true print-issued-lines: true

View File

@@ -184,6 +184,7 @@ When working on this project, follow this workflow:
- Meet the acceptance criteria - Meet the acceptance criteria
- Use the implementation notes as guidance - Use the implementation notes as guidance
- Follow the patterns established in `playbook.md` - Follow the patterns established in `playbook.md`
- Implement tests
### 6. Verify Alignment ### 6. Verify Alignment
- Ensure code follows Clean/Hexagonal Architecture principles - Ensure code follows Clean/Hexagonal Architecture principles
@@ -196,6 +197,8 @@ When working on this project, follow this workflow:
- **ALWAYS commit** after successful implementation - **ALWAYS commit** after successful implementation
- Ensure the code builds (`go build`) - Ensure the code builds (`go build`)
- Ensure all tests pass (`go test`) - Ensure all tests pass (`go test`)
- Ensure there are no linter issues (`make lint`)
- Ensure there are no fmt issues (`make fmt-check`)
- Verify all acceptance criteria are met - Verify all acceptance criteria are met
- Write a clear, descriptive commit message - Write a clear, descriptive commit message
@@ -301,6 +304,7 @@ If you make architectural decisions or significant changes:
2. Update architecture documents if structure changes 2. Update architecture documents if structure changes
3. Update stories if implementation details change 3. Update stories if implementation details change
4. Keep documentation in sync with code 4. Keep documentation in sync with code
5. Do not use any emojis
--- ---

View File

@@ -21,7 +21,7 @@ func main() {
fx.Invoke(di.RegisterLifecycleHooks), fx.Invoke(di.RegisterLifecycleHooks),
// Force HTTP server to be created (which triggers all dependencies) // Force HTTP server to be created (which triggers all dependencies)
// This ensures database, health, metrics, etc. are all created // This ensures database, health, metrics, etc. are all created
fx.Invoke(func(srv *server.Server, dbClient *database.Client) { fx.Invoke(func(_ *server.Server, _ *database.Client) {
// Both server and database are created, hooks are registered // Both server and database are created, hooks are registered
// This ensures all providers execute // This ensures all providers execute
}), }),

View File

@@ -1,3 +1,4 @@
// Package ent provides code generation for Ent schema definitions.
package ent package ent
//go:generate go run -mod=mod entgo.io/ent/cmd/ent generate ./schema //go:generate go run -mod=mod entgo.io/ent/cmd/ent generate ./schema

View File

@@ -1,3 +1,4 @@
// Package schema defines the Ent schema for audit log entities.
package schema package schema
import "entgo.io/ent" import "entgo.io/ent"

View File

@@ -19,6 +19,7 @@ import (
"git.dcentral.systems/toolz/goplt/pkg/errorbus" "git.dcentral.systems/toolz/goplt/pkg/errorbus"
"git.dcentral.systems/toolz/goplt/pkg/logger" "git.dcentral.systems/toolz/goplt/pkg/logger"
"go.opentelemetry.io/otel/trace" "go.opentelemetry.io/otel/trace"
"go.opentelemetry.io/otel/trace/noop"
"go.uber.org/fx" "go.uber.org/fx"
) )
@@ -130,7 +131,7 @@ func ProvideDatabase() fx.Option {
log.Info("Database migrations completed successfully") log.Info("Database migrations completed successfully")
return nil return nil
}, },
OnStop: func(ctx context.Context) error { OnStop: func(_ context.Context) error {
return dbClient.Close() return dbClient.Close()
}, },
}) })
@@ -147,7 +148,7 @@ func ProvideErrorBus() fx.Option {
// Register lifecycle hook to close the bus on shutdown // Register lifecycle hook to close the bus on shutdown
lc.Append(fx.Hook{ lc.Append(fx.Hook{
OnStop: func(ctx context.Context) error { OnStop: func(_ context.Context) error {
return bus.Close() return bus.Close()
}, },
}) })
@@ -181,7 +182,7 @@ func ProvideTracer() fx.Option {
enabled := cfg.GetBool("tracing.enabled") enabled := cfg.GetBool("tracing.enabled")
if !enabled { if !enabled {
// Return no-op tracer // Return no-op tracer
return trace.NewNoopTracerProvider(), nil return noop.NewTracerProvider(), nil
} }
serviceName := cfg.GetString("tracing.service_name") serviceName := cfg.GetString("tracing.service_name")
@@ -248,8 +249,7 @@ func ProvideHTTPServer() fx.Option {
// Register lifecycle hooks // Register lifecycle hooks
lc.Append(fx.Hook{ lc.Append(fx.Hook{
OnStart: func(ctx context.Context) error { OnStart: func(_ context.Context) error {
// Get server address from config // Get server address from config
port := cfg.GetInt("server.port") port := cfg.GetInt("server.port")
if port == 0 { if port == 0 {
@@ -300,7 +300,7 @@ func ProvideHTTPServer() fx.Option {
) )
// Continue anyway - server might still be starting // Continue anyway - server might still be starting
} else { } else {
resp.Body.Close() _ = resp.Body.Close()
} }
log.Info("HTTP server started successfully", log.Info("HTTP server started successfully",

View File

@@ -1,3 +1,4 @@
// Package schema defines the Ent schema for domain entities.
package schema package schema
import ( import (
@@ -46,4 +47,3 @@ func (AuditLog) Indexes() []ent.Index {
index.Fields("action"), index.Fields("action"),
} }
} }

View File

@@ -30,4 +30,3 @@ func (Permission) Edges() []ent.Edge {
edge.To("role_permissions", RolePermission.Type), edge.To("role_permissions", RolePermission.Type),
} }
} }

View File

@@ -37,4 +37,3 @@ func (Role) Edges() []ent.Edge {
edge.To("user_roles", UserRole.Type), edge.To("user_roles", UserRole.Type),
} }
} }

View File

@@ -32,4 +32,3 @@ func (RolePermission) Edges() []ent.Edge {
Field("permission_id"), Field("permission_id"),
} }
} }

View File

@@ -41,4 +41,3 @@ func (User) Edges() []ent.Edge {
edge.To("user_roles", UserRole.Type), edge.To("user_roles", UserRole.Type),
} }
} }

View File

@@ -32,4 +32,3 @@ func (UserRole) Edges() []ent.Edge {
Field("role_id"), Field("role_id"),
} }
} }

View File

@@ -1,3 +1,4 @@
// Package errorbus provides a channel-based error bus implementation.
package errorbus package errorbus
import ( import (
@@ -11,17 +12,17 @@ import (
// ChannelBus implements a channel-based error bus. // ChannelBus implements a channel-based error bus.
type ChannelBus struct { type ChannelBus struct {
errors chan errorWithContext errors chan errorWithContext
logger logger.Logger logger logger.Logger
done chan struct{} done chan struct{}
wg sync.WaitGroup wg sync.WaitGroup
once sync.Once once sync.Once
} }
type errorWithContext struct { type errorWithContext struct {
err error err error
ctx context.Context ctx context.Context
stack []byte stack []byte
} }
// NewChannelBus creates a new channel-based error bus. // NewChannelBus creates a new channel-based error bus.
@@ -162,4 +163,3 @@ func (b *ChannelBus) Close() error {
// Ensure ChannelBus implements ErrorPublisher // Ensure ChannelBus implements ErrorPublisher
var _ errorbus.ErrorPublisher = (*ChannelBus)(nil) var _ errorbus.ErrorPublisher = (*ChannelBus)(nil)

View File

@@ -1,3 +1,4 @@
// Package health provides health check implementations for various components.
package health package health
import ( import (
@@ -23,4 +24,3 @@ func NewDatabaseChecker(client *database.Client) health.HealthChecker {
func (d *DatabaseChecker) Check(ctx context.Context) error { func (d *DatabaseChecker) Check(ctx context.Context) error {
return d.client.Ping(ctx) return d.client.Ping(ctx)
} }

View File

@@ -60,7 +60,7 @@ func (r *Registry) Check(ctx context.Context) health.HealthStatus {
} }
// LivenessCheck performs a basic liveness check (no dependencies). // LivenessCheck performs a basic liveness check (no dependencies).
func (r *Registry) LivenessCheck(ctx context.Context) health.HealthStatus { func (r *Registry) LivenessCheck(_ context.Context) health.HealthStatus {
// Liveness is always healthy if the service is running // Liveness is always healthy if the service is running
return health.HealthStatus{ return health.HealthStatus{
Status: health.StatusHealthy, Status: health.StatusHealthy,
@@ -71,4 +71,3 @@ func (r *Registry) LivenessCheck(ctx context.Context) health.HealthStatus {
func (r *Registry) ReadinessCheck(ctx context.Context) health.HealthStatus { func (r *Registry) ReadinessCheck(ctx context.Context) health.HealthStatus {
return r.Check(ctx) return r.Check(ctx)
} }

View File

@@ -1,3 +1,4 @@
// Package database provides database client and connection management.
package database package database
import ( import (
@@ -20,11 +21,11 @@ type Client struct {
// Config holds database configuration. // Config holds database configuration.
type Config struct { type Config struct {
DSN string DSN string
MaxConnections int MaxConnections int
MaxIdleConns int MaxIdleConns int
ConnMaxLifetime time.Duration ConnMaxLifetime time.Duration
ConnMaxIdleTime time.Duration ConnMaxIdleTime time.Duration
} }
// NewClient creates a new Ent client with connection pooling. // NewClient creates a new Ent client with connection pooling.
@@ -46,7 +47,7 @@ func NewClient(cfg Config) (*Client, error) {
defer cancel() defer cancel()
if err := db.PingContext(ctx); err != nil { if err := db.PingContext(ctx); err != nil {
db.Close() _ = db.Close()
return nil, fmt.Errorf("failed to ping database: %w", err) return nil, fmt.Errorf("failed to ping database: %w", err)
} }
@@ -72,7 +73,7 @@ func (c *Client) Close() error {
// Migrate runs database migrations. // Migrate runs database migrations.
func (c *Client) Migrate(ctx context.Context) error { func (c *Client) Migrate(ctx context.Context) error {
return c.Client.Schema.Create(ctx) return c.Schema.Create(ctx)
} }
// Ping checks database connectivity. // Ping checks database connectivity.
@@ -84,4 +85,3 @@ func (c *Client) Ping(ctx context.Context) error {
func (c *Client) DB() *sql.DB { func (c *Client) DB() *sql.DB {
return c.db return c.db
} }

View File

@@ -1,3 +1,4 @@
// Package metrics provides Prometheus metrics collection and instrumentation.
package metrics package metrics
import ( import (
@@ -12,9 +13,9 @@ import (
// Metrics holds all Prometheus metrics. // Metrics holds all Prometheus metrics.
type Metrics struct { type Metrics struct {
httpRequestDuration *prometheus.HistogramVec httpRequestDuration *prometheus.HistogramVec
httpRequestTotal *prometheus.CounterVec httpRequestTotal *prometheus.CounterVec
httpErrorsTotal *prometheus.CounterVec httpErrorsTotal *prometheus.CounterVec
registry *prometheus.Registry registry *prometheus.Registry
} }
// NewMetrics creates a new metrics registry with all metrics. // NewMetrics creates a new metrics registry with all metrics.
@@ -94,4 +95,3 @@ func (m *Metrics) Handler() http.Handler {
func (m *Metrics) Registry() *prometheus.Registry { func (m *Metrics) Registry() *prometheus.Registry {
return m.registry return m.registry
} }

View File

@@ -1,3 +1,4 @@
// Package observability provides OpenTelemetry tracing setup and configuration.
package observability package observability
import ( import (
@@ -13,22 +14,23 @@ import (
sdktrace "go.opentelemetry.io/otel/sdk/trace" sdktrace "go.opentelemetry.io/otel/sdk/trace"
semconv "go.opentelemetry.io/otel/semconv/v1.26.0" semconv "go.opentelemetry.io/otel/semconv/v1.26.0"
"go.opentelemetry.io/otel/trace" "go.opentelemetry.io/otel/trace"
"go.opentelemetry.io/otel/trace/noop"
) )
// Config holds OpenTelemetry configuration. // Config holds OpenTelemetry configuration.
type Config struct { type Config struct {
Enabled bool Enabled bool
ServiceName string ServiceName string
ServiceVersion string ServiceVersion string
Environment string Environment string
OTLPEndpoint string OTLPEndpoint string
} }
// InitTracer initializes OpenTelemetry tracing. // InitTracer initializes OpenTelemetry tracing.
func InitTracer(ctx context.Context, cfg Config) (trace.TracerProvider, error) { func InitTracer(ctx context.Context, cfg Config) (trace.TracerProvider, error) {
if !cfg.Enabled { if !cfg.Enabled {
// Return a no-op tracer provider // Return a no-op tracer provider
return trace.NewNoopTracerProvider(), nil return noop.NewTracerProvider(), nil
} }
// Create resource with service information // Create resource with service information
@@ -91,4 +93,3 @@ func ShutdownTracer(ctx context.Context, tp trace.TracerProvider) error {
} }
return nil return nil
} }

View File

@@ -1,3 +1,4 @@
// Package server provides HTTP middleware functions for request processing.
package server package server
import ( import (
@@ -6,15 +7,17 @@ import (
"runtime" "runtime"
"time" "time"
"github.com/gin-gonic/gin"
"github.com/google/uuid"
"git.dcentral.systems/toolz/goplt/pkg/errorbus" "git.dcentral.systems/toolz/goplt/pkg/errorbus"
"git.dcentral.systems/toolz/goplt/pkg/logger" "git.dcentral.systems/toolz/goplt/pkg/logger"
"github.com/gin-gonic/gin"
"github.com/google/uuid"
) )
type contextKey string
const ( const (
requestIDKey = "request_id" requestIDKey contextKey = "request_id"
userIDKey = "user_id" userIDKey contextKey = "user_id"
) )
// RequestIDMiddleware generates a unique request ID for each request. // RequestIDMiddleware generates a unique request ID for each request.
@@ -25,7 +28,7 @@ func RequestIDMiddleware() gin.HandlerFunc {
requestID = uuid.New().String() requestID = uuid.New().String()
} }
c.Set(requestIDKey, requestID) c.Set(string(requestIDKey), requestID)
c.Header("X-Request-ID", requestID) c.Header("X-Request-ID", requestID)
c.Next() c.Next()
} }
@@ -45,7 +48,7 @@ func LoggingMiddleware(log logger.Logger) gin.HandlerFunc {
duration := time.Since(start) duration := time.Since(start)
// Get request ID from context // Get request ID from context
requestID, _ := c.Get(requestIDKey) requestID, _ := c.Get(string(requestIDKey))
requestIDStr := "" requestIDStr := ""
if id, ok := requestID.(string); ok { if id, ok := requestID.(string); ok {
requestIDStr = id requestIDStr = id
@@ -74,8 +77,8 @@ func PanicRecoveryMiddleware(errorBus errorbus.ErrorPublisher) gin.HandlerFunc {
stack = stack[:n] stack = stack[:n]
// Get request ID from context // Get request ID from context
requestID, _ := c.Get(requestIDKey) requestID, _ := c.Get(string(requestIDKey))
ctx := context.WithValue(context.Background(), "request_id", requestID) ctx := context.WithValue(context.Background(), requestIDKey, requestID)
// Create error // Create error
var panicErr error var panicErr error
@@ -138,4 +141,3 @@ func TimeoutMiddleware(timeout time.Duration) gin.HandlerFunc {
c.Next() c.Next()
} }
} }

View File

@@ -1,3 +1,4 @@
// Package errorbus provides interfaces for error publishing and handling.
package errorbus package errorbus
import ( import (
@@ -18,4 +19,3 @@ type ErrorContext struct {
Component string Component string
Metadata map[string]interface{} Metadata map[string]interface{}
} }

View File

@@ -1,3 +1,4 @@
// Package health provides interfaces and types for health checking.
package health package health
import "context" import "context"
@@ -31,4 +32,3 @@ type HealthStatus struct {
Status Status `json:"status"` Status Status `json:"status"`
Components []ComponentStatus `json:"components,omitempty"` Components []ComponentStatus `json:"components,omitempty"`
} }