get.porter.sh/porter@v1.3.0/pkg/porter/lint.go (about)

     1  package porter
     2  
     3  import (
     4  	"context"
     5  	"fmt"
     6  
     7  	"get.porter.sh/porter/pkg/config"
     8  	"get.porter.sh/porter/pkg/linter"
     9  	"get.porter.sh/porter/pkg/manifest"
    10  	"get.porter.sh/porter/pkg/portercontext"
    11  	"get.porter.sh/porter/pkg/printer"
    12  )
    13  
    14  type LintOptions struct {
    15  	printer.PrintOptions
    16  
    17  	// File path to the porter manifest. Defaults to the bundle in the current directory.
    18  	File string
    19  }
    20  
    21  var (
    22  	LintAllowFormats   = printer.Formats{printer.FormatPlaintext, printer.FormatJson}
    23  	LintDefaultFormats = printer.FormatPlaintext
    24  )
    25  
    26  func (o *LintOptions) Validate(cxt *portercontext.Context) error {
    27  	err := o.PrintOptions.Validate(LintDefaultFormats, LintAllowFormats)
    28  	if err != nil {
    29  		return err
    30  	}
    31  
    32  	return o.validateFile(cxt)
    33  }
    34  
    35  func (o *LintOptions) validateFile(cxt *portercontext.Context) error {
    36  	if o.File == "" {
    37  		manifestExists, err := cxt.FileSystem.Exists(config.Name)
    38  		if err != nil {
    39  			return fmt.Errorf("could not check if porter manifest exists in current directory: %w", err)
    40  		}
    41  
    42  		if manifestExists {
    43  			o.File = config.Name
    44  		}
    45  	}
    46  
    47  	// Verify the file can be accessed
    48  	if _, err := cxt.FileSystem.Stat(o.File); err != nil {
    49  		return fmt.Errorf("unable to access --file %s: %w", o.File, err)
    50  	}
    51  
    52  	return nil
    53  }
    54  
    55  // Lint porter.yaml for any problems and report the results.
    56  // This calls the mixins to analyze their sections of the manifest.
    57  func (p *Porter) Lint(ctx context.Context, opts LintOptions) (linter.Results, error) {
    58  	manifest, err := manifest.LoadManifestFrom(ctx, p.Config, opts.File)
    59  	if err != nil {
    60  		return nil, err
    61  	}
    62  
    63  	l := linter.New(p.Context, p.Mixins)
    64  	return l.Lint(ctx, manifest, p.Config)
    65  }
    66  
    67  // PrintLintResults lints the manifest and prints the results to the attached output.
    68  func (p *Porter) PrintLintResults(ctx context.Context, opts LintOptions) error {
    69  	results, err := p.Lint(ctx, opts)
    70  	if err != nil {
    71  		return err
    72  	}
    73  
    74  	if results.String() != "" {
    75  		switch opts.Format {
    76  		case printer.FormatPlaintext:
    77  			fmt.Fprintln(p.Out, results.String())
    78  		case printer.FormatJson:
    79  			err := printer.PrintJson(p.Out, results)
    80  			if err != nil {
    81  				return err
    82  			}
    83  		default:
    84  			return fmt.Errorf("invalid format: %s", opts.Format)
    85  		}
    86  	}
    87  
    88  	if !results.HasError() && opts.Format == printer.FormatPlaintext {
    89  		fmt.Fprintln(p.Out, "✨ Bundle validation was successful!")
    90  	}
    91  
    92  	return nil
    93  }