// Package cli provides the common boilerplate code around executing a cobra command. package cli import ( "context" "errors" "fmt" "log/slog" "os" "os/signal" "syscall" "github.com/spf13/cobra" "git.ifooth.com/common/pkg/version" ) var ( // errSignal ... errSignal = errors.New("signal") ) // Run provides the common boilerplate code around executing a cobra command. func Run(cmd *cobra.Command) int { // 不开启 自动排序 cobra.EnableCommandSorting = false cmd.CompletionOptions.DisableDefaultCmd = true cmd.SilenceErrors = true cmd.SilenceUsage = true // 添加版本 cmd.SetVersionTemplate(`{{println .Version}}`) cmd.Version = version.GetVersion() if err := execute(cmd); err != nil { fmt.Fprintf(os.Stderr, "Error: %v\n", err) return 1 } return 0 } func execute(cmd *cobra.Command) error { ctx, cancel := context.WithCancelCause(context.Background()) // graceful shutdown signal signalChan := make(chan os.Signal, 1) signal.Notify(signalChan, syscall.SIGINT, syscall.SIGTERM) go func() { select { case s := <-signalChan: slog.WarnContext(ctx, "Signal received", "signal", s) cancel(fmt.Errorf("%w %s received", errSignal, s)) case <-ctx.Done(): } }() err := cmd.ExecuteContext(ctx) if err == nil { return nil } if errors.Is(err, errSignal) { return nil } return err }