github.com/speakeasy-api/sdk-gen-config@v1.14.2/lint/lint.go (about) 1 package lint 2 3 import ( 4 "errors" 5 "fmt" 6 "io/fs" 7 "os" 8 9 "github.com/daveshanley/vacuum/model" 10 "github.com/speakeasy-api/sdk-gen-config/workspace" 11 "gopkg.in/yaml.v3" 12 ) 13 14 const ( 15 LintVersion = "1.0.0" 16 ) 17 18 const ( 19 lintFile = "lint.yaml" 20 ) 21 22 type Ruleset struct { 23 Rulesets []string `yaml:"rulesets"` 24 Rules map[string]*model.Rule `yaml:"rules"` 25 } 26 27 type Lint struct { 28 Version string `yaml:"lintVersion"` 29 DefaultRuleset string `yaml:"defaultRuleset"` 30 Rulesets map[string]Ruleset `yaml:"rulesets"` 31 } 32 33 func Load(searchDirs []string) (*Lint, string, error) { 34 var res *workspace.FindWorkspaceResult 35 36 dirsToSearch := map[string]bool{} 37 38 for _, dir := range searchDirs { 39 dirsToSearch[dir] = true 40 } 41 42 // Allow searching in the user's home directory 43 homeDir, err := os.UserHomeDir() 44 if err == nil { 45 dirsToSearch[homeDir] = false 46 } 47 48 for dir, allowRecursive := range dirsToSearch { 49 var err error 50 51 res, err = workspace.FindWorkspace(dir, workspace.FindWorkspaceOptions{ 52 FindFile: lintFile, 53 Recursive: allowRecursive, 54 }) 55 if err != nil { 56 if !errors.Is(err, fs.ErrNotExist) { 57 return nil, "", err 58 } 59 continue 60 } 61 62 break 63 } 64 if res == nil || res.Data == nil { 65 return nil, "", fs.ErrNotExist 66 } 67 68 type lintHeader struct { 69 Version string `yaml:"lintVersion"` 70 } 71 72 var header lintHeader 73 if err := yaml.Unmarshal(res.Data, &header); err != nil { 74 return nil, "", fmt.Errorf("failed to unmarshal lint.yaml: %w", err) 75 } 76 77 if header.Version != LintVersion { 78 return nil, "", fmt.Errorf("unsupported lint version: %s", header.Version) 79 } 80 81 var lint Lint 82 if err := yaml.Unmarshal(res.Data, &lint); err != nil { 83 return nil, "", fmt.Errorf("failed to unmarshal lint.yaml: %w", err) 84 } 85 86 return &lint, res.Path, nil 87 }