diff --git a/README.md b/README.md index 44b45eda..d18aa1a3 100644 --- a/README.md +++ b/README.md @@ -207,7 +207,8 @@ No configuration is necessary, however, you can create a config file and overrid ```yaml # supported options are "docker" and "podman" container-engine: docker - +# continue with analysis even if there are errors parsing the image archive +ignore-errors: false log: enabled: true path: ./dive.log diff --git a/cmd/analyze.go b/cmd/analyze.go index e6d7e8cc..49883d67 100644 --- a/cmd/analyze.go +++ b/cmd/analyze.go @@ -2,11 +2,12 @@ package cmd import ( "fmt" + "github.com/sirupsen/logrus" + "github.com/spf13/viper" "github.com/wagoodman/dive/dive" "os" "github.com/spf13/cobra" - "github.com/spf13/viper" "github.com/wagoodman/dive/runtime" ) @@ -56,11 +57,17 @@ func doAnalyzeCmd(cmd *cobra.Command, args []string) { imageStr = userImage } + ignoreErrors, err := cmd.PersistentFlags().GetBool("ignore-errors") + if err != nil { + logrus.Error("unable to get 'ignore-errors' option:", err) + } + runtime.Run(runtime.Options{ - Ci: isCi, - Source: sourceType, - Image: imageStr, - ExportFile: exportFile, - CiConfig: ciConfig, + Ci: isCi, + Source: sourceType, + Image: imageStr, + ExportFile: exportFile, + CiConfig: ciConfig, + IgnoreErrors: viper.GetBool("ignore-errors") || ignoreErrors, }) } diff --git a/cmd/root.go b/cmd/root.go index 707c556d..6f714977 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -48,6 +48,7 @@ func initCli() { rootCmd.PersistentFlags().StringVar(&cfgFile, "config", "", "config file (default is $HOME/.dive.yaml, ~/.config/dive/*.yaml, or $XDG_CONFIG_HOME/dive.yaml)") rootCmd.PersistentFlags().String("source", "docker", "The container engine to fetch the image from. Allowed values: "+strings.Join(dive.ImageSources, ", ")) rootCmd.PersistentFlags().BoolP("version", "v", false, "display version number") + rootCmd.PersistentFlags().BoolP("ignore-errors", "i", false, "ignore image parsing errors and run the analysis anyway") rootCmd.Flags().BoolVar(&isCi, "ci", false, "Skip the interactive TUI and validate against CI rules (same as env var CI=true)") rootCmd.Flags().StringVarP(&exportFile, "json", "j", "", "Skip the interactive TUI and write the layer analysis statistics to a given file.") rootCmd.Flags().StringVar(&ciConfigFile, "ci-config", ".dive-ci", "If CI=true in the environment, use the given yaml to drive validation rules.") @@ -62,6 +63,9 @@ func initCli() { } } + if err := ciConfig.BindPFlag("ignore-errors", rootCmd.PersistentFlags().Lookup("ignore-errors")); err != nil { + log.Fatalf("Unable to bind 'ignore-errors' flag: %v", err) + } } // initConfig reads in config file and ENV variables if set. @@ -98,6 +102,7 @@ func initConfig() { viper.SetDefault("filetree.show-attributes", true) viper.SetDefault("container-engine", "docker") + viper.SetDefault("ignore-errors", false) err = viper.BindPFlag("source", rootCmd.PersistentFlags().Lookup("source")) if err != nil { diff --git a/runtime/options.go b/runtime/options.go index 5554a228..e0a36766 100644 --- a/runtime/options.go +++ b/runtime/options.go @@ -6,10 +6,11 @@ import ( ) type Options struct { - Ci bool - Image string - Source dive.ImageSource - ExportFile string - CiConfig *viper.Viper - BuildArgs []string + Ci bool + Image string + Source dive.ImageSource + IgnoreErrors bool + ExportFile string + CiConfig *viper.Viper + BuildArgs []string } diff --git a/runtime/run.go b/runtime/run.go index dce54a92..4ffb5ccf 100644 --- a/runtime/run.go +++ b/runtime/run.go @@ -93,8 +93,10 @@ func run(enableUi bool, options Options, imageResolver image.Resolver, events ev for _, err := range errors { events.message(" " + err.Error()) } - events.exitWithError(fmt.Errorf("file tree has path errors")) - return + if !options.IgnoreErrors { + events.exitWithError(fmt.Errorf("file tree has path errors (use '--ignore-errors' to attempt to continue)")) + return + } } if enableUi {