Skip to content

Commit a6afc46

Browse files
committed
fix a ton of linter errors
1 parent 0e7c89e commit a6afc46

20 files changed

+249
-123
lines changed

.golangci.yml

+3
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,9 @@ issues:
3838
- funlen
3939
- dupl
4040
- maintidx
41+
- path: cmd/benchi/*
42+
linters:
43+
- containedctx
4144

4245
linters:
4346
# please, do not use `enable-all`: it's deprecated and will be removed soon.

Makefile

+2-2
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,11 @@ test:
44

55
.PHONY: lint
66
lint:
7-
go tool golangci-lint run
7+
golangci-lint run
88

99
.PHONY: fmt
1010
fmt:
11-
go tool gofumpt -l -w .
11+
gofumpt -l -w .
1212

1313
.PHONY: install-tools
1414
install-tools:

cmd/benchi/internal/log.go

+5-5
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ package internal
1616

1717
import (
1818
"bufio"
19+
"fmt"
1920
"io"
2021
"strings"
2122
"sync/atomic"
@@ -60,12 +61,11 @@ func (m LogModel) Update(msg tea.Msg) (LogModel, tea.Cmd) {
6061
return m, nil
6162
}
6263

63-
tmp := m.lines
64-
if m.displaySize > 0 && len(tmp) == m.displaySize {
65-
tmp = tmp[1:]
64+
if m.displaySize > 0 && len(m.lines) == m.displaySize {
65+
m.lines = m.lines[1:]
6666
}
6767

68-
m.lines = append(tmp, logMsg.line)
68+
m.lines = append(m.lines, logMsg.line)
6969
return m, m.readLineCmd()
7070
}
7171

@@ -84,7 +84,7 @@ func (m LogModel) readLineCmd() tea.Cmd {
8484
if err == io.EOF {
8585
return nil
8686
}
87-
return err
87+
return fmt.Errorf("failed to read log line: %w", err)
8888
}
8989
line = strings.TrimSpace(line)
9090
return LogModelMsg{id: m.id, line: line}

cmd/benchi/internal/progresstimer.go

+2-3
Original file line numberDiff line numberDiff line change
@@ -43,10 +43,9 @@ func (m ProgressTimerModel) Init() tea.Cmd {
4343
}
4444

4545
func (m ProgressTimerModel) Update(msg tea.Msg) (ProgressTimerModel, tea.Cmd) {
46-
switch msg := msg.(type) {
47-
case timer.TickMsg:
46+
if tickMsg, ok := msg.(timer.TickMsg); ok {
4847
var cmd tea.Cmd
49-
m.timer, cmd = m.timer.Update(msg)
48+
m.timer, cmd = m.timer.Update(tickMsg)
5049
return m, cmd
5150
}
5251
return m, nil

cmd/benchi/main.go

+76-44
Original file line numberDiff line numberDiff line change
@@ -44,10 +44,10 @@ import (
4444
)
4545

4646
var (
47-
configPath = flag.String("config", "", "path to the benchmark config file")
48-
outPath = flag.String("out", "./results", "path to the output folder")
49-
tools = internal.StringsFlag("tool", nil, "filter tool to be tested (can be provided multiple times)")
50-
tests = internal.StringsFlag("tests", nil, "filter test to run (can be provided multiple times)")
47+
configPathFlag = flag.String("config", "", "path to the benchmark config file")
48+
outPathFlag = flag.String("out", "./results", "path to the output folder")
49+
toolsFlag = internal.StringsFlag("tool", nil, "filter tool to be tested (can be provided multiple times)")
50+
testsFlag = internal.StringsFlag("tests", nil, "filter test to run (can be provided multiple times)")
5151
)
5252

5353
func main() {
@@ -60,27 +60,30 @@ func main() {
6060
func mainE() error {
6161
flag.Parse()
6262

63-
if configPath == nil || strings.TrimSpace(*configPath) == "" {
63+
if configPathFlag == nil || strings.TrimSpace(*configPathFlag) == "" {
6464
return fmt.Errorf("config path is required")
6565
}
6666

6767
// Create output directory if it does not exist.
68-
err := os.MkdirAll(*outPath, 0o755)
68+
err := os.MkdirAll(*outPathFlag, 0o755)
6969
if err != nil {
7070
return fmt.Errorf("failed to create output directory: %w", err)
7171
}
7272

7373
now := time.Now()
7474
infoReader, errorReader, closeLog, err := prepareLogger(now)
75+
if err != nil {
76+
return fmt.Errorf("failed to prepare logger: %w", err)
77+
}
7578
defer closeLog()
7679

7780
_, err = tea.NewProgram(newMainModel(infoReader, errorReader, now)).Run()
78-
return err
81+
return err //nolint:wrapcheck // Wrapping this error wouldn't add any value.
7982
}
8083

81-
func prepareLogger(now time.Time) (io.Reader, io.Reader, func() error, error) {
84+
func prepareLogger(now time.Time) (io.Reader, io.Reader, func(), error) {
8285
// Create log file.
83-
logPath := filepath.Join(*outPath, fmt.Sprintf("%s_benchi.log", now.Format("20060102150405")))
86+
logPath := filepath.Join(*outPathFlag, fmt.Sprintf("%s_benchi.log", now.Format("20060102150405")))
8487
logFile, err := os.Create(logPath)
8588
if err != nil {
8689
return nil, nil, nil, fmt.Errorf("failed to create log file: %w", err)
@@ -100,12 +103,14 @@ func prepareLogger(now time.Time) (io.Reader, io.Reader, func() error, error) {
100103
)
101104
slog.SetDefault(slog.New(logHandler))
102105

103-
return infoReader, errorReader, func() error {
106+
return infoReader, errorReader, func() {
104107
var errs []error
105108
errs = append(errs, logFile.Close())
106109
errs = append(errs, infoWriter.Close())
107110
errs = append(errs, errorWriter.Close())
108-
return errors.Join(errs...)
111+
if err := errors.Join(errs...); err != nil {
112+
slog.Error("Failed to close logger", "error", err)
113+
}
109114
}, nil
110115
}
111116

@@ -167,13 +172,13 @@ func (m mainModel) Init() tea.Cmd {
167172
func (mainModel) parseConfig(path string) (config.Config, error) {
168173
f, err := os.Open(path)
169174
if err != nil {
170-
return config.Config{}, err
175+
return config.Config{}, fmt.Errorf("failed to open config file %s: %w", path, err)
171176
}
172177
defer f.Close()
173178
var cfg config.Config
174179
err = yaml.NewDecoder(f).Decode(&cfg)
175180
if err != nil {
176-
return config.Config{}, err
181+
return config.Config{}, fmt.Errorf("failed to parse config file %s as YAML: %w", path, err)
177182
}
178183
return cfg, nil
179184
}
@@ -183,17 +188,10 @@ func (m mainModel) initCmd() tea.Cmd {
183188
now := time.Now()
184189

185190
// Resolve absolute paths.
186-
resultsDir, err := filepath.Abs(*outPath)
187-
if err != nil {
188-
return fmt.Errorf("failed to get absolute path for output directory: %w", err)
189-
}
190-
slog.Info("Results directory", "path", resultsDir)
191-
192-
configPath, err := filepath.Abs(*configPath)
191+
resultsDir, configPath, err := m.initPaths()
193192
if err != nil {
194-
return fmt.Errorf("failed to get absolute path for config file: %w", err)
193+
return fmt.Errorf("failed to resolve paths: %w", err)
195194
}
196-
slog.Info("Config file", "path", configPath)
197195

198196
// Parse config.
199197
cfg, err := m.parseConfig(configPath)
@@ -210,24 +208,16 @@ func (m mainModel) initCmd() tea.Cmd {
210208
}
211209

212210
// Create docker client and initialize network.
213-
dockerClient, err := client.NewClientWithOpts(client.FromEnv)
214-
if err != nil {
215-
return fmt.Errorf("failed to create docker client: %w", err)
216-
}
217-
defer dockerClient.Close()
218-
219-
slog.Info("Creating docker network", "network", benchi.NetworkName)
220-
net, err := dockerutil.CreateNetworkIfNotExist(m.ctx, dockerClient, benchi.NetworkName)
211+
dockerClient, err := m.initDocker()
221212
if err != nil {
222-
return fmt.Errorf("failed to create docker network: %w", err)
213+
return fmt.Errorf("failed to initialize docker: %w", err)
223214
}
224-
slog.Info("Using network", "network", net.Name, "network-id", net.ID)
225215

226216
testRunners, err := benchi.BuildTestRunners(cfg, benchi.TestRunnerOptions{
227217
ResultsDir: resultsDir,
228218
StartedAt: now,
229-
FilterTests: *tests,
230-
FilterTools: *tools,
219+
FilterTests: *testsFlag,
220+
FilterTools: *toolsFlag,
231221
DockerClient: dockerClient,
232222
})
233223
if err != nil {
@@ -244,6 +234,40 @@ func (m mainModel) initCmd() tea.Cmd {
244234
}
245235
}
246236

237+
func (mainModel) initPaths() (resultsDir, configPath string, err error) {
238+
resultsDir, err = filepath.Abs(*outPathFlag)
239+
if err != nil {
240+
return "", "", fmt.Errorf("failed to get absolute path for output directory: %w", err)
241+
}
242+
slog.Info("Results directory", "path", resultsDir)
243+
244+
configPath, err = filepath.Abs(*configPathFlag)
245+
if err != nil {
246+
return "", "", fmt.Errorf("failed to get absolute path for config file: %w", err)
247+
}
248+
slog.Info("Config file", "path", configPath)
249+
250+
return resultsDir, configPath, nil
251+
}
252+
253+
func (m mainModel) initDocker() (client.APIClient, error) {
254+
slog.Info("Creating docker client")
255+
dockerClient, err := client.NewClientWithOpts(client.FromEnv)
256+
if err != nil {
257+
return nil, fmt.Errorf("failed to create docker client: %w", err)
258+
}
259+
dockerClient.NegotiateAPIVersion(m.ctx)
260+
261+
slog.Info("Creating docker network", "network", benchi.NetworkName)
262+
net, err := dockerutil.CreateNetworkIfNotExist(m.ctx, dockerClient, benchi.NetworkName)
263+
if err != nil {
264+
return nil, fmt.Errorf("failed to create docker network: %w", err)
265+
}
266+
slog.Info("Using network", "network", net.Name, "network-id", net.ID)
267+
268+
return dockerClient, nil
269+
}
270+
247271
func (mainModel) runTestCmd(index int) tea.Cmd {
248272
return func() tea.Msg {
249273
return mainModelMsgNextTest{testIndex: index}
@@ -257,12 +281,18 @@ func (m mainModel) quitCmd() tea.Cmd {
257281
if err != nil {
258282
slog.Error("Failed to remove network", "network", benchi.NetworkName, "error", err)
259283
}
284+
err = m.dockerClient.Close()
285+
if err != nil {
286+
slog.Error("Failed to close docker client", "error", err)
287+
}
260288
return tea.Quit()
261289
}
262290
}
263291

292+
//nolint:funlen // This function is long because it manages messages for the whole application.
264293
func (m mainModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
265294
slog.Debug("Received message", "msg", msg, "type", fmt.Sprintf("%T", msg))
295+
266296
switch msg := msg.(type) {
267297
case mainModelMsgInitDone:
268298
m.config = msg.config
@@ -288,31 +318,33 @@ func (m mainModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
288318
}
289319
m.currentTestIndex = msg.testIndex
290320
return m, m.tests[m.currentTestIndex].Init()
321+
291322
case testModelMsgDone:
292323
nextIndex := m.currentTestIndex + 1
293324
if m.ctx.Err() != nil {
294325
// Main context is cancelled, skip to the end.
295326
nextIndex = len(m.tests)
296327
}
297328
return m, m.runTestCmd(nextIndex)
329+
298330
case tea.KeyMsg:
299331
if msg.String() == "ctrl+c" {
300-
if m.ctx.Err() == nil {
301-
// First time, cancel the main context.
332+
switch {
333+
case m.ctx.Err() == nil:
302334
m.ctxCancel()
303335
return m, nil
304-
} else if m.cleanupCtx.Err() == nil {
305-
// Second time, cancel the cleanup context.
336+
case m.cleanupCtx.Err() == nil:
306337
m.cleanupCtxCancel()
307338
return m, nil
308-
} else {
309-
// Third time, just quit.
339+
default:
310340
return m, tea.Quit
311341
}
312342
}
343+
313344
case error:
314345
slog.Error("Error message", "error", msg)
315346
return m, nil
347+
316348
case internal.LogModelMsg:
317349
var cmds []tea.Cmd
318350

@@ -388,7 +420,7 @@ func newTestModel(ctx context.Context, cleanupCtx context.Context, client client
388420
for _, f := range runner.Infrastructure() {
389421
infraFiles = append(infraFiles, f.DockerCompose)
390422
}
391-
infraContainers, err := findContainerNames(infraFiles)
423+
infraContainers, err := findContainerNames(ctx, infraFiles)
392424
if err != nil {
393425
return testModel{}, err
394426
}
@@ -397,7 +429,7 @@ func newTestModel(ctx context.Context, cleanupCtx context.Context, client client
397429
for _, f := range runner.Tools() {
398430
toolFiles = append(toolFiles, f.DockerCompose)
399431
}
400-
toolContainers, err := findContainerNames(toolFiles)
432+
toolContainers, err := findContainerNames(ctx, toolFiles)
401433
if err != nil {
402434
return testModel{}, err
403435
}
@@ -421,10 +453,10 @@ func newTestModel(ctx context.Context, cleanupCtx context.Context, client client
421453
}, nil
422454
}
423455

424-
func findContainerNames(files []string) ([]string, error) {
456+
func findContainerNames(ctx context.Context, files []string) ([]string, error) {
425457
var buf bytes.Buffer
426458
err := dockerutil.ComposeConfig(
427-
context.Background(),
459+
ctx,
428460
dockerutil.ComposeOptions{
429461
File: files,
430462
Stdout: &buf,

dockerutil/compose.go

+2-1
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ type ComposeOptions struct {
4141
}
4242

4343
func (opt ComposeOptions) flags() []string {
44-
var flags []string
44+
var flags []string //nolint:prealloc // Keep it simple, no need to preallocate.
4545
if opt.AllResources != nil && *opt.AllResources {
4646
flags = append(flags, "--all-resources")
4747
}
@@ -82,6 +82,7 @@ func composeCmd(ctx context.Context, composeOpt ComposeOptions) *exec.Cmd {
8282
args := []string{"docker", "compose"}
8383
args = append(args, composeOpt.flags()...)
8484

85+
//nolint:gosec // We control the command arguments.
8586
cmd := exec.CommandContext(ctx, args[0], args[1:]...)
8687

8788
cmd.Stdin = composeOpt.Stdin

dockerutil/config.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ import (
2727
// Returns error if the compose command fails.
2828
func ComposeConfig(ctx context.Context, composeOpt ComposeOptions, configOpt ComposeConfigOptions) error {
2929
cmd := configCmd(ctx, composeOpt, configOpt)
30-
return execCmd(cmd)
30+
return logAndRun(cmd)
3131
}
3232

3333
// ComposeConfigOptions represents the options for the config command.

dockerutil/down.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ import (
2828
// Returns error if the compose command fails.
2929
func ComposeDown(ctx context.Context, composeOpt ComposeOptions, downOpt ComposeDownOptions) error {
3030
cmd := downCmd(ctx, composeOpt, downOpt)
31-
return execCmd(cmd)
31+
return logAndRun(cmd)
3232
}
3333

3434
// ComposeDownOptions represents the options for the down command.

0 commit comments

Comments
 (0)