Skip to content

Commit 73fcc6f

Browse files
authored
[autodetect] Add go autodetection (#2381)
## Summary TSIA. ## How was it tested? unit tests
1 parent 5c665e5 commit 73fcc6f

File tree

3 files changed

+157
-0
lines changed

3 files changed

+157
-0
lines changed

pkg/autodetect/autodetect.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ func detectors(path string) []detector.Detector {
4343
return []detector.Detector{
4444
&detector.PythonDetector{Root: path},
4545
&detector.PoetryDetector{Root: path},
46+
&detector.GoDetector{Root: path},
4647
}
4748
}
4849

pkg/autodetect/detector/go.go

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
package detector
2+
3+
import (
4+
"context"
5+
"os"
6+
"path/filepath"
7+
"regexp"
8+
)
9+
10+
type GoDetector struct {
11+
Root string
12+
}
13+
14+
var _ Detector = &GoDetector{}
15+
16+
func (d *GoDetector) Relevance(path string) (float64, error) {
17+
goModPath := filepath.Join(d.Root, "go.mod")
18+
_, err := os.Stat(goModPath)
19+
if err == nil {
20+
return 1.0, nil
21+
}
22+
if os.IsNotExist(err) {
23+
return 0, nil
24+
}
25+
return 0, err
26+
}
27+
28+
func (d *GoDetector) Packages(ctx context.Context) ([]string, error) {
29+
goModPath := filepath.Join(d.Root, "go.mod")
30+
goModContent, err := os.ReadFile(goModPath)
31+
if err != nil {
32+
return nil, err
33+
}
34+
35+
// Parse the Go version from go.mod
36+
goVersion := parseGoVersion(string(goModContent))
37+
if goVersion != "" {
38+
return []string{"go@" + goVersion}, nil
39+
}
40+
return []string{"go@latest"}, nil
41+
}
42+
43+
func parseGoVersion(goModContent string) string {
44+
// Use a regular expression to find the Go version directive
45+
re := regexp.MustCompile(`(?m)^go\s+(\d+\.\d+(\.\d+)?)`)
46+
match := re.FindStringSubmatch(goModContent)
47+
48+
if len(match) >= 2 {
49+
return match[1]
50+
}
51+
52+
return ""
53+
}

pkg/autodetect/detector/go_test.go

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
package detector
2+
3+
import (
4+
"context"
5+
"os"
6+
"path/filepath"
7+
"testing"
8+
9+
"github.com/stretchr/testify/assert"
10+
)
11+
12+
func TestGoDetectorRelevance(t *testing.T) {
13+
tempDir := t.TempDir()
14+
detector := &GoDetector{Root: tempDir}
15+
16+
t.Run("No go.mod file", func(t *testing.T) {
17+
relevance, err := detector.Relevance(tempDir)
18+
assert.NoError(t, err)
19+
assert.Equal(t, 0.0, relevance)
20+
})
21+
22+
t.Run("With go.mod file", func(t *testing.T) {
23+
err := os.WriteFile(filepath.Join(tempDir, "go.mod"), []byte("module example.com"), 0o644)
24+
assert.NoError(t, err)
25+
26+
relevance, err := detector.Relevance(tempDir)
27+
assert.NoError(t, err)
28+
assert.Equal(t, 1.0, relevance)
29+
})
30+
}
31+
32+
func TestGoDetectorPackages(t *testing.T) {
33+
tempDir := t.TempDir()
34+
detector := &GoDetector{Root: tempDir}
35+
36+
t.Run("No go.mod file", func(t *testing.T) {
37+
packages, err := detector.Packages(context.Background())
38+
assert.Error(t, err)
39+
assert.Nil(t, packages)
40+
})
41+
42+
t.Run("With go.mod file and no version", func(t *testing.T) {
43+
err := os.WriteFile(filepath.Join(tempDir, "go.mod"), []byte("module example.com"), 0o644)
44+
assert.NoError(t, err)
45+
46+
packages, err := detector.Packages(context.Background())
47+
assert.NoError(t, err)
48+
assert.Equal(t, []string{"go@latest"}, packages)
49+
})
50+
51+
t.Run("With go.mod file and specific version", func(t *testing.T) {
52+
goModContent := `
53+
module example.com
54+
55+
go 1.18
56+
`
57+
err := os.WriteFile(filepath.Join(tempDir, "go.mod"), []byte(goModContent), 0o644)
58+
assert.NoError(t, err)
59+
60+
packages, err := detector.Packages(context.Background())
61+
assert.NoError(t, err)
62+
assert.Equal(t, []string{"[email protected]"}, packages)
63+
})
64+
}
65+
66+
func TestParseGoVersion(t *testing.T) {
67+
testCases := []struct {
68+
name string
69+
content string
70+
expected string
71+
}{
72+
{
73+
name: "No version",
74+
content: "module example.com",
75+
expected: "",
76+
},
77+
{
78+
name: "With version",
79+
content: `
80+
module example.com
81+
82+
go 1.18
83+
`,
84+
expected: "1.18",
85+
},
86+
{
87+
name: "With patch version",
88+
content: `
89+
module example.com
90+
91+
go 1.18.3
92+
`,
93+
expected: "1.18.3",
94+
},
95+
}
96+
97+
for _, tc := range testCases {
98+
t.Run(tc.name, func(t *testing.T) {
99+
version := parseGoVersion(tc.content)
100+
assert.Equal(t, tc.expected, version)
101+
})
102+
}
103+
}

0 commit comments

Comments
 (0)