github.com/snyk/vervet/v5@v5.11.1-0.20240202085829-ad4dd7fb6101/config/linter.go (about)

     1  package config
     2  
     3  import "fmt"
     4  
     5  const (
     6  	defaultOpticCIImage = "snyk/sweater-comb:latest"
     7  )
     8  
     9  var defaultSpectralExtraArgs = []string{"--format", "text"}
    10  
    11  // Linters defines a named map of Linter instances.
    12  // NOTE: Linters are deprecated and may be removed in v5.
    13  type Linters map[string]*Linter
    14  
    15  // Linter describes a set of standards and rules that an API should satisfy.
    16  // NOTE: Linters are deprecated and may be removed in v5.
    17  type Linter struct {
    18  	Name        string          `json:"-"`
    19  	Description string          `json:"description,omitempty"`
    20  	Spectral    *SpectralLinter `json:"spectral"`
    21  	SweaterComb *OpticCILinter  `json:"sweater-comb"`
    22  	OpticCI     *OpticCILinter  `json:"optic-ci"`
    23  }
    24  
    25  func (l *Linter) validate() error {
    26  	nlinters := 0
    27  	if l.Spectral != nil {
    28  		nlinters++
    29  	}
    30  	if l.SweaterComb != nil {
    31  		nlinters++
    32  	}
    33  	if l.OpticCI != nil {
    34  		nlinters++
    35  	}
    36  	switch nlinters {
    37  	case 0:
    38  		return fmt.Errorf("missing configuration (linters.%s)", l.Name)
    39  	case 1:
    40  		return nil
    41  	default:
    42  		return fmt.Errorf("a linter may only be of one type (linters.%s)", l.Name)
    43  	}
    44  }
    45  
    46  // SpectralLinter identifies a Linter as a collection of Spectral rulesets.
    47  // NOTE: Linters are deprecated and may be removed in v5.
    48  type SpectralLinter struct {
    49  
    50  	// Rules are a list of Spectral ruleset file locations
    51  	Rules []string `json:"rules"`
    52  
    53  	// Script identifies the path to the spectral script to use for linting.
    54  	// If not defined linting will look for spectral-cli on $PATH.
    55  	Script string `json:"script"`
    56  
    57  	// ExtraArgs may be used to pass extra arguments to `spectral lint`. If not
    58  	// specified, the default arguments `--format text` are used when running
    59  	// spectral. The `-r` flag must not be specified here, as this argument is
    60  	// automatically added from the Rules setting above.
    61  	//
    62  	// See https://meta.stoplight.io/docs/spectral/ZG9jOjI1MTg1-spectral-cli
    63  	// for the options supported.
    64  	ExtraArgs []string `json:"extraArgs"`
    65  }
    66  
    67  // OpticCILinter identifies an Optic CI Linter, which is distributed as
    68  // a self-contained docker image.
    69  // NOTE: Linters are deprecated and may be removed in v5.
    70  type OpticCILinter struct {
    71  	// Image identifies the Optic CI docker image to use for linting.
    72  	Image string
    73  
    74  	// Script identifies the path to the Optic CI script to use for linting.
    75  	// Mutually exclusive with Image; if Script is specified Docker will not be
    76  	// used.
    77  	Script string
    78  
    79  	// Original is where to source the original version of an OpenAPI spec file
    80  	// when comparing. If empty, all changes are assumed to be new additions.
    81  	Original string `json:"original,omitempty"`
    82  
    83  	// Proposed is where to source the proposed changed version of an OpenAPI
    84  	// spec file when comparing. If empty, this is assumed to be the
    85  	// local working copy.
    86  	Proposed string `json:"proposed,omitempty"`
    87  
    88  	// Debug turns on debug logging.
    89  	Debug bool `json:"debug,omitempty"`
    90  
    91  	// Deprecated: CIContext is no longer used and should be removed in the
    92  	// next major release.
    93  	CIContext string `json:"-"`
    94  
    95  	// Deprecated: UploadResults is no longer used and should be removed in the
    96  	// next major release. Uploading optic-ci comparison results to Optic
    97  	// Cloud is determined by the presence of environment variables.
    98  	UploadResults bool `json:"-"`
    99  
   100  	// Exceptions are files that are excluded from CI checks. This is an escape
   101  	// hatch of last resort, if a file needs to land and can't pass CI yet.
   102  	// They are specified as a mapping from project relative path to sha256
   103  	// sums of that spec file that is exempt. This makes the exception very
   104  	// narrow -- only a specific version of a specific file is skipped, after
   105  	// outside review and approval.
   106  	Exceptions map[string][]string
   107  
   108  	// ExtraArgs may be used to pass extra arguments to `optic-ci`.
   109  	ExtraArgs []string `json:"extraArgs"`
   110  }
   111  
   112  func (l Linters) init() error {
   113  	for name, linter := range l {
   114  		if linter == nil {
   115  			return fmt.Errorf("missing linter definition (linters.%s)", name)
   116  		}
   117  		linter.Name = name
   118  		if err := linter.validate(); err != nil {
   119  			return err
   120  		}
   121  		if linter.Spectral != nil && len(linter.Spectral.ExtraArgs) == 0 {
   122  			linter.Spectral.ExtraArgs = defaultSpectralExtraArgs
   123  		}
   124  		if linter.SweaterComb != nil {
   125  			if linter.SweaterComb.Image == "" && linter.SweaterComb.Script == "" {
   126  				linter.SweaterComb.Image = defaultOpticCIImage
   127  			}
   128  		}
   129  		if linter.OpticCI != nil {
   130  			if linter.OpticCI.Image == "" && linter.OpticCI.Script == "" {
   131  				linter.OpticCI.Image = defaultOpticCIImage
   132  			}
   133  		}
   134  	}
   135  	return nil
   136  }