Skip to content

Commit 36f752c

Browse files
authored
Merge pull request #20 from m7medVision/copilot/fix-18
Add environment variable support for API keys
2 parents 7b0ba98 + 9d39546 commit 36f752c

File tree

3 files changed

+121
-3
lines changed

3 files changed

+121
-3
lines changed

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ providers:
6060
api_key: "your-openai-api-key"
6161
model: "gpt-4o"
6262
openrouter:
63-
api_key: "your-openrouter-api-key"
63+
api_key: "$env-your-openrouter-api-key"
6464
model: "anthropic/claude-3-opus"
6565
copilot:
6666
# No API key needed, it uses the GitHub CLI token
@@ -105,4 +105,4 @@ go build -o lazycommit main.go
105105

106106
## License
107107

108-
MIT
108+
MIT

internal/config/config.go

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,19 @@ func GetAPIKey() (string, error) {
100100
return "", fmt.Errorf("API key for provider '%s' is not set", cfg.ActiveProvider)
101101
}
102102

103-
return providerConfig.APIKey, nil
103+
apiKey := providerConfig.APIKey
104+
105+
// Check if the API key is an environment variable reference
106+
if strings.HasPrefix(apiKey, "$") {
107+
envVarName := strings.TrimPrefix(apiKey, "$")
108+
envValue := os.Getenv(envVarName)
109+
if envValue == "" {
110+
return "", fmt.Errorf("environment variable '%s' for provider '%s' is not set or empty", envVarName, cfg.ActiveProvider)
111+
}
112+
return envValue, nil
113+
}
114+
115+
return apiKey, nil
104116
}
105117

106118
// GetModel returns the model for the active provider.

internal/config/config_test.go

Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
package config
2+
3+
import (
4+
"os"
5+
"testing"
6+
7+
"github.com/spf13/viper"
8+
)
9+
10+
func TestGetAPIKey_EnvironmentVariable(t *testing.T) {
11+
// Reset configuration for clean test
12+
cfg = nil
13+
viper.Reset()
14+
15+
// Set up test environment variable
16+
testEnvVar := "TEST_API_KEY"
17+
testAPIKey := "test-api-key-value-123"
18+
os.Setenv(testEnvVar, testAPIKey)
19+
defer os.Unsetenv(testEnvVar)
20+
21+
// Initialize config
22+
InitConfig()
23+
24+
// Set up test provider with environment variable reference
25+
testProvider := "openrouter"
26+
cfg.ActiveProvider = testProvider
27+
if cfg.Providers == nil {
28+
cfg.Providers = make(map[string]ProviderConfig)
29+
}
30+
cfg.Providers[testProvider] = ProviderConfig{
31+
APIKey: "$" + testEnvVar,
32+
Model: "test-model",
33+
}
34+
35+
// Test that environment variable is resolved
36+
resolvedKey, err := GetAPIKey()
37+
if err != nil {
38+
t.Fatalf("Expected no error, got: %v", err)
39+
}
40+
41+
if resolvedKey != testAPIKey {
42+
t.Errorf("Expected resolved API key to be %s, got %s", testAPIKey, resolvedKey)
43+
}
44+
}
45+
46+
func TestGetAPIKey_EnvironmentVariableNotSet(t *testing.T) {
47+
// Reset configuration for clean test
48+
cfg = nil
49+
viper.Reset()
50+
51+
// Initialize config
52+
InitConfig()
53+
54+
// Set up test provider with environment variable reference that doesn't exist
55+
testProvider := "openrouter"
56+
cfg.ActiveProvider = testProvider
57+
if cfg.Providers == nil {
58+
cfg.Providers = make(map[string]ProviderConfig)
59+
}
60+
cfg.Providers[testProvider] = ProviderConfig{
61+
APIKey: "$NONEXISTENT_API_KEY",
62+
Model: "test-model",
63+
}
64+
65+
// Test that missing environment variable returns error
66+
_, err := GetAPIKey()
67+
if err == nil {
68+
t.Fatal("Expected error for missing environment variable, got nil")
69+
}
70+
71+
expectedError := "environment variable 'NONEXISTENT_API_KEY' for provider 'openrouter' is not set or empty"
72+
if err.Error() != expectedError {
73+
t.Errorf("Expected error message '%s', got '%s'", expectedError, err.Error())
74+
}
75+
}
76+
77+
func TestGetAPIKey_RegularAPIKey(t *testing.T) {
78+
// Reset configuration for clean test
79+
cfg = nil
80+
viper.Reset()
81+
82+
// Initialize config
83+
InitConfig()
84+
85+
// Set up test provider with regular API key (not environment variable)
86+
testProvider := "openrouter"
87+
testAPIKey := "regular-api-key-123"
88+
cfg.ActiveProvider = testProvider
89+
if cfg.Providers == nil {
90+
cfg.Providers = make(map[string]ProviderConfig)
91+
}
92+
cfg.Providers[testProvider] = ProviderConfig{
93+
APIKey: testAPIKey,
94+
Model: "test-model",
95+
}
96+
97+
// Test that regular API key is returned as-is
98+
resolvedKey, err := GetAPIKey()
99+
if err != nil {
100+
t.Fatalf("Expected no error, got: %v", err)
101+
}
102+
103+
if resolvedKey != testAPIKey {
104+
t.Errorf("Expected API key to be %s, got %s", testAPIKey, resolvedKey)
105+
}
106+
}

0 commit comments

Comments
 (0)