fix incorrent exit code
Signed-off-by: yxxhero <aiopsclub@163.com>
This commit is contained in:
		
							parent
							
								
									98ca036d99
								
							
						
					
					
						commit
						76bf9952b9
					
				| 
						 | 
				
			
			@ -6,12 +6,12 @@ import (
 | 
			
		|||
 | 
			
		||||
	"github.com/spf13/cobra"
 | 
			
		||||
	"github.com/spf13/pflag"
 | 
			
		||||
	"github.com/urfave/cli"
 | 
			
		||||
	"go.uber.org/zap"
 | 
			
		||||
 | 
			
		||||
	"github.com/helmfile/helmfile/pkg/app"
 | 
			
		||||
	"github.com/helmfile/helmfile/pkg/app/version"
 | 
			
		||||
	"github.com/helmfile/helmfile/pkg/config"
 | 
			
		||||
	"github.com/helmfile/helmfile/pkg/errors"
 | 
			
		||||
	"github.com/helmfile/helmfile/pkg/helmexec"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -26,11 +26,11 @@ func toCLIError(g *config.GlobalImpl, err error) error {
 | 
			
		|||
			if g.AllowNoMatchingRelease {
 | 
			
		||||
				noMatchingExitCode = 0
 | 
			
		||||
			}
 | 
			
		||||
			return cli.NewExitError(e.Error(), noMatchingExitCode)
 | 
			
		||||
			return errors.NewExitError(e.Error(), noMatchingExitCode)
 | 
			
		||||
		case *app.MultiError:
 | 
			
		||||
			return cli.NewExitError(e.Error(), 1)
 | 
			
		||||
			return errors.NewExitError(e.Error(), 1)
 | 
			
		||||
		case *app.Error:
 | 
			
		||||
			return cli.NewExitError(e.Error(), e.Code())
 | 
			
		||||
			return errors.NewExitError(e.Error(), e.Code())
 | 
			
		||||
		default:
 | 
			
		||||
			panic(fmt.Errorf("BUG: please file an github issue for this unhandled error: %T: %v", e, e))
 | 
			
		||||
		}
 | 
			
		||||
| 
						 | 
				
			
			@ -47,6 +47,7 @@ func NewRootCmd(globalConfig *config.GlobalOptions, args []string) (*cobra.Comma
 | 
			
		|||
		Args:          cobra.MinimumNArgs(1),
 | 
			
		||||
		Version:       version.GetVersion(),
 | 
			
		||||
		SilenceUsage:  true,
 | 
			
		||||
		SilenceErrors: true,
 | 
			
		||||
		PersistentPreRunE: func(c *cobra.Command, args []string) error {
 | 
			
		||||
			// Valid levels:
 | 
			
		||||
			// https://github.com/uber-go/zap/blob/7e7e266a8dbce911a49554b945538c5b950196b8/zapcore/level.go#L126
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										3
									
								
								go.mod
								
								
								
								
							
							
						
						
									
										3
									
								
								go.mod
								
								
								
								
							| 
						 | 
				
			
			@ -24,7 +24,6 @@ require (
 | 
			
		|||
	github.com/spf13/pflag v1.0.5
 | 
			
		||||
	github.com/stretchr/testify v1.8.0
 | 
			
		||||
	github.com/tatsushid/go-prettytable v0.0.0-20141013043238-ed2d14c29939
 | 
			
		||||
	github.com/urfave/cli v1.22.10
 | 
			
		||||
	github.com/variantdev/chartify v0.10.2
 | 
			
		||||
	github.com/variantdev/dag v1.1.0
 | 
			
		||||
	github.com/variantdev/vals v0.18.0
 | 
			
		||||
| 
						 | 
				
			
			@ -62,7 +61,6 @@ require (
 | 
			
		|||
	github.com/aws/aws-sdk-go v1.40.28 // indirect
 | 
			
		||||
	github.com/bgentry/go-netrc v0.0.0-20140422174119-9fd32a8b3d3d // indirect
 | 
			
		||||
	github.com/blang/semver v3.5.1+incompatible // indirect
 | 
			
		||||
	github.com/cpuguy83/go-md2man/v2 v2.0.2 // indirect
 | 
			
		||||
	github.com/dimchansky/utfbom v1.1.1 // indirect
 | 
			
		||||
	github.com/fatih/color v1.13.0 // indirect
 | 
			
		||||
	github.com/fujiwara/tfstate-lookup v0.4.4 // indirect
 | 
			
		||||
| 
						 | 
				
			
			@ -107,7 +105,6 @@ require (
 | 
			
		|||
	github.com/pbnjay/strptime v0.0.0-20140226051138-5c05b0d668c9 // indirect
 | 
			
		||||
	github.com/pkg/errors v0.9.1 // indirect
 | 
			
		||||
	github.com/pmezard/go-difflib v1.0.0 // indirect
 | 
			
		||||
	github.com/russross/blackfriday/v2 v2.1.0 // indirect
 | 
			
		||||
	github.com/ryanuber/go-glob v1.0.0 // indirect
 | 
			
		||||
	github.com/sergi/go-diff v1.1.0 // indirect
 | 
			
		||||
	github.com/shopspring/decimal v1.2.0 // indirect
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										4
									
								
								go.sum
								
								
								
								
							
							
						
						
									
										4
									
								
								go.sum
								
								
								
								
							| 
						 | 
				
			
			@ -394,7 +394,6 @@ github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfc
 | 
			
		|||
github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
 | 
			
		||||
github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
 | 
			
		||||
github.com/cpuguy83/go-md2man/v2 v2.0.1/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
 | 
			
		||||
github.com/cpuguy83/go-md2man/v2 v2.0.2 h1:p1EgwI/C7NhT0JmVkwCD2ZBK8j4aeHQX2pMHHBfMQ6w=
 | 
			
		||||
github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
 | 
			
		||||
github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY=
 | 
			
		||||
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
 | 
			
		||||
| 
						 | 
				
			
			@ -1144,7 +1143,6 @@ github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTE
 | 
			
		|||
github.com/rubenv/sql-migrate v0.0.0-20210614095031-55d5740dbbcc/go.mod h1:HFLT6i9iR4QBOF5rdCyjddC9t59ArqWJV2xx+jwcCMo=
 | 
			
		||||
github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g=
 | 
			
		||||
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
 | 
			
		||||
github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk=
 | 
			
		||||
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
 | 
			
		||||
github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts=
 | 
			
		||||
github.com/ryanuber/columnize v2.1.0+incompatible/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts=
 | 
			
		||||
| 
						 | 
				
			
			@ -1245,8 +1243,6 @@ github.com/urfave/cli v0.0.0-20171014202726-7bc6a0acffa5/go.mod h1:70zkFmudgCuE/
 | 
			
		|||
github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA=
 | 
			
		||||
github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
 | 
			
		||||
github.com/urfave/cli v1.22.2/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
 | 
			
		||||
github.com/urfave/cli v1.22.10 h1:p8Fspmz3iTctJstry1PYS3HVdllxnEzTEsgIgtxTrCk=
 | 
			
		||||
github.com/urfave/cli v1.22.10/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
 | 
			
		||||
github.com/variantdev/chartify v0.10.2 h1:CAMlSE4kBl8ft/Xl4ob+eyFZ2KV5evkiMEI43M4CaKs=
 | 
			
		||||
github.com/variantdev/chartify v0.10.2/go.mod h1:A0nQmb+ihiBJrrbgofs1t7QVeit+/llT0vJhvkj7U0Q=
 | 
			
		||||
github.com/variantdev/dag v1.1.0 h1:xodYlSng33KWGvIGMpKUyLcIZRXKiNUx612mZJqYrDg=
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										17
									
								
								main.go
								
								
								
								
							
							
						
						
									
										17
									
								
								main.go
								
								
								
								
							| 
						 | 
				
			
			@ -1,28 +1,19 @@
 | 
			
		|||
package main
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"os"
 | 
			
		||||
 | 
			
		||||
	"github.com/urfave/cli"
 | 
			
		||||
 | 
			
		||||
	"github.com/helmfile/helmfile/cmd"
 | 
			
		||||
	"github.com/helmfile/helmfile/pkg/config"
 | 
			
		||||
	"github.com/helmfile/helmfile/pkg/errors"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func warning(format string, v ...interface{}) {
 | 
			
		||||
	format = fmt.Sprintf("WARNING: %s\n", format)
 | 
			
		||||
	fmt.Fprintf(os.Stderr, format, v...)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func main() {
 | 
			
		||||
	globalConfig := new(config.GlobalOptions)
 | 
			
		||||
	rootCmd, err := cmd.NewRootCmd(globalConfig, os.Args[1:])
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		warning("%+v", err)
 | 
			
		||||
		os.Exit(1)
 | 
			
		||||
	}
 | 
			
		||||
	errors.HandleExitCoder(err)
 | 
			
		||||
 | 
			
		||||
	if err := rootCmd.Execute(); err != nil {
 | 
			
		||||
		cli.HandleExitCoder(err)
 | 
			
		||||
		errors.HandleExitCoder(err)
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -0,0 +1,97 @@
 | 
			
		|||
/*
 | 
			
		||||
* MIT License
 | 
			
		||||
*
 | 
			
		||||
* Copyright (c) 2022 urfave/cli maintainers
 | 
			
		||||
*
 | 
			
		||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
 | 
			
		||||
* of this software and associated documentation files (the "Software"), to deal
 | 
			
		||||
* in the Software without restriction, including without limitation the rights
 | 
			
		||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 | 
			
		||||
* copies of the Software, and to permit persons to whom the Software is
 | 
			
		||||
* furnished to do so, subject to the following conditions:
 | 
			
		||||
*
 | 
			
		||||
* The above copyright notice and this permission notice shall be included in all
 | 
			
		||||
* copies or substantial portions of the Software.
 | 
			
		||||
*
 | 
			
		||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 | 
			
		||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 | 
			
		||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 | 
			
		||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 | 
			
		||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 | 
			
		||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 | 
			
		||||
* SOFTWARE.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
package errors
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"io"
 | 
			
		||||
	"os"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// OsExiter is the function used when the app exits. If not set defaults to os.Exit.
 | 
			
		||||
var OsExiter = os.Exit
 | 
			
		||||
 | 
			
		||||
// ErrWriter is used to write errors to the user. This can be anything
 | 
			
		||||
// implementing the io.Writer interface and defaults to os.Stderr.
 | 
			
		||||
var ErrWriter io.Writer = os.Stderr
 | 
			
		||||
 | 
			
		||||
type ErrorFormatter interface {
 | 
			
		||||
	Format(s fmt.State, verb rune)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ExitCoder is the interface checked by `App` and `Command` for a custom exit
 | 
			
		||||
// code
 | 
			
		||||
type ExitCoder interface {
 | 
			
		||||
	error
 | 
			
		||||
	ExitCode() int
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ExitError fulfills both the builtin `error` interface and `ExitCoder`
 | 
			
		||||
type ExitError struct {
 | 
			
		||||
	exitCode int
 | 
			
		||||
	message  interface{}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// NewExitError makes a new *ExitError
 | 
			
		||||
func NewExitError(message interface{}, exitCode int) *ExitError {
 | 
			
		||||
	return &ExitError{
 | 
			
		||||
		exitCode: exitCode,
 | 
			
		||||
		message:  message,
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Error returns the string message, fulfilling the interface required by
 | 
			
		||||
// `error`
 | 
			
		||||
func (ee *ExitError) Error() string {
 | 
			
		||||
	return fmt.Sprintf("%v", ee.message)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ExitCode returns the exit code, fulfilling the interface required by
 | 
			
		||||
// `ExitCoder`
 | 
			
		||||
func (ee *ExitError) ExitCode() int {
 | 
			
		||||
	return ee.exitCode
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// HandleExitCoder checks if the error fulfills the ExitCoder interface, and if
 | 
			
		||||
// so prints the error to stderr (if it is non-empty) and calls OsExiter with the
 | 
			
		||||
// given exit code.  If the given error is a MultiError, then this func is
 | 
			
		||||
// called on all members of the Errors slice and calls OsExiter with the last exit code.
 | 
			
		||||
func HandleExitCoder(err error) {
 | 
			
		||||
	if err == nil {
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if exitErr, ok := err.(ExitCoder); ok {
 | 
			
		||||
		if err.Error() != "" {
 | 
			
		||||
			fmt.Fprintln(ErrWriter, err)
 | 
			
		||||
		}
 | 
			
		||||
		OsExiter(exitErr.ExitCode())
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	// unknown error exit with code 3
 | 
			
		||||
	fmt.Fprintln(ErrWriter, err)
 | 
			
		||||
 | 
			
		||||
	OsExiter(3)
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,87 @@
 | 
			
		|||
/*
 | 
			
		||||
* MIT License
 | 
			
		||||
*
 | 
			
		||||
* Copyright (c) 2022 urfave/cli maintainers
 | 
			
		||||
*
 | 
			
		||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
 | 
			
		||||
* of this software and associated documentation files (the "Software"), to deal
 | 
			
		||||
* in the Software without restriction, including without limitation the rights
 | 
			
		||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 | 
			
		||||
* copies of the Software, and to permit persons to whom the Software is
 | 
			
		||||
* furnished to do so, subject to the following conditions:
 | 
			
		||||
*
 | 
			
		||||
* The above copyright notice and this permission notice shall be included in all
 | 
			
		||||
* copies or substantial portions of the Software.
 | 
			
		||||
*
 | 
			
		||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 | 
			
		||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 | 
			
		||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 | 
			
		||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 | 
			
		||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 | 
			
		||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 | 
			
		||||
* SOFTWARE.
 | 
			
		||||
 */
 | 
			
		||||
package errors
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"os"
 | 
			
		||||
	"reflect"
 | 
			
		||||
	"runtime"
 | 
			
		||||
	"strings"
 | 
			
		||||
	"testing"
 | 
			
		||||
 | 
			
		||||
	"github.com/stretchr/testify/require"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
var (
 | 
			
		||||
	wd, _        = os.Getwd()
 | 
			
		||||
	lastExitCode = 0
 | 
			
		||||
	fakeOsExiter = func(rc int) {
 | 
			
		||||
		lastExitCode = rc
 | 
			
		||||
	}
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func expect(t *testing.T, a interface{}, b interface{}) {
 | 
			
		||||
	_, fn, line, _ := runtime.Caller(1)
 | 
			
		||||
	fn = strings.Replace(fn, wd+"/", "", -1)
 | 
			
		||||
 | 
			
		||||
	require.Equalf(t, a, b, "(%s:%d) Expected %v (type %v) - Got %v (type %v)", fn, line, b, reflect.TypeOf(b), a, reflect.TypeOf(a))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestHandleExitCoder_nil(t *testing.T) {
 | 
			
		||||
	exitCode := 0
 | 
			
		||||
	called := false
 | 
			
		||||
 | 
			
		||||
	OsExiter = func(rc int) {
 | 
			
		||||
		if !called {
 | 
			
		||||
			exitCode = rc
 | 
			
		||||
			called = true
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	defer func() { OsExiter = fakeOsExiter }()
 | 
			
		||||
 | 
			
		||||
	HandleExitCoder(nil)
 | 
			
		||||
 | 
			
		||||
	expect(t, exitCode, 0)
 | 
			
		||||
	expect(t, called, false)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestHandleExitCoder_ExitCoder(t *testing.T) {
 | 
			
		||||
	exitCode := 0
 | 
			
		||||
	called := false
 | 
			
		||||
 | 
			
		||||
	OsExiter = func(rc int) {
 | 
			
		||||
		if !called {
 | 
			
		||||
			exitCode = rc
 | 
			
		||||
			called = true
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	defer func() { OsExiter = fakeOsExiter }()
 | 
			
		||||
 | 
			
		||||
	HandleExitCoder(NewExitError("galactic perimeter breach", 9))
 | 
			
		||||
 | 
			
		||||
	expect(t, exitCode, 9)
 | 
			
		||||
	expect(t, called, true)
 | 
			
		||||
}
 | 
			
		||||
		Loading…
	
		Reference in New Issue