Skip to content

Commit 61739ea

Browse files
committed
refactor(config): update and standardize configuration keys
- rename and clarify git and LLM config keys for consistency - adjust default values for timeouts and concurrency - update version handling to use structured metadata - modify test cases to reflect new config key names - improve error handling and parsing for duration values Signed-off-by: kovacs <mritd@linux.com>
1 parent c903721 commit 61739ea

12 files changed

Lines changed: 141 additions & 67 deletions

File tree

README.md

Lines changed: 17 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -110,23 +110,23 @@ All settings are configured via `~/.gitconfig` under the `[gitflow]` section.
110110
llm-api-key = sk-or-v1-xxxxx
111111

112112
# LLM settings
113-
llm-host = https://openrouter.ai
113+
llm-api-host = https://openrouter.ai
114114
llm-model = mistralai/devstral-2512:free
115115
llm-temperature = 0.3
116-
llm-context = 5
117-
llm-timeout = 120
118-
llm-retries = 0
119-
llm-lang = en
120-
llm-concurrency = 5
116+
llm-diff-context = 5
117+
llm-request-timeout = 2m
118+
llm-max-retries = 0
119+
llm-output-lang = en
120+
llm-max-concurrency = 3
121121

122122
# Custom prompts (optional, language-specific)
123-
llm-file-prompt = "Summarize this diff briefly."
123+
llm-file-analysis-prompt = "Summarize this diff briefly."
124124
llm-commit-prompt-en = "Your custom English commit prompt."
125125
llm-commit-prompt-zh = "Your custom Chinese commit prompt."
126126
llm-commit-prompt-bilingual = "Your custom bilingual commit prompt."
127127

128128
# Lucky commit prefix (hex characters, max 12)
129-
lucky-commit = abc
129+
lucky-commit-prefix = abc
130130

131131
# SSH strict host key checking (default: false)
132132
ssh-strict-host-key = false
@@ -137,19 +137,19 @@ All settings are configured via `~/.gitconfig` under the `[gitflow]` section.
137137
| Key | Description | Default |
138138
|-----|-------------|---------|
139139
| `llm-api-key` | API key for cloud LLM providers | - |
140-
| `llm-host` | LLM API endpoint | see below |
140+
| `llm-api-host` | LLM API endpoint | see below |
141141
| `llm-model` | LLM model name | see below |
142142
| `llm-temperature` | Model temperature | `0.3` |
143-
| `llm-context` | Diff context lines | `5` |
144-
| `llm-timeout` | Request timeout (seconds) | `120` |
145-
| `llm-retries` | Retry count on failure | `0` |
146-
| `llm-lang` | Output language (`en`, `zh`, `bilingual`) | `en` |
147-
| `llm-concurrency` | Parallel file analysis limit | `5` |
148-
| `llm-file-prompt` | Custom file analysis prompt | - |
143+
| `llm-diff-context` | Diff context lines | `5` |
144+
| `llm-request-timeout` | Request timeout (Go duration, e.g., `2m`, `30s`) | `2m` |
145+
| `llm-max-retries` | Max retry count on failure | `0` |
146+
| `llm-output-lang` | Output language (`en`, `zh`, `bilingual`) | `en` |
147+
| `llm-max-concurrency` | Max parallel file analysis | `3` |
148+
| `llm-file-analysis-prompt` | Custom file analysis prompt | - |
149149
| `llm-commit-prompt-en` | Custom English commit prompt | - |
150150
| `llm-commit-prompt-zh` | Custom Chinese commit prompt | - |
151151
| `llm-commit-prompt-bilingual` | Custom bilingual commit prompt | - |
152-
| `lucky-commit` | Lucky commit hex prefix (max 12 chars) | - |
152+
| `lucky-commit-prefix` | Lucky commit hex prefix (max 12 chars) | - |
153153
| `ssh-strict-host-key` | SSH strict host key checking | `false` |
154154

