Skip to content

Commit 8c8dfac

Browse files
authored
fix: avoid 2nd Rego compilation in json format (#132)
Co-authored-by: Becojo <[email protected]>
1 parent 5269205 commit 8c8dfac

File tree

6 files changed

+74
-46
lines changed

6 files changed

+74
-46
lines changed

analyze/analyze.go

Lines changed: 6 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ type GitClient interface {
5252
GetRepoHeadBranchName(ctx context.Context, repoPath string) (string, error)
5353
}
5454

55-
func NewAnalyzer(scmClient ScmClient, gitClient GitClient, formatter Formatter, config *models.Config) *Analyzer {
55+
func NewAnalyzer(scmClient ScmClient, gitClient GitClient, formatter Formatter, config *models.Config, opaClient *opa.Opa) *Analyzer {
5656
if config == nil {
5757
config = &models.Config{}
5858
}
@@ -61,6 +61,7 @@ func NewAnalyzer(scmClient ScmClient, gitClient GitClient, formatter Formatter,
6161
GitClient: gitClient,
6262
Formatter: formatter,
6363
Config: config,
64+
Opa: opaClient,
6465
}
6566
}
6667

@@ -69,6 +70,7 @@ type Analyzer struct {
6970
GitClient GitClient
7071
Formatter Formatter
7172
Config *models.Config
73+
Opa *opa.Opa
7274
}
7375

7476
func (a *Analyzer) AnalyzeOrg(ctx context.Context, org string, numberOfGoroutines *int) error {
@@ -84,12 +86,8 @@ func (a *Analyzer) AnalyzeOrg(ctx context.Context, org string, numberOfGoroutine
8486
log.Debug().Msgf("Fetching list of repositories for organization: %s on %s", org, provider)
8587
orgReposBatches := a.ScmClient.GetOrgRepos(ctx, org)
8688

87-
opaClient, err := a.newOpa(ctx)
88-
if err != nil {
89-
return err
90-
}
9189
pkgsupplyClient := pkgsupply.NewStaticClient()
92-
inventory := scanner.NewInventory(opaClient, pkgsupplyClient, provider, providerVersion)
90+
inventory := scanner.NewInventory(a.Opa, pkgsupplyClient, provider, providerVersion)
9391

9492
log.Debug().Msgf("Starting repository analysis for organization: %s on %s", org, provider)
9593
bar := progressbar.NewOptions(
@@ -185,13 +183,8 @@ func (a *Analyzer) AnalyzeRepo(ctx context.Context, repoString string, ref strin
185183

186184
log.Debug().Msgf("Provider: %s, Version: %s", provider, providerVersion)
187185

188-
opaClient, err := a.newOpa(ctx)
189-
if err != nil {
190-
return err
191-
}
192186
pkgsupplyClient := pkgsupply.NewStaticClient()
193-
194-
inventory := scanner.NewInventory(opaClient, pkgsupplyClient, provider, providerVersion)
187+
inventory := scanner.NewInventory(a.Opa, pkgsupplyClient, provider, providerVersion)
195188

196189
log.Debug().Msgf("Starting repository analysis for: %s/%s on %s", org, repoName, provider)
197190
bar := progressbar.NewOptions(
@@ -240,13 +233,8 @@ func (a *Analyzer) AnalyzeLocalRepo(ctx context.Context, repoPath string) error
240233

241234
log.Debug().Msgf("Provider: %s, Version: %s", provider, providerVersion)
242235

243-
opaClient, err := a.newOpa(ctx)
244-
if err != nil {
245-
return err
246-
}
247236
pkgsupplyClient := pkgsupply.NewStaticClient()
248-
249-
inventory := scanner.NewInventory(opaClient, pkgsupplyClient, provider, providerVersion)
237+
inventory := scanner.NewInventory(a.Opa, pkgsupplyClient, provider, providerVersion)
250238

251239
log.Debug().Msgf("Starting repository analysis for: %s/%s on %s", org, repoName, provider)
252240
bar := progressbar.NewOptions(
@@ -337,14 +325,3 @@ func (a *Analyzer) cloneRepoToTemp(ctx context.Context, gitURL string, token str
337325
}
338326
return tempDir, nil
339327
}
340-
341-
func (a *Analyzer) newOpa(ctx context.Context) (*opa.Opa, error) {
342-
opaClient, err := opa.NewOpa()
343-
if err != nil {
344-
log.Error().Err(err).Msg("Failed to create OPA client")
345-
return nil, err
346-
}
347-
_ = opaClient.WithConfig(ctx, a.Config)
348-
349-
return opaClient, nil
350-
}

cmd/analyzeLocal.go

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,12 @@ Example: poutine analyze_local /path/to/repo`,
2020
ctx := cmd.Context()
2121
repoPath := args[0]
2222

23-
formatter := GetFormatter()
23+
opaClient, err := newOpa(ctx)
24+
if err != nil {
25+
return err
26+
}
27+
28+
formatter := GetFormatter(opaClient)
2429

2530
localScmClient, err := local.NewGitSCMClient(ctx, repoPath, nil)
2631
if err != nil {
@@ -29,7 +34,7 @@ Example: poutine analyze_local /path/to/repo`,
2934

3035
localGitClient := gitops.NewLocalGitClient(nil)
3136

32-
analyzer := analyze.NewAnalyzer(localScmClient, localGitClient, formatter, config)
37+
analyzer := analyze.NewAnalyzer(localScmClient, localGitClient, formatter, config, opaClient)
3338

3439
err = analyzer.AnalyzeLocalRepo(ctx, repoPath)
3540
if err != nil {

cmd/root.go

Lines changed: 21 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -152,17 +152,15 @@ func cleanup() {
152152
log.Debug().Msg("Finished cleaning up temp directories")
153153
}
154154

155-
func GetFormatter() analyze.Formatter {
155+
func GetFormatter(opaClient *opa.Opa) analyze.Formatter {
156156
switch Format {
157157
case "pretty":
158158
return &pretty.Format{}
159-
case "json":
160-
opaClient, _ := opa.NewOpa()
161-
return json.NewFormat(opaClient, Format, os.Stdout)
162159
case "sarif":
163160
return sarif.NewFormat(os.Stdout)
164161
}
165-
return &pretty.Format{}
162+
163+
return json.NewFormat(opaClient, Format, os.Stdout)
166164
}
167165

168166
func GetAnalyzer(ctx context.Context, command string) (*analyze.Analyzer, error) {
@@ -171,10 +169,26 @@ func GetAnalyzer(ctx context.Context, command string) (*analyze.Analyzer, error)
171169
return nil, fmt.Errorf("failed to create SCM client: %w", err)
172170
}
173171

174-
formatter := GetFormatter()
172+
opaClient, err := newOpa(ctx)
173+
if err != nil {
174+
log.Error().Err(err).Msg("Failed to create OPA client")
175+
return nil, err
176+
}
175177

178+
formatter := GetFormatter(opaClient)
176179
gitClient := gitops.NewGitClient(nil)
177180

178-
analyzer := analyze.NewAnalyzer(scmClient, gitClient, formatter, config)
181+
analyzer := analyze.NewAnalyzer(scmClient, gitClient, formatter, config, opaClient)
179182
return analyzer, nil
180183
}
184+
185+
func newOpa(ctx context.Context) (*opa.Opa, error) {
186+
opaClient, err := opa.NewOpa()
187+
if err != nil {
188+
log.Error().Err(err).Msg("Failed to create OPA client")
189+
return nil, err
190+
}
191+
_ = opaClient.WithConfig(ctx, config)
192+
193+
return opaClient, nil
194+
}

formatters/json/json.go

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -23,20 +23,28 @@ type Format struct {
2323
}
2424

2525
func (f *Format) Format(ctx context.Context, report *opa.FindingsResult, packages []*models.PackageInsights) error {
26-
var reportString string
26+
var result struct {
27+
Output string `json:"output"`
28+
Error string `json:"error"`
29+
}
2730
err := f.opa.Eval(ctx,
28-
"data.poutine.format[input.format].result",
31+
"data.poutine.queries.format.result",
2932
map[string]interface{}{
30-
"packages": packages,
31-
"results": report,
32-
"format": f.format,
33+
"packages": packages,
34+
"results": report,
35+
"format": f.format,
36+
"builtin_formats": []string{"sarif", "pretty"},
3337
},
34-
&reportString,
38+
&result,
3539
)
3640
if err != nil {
3741
return err
3842
}
3943

40-
fmt.Fprint(f.out, reportString)
44+
if result.Error != "" {
45+
return fmt.Errorf(result.Error)
46+
}
47+
48+
fmt.Fprint(f.out, result.Output)
4149
return nil
4250
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
package poutine.queries.format
2+
3+
import rego.v1
4+
5+
default output := ""
6+
7+
output = data.poutine.format[input.format].result
8+
9+
formats contains format if data.poutine.format[format]
10+
11+
formats contains input.builtin_formats[_]
12+
13+
errors contains error if {
14+
not input.format in formats
15+
error := sprintf("format %s not found in the available formats: %s", [
16+
input.format,
17+
concat(", ", formats),
18+
])
19+
}
20+
21+
result = {
22+
"output": output,
23+
"error": concat(", ", errors),
24+
}

providers/github/client.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -254,7 +254,7 @@ func (c *Client) GetOrgRepos(ctx context.Context, org string) <-chan analyze.Rep
254254
for {
255255
var query struct {
256256
RepositoryOwner struct {
257-
Login string
257+
Login string
258258
Repositories struct {
259259
TotalCount int
260260
Nodes []GithubRepository

0 commit comments

Comments
 (0)