github.com/windmeup/goreleaser@v1.21.95/cmd/root.go (about) 1 package cmd 2 3 import ( 4 "errors" 5 "fmt" 6 "time" 7 8 goversion "github.com/caarlos0/go-version" 9 "github.com/caarlos0/log" 10 "github.com/charmbracelet/lipgloss" 11 "github.com/spf13/cobra" 12 "github.com/windmeup/goreleaser/pkg/context" 13 cobracompletefig "github.com/withfig/autocomplete-tools/integrations/cobra" 14 ) 15 16 var ( 17 boldStyle = lipgloss.NewStyle().Bold(true) 18 codeStyle = lipgloss.NewStyle().Italic(true) 19 ) 20 21 func Execute(version goversion.Info, exit func(int), args []string) { 22 newRootCmd(version, exit).Execute(args) 23 } 24 25 func (cmd *rootCmd) Execute(args []string) { 26 cmd.cmd.SetArgs(args) 27 28 if shouldPrependRelease(cmd.cmd, args) { 29 cmd.cmd.SetArgs(append([]string{"release"}, args...)) 30 } 31 32 if err := cmd.cmd.Execute(); err != nil { 33 code := 1 34 msg := "command failed" 35 eerr := &exitError{} 36 if errors.As(err, &eerr) { 37 code = eerr.code 38 if eerr.details != "" { 39 msg = eerr.details 40 } 41 } 42 log.WithError(err).Error(msg) 43 cmd.exit(code) 44 } 45 } 46 47 type rootCmd struct { 48 cmd *cobra.Command 49 verbose bool 50 exit func(int) 51 52 // Deprecated: use verbose instead. 53 debug bool 54 } 55 56 func newRootCmd(version goversion.Info, exit func(int)) *rootCmd { 57 root := &rootCmd{ 58 exit: exit, 59 } 60 cmd := &cobra.Command{ 61 Use: "goreleaser", 62 Short: "Deliver Go binaries as fast and easily as possible", 63 Long: `GoReleaser is a release automation tool for Go projects. 64 Its goal is to simplify the build, release and publish steps while providing variant customization options for all steps. 65 66 GoReleaser is built for CI tools, you only need to download and execute it in your build script. Of course, you can also install it locally if you wish. 67 68 You can customize your entire release process through a single .goreleaser.yaml file. 69 70 Check out our website for more information, examples and documentation: https://goreleaser.com 71 `, 72 Version: version.String(), 73 SilenceUsage: true, 74 SilenceErrors: true, 75 Args: cobra.NoArgs, 76 ValidArgsFunction: cobra.NoFileCompletions, 77 PersistentPreRun: func(_ *cobra.Command, _ []string) { 78 if root.verbose || root.debug { 79 log.SetLevel(log.DebugLevel) 80 log.Debug("verbose output enabled") 81 } 82 }, 83 PersistentPostRun: func(_ *cobra.Command, _ []string) { 84 log.Info("thanks for using goreleaser!") 85 }, 86 } 87 cmd.SetVersionTemplate("{{.Version}}") 88 89 cmd.PersistentFlags().BoolVar(&root.debug, "debug", false, "Enable verbose mode") 90 cmd.PersistentFlags().BoolVar(&root.verbose, "verbose", false, "Enable verbose mode") 91 _ = cmd.Flags().MarkDeprecated("debug", "please use --verbose instead") 92 _ = cmd.Flags().MarkHidden("debug") 93 cmd.AddCommand( 94 newBuildCmd().cmd, 95 newReleaseCmd().cmd, 96 newCheckCmd().cmd, 97 newHealthcheckCmd().cmd, 98 newInitCmd().cmd, 99 newDocsCmd().cmd, 100 newManCmd().cmd, 101 newSchemaCmd().cmd, 102 cobracompletefig.CreateCompletionSpecCommand(), 103 ) 104 root.cmd = cmd 105 return root 106 } 107 108 func shouldPrependRelease(cmd *cobra.Command, args []string) bool { 109 // find current cmd, if its not root, it means the user actively 110 // set a command, so let it go 111 xmd, _, _ := cmd.Find(args) 112 if xmd != cmd { 113 return false 114 } 115 116 // allow help and the two __complete commands. 117 if len(args) > 0 && (args[0] == "help" || args[0] == "completion" || 118 args[0] == cobra.ShellCompRequestCmd || args[0] == cobra.ShellCompNoDescRequestCmd) { 119 return false 120 } 121 122 // if we have != 1 args, assume its a release 123 if len(args) != 1 { 124 return true 125 } 126 127 // given that its 1, check if its one of the valid standalone flags 128 // for the root cmd 129 for _, s := range []string{"-h", "--help", "-v", "--version"} { 130 if s == args[0] { 131 // if it is, we should run the root cmd 132 return false 133 } 134 } 135 136 // otherwise, we should probably prepend release 137 return true 138 } 139 140 func deprecateWarn(ctx *context.Context) { 141 if ctx.Deprecated { 142 log.Warn(boldStyle.Render("you are using deprecated options, check the output above for details")) 143 } 144 } 145 146 func timedRunE(verb string, rune func(cmd *cobra.Command, args []string) error) func(cmd *cobra.Command, args []string) error { 147 return func(cmd *cobra.Command, args []string) error { 148 start := time.Now() 149 150 log.Infof(boldStyle.Render(fmt.Sprintf("starting %s...", verb))) 151 152 if err := rune(cmd, args); err != nil { 153 return wrapError(err, boldStyle.Render(fmt.Sprintf("%s failed after %s", verb, time.Since(start).Truncate(time.Second)))) 154 } 155 156 log.Infof(boldStyle.Render(fmt.Sprintf("%s succeeded after %s", verb, time.Since(start).Truncate(time.Second)))) 157 return nil 158 } 159 }