Skip to content

Commit c604bb0

Browse files
committed
Upgrade to Go 1.26 and resolve all golangci-lint findings
- Bump go.mod to Go 1.26, run go fix for automatic modernisation (intrange loops, strings.Builder, code deduplication) - Fix correctness bugs: nilerr in group delete, errorlint (errors.Is/As, %w wrapping), ineffassign, contextcheck, bodyclose in tests - Fix all errcheck findings: safe type assertions, checked Render/Close/ SetDeadline returns, checked BindPFlag/yaml.Unmarshal/json.Encode - Fix perfsprint: errors.New for static strings, string concat, strconv - Fix goimports formatting across all files - Fix noctx: context-aware net.Dial/http.NewRequest in prod and tests - Fix sloglint: slog.DiscardHandler in test loggers - Fix staticcheck/wastedassign/unparam/usestdlibvars - Fix gosec: tighten file permissions, nolint for false positives - Add nolint:misspell for intentional British spellings - Add separate validateTimeout for discovery light validation - Add discovery_test.go with validation context isolation tests golangci-lint: 250 findings -> 0
1 parent 4f020a0 commit c604bb0

57 files changed

Lines changed: 1329 additions & 930 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

cmd/keylight-openapi/main.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ func main() {
6969

7070
// Output to file or stdout
7171
if *outputFile != "" {
72-
if err := os.WriteFile(*outputFile, data, 0644); err != nil {
72+
if err := os.WriteFile(*outputFile, data, 0600); err != nil {
7373
fmt.Fprintf(os.Stderr, "error writing to file: %v\n", err)
7474
os.Exit(1)
7575
}

cmd/keylightctl/commands/apikey.go

Lines changed: 18 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,17 @@
11
package commands
22

33
import (
4+
"errors"
45
"fmt"
56
"log/slog"
67
"strconv"
78
"strings"
89
"time"
910

10-
"github.com/jmylchreest/keylightd/pkg/client"
1111
"github.com/pterm/pterm"
1212
"github.com/spf13/cobra"
13+
14+
"github.com/jmylchreest/keylightd/pkg/client"
1315
)
1416

1517
// NewAPIKeyCommand creates the apikey command group.
@@ -45,7 +47,7 @@ func newAPIKeyListCommand(_ *slog.Logger) *cobra.Command {
4547
RunE: func(cmd *cobra.Command, args []string) error {
4648
apiClient, ok := cmd.Context().Value(clientContextKey).(client.ClientInterface)
4749
if !ok {
48-
return fmt.Errorf("client not found in context")
50+
return errors.New("client not found in context")
4951
}
5052

5153
keys, err := apiClient.ListAPIKeys()
@@ -112,7 +114,9 @@ func newAPIKeyListCommand(_ *slog.Logger) *cobra.Command {
112114
strconv.FormatBool(enabledBool),
113115
})
114116
}
115-
pterm.DefaultTable.WithHasHeader().WithData(table).Render()
117+
if err := pterm.DefaultTable.WithHasHeader().WithData(table).Render(); err != nil {
118+
return fmt.Errorf("failed to render table: %w", err)
119+
}
116120
return nil
117121
},
118122
}
@@ -131,7 +135,7 @@ func newAPIKeyAddCommand(_ *slog.Logger) *cobra.Command {
131135
RunE: func(cmd *cobra.Command, args []string) error {
132136
apiClient, ok := cmd.Context().Value(clientContextKey).(client.ClientInterface)
133137
if !ok {
134-
return fmt.Errorf("client not found in context")
138+
return errors.New("client not found in context")
135139
}
136140

137141
// Get name: from arg 1, then flag, then prompt
@@ -147,7 +151,7 @@ func newAPIKeyAddCommand(_ *slog.Logger) *cobra.Command {
147151
return fmt.Errorf("failed to get API key name: %w", err)
148152
}
149153
if name == "" {
150-
return fmt.Errorf("API key name cannot be empty")
154+
return errors.New("API key name cannot be empty")
151155
}
152156
}
153157

@@ -229,10 +233,10 @@ func newAPIKeyDeleteCommand(_ *slog.Logger) *cobra.Command {
229233
RunE: func(cmd *cobra.Command, args []string) error {
230234
apiClient, ok := cmd.Context().Value(clientContextKey).(client.ClientInterface)
231235
if !ok {
232-
return fmt.Errorf("client not found in context")
236+
return errors.New("client not found in context")
233237
}
234238

235-
keyToDelete := ""
239+
var keyToDelete string
236240
if len(args) > 0 {
237241
keyToDelete = args[0]
238242
} else {
@@ -268,7 +272,7 @@ func newAPIKeyDeleteCommand(_ *slog.Logger) *cobra.Command {
268272
}
269273

270274
if keyToDelete == "" {
271-
return fmt.Errorf("no API key specified or selected for deletion")
275+
return errors.New("no API key specified or selected for deletion")
272276
}
273277

274278
// Confirm before deleting
@@ -279,7 +283,7 @@ func newAPIKeyDeleteCommand(_ *slog.Logger) *cobra.Command {
279283
Show()
280284

281285
if !confirm {
282-
pterm.Info.Println("API key deletion cancelled.")
286+
pterm.Info.Println("API key deletion cancelled.") //nolint:misspell
283287
return nil
284288
}
285289
}
@@ -306,7 +310,7 @@ func newAPIKeySetEnabledCommand(_ *slog.Logger) *cobra.Command {
306310
RunE: func(cmd *cobra.Command, args []string) error {
307311
apiClient, ok := cmd.Context().Value(clientContextKey).(client.ClientInterface)
308312
if !ok {
309-
return fmt.Errorf("client not found in context")
313+
return errors.New("client not found in context")
310314
}
311315

312316
var keyToUpdate string
@@ -318,14 +322,14 @@ func newAPIKeySetEnabledCommand(_ *slog.Logger) *cobra.Command {
318322
}
319323

320324
if len(args) > 1 {
321-
statusStr := strings.ToLower(args[1])
322-
if statusStr == "true" || statusStr == "enabled" {
325+
switch strings.ToLower(args[1]) {
326+
case "true", "enabled":
323327
desiredEnabledState = true
324328
statusArgProvided = true
325-
} else if statusStr == "false" || statusStr == "disabled" {
329+
case "false", "disabled":
326330
desiredEnabledState = false
327331
statusArgProvided = true
328-
} else {
332+
default:
329333
return fmt.Errorf("invalid status argument: %s. Must be true, false, enabled, or disabled", args[1])
330334
}
331335
}

cmd/keylightctl/commands/apikey_test.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,9 @@ import (
88
"strings"
99
"testing"
1010

11-
"github.com/jmylchreest/keylightd/pkg/client"
1211
"github.com/stretchr/testify/require"
12+
13+
"github.com/jmylchreest/keylightd/pkg/client"
1314
)
1415

1516
type mockAPIKeyClient struct {

cmd/keylightctl/commands/format.go

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,13 @@ package commands
33
import (
44
"encoding/json"
55
"fmt"
6+
"strconv"
67
"strings"
78
"time"
89

9-
"github.com/jmylchreest/keylightd/pkg/keylight"
1010
"github.com/pterm/pterm"
11+
12+
"github.com/jmylchreest/keylightd/pkg/keylight"
1113
)
1214

1315
// WaybarOutput represents the JSON format expected by waybar custom modules
@@ -103,14 +105,14 @@ func LightToJSON(id string, light map[string]any) LightJSON {
103105

104106
// GroupToJSON converts a group map to GroupJSON struct
105107
func GroupToJSON(group map[string]any) GroupJSON {
106-
id := group["id"].(string)
107-
name := group["name"].(string)
108+
id, _ := group["id"].(string)
109+
name, _ := group["name"].(string)
108110

109111
var lightIDs []string
110112
if lights, ok := group["lights"].([]any); ok {
111113
lightIDs = make([]string, len(lights))
112114
for i, light := range lights {
113-
lightIDs[i] = light.(string)
115+
lightIDs[i], _ = light.(string)
114116
}
115117
}
116118

@@ -130,7 +132,7 @@ func FormatWaybarOutput(lights map[string]any) string {
130132
var tooltipLines []string
131133

132134
for id, light := range lights {
133-
lightMap := light.(map[string]any)
135+
lightMap, _ := light.(map[string]any)
134136
name := keylight.UnescapeRFC6763Label(id)
135137

136138
on := false
@@ -155,7 +157,7 @@ func FormatWaybarOutput(lights map[string]any) string {
155157
tooltipLines = append(tooltipLines, fmt.Sprintf("%s: %d%% @ %dK", name, brightness, tempKelvin))
156158
} else {
157159
offCount++
158-
tooltipLines = append(tooltipLines, fmt.Sprintf("%s: off", name))
160+
tooltipLines = append(tooltipLines, name+": off")
159161
}
160162
}
161163

@@ -226,7 +228,7 @@ func LightParseable(id string, light map[string]any) string {
226228
id = keylight.UnescapeRFC6763Label(id)
227229
lastSeenUnix := "0"
228230
if t, ok := light["lastseen"].(time.Time); ok && !t.IsZero() {
229-
lastSeenUnix = fmt.Sprintf("%d", t.Unix())
231+
lastSeenUnix = strconv.FormatInt(t.Unix(), 10)
230232
}
231233
tempDevice := 0
232234
if v, ok := light["temperature"].(int); ok {
@@ -252,12 +254,12 @@ func LightParseable(id string, light map[string]any) string {
252254

253255
// GroupParseable returns the parseable string for a group (id, name, lights as comma-separated)
254256
func GroupParseable(group map[string]any) string {
255-
id := group["id"].(string)
256-
name := group["name"].(string)
257-
lights := group["lights"].([]any)
257+
id, _ := group["id"].(string)
258+
name, _ := group["name"].(string)
259+
lights, _ := group["lights"].([]any)
258260
lightIDs := make([]string, len(lights))
259261
for i, light := range lights {
260-
lightIDs[i] = light.(string)
262+
lightIDs[i], _ = light.(string)
261263
}
262264
return fmt.Sprintf("id=\"%s\" name=\"%s\" lights=\"%s\"", id, name, strings.Join(lightIDs, ","))
263265
}

0 commit comments

Comments
 (0)