Skip to content

Commit 481a128

Browse files
fix: semgrep init
1 parent a84eb7c commit 481a128

File tree

4 files changed

+50
-161
lines changed

4 files changed

+50
-161
lines changed
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
// Package embedded contains embedded files used by the tools package
2+
package embedded
3+
4+
import "embed"
5+
6+
//go:embed rules.yaml
7+
var rulesFS embed.FS
8+
9+
// GetSemgrepRules returns the embedded Semgrep rules
10+
func GetSemgrepRules() []byte {
11+
data, err := rulesFS.ReadFile("rules.yaml")
12+
if err != nil {
13+
panic(err) // This should never happen as the file is embedded
14+
}
15+
return data
16+
}

tools/semgrepConfigCreator.go

Lines changed: 14 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,9 @@ package tools
22

33
import (
44
"codacy/cli-v2/domain"
5+
"codacy/cli-v2/plugins/tools/semgrep/embedded"
56
"fmt"
67
"os"
7-
"path/filepath"
88
"strings"
99

1010
"gopkg.in/yaml.v3"
@@ -20,19 +20,18 @@ type semgrepRulesFile struct {
2020
var getExecutablePath = os.Executable
2121

2222
// FilterRulesFromFile extracts enabled rules from a rules.yaml file based on configuration
23-
func FilterRulesFromFile(rulesFilePath string, config []domain.PatternConfiguration) ([]byte, error) {
24-
// Read the rules.yaml file
25-
data, err := os.ReadFile(rulesFilePath)
26-
if err != nil {
27-
return nil, fmt.Errorf("failed to read rules file: %w", err)
28-
}
29-
30-
// Parse the YAML file
23+
func FilterRulesFromFile(rulesData []byte, config []domain.PatternConfiguration) ([]byte, error) {
24+
// Parse the YAML data
3125
var allRules semgrepRulesFile
32-
if err := yaml.Unmarshal(data, &allRules); err != nil {
26+
if err := yaml.Unmarshal(rulesData, &allRules); err != nil {
3327
return nil, fmt.Errorf("failed to parse rules file: %w", err)
3428
}
3529

30+
// If no configuration provided, return all rules
31+
if len(config) == 0 {
32+
return rulesData, nil
33+
}
34+
3635
// Create a map of enabled pattern IDs for faster lookup
3736
enabledPatterns := make(map[string]bool)
3837
for _, pattern := range config {
@@ -67,45 +66,14 @@ func FilterRulesFromFile(rulesFilePath string, config []domain.PatternConfigurat
6766
return yaml.Marshal(filteredRules)
6867
}
6968

70-
// GetSemgrepConfig gets the Semgrep configuration based on the pattern configuration
69+
// GetSemgrepConfig gets the Semgrep configuration based on the pattern configuration.
70+
// If no configuration is provided, returns all default rules.
7171
func GetSemgrepConfig(config []domain.PatternConfiguration) ([]byte, error) {
72-
// Get the executable's directory
73-
execPath, err := getExecutablePath()
74-
if err != nil {
75-
return nil, fmt.Errorf("failed to get executable path: %w", err)
76-
}
77-
execDir := filepath.Dir(execPath)
78-
79-
// Get the default rules file location relative to the executable
80-
rulesFile := filepath.Join(execDir, "plugins", "tools", "semgrep", "rules.yaml")
81-
82-
// Check if it exists and config is not empty
83-
if _, err := os.Stat(rulesFile); err == nil && len(config) > 0 {
84-
// Try to filter rules from the file
85-
return FilterRulesFromFile(rulesFile, config)
86-
}
87-
88-
// If rules.yaml doesn't exist or config is empty, return an error
89-
return nil, fmt.Errorf("rules.yaml not found or empty configuration")
72+
return FilterRulesFromFile(embedded.GetSemgrepRules(), config)
9073
}
9174

9275
// GetDefaultSemgrepConfig gets the default Semgrep configuration
9376
func GetDefaultSemgrepConfig() ([]byte, error) {
94-
// Get the executable's directory
95-
execPath, err := getExecutablePath()
96-
if err != nil {
97-
return nil, fmt.Errorf("failed to get executable path: %w", err)
98-
}
99-
execDir := filepath.Dir(execPath)
100-
101-
// Get the default rules file location relative to the executable
102-
rulesFile := filepath.Join(execDir, "plugins", "tools", "semgrep", "rules.yaml")
103-
104-
// If the file exists, return its contents
105-
if _, err := os.Stat(rulesFile); err == nil {
106-
return os.ReadFile(rulesFile)
107-
}
108-
109-
// Return an error if rules.yaml doesn't exist
110-
return nil, fmt.Errorf("rules.yaml not found")
77+
// Return the embedded rules
78+
return embedded.GetSemgrepRules(), nil
11179
}

tools/semgrepConfigCreator_test.go

Lines changed: 20 additions & 115 deletions
Original file line numberDiff line numberDiff line change
@@ -2,135 +2,67 @@ package tools
22

33
import (
44
"codacy/cli-v2/domain"
5-
"os"
6-
"path/filepath"
5+
"codacy/cli-v2/plugins/tools/semgrep/embedded"
76
"testing"
87

98
"github.com/stretchr/testify/assert"
109
"gopkg.in/yaml.v3"
1110
)
1211

13-
// Sample rules YAML content for testing
14-
const sampleRulesYAML = `rules:
15-
- id: rule1
16-
pattern: |
17-
$X
18-
message: "Test rule 1"
19-
languages: [go]
20-
severity: INFO
21-
- id: rule2
22-
pattern: |
23-
$Y
24-
message: "Test rule 2"
25-
languages: [javascript]
26-
severity: WARNING
27-
- id: rule3
28-
pattern-either:
29-
- pattern: "foo()"
30-
- pattern: "bar()"
31-
message: "Test rule 3"
32-
languages: [python]
33-
severity: ERROR
34-
`
35-
3612
// TestFilterRulesFromFile tests the FilterRulesFromFile function
3713
func TestFilterRulesFromFile(t *testing.T) {
38-
// Create a temporary rules file
39-
tempDir := t.TempDir()
40-
rulesFile := filepath.Join(tempDir, "rules.yaml")
41-
err := os.WriteFile(rulesFile, []byte(sampleRulesYAML), 0644)
42-
assert.NoError(t, err)
14+
// Get the actual rules file content
15+
rulesData := embedded.GetSemgrepRules()
4316

4417
// Test case 1: Filter with enabled rules
4518
config := []domain.PatternConfiguration{
4619
{
4720
Enabled: true,
4821
PatternDefinition: domain.PatternDefinition{
49-
Id: "Semgrep_rule1",
50-
Enabled: true,
51-
},
52-
},
53-
{
54-
Enabled: true,
55-
PatternDefinition: domain.PatternDefinition{
56-
Id: "Semgrep_rule3",
22+
Id: "Semgrep_ai.csharp.detect-openai.detect-openai",
5723
Enabled: true,
5824
},
5925
},
6026
}
6127

62-
result, err := FilterRulesFromFile(rulesFile, config)
28+
result, err := FilterRulesFromFile(rulesData, config)
6329
assert.NoError(t, err)
6430

65-
// Parse the result and verify the rules
31+
// Parse the result and verify we got filtered rules
6632
var parsedRules semgrepRulesFile
6733
err = yaml.Unmarshal(result, &parsedRules)
6834
assert.NoError(t, err)
69-
assert.Equal(t, 2, len(parsedRules.Rules))
70-
71-
// Check that it contains rule1 and rule3 but not rule2
72-
ruleIDs := map[string]bool{}
73-
for _, rule := range parsedRules.Rules {
74-
id, _ := rule["id"].(string)
75-
ruleIDs[id] = true
76-
}
77-
assert.True(t, ruleIDs["rule1"])
78-
assert.False(t, ruleIDs["rule2"])
79-
assert.True(t, ruleIDs["rule3"])
35+
assert.Equal(t, 1, len(parsedRules.Rules))
8036

8137
// Test case 2: No enabled rules should return an error
8238
noEnabledConfig := []domain.PatternConfiguration{
8339
{
8440
Enabled: false,
8541
PatternDefinition: domain.PatternDefinition{
86-
Id: "Semgrep_rule1",
42+
Id: "Semgrep_nonexistent",
8743
Enabled: false,
8844
},
8945
},
9046
}
9147

92-
_, err = FilterRulesFromFile(rulesFile, noEnabledConfig)
48+
_, err = FilterRulesFromFile(rulesData, noEnabledConfig)
9349
assert.Error(t, err)
9450
assert.Contains(t, err.Error(), "no matching rules found")
9551

96-
// Test case 3: Non-existent rules file should return an error
97-
_, err = FilterRulesFromFile(filepath.Join(tempDir, "nonexistent.yaml"), config)
52+
// Test case 3: Invalid YAML should return an error
53+
_, err = FilterRulesFromFile([]byte("invalid yaml"), config)
9854
assert.Error(t, err)
99-
assert.Contains(t, err.Error(), "failed to read rules file")
55+
assert.Contains(t, err.Error(), "failed to parse rules file")
10056
}
10157

10258
// TestGetSemgrepConfig tests the GetSemgrepConfig function
10359
func TestGetSemgrepConfig(t *testing.T) {
104-
// Create a temporary rules file
105-
tempDir := t.TempDir()
106-
testRulesFile := filepath.Join(tempDir, "rules.yaml")
107-
err := os.WriteFile(testRulesFile, []byte(sampleRulesYAML), 0644)
108-
assert.NoError(t, err)
109-
110-
// Create a mock executable path that points to our temp directory
111-
originalGetExecutablePath := getExecutablePath
112-
getExecutablePath = func() (string, error) {
113-
return filepath.Join(tempDir, "test-executable"), nil
114-
}
115-
defer func() {
116-
getExecutablePath = originalGetExecutablePath
117-
}()
118-
119-
// Create the plugins directory structure
120-
pluginsDir := filepath.Join(tempDir, "plugins", "tools", "semgrep")
121-
err = os.MkdirAll(pluginsDir, 0755)
122-
assert.NoError(t, err)
123-
124-
// Copy our test file to the plugins directory
125-
err = os.WriteFile(filepath.Join(pluginsDir, "rules.yaml"), []byte(sampleRulesYAML), 0644)
126-
assert.NoError(t, err)
127-
12860
// Test with valid configuration
12961
config := []domain.PatternConfiguration{
13062
{
13163
Enabled: true,
13264
PatternDefinition: domain.PatternDefinition{
133-
Id: "Semgrep_rule1",
65+
Id: "Semgrep_ai.csharp.detect-openai.detect-openai",
13466
Enabled: true,
13567
},
13668
},
@@ -144,49 +76,22 @@ func TestGetSemgrepConfig(t *testing.T) {
14476
assert.NoError(t, err)
14577
assert.Equal(t, 1, len(parsedRules.Rules))
14678

147-
// Test with empty configuration
148-
_, err = GetSemgrepConfig([]domain.PatternConfiguration{})
149-
assert.Error(t, err)
79+
// Test with empty configuration (should return all rules)
80+
result, err = GetSemgrepConfig([]domain.PatternConfiguration{})
81+
assert.NoError(t, err)
82+
err = yaml.Unmarshal(result, &parsedRules)
83+
assert.NoError(t, err)
84+
assert.True(t, len(parsedRules.Rules) > 0)
15085
}
15186

15287
// TestGetDefaultSemgrepConfig tests the GetDefaultSemgrepConfig function
15388
func TestGetDefaultSemgrepConfig(t *testing.T) {
154-
// Create a temporary rules file
155-
tempDir := t.TempDir()
156-
testRulesFile := filepath.Join(tempDir, "rules.yaml")
157-
err := os.WriteFile(testRulesFile, []byte(sampleRulesYAML), 0644)
158-
assert.NoError(t, err)
159-
160-
// Create a mock executable path that points to our temp directory
161-
originalGetExecutablePath := getExecutablePath
162-
getExecutablePath = func() (string, error) {
163-
return filepath.Join(tempDir, "test-executable"), nil
164-
}
165-
defer func() {
166-
getExecutablePath = originalGetExecutablePath
167-
}()
168-
169-
// Create the plugins directory structure
170-
pluginsDir := filepath.Join(tempDir, "plugins", "tools", "semgrep")
171-
err = os.MkdirAll(pluginsDir, 0755)
172-
assert.NoError(t, err)
173-
174-
// Copy our test file to the plugins directory
175-
err = os.WriteFile(filepath.Join(pluginsDir, "rules.yaml"), []byte(sampleRulesYAML), 0644)
176-
assert.NoError(t, err)
177-
17889
// Test getting default config
17990
result, err := GetDefaultSemgrepConfig()
18091
assert.NoError(t, err)
18192

18293
var parsedRules semgrepRulesFile
18394
err = yaml.Unmarshal(result, &parsedRules)
18495
assert.NoError(t, err)
185-
assert.Equal(t, 3, len(parsedRules.Rules))
186-
187-
// Test when rules.yaml doesn't exist
188-
os.Remove(filepath.Join(pluginsDir, "rules.yaml"))
189-
_, err = GetDefaultSemgrepConfig()
190-
assert.Error(t, err)
191-
assert.Contains(t, err.Error(), "rules.yaml not found")
96+
assert.True(t, len(parsedRules.Rules) > 0)
19297
}

0 commit comments

Comments
 (0)