mirror of
https://github.com/holos-run/holos.git
synced 2026-03-22 10:15:01 +00:00
Without this patch `holos cue vet` always returns exit code 0, even when
there are errors.
This patch fixes the problem by catching the error and returning it to
our own top level error handler. Note the final error, "could not run:
terminating because of errors" which wraps the generic error reported by
cue in the presence of multiple errors.
Result:
```
❯ holos cue vet ./policy --path 'strings.ToLower(kind)' /tmp/podinfo.gen.yaml
deployment.kind: conflicting values "Forbidden" and "Deployment":
./policy/validations.cue:18:8
../../../../../tmp/podinfo.gen.yaml:25:7
deployment.spec.template.spec.containers.0.resources.limits: conflicting values null and {[string]:"k8s.io/apimachinery/pkg/api/resource".#Quantity} (mismatched types null and struct):
./cue.mod/gen/k8s.io/api/apps/v1/types_go_gen.cue:355:9
./cue.mod/gen/k8s.io/api/apps/v1/types_go_gen.cue:376:12
./cue.mod/gen/k8s.io/api/core/v1/types_go_gen.cue:2840:11
./cue.mod/gen/k8s.io/api/core/v1/types_go_gen.cue:2968:14
./cue.mod/gen/k8s.io/api/core/v1/types_go_gen.cue:3882:15
./cue.mod/gen/k8s.io/api/core/v1/types_go_gen.cue:3882:18
./cue.mod/gen/k8s.io/api/core/v1/types_go_gen.cue:5027:9
./cue.mod/gen/k8s.io/api/core/v1/types_go_gen.cue:6407:16
./policy/validations.cue:17:13
../../../../../tmp/podinfo.gen.yaml:104:19
could not run: terminating because of errors
```
138 lines
4.1 KiB
Go
138 lines
4.1 KiB
Go
package cli
|
|
|
|
import (
|
|
_ "embed"
|
|
"fmt"
|
|
"log/slog"
|
|
|
|
"github.com/spf13/cobra"
|
|
|
|
"github.com/holos-run/holos/version"
|
|
|
|
"github.com/holos-run/holos/internal/holos"
|
|
"github.com/holos-run/holos/internal/logger"
|
|
"github.com/holos-run/holos/internal/server"
|
|
|
|
"github.com/holos-run/holos/internal/cli/command"
|
|
"github.com/holos-run/holos/internal/cli/create"
|
|
"github.com/holos-run/holos/internal/cli/destroy"
|
|
"github.com/holos-run/holos/internal/cli/get"
|
|
"github.com/holos-run/holos/internal/cli/kv"
|
|
"github.com/holos-run/holos/internal/cli/login"
|
|
"github.com/holos-run/holos/internal/cli/logout"
|
|
"github.com/holos-run/holos/internal/cli/preflight"
|
|
"github.com/holos-run/holos/internal/cli/pull"
|
|
"github.com/holos-run/holos/internal/cli/push"
|
|
"github.com/holos-run/holos/internal/cli/register"
|
|
"github.com/holos-run/holos/internal/cli/render"
|
|
"github.com/holos-run/holos/internal/cli/token"
|
|
"github.com/holos-run/holos/internal/cli/txtar"
|
|
|
|
cue "cuelang.org/go/cmd/cue/cmd"
|
|
)
|
|
|
|
//go:embed help.txt
|
|
var helpLong string
|
|
|
|
// New returns a new root *cobra.Command for command line execution.
|
|
func New(cfg *holos.Config, feature holos.Flagger) *cobra.Command {
|
|
rootCmd := &cobra.Command{
|
|
Use: "holos",
|
|
Short: "holos manages a holistic integrated software development platform",
|
|
Long: helpLong,
|
|
Version: version.GetVersion(),
|
|
Args: cobra.NoArgs,
|
|
CompletionOptions: cobra.CompletionOptions{
|
|
HiddenDefaultCmd: true, // Don't complete the complete subcommand itself
|
|
},
|
|
SilenceUsage: true,
|
|
SilenceErrors: true,
|
|
PersistentPreRunE: func(c *cobra.Command, args []string) error {
|
|
if err := cfg.Finalize(); err != nil {
|
|
return err
|
|
}
|
|
log := cfg.Logger()
|
|
c.Root().SetContext(logger.NewContext(c.Context(), log))
|
|
// Set the default logger after flag parsing.
|
|
slog.SetDefault(log)
|
|
return nil
|
|
},
|
|
RunE: func(c *cobra.Command, args []string) error {
|
|
return c.Usage()
|
|
},
|
|
}
|
|
rootCmd.SetVersionTemplate("{{.Version}}\n")
|
|
rootCmd.SetOut(cfg.Stdout())
|
|
rootCmd.PersistentFlags().SortFlags = false
|
|
rootCmd.PersistentFlags().AddGoFlagSet(cfg.LogFlagSet())
|
|
|
|
// Hide the help command
|
|
rootCmd.SetHelpCommand(&cobra.Command{Hidden: true})
|
|
rootCmd.PersistentFlags().BoolP("help", "h", false, "Print usage")
|
|
rootCmd.PersistentFlags().Lookup("help").Hidden = true
|
|
|
|
// subcommands
|
|
rootCmd.AddCommand(render.New(cfg, feature))
|
|
rootCmd.AddCommand(get.New(cfg, feature))
|
|
rootCmd.AddCommand(create.New(cfg, feature))
|
|
rootCmd.AddCommand(destroy.New(cfg, feature))
|
|
rootCmd.AddCommand(preflight.New(cfg, feature))
|
|
rootCmd.AddCommand(login.New(cfg, feature))
|
|
rootCmd.AddCommand(logout.New(cfg, feature))
|
|
rootCmd.AddCommand(token.New(cfg, feature))
|
|
rootCmd.AddCommand(newInitCommand(feature))
|
|
rootCmd.AddCommand(register.New(cfg, feature))
|
|
rootCmd.AddCommand(pull.New(cfg, feature))
|
|
rootCmd.AddCommand(push.New(cfg, feature))
|
|
rootCmd.AddCommand(newOrgCmd(feature))
|
|
|
|
// Maybe not needed?
|
|
rootCmd.AddCommand(txtar.New(cfg))
|
|
|
|
// Deprecated, remove?
|
|
rootCmd.AddCommand(kv.New(cfg, feature))
|
|
|
|
// Server
|
|
rootCmd.AddCommand(server.New(cfg, feature))
|
|
|
|
// CUE
|
|
rootCmd.AddCommand(newCueCmd())
|
|
|
|
// Show
|
|
rootCmd.AddCommand(newShowCmd())
|
|
|
|
return rootCmd
|
|
}
|
|
|
|
func newOrgCmd(feature holos.Flagger) (cmd *cobra.Command) {
|
|
cmd = command.New("orgid")
|
|
cmd.Short = "print the current context org id."
|
|
cmd.Hidden = !feature.Flag(holos.ServerFeature)
|
|
cmd.RunE = func(cmd *cobra.Command, args []string) error {
|
|
ctx := cmd.Root().Context()
|
|
cc := holos.NewClientContext(ctx)
|
|
_, err := fmt.Fprintln(cmd.OutOrStdout(), cc.OrgID)
|
|
return err
|
|
}
|
|
return cmd
|
|
}
|
|
|
|
func newCueCmd() (cmd *cobra.Command) {
|
|
// Get a handle on the cue root command fields.
|
|
root, _ := cue.New([]string{})
|
|
// Copy the fields to our embedded command.
|
|
cmd = command.New("cue")
|
|
cmd.Short = root.Short
|
|
cmd.Long = root.Long
|
|
// Pass all arguments through to RunE.
|
|
cmd.DisableFlagParsing = true
|
|
cmd.Args = cobra.ArbitraryArgs
|
|
|
|
// We do it this way so we handle errors correctly.
|
|
cmd.RunE = func(cmd *cobra.Command, args []string) error {
|
|
cueRootCommand, _ := cue.New(args)
|
|
return cueRootCommand.Run(cmd.Root().Context())
|
|
}
|
|
return cmd
|
|
}
|