internal/changelog/linter.go (91 lines of code) (raw):

// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one // or more contributor license agreements. Licensed under the Elastic License 2.0; // you may not use this file except in compliance with the Elastic License 2.0. package changelog import ( "fmt" "github.com/spf13/afero" "github.com/spf13/viper" ) func NewLinter(fs afero.Fs) Linter { return newLinter(fs) } type Linter struct { fs afero.Fs entryValidators entryValidators errors []error } func newLinter(fs afero.Fs) Linter { return Linter{ fs: fs, entryValidators: defaultEntryValidators, } } type LinterErrors []error func (l Linter) Lint(dest, version string) []error { c, err := FromFile(l.fs, fmt.Sprintf("./%s/%s.yaml", dest, version)) if err != nil { return []error{fmt.Errorf("error loading changelog from file: %w", err)} } for _, entry := range c.Entries { for _, validator := range l.entryValidators { err := validator(entry) if err != nil { l.errors = append(l.errors, err) } } } return l.errors } type entryValidationFn func(Entry) error type entryValidators map[string]entryValidationFn var defaultEntryValidators = entryValidators{ "pr_multipleids": validator_PRMultipleIDs, "pr_noids": validator_PRnoIDs, "issue_noids": validator_IssueNoIDs, "component_valid": validator_componentValid(viper.GetStringSlice("components")), } func validator_PRMultipleIDs(entry Entry) error { if len(entry.LinkedPR) > 1 { return fmt.Errorf("changelog entry: %s has multiple PR ids", entry.File.Name) } return nil } func validator_PRnoIDs(entry Entry) error { if len(entry.LinkedPR) == 0 { return fmt.Errorf("changelog entry: %s has no PR id", entry.File.Name) } return nil } func validator_IssueNoIDs(entry Entry) error { if len(entry.LinkedIssue) == 0 { return fmt.Errorf("changelog entry: %s has no issue id", entry.File.Name) } return nil } func validator_componentValid(configComponents []string) entryValidationFn { return func(entry Entry) error { switch len(configComponents) { case 0: return nil case 1: c := configComponents[0] if c != entry.Component && len(entry.Component) > 0 { return fmt.Errorf("changelog entry: %s -> component [%s] not found in config: %s", entry.File.Name, entry.Component, configComponents) } default: var match string if entry.Component == "" { return fmt.Errorf("changelog entry: %s -> component cannot be assumed, choose it from config: %s", entry.File.Name, configComponents) } match = "" for _, c := range configComponents { if entry.Component != c { continue } match = entry.Component } if match == "" { return fmt.Errorf("changelog entry: %s -> component [%s] not found in config: %s", entry.File.Name, entry.Component, configComponents) } } return nil } }