()
| 26 | ) |
| 27 | |
| 28 | func newPolicyDevelopLintCmd() *cobra.Command { |
| 29 | var ( |
| 30 | policyPath string |
| 31 | format bool |
| 32 | regalConfig string |
| 33 | ) |
| 34 | |
| 35 | cmd := &cobra.Command{ |
| 36 | Use: "lint", |
| 37 | Short: "Lint chainloop policy structure and content", |
| 38 | Long: `Performs comprehensive validation of: |
| 39 | - *.yaml files (schema validation) |
| 40 | - *.rego (formatting, linting, structure)`, |
| 41 | RunE: func(cmd *cobra.Command, _ []string) error { |
| 42 | a, err := action.NewPolicyLint(ActionOpts) |
| 43 | if err != nil { |
| 44 | return err |
| 45 | } |
| 46 | |
| 47 | result, err := a.Run(cmd.Context(), &action.PolicyLintOpts{ |
| 48 | PolicyPath: policyPath, |
| 49 | Format: format, |
| 50 | RegalConfig: regalConfig, |
| 51 | }) |
| 52 | if err != nil { |
| 53 | return err |
| 54 | } |
| 55 | |
| 56 | if result.Valid { |
| 57 | logger.Info().Msg("policy is valid!") |
| 58 | return nil |
| 59 | } |
| 60 | |
| 61 | if err := output.EncodeOutput(flagOutputFormat, result, policyLintTable); err != nil { |
| 62 | return fmt.Errorf("failed to encode output: %w", err) |
| 63 | } |
| 64 | return fmt.Errorf("%d issues found", len(result.Errors)) |
| 65 | }, |
| 66 | } |
| 67 | |
| 68 | cmd.Flags().StringVarP(&policyPath, "policy", "p", "policy.yaml", "Path to policy file") |
| 69 | cmd.Flags().BoolVar(&format, "format", false, "Auto-format standalone policy rego files with opa fmt (embedded policies not supported)") |
| 70 | cmd.Flags().StringVar(®alConfig, "regal-config", "", "Path to custom regal config (Default: https://github.com/chainloop-dev/chainloop/tree/main/app/cli/internal/policydevel/.regal.yaml)") |
| 71 | return cmd |
| 72 | } |
| 73 | |
| 74 | // Table rendering function for policy lint results |
| 75 | func policyLintTable(result *action.PolicyLintResult) error { |
no test coverage detected