diff --git a/CHANGELOG.md b/CHANGELOG.md index c343549..51c0f13 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +* [PR-8](https://github.com/rimi-itk/gh-itkdev/pull/8) + Added Viper * [PR-7](https://github.com/rimi-itk/gh-itkdev/pull/7) Fixed URL parsing diff --git a/README.md b/README.md index f191731..ee4779b 100644 --- a/README.md +++ b/README.md @@ -25,7 +25,7 @@ gh extension install . ## Usage -### `changelog` +### `gh itkdev changelog` Manage changelog based on [keep a changelog](https://keepachangelog.com/en/1.1.0/): @@ -36,21 +36,43 @@ gh itkdev changelog --help Create changelog: ```shell -gh itkdev changelog --create +gh itkdev changelog create ``` -Update changelog for a pull request: +Add pull request to changelog: ```shell -gh itkdev changelog --fucking-changelog +gh itkdev changelog add-pull-request ``` -Update changelog for a release (`«tag»`): +Prepare a new release: ```shell -gh itkdev changelog --release «tag» +gh itkdev changelog add-release «tag» ``` +## Configuration + +Default option values can be set in `.gh-itkdev.yaml` in the project folder or in `$HOME`. + +``` yaml +changelog: + «sub command»: + «option»: «value» +``` + +### Example + +Set the default branch for `add-release` to `main`: + +``` yaml +changelog: + add-release: + base: main +``` + +Use `gh itkdev config` to dump the current config. + ## Development ``` shell diff --git a/changelog/fuckingchangelog.go b/changelog/add_pull_request.go similarity index 93% rename from changelog/fuckingchangelog.go rename to changelog/add_pull_request.go index 5b7283c..c9934c0 100644 --- a/changelog/fuckingchangelog.go +++ b/changelog/add_pull_request.go @@ -58,7 +58,7 @@ func addPullRequest(changelog string, pr pullRequest, itemTemplate string) (stri return strings.Join(lines, "\n") + "\n", nil } -func FuckingChangelog(name string, itemTemplate string) { +func AddPullRequest(name string, entryTemplate string) { b, err := os.ReadFile(name) if err != nil { log.Fatal(err) @@ -74,7 +74,7 @@ func FuckingChangelog(name string, itemTemplate string) { log.Fatalf("error getting pull request: %s\n", err) } - updatedChangelog, err := addPullRequest(changelog, pr, itemTemplate) + updatedChangelog, err := addPullRequest(changelog, pr, entryTemplate) if err != nil { log.Fatalf("error adding pull request: %s\n", err) } diff --git a/changelog/fuckingchangelog_test.go b/changelog/add_pull_request_test.go similarity index 98% rename from changelog/fuckingchangelog_test.go rename to changelog/add_pull_request_test.go index 7b767c2..e942eed 100644 --- a/changelog/fuckingchangelog_test.go +++ b/changelog/add_pull_request_test.go @@ -6,7 +6,7 @@ import ( "github.com/stretchr/testify/assert" ) -func TestFuckingChangelog(t *testing.T) { +func TestAddPullRequest(t *testing.T) { defaultItemTemplate := `* [PR-{{ .Number }}]({{ .Url }}) {{ .Title }}` testCases := []struct { diff --git a/changelog/release.go b/changelog/add_release.go similarity index 98% rename from changelog/release.go rename to changelog/add_release.go index 9769ba5..f5d0df6 100644 --- a/changelog/release.go +++ b/changelog/add_release.go @@ -111,7 +111,7 @@ func updateReleaseChangelog(changelog string, release string) (string, error) { return strings.Join(lines, "\n") + "\n", nil } -func Release(release string, base string, name string, commit bool) { +func AddRelease(release string, base string, name string, commit bool) { b, err := os.ReadFile(name) if err != nil { log.Fatal(err) diff --git a/changelog/release_test.go b/changelog/add_release_test.go similarity index 98% rename from changelog/release_test.go rename to changelog/add_release_test.go index 758c6ae..31a0b78 100644 --- a/changelog/release_test.go +++ b/changelog/add_release_test.go @@ -8,7 +8,7 @@ import ( "github.com/stretchr/testify/assert" ) -func TestRelease(t *testing.T) { +func TestAddRelease(t *testing.T) { testCases := []struct { changelog string release string diff --git a/cmd/changelog.go b/cmd/changelog.go deleted file mode 100644 index f7dbb87..0000000 --- a/cmd/changelog.go +++ /dev/null @@ -1,54 +0,0 @@ -package cmd - -import ( - "fmt" - - "github.com/rimi-itk/gh-itkdev/changelog" - "github.com/spf13/cobra" -) - -// changelogCmd represents the changelog command -var ( - create bool - - fuckingChangelog bool - pullRequestItemTemplate string = `* [PR-{{ .Number }}]({{ .Url }}) - {{ .Title }}` - - release string - baseBranch string = "develop" - commit bool = false - - changelogName string = "CHANGELOG.md" - - changelogCmd = &cobra.Command{ - Use: "changelog", - Short: "Update changelog", - Run: func(cmd *cobra.Command, args []string) { - if create { - changelog.Create(changelogName) - } else if fuckingChangelog { - changelog.FuckingChangelog(changelogName, pullRequestItemTemplate) - } else if release != "" { - changelog.Release(release, baseBranch, changelogName, commit) - } else { - cmd.Usage() - } - }, - } -) - -func init() { - rootCmd.AddCommand(changelogCmd) - - changelogCmd.Flags().BoolVarP(&create, "create", "", false, fmt.Sprintf("create a changelog (%q) if it does not exist", changelogName)) - - changelogCmd.Flags().BoolVarP(&fuckingChangelog, "fucking-changelog", "", false, "add missing pull request entry to changelog") - changelogCmd.Flags().StringVarP(&pullRequestItemTemplate, "item-template", "", pullRequestItemTemplate, "pull request item template") - - changelogCmd.Flags().StringVarP(&release, "release", "", "", "create a release branch with updated changelog") - changelogCmd.Flags().StringVarP(&baseBranch, "base", "", baseBranch, "base branch for release") - changelogCmd.Flags().BoolVarP(&commit, "commit", "", commit, "commit changes") - - changelogCmd.Flags().StringVarP(&changelogName, "changelog", "", changelogName, "changelog name") -} diff --git a/cmd/changelog/add_pull_request.go b/cmd/changelog/add_pull_request.go new file mode 100644 index 0000000..91e19b1 --- /dev/null +++ b/cmd/changelog/add_pull_request.go @@ -0,0 +1,37 @@ +/* +Copyright © 2024 NAME HERE +*/ +package changelog + +import ( + "log" + + "github.com/rimi-itk/gh-itkdev/changelog" + "github.com/spf13/cobra" + "github.com/spf13/viper" +) + +var ( + entryTemplate = `* [PR-{{ .Number }}]({{ .Url }}) + {{ .Title }}` + addPullRequestCmd = &cobra.Command{ + Use: "add-pull-request", + Short: "Add missing pull request entry to changelog", + Run: func(cmd *cobra.Command, args []string) { + log.Printf("\n\nadd-pull-request: viper: %q\nentryTemplate: %q\n\n", viper.AllSettings(), entryTemplate) + log.Println(viper.GetString("changelog.add-pull-request.entry-template")) + changelog.AddPullRequest(changelogName, entryTemplate) + }, + } +) + +func init() { + log.Println("add-pull-request") + + viperPrefix := "changelog.add-pull-request." + flagName := "entry-template" + addPullRequestCmd.Flags().StringVarP(&entryTemplate, flagName, "", entryTemplate, "pull request entry template") + viper.BindPFlag(viperPrefix+flagName, addPullRequestCmd.Flags().Lookup(flagName)) + + ChangelogCmd.AddCommand(addPullRequestCmd) +} diff --git a/cmd/changelog/add_release.go b/cmd/changelog/add_release.go new file mode 100644 index 0000000..3619e3e --- /dev/null +++ b/cmd/changelog/add_release.go @@ -0,0 +1,47 @@ +/* +Copyright © 2024 NAME HERE +*/ +package changelog + +import ( + "github.com/rimi-itk/gh-itkdev/changelog" + "github.com/spf13/cobra" + "github.com/spf13/viper" +) + +// createCmd represents the create command +var ( + base = "develop" + commit = false + + addReleaseCmd = &cobra.Command{ + Use: "add-release", + Short: "Create a release branch and update the changelog", + Long: `Create a release branch named release/«release» and update the changelog as per https://keepachangelog.com/en/1.1.0/ + +Examples: + +gh itkdev changelog add-release 0.1.0 +gh itkdev changelog add-release v0.1.0 +`, + Args: cobra.ExactArgs(1), + Run: func(cmd *cobra.Command, args []string) { + release := args[0] + + changelog.AddRelease(release, base, changelogName, commit) + }, + } +) + +func init() { + viperPrefix := "changelog.add-release." + flagName := "base" + addReleaseCmd.Flags().StringVarP(&base, flagName, "", base, "base branch for release") + viper.BindPFlag(viperPrefix+flagName, addReleaseCmd.Flags().Lookup(flagName)) + + flagName = "commit" + addReleaseCmd.Flags().BoolVarP(&commit, flagName, "", commit, "commit changes") + viper.BindPFlag(viperPrefix+flagName, addReleaseCmd.Flags().Lookup(flagName)) + + ChangelogCmd.AddCommand(addReleaseCmd) +} diff --git a/cmd/changelog/changelog.go b/cmd/changelog/changelog.go new file mode 100644 index 0000000..695c880 --- /dev/null +++ b/cmd/changelog/changelog.go @@ -0,0 +1,19 @@ +package changelog + +import ( + "github.com/spf13/cobra" + "github.com/spf13/viper" +) + +var ( + changelogName = "CHANGELOG.md" + ChangelogCmd = &cobra.Command{ + Use: "changelog", + Short: "Update changelog", + } +) + +func init() { + ChangelogCmd.PersistentFlags().StringVarP(&changelogName, "changelog", "", changelogName, "changelog name") + viper.BindPFlag("changelog.changelog", ChangelogCmd.PersistentFlags().Lookup("changelog")) +} diff --git a/cmd/changelog/create.go b/cmd/changelog/create.go new file mode 100644 index 0000000..b92a761 --- /dev/null +++ b/cmd/changelog/create.go @@ -0,0 +1,23 @@ +/* +Copyright © 2024 NAME HERE +*/ +package changelog + +import ( + "github.com/rimi-itk/gh-itkdev/changelog" + "github.com/spf13/cobra" +) + +// createCmd represents the create command +var createCmd = &cobra.Command{ + Use: "create", + Short: "Create a changelog if it does not exist", + Long: `Create a changelog if it does not exist. The changelog will used the format defined by https://keepachangelog.com/en/1.1.0/.`, + Run: func(cmd *cobra.Command, args []string) { + changelog.Create(changelogName) + }, +} + +func init() { + ChangelogCmd.AddCommand(createCmd) +} diff --git a/cmd/config.go b/cmd/config.go new file mode 100644 index 0000000..364e94b --- /dev/null +++ b/cmd/config.go @@ -0,0 +1,27 @@ +/* +Copyright © 2024 NAME HERE +*/ +package cmd + +import ( + "fmt" + "log" + + "github.com/spf13/cobra" + "github.com/spf13/viper" + + "gopkg.in/yaml.v2" +) + +var configCmd = &cobra.Command{ + Use: "config", + Short: "Show active config", + Run: func(cmd *cobra.Command, args []string) { + yaml, err := yaml.Marshal(viper.AllSettings()) + if err != nil { + log.Fatal(err) + } + + fmt.Println(string(yaml)) + }, +} diff --git a/cmd/root.go b/cmd/root.go index 428b9ca..adc6188 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -1,9 +1,12 @@ package cmd import ( - "os" + "fmt" + "log" + "github.com/rimi-itk/gh-itkdev/cmd/changelog" "github.com/spf13/cobra" + "github.com/spf13/viper" ) // rootCmd represents the base command when called without any subcommands @@ -13,22 +16,31 @@ var rootCmd = &cobra.Command{ } // Execute adds all child commands to the root command and sets flags appropriately. -// This is called by main.main(). It only needs to happen once to the rootCmd. +// This is called by main.main(). It only needs to happen once to the RootCmd. func Execute() { err := rootCmd.Execute() - if err != nil { - os.Exit(1) - } + cobra.CheckErr(err) } func init() { - // Here you will define your flags and configuration settings. - // Cobra supports persistent flags, which, if defined here, - // will be global for your application. + cobra.OnInitialize(initConfig) + + rootCmd.AddCommand(changelog.ChangelogCmd) + rootCmd.AddCommand(configCmd) +} - // rootCmd.PersistentFlags().StringVar(&cfgFile, "config", "", "config file (default is $HOME/.gh-itkdev.yaml)") +func initConfig() { + viper.SetConfigName(".gh-itkdev") + viper.AddConfigPath(".") + viper.AddConfigPath("$HOME") - // Cobra also supports local flags, which will only run - // when this action is called directly. - rootCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle") + viper.AutomaticEnv() + + if err := viper.ReadInConfig(); err != nil { + if _, ok := err.(viper.ConfigFileNotFoundError); !ok { + log.Fatalf("Unable to read config file %s: %s\n", viper.ConfigFileUsed(), err) + } + } else { + fmt.Printf("Using config file %s\n", viper.ConfigFileUsed()) + } } diff --git a/go.mod b/go.mod index 9403c85..197119e 100644 --- a/go.mod +++ b/go.mod @@ -5,27 +5,44 @@ go 1.22 require ( github.com/cli/go-gh v1.2.1 github.com/spf13/cobra v1.8.0 + github.com/spf13/viper v1.18.2 github.com/stretchr/testify v1.9.0 + gopkg.in/yaml.v2 v2.4.0 ) require ( github.com/cli/safeexec v1.0.0 // indirect github.com/cli/shurcooL-graphql v0.0.2 // indirect - github.com/davecgh/go-spew v1.1.1 // indirect + github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect + github.com/fsnotify/fsnotify v1.7.0 // indirect + github.com/hashicorp/hcl v1.0.0 // indirect github.com/henvic/httpretty v0.0.6 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect - github.com/kr/pretty v0.3.1 // indirect github.com/lucasb-eyer/go-colorful v1.2.0 // indirect + github.com/magiconair/properties v1.8.7 // indirect github.com/mattn/go-isatty v0.0.17 // indirect github.com/mattn/go-runewidth v0.0.14 // indirect + github.com/mitchellh/mapstructure v1.5.0 // indirect github.com/muesli/termenv v0.12.0 // indirect - github.com/pmezard/go-difflib v1.0.0 // indirect + github.com/pelletier/go-toml/v2 v2.1.0 // indirect + github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect github.com/rivo/uniseg v0.4.4 // indirect github.com/rogpeppe/go-internal v1.10.0 // indirect + github.com/sagikazarmark/locafero v0.4.0 // indirect + github.com/sagikazarmark/slog-shim v0.1.0 // indirect + github.com/sourcegraph/conc v0.3.0 // indirect + github.com/spf13/afero v1.11.0 // indirect + github.com/spf13/cast v1.6.0 // indirect github.com/spf13/pflag v1.0.5 // indirect + github.com/subosito/gotenv v1.6.0 // indirect github.com/thlib/go-timezone-local v0.0.0-20210907160436-ef149e42d28e // indirect - golang.org/x/net v0.7.0 // indirect - golang.org/x/sys v0.5.0 // indirect - golang.org/x/term v0.5.0 // indirect + go.uber.org/atomic v1.9.0 // indirect + go.uber.org/multierr v1.9.0 // indirect + golang.org/x/exp v0.0.0-20230905200255-921286631fa9 // indirect + golang.org/x/net v0.19.0 // indirect + golang.org/x/sys v0.15.0 // indirect + golang.org/x/term v0.15.0 // indirect + golang.org/x/text v0.14.0 // indirect + gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/go.sum b/go.sum index 7545225..00198bf 100644 --- a/go.sum +++ b/go.sum @@ -7,11 +7,20 @@ github.com/cli/safeexec v1.0.0/go.mod h1:Z/D4tTN8Vs5gXYHDCbaM1S/anmEDnJb1iW0+EJ5 github.com/cli/shurcooL-graphql v0.0.2 h1:rwP5/qQQ2fM0TzkUTwtt6E2LbIYf6R+39cUXTa04NYk= github.com/cli/shurcooL-graphql v0.0.2/go.mod h1:tlrLmw/n5Q/+4qSvosT+9/W5zc8ZMjnJeYBxSdb4nWA= github.com/cpuguy83/go-md2man/v2 v2.0.3/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= -github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= -github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= +github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8= +github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0= +github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA= +github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM= +github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= +github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/h2non/parth v0.0.0-20190131123155-b4df798d6542 h1:2VTzZjLZBgl62/EtslCrtky5vbi9dd7HrQPQIx6wqiw= github.com/h2non/parth v0.0.0-20190131123155-b4df798d6542/go.mod h1:Ow0tF8D4Kplbc8s8sSb3V2oUCygFHVp8gC3Dn6U4MNI= +github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= +github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= github.com/henvic/httpretty v0.0.6 h1:JdzGzKZBajBfnvlMALXXMVQWxWMF/ofTy8C3/OSUTxs= github.com/henvic/httpretty v0.0.6/go.mod h1:X38wLjWXHkXT7r2+uK8LjCMne9rsuNaBLJ+5cU2/Pmo= github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= @@ -22,54 +31,93 @@ github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/lucasb-eyer/go-colorful v1.2.0 h1:1nnpGOrhyZZuNyfu1QjKiUICQ74+3FNCN69Aj6K7nkY= github.com/lucasb-eyer/go-colorful v1.2.0/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0= +github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY= +github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0= github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= github.com/mattn/go-isatty v0.0.17 h1:BTarxUcIeDqL27Mc+vyvdWYSL28zpIhv3RoTdsLMPng= github.com/mattn/go-isatty v0.0.17/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= github.com/mattn/go-runewidth v0.0.13/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= github.com/mattn/go-runewidth v0.0.14 h1:+xnbZSEeDbOIg5/mE6JF0w6n9duR1l3/WmbinWVwUuU= github.com/mattn/go-runewidth v0.0.14/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= +github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= +github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/muesli/reflow v0.3.0 h1:IFsN6K9NfGtjeggFP+68I4chLZV2yIKsXJFNZ+eWh6s= github.com/muesli/reflow v0.3.0/go.mod h1:pbwTDkVPibjO2kyvBQRBxTWEEGDGq0FlB1BIKtnHY/8= github.com/muesli/termenv v0.12.0 h1:KuQRUE3PgxRFWhq4gHvZtPSLCGDqM5q/cYr1pZ39ytc= github.com/muesli/termenv v0.12.0/go.mod h1:WCCv32tusQ/EEZ5S8oUIIrC/nIuBcxCVqlN4Xfkv+7A= -github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= -github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pelletier/go-toml/v2 v2.1.0 h1:FnwAJ4oYMvbT/34k9zzHuZNrhlz48GB3/s6at6/MHO4= +github.com/pelletier/go-toml/v2 v2.1.0/go.mod h1:tJU2Z3ZkXwnxa4DPO899bsyIoywizdUvyaeZurnPPDc= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= +github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= github.com/rivo/uniseg v0.4.4 h1:8TfxU8dW6PdqD27gjM8MVNuicgxIjxpm4K7x4jp8sis= github.com/rivo/uniseg v0.4.4/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= -github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ= github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/sagikazarmark/locafero v0.4.0 h1:HApY1R9zGo4DBgr7dqsTH/JJxLTTsOt7u6keLGt6kNQ= +github.com/sagikazarmark/locafero v0.4.0/go.mod h1:Pe1W6UlPYUk/+wc/6KFhbORCfqzgYEpgQ3O5fPuL3H4= +github.com/sagikazarmark/slog-shim v0.1.0 h1:diDBnUNK9N/354PgrxMywXnAwEr1QZcOr6gto+ugjYE= +github.com/sagikazarmark/slog-shim v0.1.0/go.mod h1:SrcSrq8aKtyuqEI1uvTDTK1arOWRIczQRv+GVI1AkeQ= +github.com/sourcegraph/conc v0.3.0 h1:OQTbbt6P72L20UqAkXXuLOj79LfEanQ+YQFNpLA9ySo= +github.com/sourcegraph/conc v0.3.0/go.mod h1:Sdozi7LEKbFPqYX2/J+iBAM6HpqSLTASQIKqDmF7Mt0= +github.com/spf13/afero v1.11.0 h1:WJQKhtpdm3v2IzqG8VMqrr6Rf3UYpEF239Jy9wNepM8= +github.com/spf13/afero v1.11.0/go.mod h1:GH9Y3pIexgf1MTIWtNGyogA5MwRIDXGUr+hbWNoBjkY= +github.com/spf13/cast v1.6.0 h1:GEiTHELF+vaR5dhz3VqZfFSzZjYbgeKDpBxQVS4GYJ0= +github.com/spf13/cast v1.6.0/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo= github.com/spf13/cobra v1.8.0 h1:7aJaZx1B85qltLMc546zn58BxxfZdR/W22ej9CFoEf0= github.com/spf13/cobra v1.8.0/go.mod h1:WXLWApfZ71AjXPya3WOlMsY9yMs7YeiHhFVlvLyhcho= github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= +github.com/spf13/viper v1.18.2 h1:LUXCnvUvSM6FXAsj6nnfc8Q2tp1dIgUfY9Kc8GsSOiQ= +github.com/spf13/viper v1.18.2/go.mod h1:EKmWIqdnk5lOcmR72yw6hS+8OPYcwD0jteitLMVB+yk= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= +github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= +github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= +github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8= +github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU= github.com/thlib/go-timezone-local v0.0.0-20210907160436-ef149e42d28e h1:BuzhfgfWQbX0dWzYzT1zsORLnHRv3bcRcsaUk0VmXA8= github.com/thlib/go-timezone-local v0.0.0-20210907160436-ef149e42d28e/go.mod h1:/Tnicc6m/lsJE0irFMA0LfIwTBo4QP7A8IfyIv4zZKI= +go.uber.org/atomic v1.9.0 h1:ECmE8Bn/WFTYwEW/bpKD3M8VtR/zQVbavAoalC1PYyE= +go.uber.org/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= +go.uber.org/multierr v1.9.0 h1:7fIwc/ZtS0q++VgcfqFDxSBZVv/Xo49/SYnDFupUwlI= +go.uber.org/multierr v1.9.0/go.mod h1:X2jQV1h+kxSjClGpnseKVIxpmcjrj7MNnI0bnlfKTVQ= +golang.org/x/exp v0.0.0-20230905200255-921286631fa9 h1:GoHiUyI/Tp2nVkLI2mCxVkOjsbSXD66ic0XW0js0R9g= +golang.org/x/exp v0.0.0-20230905200255-921286631fa9/go.mod h1:S2oDrQGGwySpoQPVqRShND87VCbxmc6bL1Yd2oYrm6k= golang.org/x/net v0.0.0-20220923203811-8be639271d50/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk= -golang.org/x/net v0.7.0 h1:rJrUqqhjsgNp7KqAIc25s9pZnjU7TUcSY7HcVZjdn1g= -golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= +golang.org/x/net v0.19.0 h1:zTwKpTd2XuCqf8huc7Fo2iSy+4RHPd10s4KzeTnVr1c= +golang.org/x/net v0.19.0/go.mod h1:CfAk/cbD4CthTvqiEl8NpboMuiuOYsAr/7NOjZJtv1U= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210831042530-f4d43177bf5e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220209214540-3681064d5158/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.5.0 h1:MUK/U/4lj1t1oPg0HfuXDN/Z1wv31ZJ/YcPiGccS4DU= -golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc= +golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= -golang.org/x/term v0.5.0 h1:n2a8QNdAb0sZNpU9R1ALUXBbY+w51fCQDN+7EdxNBsY= -golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= +golang.org/x/term v0.15.0 h1:y/Oo/a/q3IXu26lQgl04j/gjuBDOBlx7X6Om1j2CPW4= +golang.org/x/term v0.15.0/go.mod h1:BDl952bC7+uMoWR75FIrCDx79TPU9oHkTZ9yRbYOrX0= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= +golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= +golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY= -gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo= +gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/h2non/gock.v1 v1.1.2 h1:jBbHXgGBK/AoPVfJh5x4r/WxIrElvbLel8TCZkkZJoY= gopkg.in/h2non/gock.v1 v1.1.2/go.mod h1:n7UGz/ckNChHiK05rDoiC4MYSunEC/lyaUm2WWaDva0= +gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA= +gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= +gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= +gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=