From 2bf6b1d5e57102ac06d8a74eafe626dcc64b89f4 Mon Sep 17 00:00:00 2001 From: pallam Date: Tue, 25 Jun 2024 15:31:12 +0300 Subject: [PATCH 1/3] feat: add version checking flags, to prevent misconfiguration between sqlboiler installed in project and executable version --- README.md | 49 ++++++++++++++++++++----------- boilingcore/boilingcore.go | 59 ++++++++++++++++++++++++++++++++++++++ boilingcore/config.go | 3 ++ main.go | 6 +++- 4 files changed, 99 insertions(+), 18 deletions(-) diff --git a/README.md b/README.md index 4a9ee37b3..1c7550dca 100644 --- a/README.md +++ b/README.md @@ -62,6 +62,7 @@ Table of Contents * [Configuration](#configuration) * [Initial Generation](#initial-generation) * [Regeneration](#regeneration) + * [Controlling Version](#controlling-version) * [Controlling Generation](#controlling-generation) * [Aliases](#aliases) * [Types](#types) @@ -372,23 +373,25 @@ blacklist = ["migrations", "addresses.name", "*.secret_col"] You can also pass in these top level configuration values if you would prefer not to pass them through the command line or environment variables: -| Name | Defaults | -| ------------------- | --------- | -| pkgname | "models" | -| output | "models" | -| tag | [] | -| debug | false | -| add-global-variants | false | -| add-panic-variants | false | -| add-enum-types | false | -| enum-null-prefix | "Null" | -| no-context | false | -| no-hooks | false | -| no-tests | false | -| no-auto-timestamps | false | -| no-rows-affected | false | -| no-driver-templates | false | -| tag-ignore | [] | +| Name | Defaults | +|---------------------------|----------| +| pkgname | "models" | +| output | "models" | +| tag | [] | +| debug | false | +| add-global-variants | false | +| add-panic-variants | false | +| add-enum-types | false | +| enum-null-prefix | "Null" | +| no-context | false | +| no-hooks | false | +| no-tests | false | +| no-auto-timestamps | false | +| no-rows-affected | false | +| no-driver-templates | false | +| tag-ignore | [] | +| verify-mod-version | false | +| strict-verify-mod-version | false | ##### Full Example @@ -464,6 +467,8 @@ Flags: --tag-ignore strings List of column names that should have tags values set to '-' (ignored during parsing) --templates strings A templates directory, overrides the embedded template folders in sqlboiler --version Print the version + --verify-mod-version Verify that version of sqlboiler executable is same as the version of the project + --strict-verify-mod-version If --verify-mod-version flag enabled, and check fails, sqlboiler fails too --wipe Delete the output folder (rm -rf) before generation to ensure sanity ``` @@ -512,6 +517,16 @@ the same source. And the intention is to always regenerate from a pure state. The only reason the `--wipe` flag isn't defaulted to on is because we don't like programs that `rm -rf` things on the filesystem without being asked to. +#### Controlling Version + +When sqlboiler is used on a regular basis, sometimes problems arise on the +developers' side that the version they are using does not match the version +specified in the project. + +To solve this problem, you can use the `--verify-mod-version` and +`--strict-verify-mod-version` flags (or aliased version in toml), which +will warn and prohibit (when using strict) code generation when using sqlboiler. + #### Controlling Generation The templates get executed in a specific way each time. There's a variety of diff --git a/boilingcore/boilingcore.go b/boilingcore/boilingcore.go index 8afa911c0..2e23c74a1 100644 --- a/boilingcore/boilingcore.go +++ b/boilingcore/boilingcore.go @@ -80,6 +80,17 @@ func New(config *Config) (*State, error) { ) } + if s.Config.VerifyModVersion { + if err := s.verifyModVersion(); err != nil { + if s.Config.StrictVerifyModVersion { + fmt.Printf("Error: %s\n", err.Error()) + os.Exit(1) + } else { + fmt.Printf("Warn: %s\n", err.Error()) + } + } + } + s.Driver = drivers.GetDriver(config.DriverName) s.initInflections() @@ -694,3 +705,51 @@ func denormalizeSlashes(path string) string { path = strings.ReplaceAll(path, `\`, `/`) return path } + +func (s *State) verifyModVersion() error { + dir, err := os.Getwd() + if err != nil { + return fmt.Errorf("could not get working directory: %v", err) + } + var path string + for dir != "/" && dir != "." { + resolvedPath := filepath.Join(dir, "go.mod") + + _, err := os.Stat(resolvedPath) + if os.IsNotExist(err) { + dir = filepath.Dir(dir) + } else { + path = resolvedPath + break + } + } + if path == "" { + return fmt.Errorf(fmt.Sprintf("could not find go.mod in any parent directory")) + } + + gomodbytes, err := os.ReadFile(path) + if err != nil { + return fmt.Errorf(fmt.Sprintf("could not read go.mod: %v", err)) + } + + re, err := regexp.Compile(`github\.com\/volatiletech\/sqlboiler\/v4 v(\d*\.\d*\.\d*)`) + if err != nil { + return fmt.Errorf(fmt.Sprintf("failed to parse regexp: %v", err)) + } + + match := re.FindSubmatch(gomodbytes) + if len(match) == 0 { + return fmt.Errorf(fmt.Sprintf("could not find sqlboiler version in go.mod")) + } + if string(match[1]) != s.Config.Version { + return fmt.Errorf( + "\tsqlboiler version in go.mod (%s) does not match executable version (%s)."+ + "\n\tYou can update it with:"+ + "\n\tgo get github.com/volatiletech/sqlboiler/v4", + string(match[0]), + s.Config.Version, + ) + } + + return nil +} diff --git a/boilingcore/config.go b/boilingcore/config.go index 5635d878f..818953acd 100644 --- a/boilingcore/config.go +++ b/boilingcore/config.go @@ -70,6 +70,9 @@ type Config struct { Inflections Inflections `toml:"inflections,omitempty" json:"inflections,omitempty"` ForeignKeys []drivers.ForeignKey `toml:"foreign_keys,omitempty" json:"foreign_keys,omitempty" ` + VerifyModVersion bool `toml:"verify_mod_version,omitempty" json:"verify_mod_version,omitempty"` + StrictVerifyModVersion bool `toml:"strict_verify_mod_version,omitempty" json:"strict_verify_mod_version"` + Version string `toml:"version" json:"version"` } diff --git a/main.go b/main.go index 4f00a84b7..936939016 100644 --- a/main.go +++ b/main.go @@ -112,6 +112,8 @@ func main() { rootCmd.PersistentFlags().StringP("struct-tag-casing", "", "snake", "Decides the casing for go structure tag names. camel, title or snake (default snake)") rootCmd.PersistentFlags().StringP("relation-tag", "r", "-", "Relationship struct tag name") rootCmd.PersistentFlags().StringSliceP("tag-ignore", "", nil, "List of column names that should have tags values set to '-' (ignored during parsing)") + rootCmd.PersistentFlags().BoolP("verify-mod-version", "", false, "Verify that version of SQLBoiler executable is same as the version of the project") + rootCmd.PersistentFlags().BoolP("strict-verify-mod-version", "", false, "If verify-mod-version flag enabled, and check fails, SQLBoiler fails too") // hide flags not recommended for use rootCmd.PersistentFlags().MarkHidden("replace") @@ -198,7 +200,9 @@ func preRun(cmd *cobra.Command, args []string) error { SingularExact: viper.GetStringMapString("inflections.singular_exact"), Irregular: viper.GetStringMapString("inflections.irregular"), }, - ForeignKeys: boilingcore.ConvertForeignKeys(viper.Get("foreign_keys")), + ForeignKeys: boilingcore.ConvertForeignKeys(viper.Get("foreign_keys")), + VerifyModVersion: viper.GetBool("verify-mod-version"), + StrictVerifyModVersion: viper.GetBool("strict-verify-mod-version"), Version: sqlBoilerVersion, } From 4671186ba7bf8ac3c3e1f9e3591d1fba2fa20dca Mon Sep 17 00:00:00 2001 From: pallam Date: Wed, 26 Jun 2024 22:07:43 +0300 Subject: [PATCH 2/3] feat: set mod version verification as default behavior --- README.md | 6 +++--- boilingcore/boilingcore.go | 14 ++++++-------- boilingcore/config.go | 1 - main.go | 4 +--- 4 files changed, 10 insertions(+), 15 deletions(-) diff --git a/README.md b/README.md index 1c7550dca..f42d8c8ec 100644 --- a/README.md +++ b/README.md @@ -523,9 +523,9 @@ When sqlboiler is used on a regular basis, sometimes problems arise on the developers' side that the version they are using does not match the version specified in the project. -To solve this problem, you can use the `--verify-mod-version` and -`--strict-verify-mod-version` flags (or aliased version in toml), which -will warn and prohibit (when using strict) code generation when using sqlboiler. +Sqlboiler will warn, if version in project and executable mismatch. +Sqlboiler can also fail to prevent code generation, when +`--strict-verify-mod-version` flag (or aliased version in toml) is enabled. #### Controlling Generation diff --git a/boilingcore/boilingcore.go b/boilingcore/boilingcore.go index 2e23c74a1..8bc701b93 100644 --- a/boilingcore/boilingcore.go +++ b/boilingcore/boilingcore.go @@ -80,14 +80,12 @@ func New(config *Config) (*State, error) { ) } - if s.Config.VerifyModVersion { - if err := s.verifyModVersion(); err != nil { - if s.Config.StrictVerifyModVersion { - fmt.Printf("Error: %s\n", err.Error()) - os.Exit(1) - } else { - fmt.Printf("Warn: %s\n", err.Error()) - } + if err := s.verifyModVersion(); err != nil { + if s.Config.StrictVerifyModVersion { + fmt.Printf("Error: %s\n", err.Error()) + os.Exit(1) + } else { + fmt.Printf("Warn: %s\n", err.Error()) } } diff --git a/boilingcore/config.go b/boilingcore/config.go index 818953acd..2765b3171 100644 --- a/boilingcore/config.go +++ b/boilingcore/config.go @@ -70,7 +70,6 @@ type Config struct { Inflections Inflections `toml:"inflections,omitempty" json:"inflections,omitempty"` ForeignKeys []drivers.ForeignKey `toml:"foreign_keys,omitempty" json:"foreign_keys,omitempty" ` - VerifyModVersion bool `toml:"verify_mod_version,omitempty" json:"verify_mod_version,omitempty"` StrictVerifyModVersion bool `toml:"strict_verify_mod_version,omitempty" json:"strict_verify_mod_version"` Version string `toml:"version" json:"version"` diff --git a/main.go b/main.go index 936939016..5517077bd 100644 --- a/main.go +++ b/main.go @@ -112,8 +112,7 @@ func main() { rootCmd.PersistentFlags().StringP("struct-tag-casing", "", "snake", "Decides the casing for go structure tag names. camel, title or snake (default snake)") rootCmd.PersistentFlags().StringP("relation-tag", "r", "-", "Relationship struct tag name") rootCmd.PersistentFlags().StringSliceP("tag-ignore", "", nil, "List of column names that should have tags values set to '-' (ignored during parsing)") - rootCmd.PersistentFlags().BoolP("verify-mod-version", "", false, "Verify that version of SQLBoiler executable is same as the version of the project") - rootCmd.PersistentFlags().BoolP("strict-verify-mod-version", "", false, "If verify-mod-version flag enabled, and check fails, SQLBoiler fails too") + rootCmd.PersistentFlags().BoolP("strict-verify-mod-version", "", false, "Prevent code generation, if project version of sqlboiler not match with executable") // hide flags not recommended for use rootCmd.PersistentFlags().MarkHidden("replace") @@ -201,7 +200,6 @@ func preRun(cmd *cobra.Command, args []string) error { Irregular: viper.GetStringMapString("inflections.irregular"), }, ForeignKeys: boilingcore.ConvertForeignKeys(viper.Get("foreign_keys")), - VerifyModVersion: viper.GetBool("verify-mod-version"), StrictVerifyModVersion: viper.GetBool("strict-verify-mod-version"), Version: sqlBoilerVersion, From 095b846683738666ccf09fbb11a1194e72f3150c Mon Sep 17 00:00:00 2001 From: pallam Date: Wed, 26 Jun 2024 22:10:17 +0300 Subject: [PATCH 3/3] typo: updated README.md --- README.md | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/README.md b/README.md index f42d8c8ec..b1a2c7a6c 100644 --- a/README.md +++ b/README.md @@ -390,7 +390,6 @@ not to pass them through the command line or environment variables: | no-rows-affected | false | | no-driver-templates | false | | tag-ignore | [] | -| verify-mod-version | false | | strict-verify-mod-version | false | ##### Full Example @@ -467,8 +466,7 @@ Flags: --tag-ignore strings List of column names that should have tags values set to '-' (ignored during parsing) --templates strings A templates directory, overrides the embedded template folders in sqlboiler --version Print the version - --verify-mod-version Verify that version of sqlboiler executable is same as the version of the project - --strict-verify-mod-version If --verify-mod-version flag enabled, and check fails, sqlboiler fails too + --strict-verify-mod-version Prevent code generation, if project version of sqlboiler not match with executable --wipe Delete the output folder (rm -rf) before generation to ensure sanity ```