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