mirror of
https://github.com/httprunner/httprunner.git
synced 2026-05-11 18:11:21 +08:00
- Add support for loading environment variables from ~/.hrp/.env - Implement priority order: current working directory > ~/.hrp/.env > system environment variables - Use godotenv.Overload() for both global and local .env files to ensure proper priority - Maintain backward compatibility with existing functionality - Add comprehensive error handling and logging
126 lines
3.0 KiB
Go
126 lines
3.0 KiB
Go
package config
|
|
|
|
import (
|
|
"encoding/json"
|
|
"os"
|
|
"path/filepath"
|
|
"strconv"
|
|
"sync"
|
|
|
|
"github.com/joho/godotenv"
|
|
"github.com/rs/zerolog/log"
|
|
)
|
|
|
|
var loadEnvOnce sync.Once
|
|
|
|
// LoadEnv loads environment variables from .env file
|
|
// it will search for .env file from current working directory upward recursively
|
|
// if not found, it will try to load from ~/.hrp/.env as fallback
|
|
// Priority: current working directory > ~/.hrp/.env > system environment variables
|
|
func LoadEnv() (err error) {
|
|
loadEnvOnce.Do(func() {
|
|
// first try to load from ~/.hrp/.env, override system env variables (medium priority)
|
|
var homeDir string
|
|
homeDir, err = os.UserHomeDir()
|
|
if err != nil {
|
|
log.Warn().Err(err).Msg("get user home directory failed")
|
|
} else {
|
|
globalEnvFile := filepath.Join(homeDir, ".hrp", ".env")
|
|
if _, e := os.Stat(globalEnvFile); e == nil {
|
|
// load global .env file and override system environment variables
|
|
err = godotenv.Overload(globalEnvFile)
|
|
if err != nil {
|
|
log.Error().Err(err).
|
|
Str("path", globalEnvFile).Msg("load global env file failed")
|
|
return
|
|
}
|
|
log.Info().Str("path", globalEnvFile).Msg("load global env success")
|
|
}
|
|
}
|
|
|
|
// get current working directory
|
|
var cwd string
|
|
cwd, err = os.Getwd()
|
|
if err != nil {
|
|
log.Error().Err(err).Msg("get current working directory failed")
|
|
return
|
|
}
|
|
|
|
// locate .env file from current working directory upward recursively
|
|
envPath := cwd
|
|
for {
|
|
envFile := filepath.Join(envPath, ".env")
|
|
if _, e := os.Stat(envFile); e == nil {
|
|
// found .env file
|
|
// override existing env variables (highest priority)
|
|
err = godotenv.Overload(envFile)
|
|
if err != nil {
|
|
log.Error().Err(err).
|
|
Str("path", envFile).Msg("overload env file failed")
|
|
return
|
|
}
|
|
log.Info().Str("path", envFile).Msg("overload env success")
|
|
return
|
|
}
|
|
|
|
// reached root directory
|
|
parent := filepath.Dir(envPath)
|
|
if parent == envPath {
|
|
log.Info().Msg("no .env file found from current directory to root")
|
|
return
|
|
}
|
|
envPath = parent
|
|
}
|
|
})
|
|
return err
|
|
}
|
|
|
|
func GetEnvConfig(key string) string {
|
|
return os.Getenv(key)
|
|
}
|
|
|
|
func GetEnvConfigInJSON(key string) (map[string]interface{}, error) {
|
|
value := GetEnvConfig(key)
|
|
if value == "" {
|
|
return nil, nil
|
|
}
|
|
|
|
var result map[string]interface{}
|
|
if err := json.Unmarshal([]byte(value), &result); err != nil {
|
|
return nil, err
|
|
}
|
|
return result, nil
|
|
}
|
|
|
|
func GetEnvConfigInBool(key string) bool {
|
|
value := GetEnvConfig(key)
|
|
if value == "" {
|
|
return false
|
|
}
|
|
|
|
boolValue, _ := strconv.ParseBool(value)
|
|
return boolValue
|
|
}
|
|
|
|
// GetEnvConfigOrDefault get env config or default value
|
|
func GetEnvConfigOrDefault(key, defaultValue string) string {
|
|
value := GetEnvConfig(key)
|
|
if value == "" {
|
|
return defaultValue
|
|
}
|
|
return value
|
|
}
|
|
|
|
func GetEnvConfigInInt(key string, defaultValue int) int {
|
|
value := GetEnvConfig(key)
|
|
if value == "" {
|
|
return defaultValue
|
|
}
|
|
|
|
intValue, err := strconv.Atoi(value)
|
|
if err != nil {
|
|
return defaultValue
|
|
}
|
|
return intValue
|
|
}
|