fix(ax): harden structured output paths

This commit is contained in:
Virgil 2026-03-30 12:26:16 +00:00
parent 1660fe025f
commit eec45af6cc
6 changed files with 46 additions and 6 deletions

View file

@ -197,7 +197,7 @@ func addLintCommands(root *cli.Command) {
if err != nil {
return err
}
fmt.Println(string(data))
cli.Print("%s\n", string(data))
return nil
})

View file

@ -93,7 +93,7 @@ func RunDocblockCheck(paths []string, threshold float64, verbose, jsonOutput boo
if err != nil {
return err
}
fmt.Println(string(data))
cli.Print("%s\n", string(data))
if !result.Passed {
return cli.Err("docblock coverage %.1f%% below threshold %.1f%%", result.Coverage, threshold)
}

View file

@ -252,7 +252,7 @@ func addPHPAuditCommand(parent *cli.Command) {
if err != nil {
return err
}
fmt.Println(string(data))
cli.Print("%s\n", string(data))
if payload.HasVulnerabilities {
return cli.Err("vulnerabilities found in dependencies")
@ -344,7 +344,7 @@ func addPHPSecurityCommand(parent *cli.Command) {
if err != nil {
return err
}
fmt.Println(string(data))
cli.Print("%s\n", string(data))
summary := result.Summary
if summary.Critical > 0 || summary.High > 0 {
@ -358,7 +358,7 @@ func addPHPSecurityCommand(parent *cli.Command) {
if err != nil {
return err
}
fmt.Println(string(data))
cli.Print("%s\n", string(data))
summary := result.Summary
if summary.Critical > 0 || summary.High > 0 {

View file

@ -212,7 +212,7 @@ func runReview() error {
if err != nil {
return err
}
fmt.Println(string(data))
cli.Print("%s\n", string(data))
if successfulFetches == 0 && len(fetchErrors) > 0 {
return cli.Err("failed to fetch pull requests for %s", repoFullName)
}

View file

@ -30,6 +30,7 @@ func LoadDir(dir string) (*Catalog, error) {
if err != nil {
return nil, coreerr.E("Catalog.LoadDir", "loading catalog from "+dir, err)
}
sortDirEntries(entries)
var rules []Rule
for _, entry := range entries {
@ -56,6 +57,7 @@ func LoadFS(fsys fs.FS, dir string) (*Catalog, error) {
if err != nil {
return nil, coreerr.E("Catalog.LoadFS", "loading catalog from embedded "+dir, err)
}
sortDirEntries(entries)
var rules []Rule
for _, entry := range entries {
@ -76,6 +78,12 @@ func LoadFS(fsys fs.FS, dir string) (*Catalog, error) {
return &Catalog{Rules: rules}, nil
}
func sortDirEntries(entries []fs.DirEntry) {
slices.SortFunc(entries, func(a, b fs.DirEntry) int {
return strings.Compare(a.Name(), b.Name())
})
}
// ForLanguage returns all rules that apply to the given language.
func (c *Catalog) ForLanguage(lang string) []Rule {
var result []Rule

View file

@ -29,6 +29,38 @@ func TestLoadDir_Good(t *testing.T) {
assert.NotNil(t, cat.ByID("go-mod-001"))
}
func TestLoadDir_SortsFilesDeterministically(t *testing.T) {
dir := t.TempDir()
err := os.WriteFile(filepath.Join(dir, "z.yaml"), []byte(`- id: z-rule
title: "Z rule"
severity: info
languages: [go]
pattern: 'z'
fix: "z"
detection: regex
auto_fixable: false
`), 0o644)
require.NoError(t, err)
err = os.WriteFile(filepath.Join(dir, "a.yaml"), []byte(`- id: a-rule
title: "A rule"
severity: info
languages: [go]
pattern: 'a'
fix: "a"
detection: regex
auto_fixable: false
`), 0o644)
require.NoError(t, err)
cat, err := LoadDir(dir)
require.NoError(t, err)
require.Len(t, cat.Rules, 2)
assert.Equal(t, "a-rule", cat.Rules[0].ID)
assert.Equal(t, "z-rule", cat.Rules[1].ID)
}
func TestLoadDir_Bad_NonexistentDir(t *testing.T) {
_, err := LoadDir("/nonexistent/path/that/does/not/exist")
assert.Error(t, err)