github.com/harryzcy/snuuze@v0.3.3-0.20240314015559-83a8fc5627a8/config/hosting.go (about) 1 package config 2 3 import ( 4 "bytes" 5 "fmt" 6 "os" 7 "reflect" 8 "strconv" 9 "unicode" 10 11 "github.com/harryzcy/snuuze/types" 12 "github.com/spf13/viper" 13 ) 14 15 var ( 16 ConfigFile = defaultValue(os.Getenv("SNUUZE_CONFIG_FILE"), "config.yaml") 17 18 hostingConfig types.HostingConfig 19 ) 20 21 // LoadConfig loads the configuration for the application 22 func LoadHostingConfig() error { 23 c := viper.New() 24 c.SetConfigFile(ConfigFile) 25 c.SetEnvPrefix("SNUUZE") 26 c.AddConfigPath(".") 27 c.AddConfigPath(".github") 28 err := c.ReadInConfig() 29 if err != nil { 30 return fmt.Errorf("fatal error config file: %w", err) 31 } 32 33 err = c.Unmarshal(&hostingConfig) 34 if err != nil { 35 return fmt.Errorf("unable to decode into struct, %w", err) 36 } 37 38 loadEnvs(c) 39 40 return nil 41 } 42 43 func loadEnvs(c *viper.Viper) { 44 v := reflect.ValueOf(&hostingConfig).Elem() 45 loadEnv(c, "", v) 46 } 47 48 func loadEnv(c *viper.Viper, parent string, v reflect.Value) { 49 t := v.Type() 50 for i := 0; i < t.NumField(); i++ { 51 field := v.Field(i) 52 53 name := t.Field(i).Tag.Get("yaml") 54 if parent != "" { 55 name = parent + "." + name 56 } 57 58 if field.Type().Kind() == reflect.Struct { 59 loadEnv(c, name, field) 60 continue 61 } 62 63 envName := "SNUUZE_" + toEnvName(name) 64 value := os.Getenv(envName) 65 if value == "" { 66 continue 67 } 68 69 if field.IsValid() && field.CanSet() { 70 fmt.Println(76, field.Kind()) 71 switch field.Kind() { 72 case reflect.String: 73 field.SetString(value) 74 case reflect.Bool: 75 isTrue, err := strconv.ParseBool(value) 76 if err != nil { 77 panic(err) 78 } 79 field.SetBool(isTrue) 80 case reflect.Int, reflect.Int64: 81 if value != "" { 82 intValue, err := strconv.ParseInt(value, 10, 64) 83 if err != nil { 84 panic(err) 85 } 86 if !field.OverflowInt(intValue) { 87 field.SetInt(intValue) 88 } 89 } 90 default: 91 panic("unsupported type") 92 } 93 } 94 } 95 } 96 97 func toEnvName(name string) string { 98 if len(name) == 0 { 99 return "" 100 } 101 102 var buf bytes.Buffer 103 buf.WriteRune(unicode.ToUpper(rune(name[0]))) 104 105 previousLower := name[0] >= 'a' && name[0] <= 'z' 106 for _, r := range name[1:] { 107 if r == '.' { 108 buf.WriteRune('_') 109 previousLower = false 110 continue 111 } 112 113 if r >= 'A' && r <= 'Z' { 114 if previousLower { 115 buf.WriteRune('_') 116 } 117 } 118 119 buf.WriteRune(unicode.ToUpper(r)) 120 previousLower = r >= 'a' && r <= 'z' 121 } 122 return buf.String() 123 } 124 125 func GetHostingConfig() types.HostingConfig { 126 return hostingConfig 127 } 128 129 // TempDir returns the temporary directory to store the data 130 func TempDir() string { 131 return defaultValue(hostingConfig.Data.TempDir, os.TempDir()) 132 } 133 134 func GitHubToken() string { 135 return defaultValue(hostingConfig.GitHub.Token, os.Getenv("GITHUB_TOKEN")) 136 } 137 138 func GoPath() string { 139 return os.Getenv("GOPATH") 140 } 141 142 func GoProxy() string { 143 return defaultValue(os.Getenv("GOPROXY"), "https://proxy.golang.org,direct") 144 } 145 146 func defaultValue[T comparable](value, defaultValue T) T { 147 if value == *new(T) { 148 return defaultValue 149 } 150 151 return value 152 }