Skip to content

Commit d2b4b94

Browse files
authored
Add Prepare method for reusing state across linter runs (#1506)
This paves the way for moving initialization logic to Rego later: #359 As well as moving the `DetermineEnabledRules` and `DetermineEnabledAggregateRules` methods to instead use the same query later on. Fixes #1394 Signed-off-by: Anders Eknert <anders@styra.com>
1 parent b24a7a9 commit d2b4b94

7 files changed

Lines changed: 279 additions & 165 deletions

File tree

bundle/regal/rules/imports/circular-import/circular_import.rego

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,8 @@ import data.regal.result
1212
import data.regal.util
1313

1414
_refs contains ref if {
15-
r := ast.found.refs[_][_]
16-
17-
r.value[0].value == "data"
15+
some r
16+
ast.found.refs[_][r].value[0].value == "data"
1817

1918
ast.static_ref(r)
2019

cmd/fix.go

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -411,8 +411,7 @@ please run fix from a clean state to support the use of git to undo, or use --fo
411411

412412
if !params.dryRun {
413413
for _, file := range fileProvider.DeletedFiles() {
414-
err := os.Remove(file)
415-
if err != nil {
414+
if err := os.Remove(file); err != nil {
416415
return fmt.Errorf("failed to delete file %s: %w", file, err)
417416
}
418417

cmd/lint.go

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -249,8 +249,7 @@ func lint(args []string, params *lintCommandParams) (report.Report, error) {
249249
m.Timer(regalmetrics.RegalConfigSearch).Stop()
250250
}
251251

252-
regal := linter.NewEmptyLinter().
253-
WithAddedBundle(&rbundle.LoadedBundle).
252+
regal := linter.NewLinter().
254253
WithDisableAll(params.disableAll).
255254
WithDisabledCategories(params.disableCategory.v...).
256255
WithDisabledRules(params.disable.v...).
@@ -330,6 +329,11 @@ func lint(args []string, params *lintCommandParams) (report.Report, error) {
330329

331330
go updateCheckAndWarn(params, &rbundle.LoadedBundle, &userConfig)
332331

332+
regal, err = regal.Prepare(ctx)
333+
if err != nil {
334+
return report.Report{}, fmt.Errorf("failed to prepare for linting: %w", err)
335+
}
336+
333337
result, err := regal.Lint(ctx)
334338
if err != nil {
335339
return report.Report{}, formatError(params.format, fmt.Errorf("error(s) encountered while linting: %w", err))

e2e/cli_test.go

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import (
2222

2323
"github.com/open-policy-agent/opa/v1/tester"
2424

25+
"github.com/styrainc/regal/internal/mode"
2526
"github.com/styrainc/regal/internal/testutil"
2627
"github.com/styrainc/regal/pkg/config"
2728
"github.com/styrainc/regal/pkg/report"
@@ -181,10 +182,11 @@ func TestLintNonExistentDir(t *testing.T) {
181182
}
182183
}
183184

184-
// NOTE(ae): this test *will fail* when run via "go test -e2e" and a normal development binary is used for the test.
185-
// This is because proposing fixes is only enabled when regal is built with the "regal_standalone" build tag. I spent
186-
// way more time on chasing that down than I would have wanted, so leaving this here for future me and others.
187185
func TestLintProposeToRunFix(t *testing.T) {
186+
if !mode.Standalone {
187+
t.Skip("test requires regal to be built with the 'regal_standalone' build tag")
188+
}
189+
188190
t.Parallel()
189191
stdout, stderr := bytes.Buffer{}, bytes.Buffer{}
190192

@@ -1045,8 +1047,7 @@ allow := true
10451047
func TestFixWithConflicts(t *testing.T) {
10461048
t.Parallel()
10471049

1048-
stdout := bytes.Buffer{}
1049-
stderr := bytes.Buffer{}
1050+
stdout, stderr := bytes.Buffer{}, bytes.Buffer{}
10501051

10511052
initialState := map[string]string{
10521053
".regal/config.yaml": "", // needed to find the root in the right place
@@ -1112,8 +1113,7 @@ Cannot move multiple files to: bar/bar.rego
11121113
func TestFixWithConflictRenaming(t *testing.T) {
11131114
t.Parallel()
11141115

1115-
stdout := bytes.Buffer{}
1116-
stderr := bytes.Buffer{}
1116+
stdout, stderr := bytes.Buffer{}, bytes.Buffer{}
11171117

11181118
initialState := map[string]string{
11191119
".regal/config.yaml": "", // needed to find the root in the right place
@@ -1292,8 +1292,7 @@ rules:
12921292
func TestLintAnnotationCustomAttributeMultipleItems(t *testing.T) {
12931293
t.Parallel()
12941294

1295-
stdout := bytes.Buffer{}
1296-
stderr := bytes.Buffer{}
1295+
stdout, stderr := bytes.Buffer{}, bytes.Buffer{}
12971296
cwd := testutil.Must(os.Getwd())(t)
12981297

12991298
err := regal(&stdout, &stderr)(

internal/io/io.go

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import (
1717
"github.com/open-policy-agent/opa/v1/loader/filter"
1818
"github.com/open-policy-agent/opa/v1/rego"
1919
"github.com/open-policy-agent/opa/v1/types"
20+
outil "github.com/open-policy-agent/opa/v1/util"
2021

2122
"github.com/styrainc/roast/pkg/encoding"
2223
)
@@ -182,6 +183,55 @@ func FindManifestLocations(root string) ([]string, error) {
182183
return foundBundleRoots, nil
183184
}
184185

186+
func ModulesFromCustomRuleFS(customRuleFS files.FS, rootPath string) (map[string]*ast.Module, error) {
187+
modules := make(map[string]*ast.Module)
188+
filter := ExcludeTestFilter()
189+
190+
err := files.WalkDir(customRuleFS, rootPath, func(path string, d files.DirEntry, err error) error {
191+
if err != nil {
192+
return fmt.Errorf("failed to walk custom rule FS: %w", err)
193+
}
194+
195+
if d.IsDir() {
196+
return nil
197+
}
198+
199+
info, err := d.Info()
200+
if err != nil {
201+
return fmt.Errorf("failed to get info for custom rule file: %w", err)
202+
}
203+
204+
if filter("", info, 0) {
205+
return nil
206+
}
207+
208+
f, err := customRuleFS.Open(path)
209+
if err != nil {
210+
return fmt.Errorf("failed to open custom rule file: %w", err)
211+
}
212+
defer f.Close()
213+
214+
bs, err := io.ReadAll(f)
215+
if err != nil {
216+
return fmt.Errorf("failed to read custom rule file: %w", err)
217+
}
218+
219+
m, err := ast.ParseModule(path, outil.ByteSliceToString(bs))
220+
if err != nil {
221+
return fmt.Errorf("failed to parse custom rule file %q: %w", path, err)
222+
}
223+
224+
modules[path] = m
225+
226+
return nil
227+
})
228+
if err != nil {
229+
return nil, fmt.Errorf("failed to walk custom rule FS: %w", err)
230+
}
231+
232+
return modules, nil
233+
}
234+
185235
// NOTE: These are mirrored here merely to provide correct capabilities for the
186236
// parser. Can't import other packages from here as almost all of them depend on
187237
// this package. We should probably move these definitions to somewhere where all

0 commit comments

Comments
 (0)