Skip to content

Commit

Permalink
Merge pull request #68 from restechnica/feature/multiple-default-conf…
Browse files Browse the repository at this point in the history
…ig-file-names

feature/multiple-default-config-file-names
  • Loading branch information
shiouen authored Jan 17, 2024
2 parents b2e0380 + f8f223d commit fa39cf7
Show file tree
Hide file tree
Showing 8 changed files with 85 additions and 33 deletions.
2 changes: 1 addition & 1 deletion .semverbot.toml
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,4 @@ major = ["release"]
delimiters = "/"

[modes.git-commit]
delimiters = "[]"
delimiters = "[]/"
19 changes: 14 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,14 @@ Increments the `patch` level.

## How to configure

`sbot` supports a configuration file. It looks for a `.semverbot.toml` file in the current working directory by default.
`sbot` supports a configuration file. It looks in the current working directory by default.

Supported default paths:
- `.semverbot.toml`
- `.sbot.toml`
- `.semverbot/config.toml`
- `.sbot/config.toml`

`.json` and `.yaml` formats are not officially supported, but might work. Using `.toml` is highly recommended.

### Defaults
Expand Down Expand Up @@ -157,7 +164,7 @@ major = ["release"]
delimiters = "/"

[modes.git-commit]
delimiters = "[]"
delimiters = "[]/"
```

## Configuration properties
Expand Down Expand Up @@ -224,7 +231,9 @@ A string of delimiters which are used to split a git commit message.
e.g. delimiters `"[]"` will split `[feature] some-feature` into `["feature", " some-feature"]`,
and the `feature` and ` some-feature` strings will be matched against semver map values.

Defaults to `"[]"` due to its popular use in git commit messages.
Defaults to `"[]/"` due to their popular use in git commit messages. The "/" character is often used in pull request
commit messages on GitHub, GitLab and Bitbucket. If somehow the branch name recognition
fails, the merge commit message is used as backup.

## Examples

Expand Down Expand Up @@ -284,7 +293,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
-

- name: set up path
run: |
mkdir bin
Expand All @@ -307,7 +316,7 @@ jobs:
echo "current version: ${current_version}"
echo "next version: ${release_version}"
... build / publish ...
# ... build / publish ...

- name: release version
run: |
Expand Down
2 changes: 1 addition & 1 deletion internal/constants.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ const (
DefaultGitBranchDelimiters = "/"

// DefaultGitCommitDelimiters the default delimiters used by the git-commit mode.
DefaultGitCommitDelimiters = "[]"
DefaultGitCommitDelimiters = "[]/"

// DefaultGitTagsPrefix the default prefix prepended to git tags.
DefaultGitTagsPrefix = "v"
Expand Down
6 changes: 0 additions & 6 deletions internal/ldflags/definitions.go

This file was deleted.

7 changes: 7 additions & 0 deletions internal/ldflags/x.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package ldflags

// -X key=value ldflags definitions, injected at build time.
var (
// Version The release version of the sbot binary.
Version string = "dev"
)
57 changes: 38 additions & 19 deletions pkg/cli/commands/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ package commands
import (
"errors"
"os"
"path/filepath"
"strings"

"github.com/rs/zerolog"
Expand All @@ -13,6 +12,7 @@ import (

"github.com/restechnica/semverbot/pkg/cli"
v1 "github.com/restechnica/semverbot/pkg/cli/commands/v1"
"github.com/restechnica/semverbot/pkg/ext/viperx"
"github.com/restechnica/semverbot/pkg/git"
"github.com/restechnica/semverbot/pkg/semver"
)
Expand Down Expand Up @@ -49,19 +49,18 @@ func NewRootCommand() *cobra.Command {
// RootCommandPersistentPreRunE runs before the command and any subcommand runs.
// Returns an error if it failed.
func RootCommandPersistentPreRunE(cmd *cobra.Command, args []string) (err error) {
// silence usage and errors because errors at this point are unrelated to CLI usage errors
cmd.SilenceErrors = true
// silence usage output on error because errors at this point are unrelated to CLI usage
cmd.SilenceUsage = true

ConfigureLogging()

log.Debug().Str("command", "root").Msg("starting pre-run...")

log.Debug().Msg("loading default config...")
log.Debug().Msg("loading default config values...")

LoadDefaultConfig()
LoadDefaultConfigValues()

if err = LoadConfig(); err != nil {
if err = LoadConfigFile(cmd); err != nil {
return err
}

Expand All @@ -75,6 +74,9 @@ func RootCommandPersistentPreRunE(cmd *cobra.Command, args []string) (err error)
return err
}

// silence errors which at this point are unrelated to CLI (cobra/viper) errors
cmd.SilenceErrors = false

return err
}

Expand All @@ -94,27 +96,44 @@ func SetLogLevel() {
}
}

// LoadConfig loads the SemverBot configuration file.
// Returns an error if it fails.
func LoadConfig() (err error) {
viper.AddConfigPath(filepath.Dir(cli.ConfigFlag))
viper.SetConfigName(strings.TrimSuffix(filepath.Base(cli.ConfigFlag), filepath.Ext(cli.ConfigFlag)))
viper.SetConfigType(strings.Split(filepath.Ext(cli.ConfigFlag), ".")[1])
// LoadConfigFile loads the SemverBot configuration file.
// If the config flag was used, it will try to load only that path.
// If the config flag was not used, multiple default config file paths will be tried.
// Returns no error if config files are not found, returns an error if it fails otherwise.
func LoadConfigFile(cmd *cobra.Command) (err error) {
configFlag := cmd.Flag("config")

if configFlag.Changed {
if err = viperx.LoadConfig(cli.ConfigFlag); err != nil {
if errors.As(err, &viper.ConfigFileNotFoundError{}) {
log.Warn().Msgf("config file %s not found", cli.ConfigFlag)
return nil
}
}

return err
}

log.Debug().Str("path", cli.ConfigFlag).Msg("loading config...")
paths := append([]string{cli.DefaultConfigFilePath}, cli.DefaultAdditionalConfigFilePaths...)

if err = viper.ReadInConfig(); err != nil {
if errors.As(err, &viper.ConfigFileNotFoundError{}) {
log.Warn().Msg("config file not found")
return nil
for _, path := range paths {
if err = viperx.LoadConfig(path); err == nil {
return err
}

if !errors.As(err, &viper.ConfigFileNotFoundError{}) {
return err
}

err = nil
log.Warn().Msgf("config file %s not found", path)
}

return err
}

// LoadDefaultConfig loads the default SemverBot config.
func LoadDefaultConfig() {
// LoadDefaultConfigValues loads the default SemverBot config.
func LoadDefaultConfigValues() {
viper.SetDefault(cli.GitTagsPrefixConfigKey, cli.DefaultGitTagsPrefix)
viper.SetDefault(cli.ModeConfigKey, cli.DefaultMode)
viper.SetDefault(cli.ModesGitBranchDelimitersConfigKey, cli.DefaultGitBranchDelimiters)
Expand Down
4 changes: 3 additions & 1 deletion pkg/cli/defaults.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@ import (
)

var (
// DefaultAdditionalConfigFilePaths additional default relative filepaths to the config file.
DefaultAdditionalConfigFilePaths = []string{".sbot.toml", ".semverbot/config.toml", ".sbot/config.toml"}

// DefaultConfigFilePath the default relative filepath to the config file.
DefaultConfigFilePath = internal.DefaultConfigFilePath

Expand Down Expand Up @@ -50,7 +53,6 @@ delimiters = "%s"
[modes.git-commit]
delimiters = "%s"
`

return fmt.Sprintf(
Expand Down
21 changes: 21 additions & 0 deletions pkg/ext/viperx/viper.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package viperx

import (
"path/filepath"
"strings"

"github.com/rs/zerolog/log"
"github.com/spf13/viper"
)

// LoadConfig loads a configuration file.
// Returns an error if it fails.
func LoadConfig(path string) (err error) {
viper.AddConfigPath(filepath.Dir(path))
viper.SetConfigName(strings.TrimSuffix(filepath.Base(path), filepath.Ext(path)))
viper.SetConfigType(strings.Split(filepath.Ext(path), ".")[1])

log.Debug().Str("path", path).Msg("loading config file...")

return viper.ReadInConfig()
}

0 comments on commit fa39cf7

Please sign in to comment.