Skip to content

Commit 44c7fb8

Browse files
umputunCopilot
andauthored
Migrate to golangci-lint v2 and fix linting issues (#3)
* Add FTP container implementation for testing FTP operations - Add FTPTestContainer for testing FTP file transfers - Implement methods for uploading, downloading, and listing files - Add comprehensive path handling for directories - Add secure file operations with path validation - Update README with documentation and examples * Update linting configuration and fix issues - Add golangci-lint v2 configuration file - Update CI workflow to use golangci-lint v2 - Fix error handling in stdout/stderr captures - Improve file security with path validation - Add safe handling for file operations - Fix unhandled errors in environment variable operations - Update test assertions for better reliability * Update containers/ftp.go fix typo Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --------- Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
1 parent 6ab8926 commit 44c7fb8

File tree

9 files changed

+111
-22
lines changed

9 files changed

+111
-22
lines changed

.github/workflows/ci.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,9 +30,9 @@ jobs:
3030
TZ: "America/Chicago"
3131

3232
- name: golangci-lint
33-
uses: golangci/golangci-lint-action@v3
33+
uses: golangci/golangci-lint-action@v7
3434
with:
35-
version: latest
35+
version: v2.0.2
3636

3737
- name: install goveralls
3838
run: go install github.com/mattn/goveralls@latest

.gitignore

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,9 @@
1313

1414
# Output of the go coverage tool, specifically when used with LiteIDE
1515
*.out
16-
17-
# Dependency directories (remove the comment below to include it)
18-
# vendor/
16+
*.cov
1917

2018
# Go workspace file
2119
go.work
20+
21+
**/CLAUDE.local.md

.golangci.yml

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
version: "2"
2+
run:
3+
concurrency: 4
4+
linters:
5+
default: none
6+
enable:
7+
- copyloopvar
8+
- gochecknoinits
9+
- gocritic
10+
- gosec
11+
- govet
12+
- ineffassign
13+
- misspell
14+
- nakedret
15+
- prealloc
16+
- revive
17+
- staticcheck
18+
- unconvert
19+
- unparam
20+
- unused
21+
- testifylint
22+
- nestif
23+
settings:
24+
goconst:
25+
min-len: 2
26+
min-occurrences: 2
27+
gocritic:
28+
disabled-checks:
29+
- wrapperFunc
30+
enabled-tags:
31+
- performance
32+
- style
33+
- experimental
34+
gocyclo:
35+
min-complexity: 15
36+
lll:
37+
line-length: 140
38+
misspell:
39+
locale: US
40+
exclusions:
41+
generated: lax
42+
rules:
43+
- linters:
44+
- gosec
45+
text: 'G114: Use of net/http serve function that has no support for setting timeouts'
46+
- linters:
47+
- revive
48+
- unparam
49+
path: _test\.go$
50+
text: unused-parameter
51+
paths:
52+
- third_party$
53+
- builtin$
54+
- examples$
55+
formatters:
56+
exclusions:
57+
generated: lax
58+
paths:
59+
- third_party$
60+
- builtin$
61+
- examples$

capture.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
// Package testutils provides utilities for testing Go applications
12
package testutils
23

34
import (

capture_test.go

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -134,8 +134,14 @@ func TestCaptureStdoutAndStderr(t *testing.T) {
134134
wantOut: string([]byte{0, 1, 2, 3}),
135135
wantErr: string([]byte{4, 5, 6, 7}),
136136
f: func() {
137-
os.Stdout.Write([]byte{0, 1, 2, 3})
138-
os.Stderr.Write([]byte{4, 5, 6, 7})
137+
_, err := os.Stdout.Write([]byte{0, 1, 2, 3})
138+
if err != nil {
139+
t.Logf("failed to write to stdout: %v", err)
140+
}
141+
_, err = os.Stderr.Write([]byte{4, 5, 6, 7})
142+
if err != nil {
143+
t.Logf("failed to write to stderr: %v", err)
144+
}
139145
},
140146
},
141147
{

containers/mongo_test.go

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -60,13 +60,19 @@ func TestMongoTestContainer(t *testing.T) {
6060
// save current MONGO_TEST value
6161
origEnv := os.Getenv("MONGO_TEST")
6262
testValue := "mongodb://original-value:27017"
63-
os.Setenv("MONGO_TEST", testValue)
63+
if err := os.Setenv("MONGO_TEST", testValue); err != nil {
64+
t.Fatalf("Failed to set MONGO_TEST environment variable: %v", err)
65+
}
6466
defer func() {
6567
// restore original value
6668
if origEnv == "" {
67-
os.Unsetenv("MONGO_TEST")
69+
if err := os.Unsetenv("MONGO_TEST"); err != nil {
70+
t.Logf("Warning: failed to unset MONGO_TEST environment variable: %v", err)
71+
}
6872
} else {
69-
os.Setenv("MONGO_TEST", origEnv)
73+
if err := os.Setenv("MONGO_TEST", origEnv); err != nil {
74+
t.Logf("Warning: failed to restore MONGO_TEST environment variable: %v", err)
75+
}
7076
}
7177
}()
7278

@@ -82,11 +88,15 @@ func TestMongoTestContainer(t *testing.T) {
8288
t.Run("close with no original environment variable", func(t *testing.T) {
8389
// save current MONGO_TEST value
8490
origEnv := os.Getenv("MONGO_TEST")
85-
os.Unsetenv("MONGO_TEST")
91+
if err := os.Unsetenv("MONGO_TEST"); err != nil {
92+
t.Fatalf("Failed to unset MONGO_TEST environment variable: %v", err)
93+
}
8694
defer func() {
8795
// restore original value
8896
if origEnv != "" {
89-
os.Setenv("MONGO_TEST", origEnv)
97+
if err := os.Setenv("MONGO_TEST", origEnv); err != nil {
98+
t.Logf("Warning: failed to restore MONGO_TEST environment variable: %v", err)
99+
}
90100
}
91101
}()
92102

containers/ssh_test.go

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ package containers
33
import (
44
"context"
55
"os/exec"
6-
"strings"
76
"testing"
87

98
"github.com/stretchr/testify/assert"
@@ -36,11 +35,13 @@ func TestSSHTestContainer(t *testing.T) {
3635
defer func() { require.NoError(t, ssh.Close(ctx)) }()
3736

3837
// use ssh-keyscan to verify the host is accessible
39-
cmd := exec.Command("ssh-keyscan", "-p", ssh.Port.Port(), ssh.Host)
38+
// values come from the test container itself, so this is not vulnerable to command injection
39+
// ssh.Port and ssh.Host are generated by the test container and are not user input
40+
cmd := exec.Command("ssh-keyscan", "-p", ssh.Port.Port(), ssh.Host) // #nosec G204 -- these params are from our test container
4041
out, err := cmd.CombinedOutput()
4142
require.NoError(t, err)
4243
t.Logf("ssh-keyscan output: %s", out)
43-
assert.True(t, strings.Contains(string(out), "ssh-"), "should return ssh key")
44+
assert.Contains(t, string(out), "ssh-", "should return ssh key")
4445
})
4546

4647
t.Run("multiple containers", func(t *testing.T) {

file_utils_test.go

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,10 @@ func TestWriteTestFile(t *testing.T) {
1919
require.False(t, os.IsNotExist(err), "WriteTestFile did not create file at %s", filePath)
2020

2121
// check content
22-
data, err := os.ReadFile(filePath)
22+
// although ReadFile takes a path from a test-generated file, this is safe
23+
// because the file is created in a temporary directory controlled by the test
24+
// this is safe because the file path was created by WriteTestFile in a controlled manner
25+
data, err := os.ReadFile(filePath) // #nosec G304 -- safe file access in test
2326
require.NoError(t, err, "Failed to read test file")
2427
require.Equal(t, content, string(data), "File content doesn't match expected")
2528

@@ -43,7 +46,10 @@ func TestWriteTestFile(t *testing.T) {
4346
content := "line 1\nline 2\nline 3"
4447
filePath := WriteTestFile(t, content)
4548

46-
data, err := os.ReadFile(filePath)
49+
// although ReadFile takes a path from a test-generated file, this is safe
50+
// because the file is created in a temporary directory controlled by the test
51+
// this is safe because the file path was created by WriteTestFile in a controlled manner
52+
data, err := os.ReadFile(filePath) // #nosec G304 -- safe file access in test
4753
require.NoError(t, err)
4854
require.Equal(t, content, string(data))
4955
})

http_utils_test.go

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,10 @@ func TestMockHTTPServer(t *testing.T) {
1717
w.WriteHeader(http.StatusOK)
1818
// in real request handling, the error is typically ignored as it's a disconnect which HTTP server handles
1919
// ResponseWriter interface doesn't have a way to check for errors in tests
20-
// nolint:errcheck // http.ResponseWriter errors are handled by the HTTP server
21-
w.Write([]byte(`{"status":"ok"}`))
20+
_, err := w.Write([]byte(`{"status":"ok"}`))
21+
if err != nil {
22+
t.Logf("failed to write response: %v", err)
23+
}
2224
})
2325

2426
// get the server URL and cleanup function
@@ -68,8 +70,10 @@ func TestHTTPRequestCaptor(t *testing.T) {
6870
// create a test handler that will receive forwarded requests
6971
testHandler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
7072
w.WriteHeader(http.StatusOK)
71-
// nolint:errcheck // http.ResponseWriter errors are handled by the HTTP server
72-
w.Write([]byte("response"))
73+
_, err := w.Write([]byte("response"))
74+
if err != nil {
75+
t.Logf("failed to write response: %v", err)
76+
}
7377
})
7478

7579
// create the request captor
@@ -119,7 +123,7 @@ func TestHTTPRequestCaptor(t *testing.T) {
119123

120124
// test GetRequests
121125
allRequests := captor.GetRequests()
122-
require.Equal(t, 3, len(allRequests), "Wrong number of requests from GetRequests")
126+
require.Len(t, allRequests, 3, "Wrong number of requests from GetRequests")
123127

124128
// test Reset
125129
captor.Reset()

0 commit comments

Comments
 (0)