155155
### Auto Generate (AI)
@@ -198,7 +198,7 @@ Generate commit hashes with a specific prefix using [lucky_commit](https://githu
198198
cargo install lucky_commit
199199

200200
# Set the desired prefix (hex characters, max 12)
201-
git config --global gitflow.lucky-commit abc
201+
git config --global gitflow.lucky-commit-prefix abc
202202

203203
# Commit as usual - hash will start with "abc"
204204
git ci

Taskfile.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ vars:
44
VERSION:
55
sh: git symbolic-ref -q --short HEAD || git describe --tags --exact-match 2>/dev/null || echo "dev"
66
BUILD_COMMIT:
7-
sh: git rev-parse --short HEAD 2>/dev/null || echo "unknown"
7+
sh: git rev-parse HEAD 2>/dev/null || echo "unknown"
88
BUILD_DATE:
99
sh: date "+%F %T"
1010

cmd/root.go

Lines changed: 64 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,26 @@ package cmd
44
import (
55
"fmt"
66
"os"
7+
"strings"
78

9+
"github.com/charmbracelet/lipgloss"
810
"github.com/spf13/cobra"
911

1012
"github.com/mritd/gitflow-toolkit/v3/internal/ui/common"
1113
)
1214

13-
var version = "dev"
15+
// VersionInfo holds version information for display.
16+
type VersionInfo struct {
17+
Version string
18+
Commit string
19+
BuildDate string
20+
GoVersion string
21+
Platform string
22+
}
23+
24+
var versionInfo = VersionInfo{
25+
Version: "dev",
26+
}
1427

1528
// rootCmd represents the base command when called without any subcommands.
1629
var rootCmd = &cobra.Command{
@@ -38,7 +51,6 @@ Available commit types:
3851
chore - Changing CI/CD
3952
perf - Improving performance
4053
hotfix - Bug fix urgently`,
41-
Version: version,
4254
}
4355

4456
// Execute adds all child commands to the root command and sets flags appropriately.
@@ -62,8 +74,54 @@ func init() {
6274
rootCmd.CompletionOptions.DisableDefaultCmd = true
6375
}
6476

65-
// SetVersion sets the version string.
66-
func SetVersion(v string) {
67-
version = v
68-
rootCmd.Version = v
77+
// SetVersionInfo sets the version information.
78+
func SetVersionInfo(info VersionInfo) {
79+
versionInfo = info
80+
rootCmd.Version = info.Version
81+
// Set custom version template after version info is populated
82+
rootCmd.SetVersionTemplate(renderVersion())
83+
}
84+
85+
// renderVersion renders a styled version output.
86+
func renderVersion() string {
87+
var sb strings.Builder
88+
89+
// Title style
90+
titleStyle := lipgloss.NewStyle().
91+
Foreground(common.ColorTitleFg).
92+
Background(common.ColorTitleBg).
93+
Bold(true).
94+
Padding(0, 1)
95+
96+
// Label style (width includes space after colon)
97+
labelStyle := lipgloss.NewStyle().
98+
Foreground(common.ColorMuted).
99+
Width(14)
100+
101+
// Value style
102+
valueStyle := lipgloss.NewStyle().
103+
Foreground(common.ColorSuccess)
104+
105+
// Commit style (dimmer for long hash)
106+
commitStyle := lipgloss.NewStyle().
107+
Foreground(common.ColorMuted)
108+
109+
// Layout
110+
titleLayout := lipgloss.NewStyle().Padding(1, 0, 0, 2)
111+
contentLayout := lipgloss.NewStyle().PaddingLeft(2)
112+
113+
sb.WriteString(titleLayout.Render(titleStyle.Render("gitflow-toolkit")))
114+
sb.WriteString("\n\n")
115+
116+
// Version info rows
117+
sb.WriteString(contentLayout.Render(labelStyle.Render("Version:") + valueStyle.Render(versionInfo.Version)))
118+
sb.WriteString("\n")
119+
sb.WriteString(contentLayout.Render(labelStyle.Render("Built:") + valueStyle.Render(versionInfo.BuildDate)))
120+
sb.WriteString("\n")
121+
sb.WriteString(contentLayout.Render(labelStyle.Render("Go Version:") + valueStyle.Render(versionInfo.GoVersion)))
122+
sb.WriteString("\n")
123+
sb.WriteString(contentLayout.Render(labelStyle.Render("Commit Hash:") + commitStyle.Render(versionInfo.Commit)))
124+
sb.WriteString("\n\n")
125+
126+
return sb.String()
69127
}

config/gitconfig.go

Lines changed: 21 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import (
55
"runtime"
66
"strconv"
77
"strings"
8+
"time"
89
)
910

1011
// GitConfigSection name for gitflow-toolkit settings.
@@ -13,20 +14,20 @@ const GitConfigSection = "gitflow"
1314
// GitConfig keys.
1415
const (
1516
GitConfigLLMAPIKey = "llm-api-key"
16-
GitConfigLLMHost = "llm-host"
17+
GitConfigLLMAPIHost = "llm-api-host"
1718
GitConfigLLMModel = "llm-model"
1819
GitConfigLLMTemperature = "llm-temperature"
19-
GitConfigLLMTimeout = "llm-timeout"
20-
GitConfigLLMRetries = "llm-retries"
21-
GitConfigLLMLang = "llm-lang"
22-
GitConfigLLMContext = "llm-context"
23-
GitConfigLLMConcurrency = "llm-concurrency"
24-
GitConfigLLMFilePrompt = "llm-file-prompt"
20+
GitConfigLLMRequestTimeout = "llm-request-timeout"
21+
GitConfigLLMMaxRetries = "llm-max-retries"
22+
GitConfigLLMOutputLang = "llm-output-lang"
23+
GitConfigLLMDiffContext = "llm-diff-context"
24+
GitConfigLLMMaxConcurrency = "llm-max-concurrency"
25+
GitConfigLLMFileAnalysisPrompt = "llm-file-analysis-prompt"
2526
GitConfigLLMCommitPromptEN = "llm-commit-prompt-en"
2627
GitConfigLLMCommitPromptZH = "llm-commit-prompt-zh"
2728
GitConfigLLMCommitPromptBilingual = "llm-commit-prompt-bilingual"
28-
GitConfigLuckyCommit = "lucky-commit"
29-
GitConfigSSHStrictHost = "ssh-strict-host-key"
29+
GitConfigLuckyCommitPrefix = "lucky-commit-prefix"
30+
GitConfigSSHStrictHostKey = "ssh-strict-host-key"
3031
)
3132

3233
// gitConfig runs git config --get and returns the value.
@@ -80,3 +81,14 @@ func GetBool(gitKey string, defaultVal bool) bool {
8081
}
8182
return defaultVal
8283
}
84+
85+
// GetDuration returns a time.Duration config value from gitconfig, or default if not set.
86+
// Supports Go duration format (e.g., "30s", "2m", "1h30m").
87+
func GetDuration(gitKey string, defaultVal time.Duration) time.Duration {
88+
if val := gitConfig(gitKey); val != "" {
89+
if d, err := time.ParseDuration(val); err == nil {
90+
return d
91+
}
92+
}
93+
return defaultVal
94+
}

consts/consts.go

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
// Package consts defines constants for gitflow-toolkit.
22
package consts
33

4+
import "time"
5+
46
// Commit types following Angular commit message specification.
57
const (
68
Feat = "feat"
@@ -55,12 +57,12 @@ const (
5557
const (
5658
LLMDefaultOllamaHost = "http://localhost:11434"
5759
LLMDefaultOpenRouterHost = "https://openrouter.ai"
58-
LLMDefaultContext = 5
59-
LLMDefaultTimeout = 120
60+
LLMDefaultDiffContext = 5
61+
LLMDefaultRequestTimeout = 2 * time.Minute
6062
LLMDefaultRetries = 0
6163
LLMDefaultLang = "en"
6264
LLMDefaultTemperature = 0.3
63-
LLMDefaultConcurrency = 5
65+
LLMDefaultConcurrency = 3
6466
)
6567

6668
// LLM language options.

internal/git/git.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ func Run(args ...string) (string, error) {
3030
}
3131

3232
// Disable strict host key checking unless explicitly enabled via gitconfig
33-
if !config.GetBool(config.GitConfigSSHStrictHost, false) {
33+
if !config.GetBool(config.GitConfigSSHStrictHostKey, false) {
3434
cmd.Env = append(os.Environ(), "GIT_SSH_COMMAND=ssh -o StrictHostKeyChecking=no")
3535
}
3636

internal/git/lucky.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ var (
2121
// GetLuckyPrefix returns the lucky commit prefix from gitconfig.
2222
// Returns empty string if not set.
2323
func GetLuckyPrefix() string {
24-
return config.GetString(config.GitConfigLuckyCommit, "")
24+
return config.GetString(config.GitConfigLuckyCommitPrefix, "")
2525
}
2626

2727
// ValidateLuckyPrefix validates and normalizes the prefix.

internal/git/lucky_test.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ func TestValidateLuckyPrefix(t *testing.T) {
2323
{"exactly 12 chars", "1234567890ab", "1234567890ab", false},
2424
{"invalid chars", "xyz123", "", true},
2525
{"invalid with space", "abc 123", "", true},
26-
{"valid all zeros", "0000000000000000", "0000000000000000", false},
26+
{"valid all zeros", "000000000000", "000000000000", false},
2727
}
2828

2929
for _, tt := range tests {
@@ -65,7 +65,7 @@ func TestCheckLuckyCommit(t *testing.T) {
6565
func TestGetLuckyPrefix(t *testing.T) {
6666
// NOTE: GetLuckyPrefix reads from gitconfig, which cannot be easily mocked.
6767
// Skip if gitconfig has lucky-commit set.
68-
if prefix := config.GetString(config.GitConfigLuckyCommit, ""); prefix != "" {
68+
if prefix := config.GetString(config.GitConfigLuckyCommitPrefix, ""); prefix != "" {
6969
t.Skip("Skipping: gitconfig has lucky-commit set")
7070
}
7171

internal/llm/client.go

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ func NewClient() *Client {
7878
}
7979

8080
// Get host
81-
host := config.GetString(config.GitConfigLLMHost, "")
81+
host := config.GetString(config.GitConfigLLMAPIHost, "")
8282
if host == "" {
8383
host = defaultHost
8484
} else {
@@ -98,12 +98,12 @@ func NewClient() *Client {
9898
model := config.GetString(config.GitConfigLLMModel, defaultModel)
9999

100100
// Get other settings
101-
timeout := config.GetInt(config.GitConfigLLMTimeout, consts.LLMDefaultTimeout)
102-
retries := config.GetInt(config.GitConfigLLMRetries, consts.LLMDefaultRetries)
101+
timeout := config.GetDuration(config.GitConfigLLMRequestTimeout, consts.LLMDefaultRequestTimeout)
102+
retries := config.GetInt(config.GitConfigLLMMaxRetries, consts.LLMDefaultRetries)
103103
temperature := config.GetFloat(config.GitConfigLLMTemperature, consts.LLMDefaultTemperature)
104104

105105
// Get language (validate value)
106-
lang := config.GetString(config.GitConfigLLMLang, consts.LLMDefaultLang)
106+
lang := config.GetString(config.GitConfigLLMOutputLang, consts.LLMDefaultLang)
107107
switch lang {
108108
case consts.LLMLangEN, consts.LLMLangZH, consts.LLMLangBilingual:
109109
// valid
@@ -112,7 +112,7 @@ func NewClient() *Client {
112112
}
113113

114114
// Get custom prompts
115-
filePrompt := config.GetString(config.GitConfigLLMFilePrompt, "")
115+
filePrompt := config.GetString(config.GitConfigLLMFileAnalysisPrompt, "")
116116
commitPromptEN := config.GetString(config.GitConfigLLMCommitPromptEN, "")
117117
commitPromptZH := config.GetString(config.GitConfigLLMCommitPromptZH, "")
118118
commitPromptBilingual := config.GetString(config.GitConfigLLMCommitPromptBilingual, "")
@@ -121,7 +121,7 @@ func NewClient() *Client {
121121
provider: provider,
122122
host: host,
123123
apiKey: apiKey,
124-
timeout: time.Duration(timeout) * time.Second,
124+
timeout: timeout,
125125
retries: retries,
126126
lang: lang,
127127
model: model,
@@ -368,12 +368,12 @@ func (c *Client) GetCommitPrompt(lang string) string {
368368
}
369369
}
370370

371-
// GetContext returns the configured diff context lines.
372-
func GetContext() int {
373-
return config.GetInt(config.GitConfigLLMContext, consts.LLMDefaultContext)
371+
// GetDiffContext returns the configured diff context lines.
372+
func GetDiffContext() int {
373+
return config.GetInt(config.GitConfigLLMDiffContext, consts.LLMDefaultDiffContext)
374374
}
375375

376376
// GetConcurrency returns the configured concurrency limit for parallel file analysis.
377377
func GetConcurrency() int {
378-
return config.GetInt(config.GitConfigLLMConcurrency, consts.LLMDefaultConcurrency)
378+
return config.GetInt(config.GitConfigLLMMaxConcurrency, consts.LLMDefaultConcurrency)
379379
}

internal/llm/client_test.go

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,8 @@ import (
88
"testing"
99
"time"
1010

11-
"github.com/mritd/gitflow-toolkit/v3/consts"
1211
"github.com/mritd/gitflow-toolkit/v3/config"
12+
"github.com/mritd/gitflow-toolkit/v3/consts"
1313
)
1414

1515
func TestNormalizeHost(t *testing.T) {
@@ -43,7 +43,7 @@ func TestNewClient_Defaults(t *testing.T) {
4343
// Skip if any gitconfig LLM settings are set.
4444
if config.GetString(config.GitConfigLLMAPIKey, "") != "" ||
4545
config.GetString(config.GitConfigLLMModel, "") != "" ||
46-
config.GetString(config.GitConfigLLMHost, "") != "" {
46+
config.GetString(config.GitConfigLLMAPIHost, "") != "" {
4747
t.Skip("Skipping: gitconfig has LLM settings")
4848
}
4949

@@ -58,8 +58,8 @@ func TestNewClient_Defaults(t *testing.T) {
5858
if c.model != consts.LLMDefaultOllamaModel {
5959
t.Errorf("model = %q, want %q", c.model, consts.LLMDefaultOllamaModel)
6060
}
61-
if c.timeout != time.Duration(consts.LLMDefaultTimeout)*time.Second {
62-
t.Errorf("timeout = %v, want %v", c.timeout, time.Duration(consts.LLMDefaultTimeout)*time.Second)
61+
if c.timeout != consts.LLMDefaultRequestTimeout {
62+
t.Errorf("timeout = %v, want %v", c.timeout, consts.LLMDefaultRequestTimeout)
6363
}
6464
})
6565
}
@@ -213,15 +213,15 @@ func TestGenerate_OpenAI(t *testing.T) {
213213
})
214214
}
215215

216-
func TestGetContext(t *testing.T) {
216+
func TestGetDiffContext(t *testing.T) {
217217
// NOTE: This test may be affected by ~/.gitconfig settings.
218-
if ctx := config.GetString(config.GitConfigLLMContext, ""); ctx != "" {
219-
t.Skip("Skipping: gitconfig has llm-context set")
218+
if ctx := config.GetString(config.GitConfigLLMDiffContext, ""); ctx != "" {
219+
t.Skip("Skipping: gitconfig has llm-diff-context set")
220220
}
221221

222222
t.Run("default", func(t *testing.T) {
223-
if got := GetContext(); got != consts.LLMDefaultContext {
224-
t.Errorf("GetContext() = %d, want %d", got, consts.LLMDefaultContext)
223+
if got := GetDiffContext(); got != consts.LLMDefaultDiffContext {
224+
t.Errorf("GetDiffContext() = %d, want %d", got, consts.LLMDefaultDiffContext)
225225
}
226226
})
227227
}

0 commit comments

Comments
 (0)