docs: add releasing process documentation

chore: update go.mod dependencies and versions

chore: update go.sum with new dependency versions

scripts: add coverage check script

scripts: add release notes generation script

test: refactor tests to use goconvey for assertions

test: enhance webserver tests with additional cases and goconvey

fix: improve error logging in web server start and stop methods
This commit is contained in:
2026-03-29 20:47:30 +02:00
parent d5660ba8ca
commit 9b0d844ec3
11 changed files with 794 additions and 206 deletions
+45 -21
View File
@@ -1,9 +1,7 @@
package config
import (
"errors"
"fmt"
"io/ioutil"
"os"
"os/user"
"path/filepath"
@@ -16,7 +14,10 @@ import (
func GetConfigurationFiles(appName string) []string {
// First checking local config
executablePath, _ := os.Executable()
executablePath, executableErr := os.Executable()
if executableErr != nil {
executablePath = os.Args[0]
}
fname := filepath.Base(executablePath)
fext := filepath.Ext(executablePath)
fdir := filepath.Dir(executablePath)
@@ -26,8 +27,11 @@ func GetConfigurationFiles(appName string) []string {
for _, ext := range ymlExts {
fileNames = append(fileNames, filepath.Join(fdir, fnameWoExt+ext))
}
usr, _ := user.Current()
fileNames = append(fileNames, filepath.Join(usr.HomeDir, "."+appName, "config"))
homeDir := "."
if usr, userErr := user.Current(); userErr == nil {
homeDir = usr.HomeDir
}
fileNames = append(fileNames, filepath.Join(homeDir, "."+appName, "config"))
// Check for global config
fileNames = append(fileNames, util.GetGlobalConfigurationFile(appName, "config"))
return fileNames
@@ -48,6 +52,33 @@ func LoadConfiguration[T any](config T) error {
return LoadConfigurationFromFile(config, "")
}
func resolveConfigFile[T any](config T, configFile string) (string, error) {
if configFile != "" {
if !util.FileExists(configFile) {
return "", fmt.Errorf("given configuration file %s cannot be found", configFile)
}
return configFile, nil
}
appName := getAppNameFromConfig(config)
if appName == "" {
return "", nil
}
return GetConfigurationFile(appName), nil
}
func getAppNameFromConfig[T any](config T) string {
method := reflect.ValueOf(config).MethodByName("AppName")
if !method.IsValid() {
return ""
}
results := method.Call(nil)
if len(results) == 0 {
return ""
}
return results[0].String()
}
func IsStructPointer[T any](config T) bool {
value := reflect.ValueOf(config)
return value.Type().Kind() == reflect.Pointer && reflect.Indirect(value).Type().Kind() == reflect.Struct
@@ -56,32 +87,25 @@ func IsStructPointer[T any](config T) bool {
func LoadConfigurationFromFile[T any](config T, configFile string) error {
if !IsStructPointer(config) {
genericType := reflect.TypeOf(config)
return errors.New(fmt.Sprintf("Type: %s.%s is not a struct pointer", genericType.PkgPath(), genericType.Name()))
return fmt.Errorf("type: %s.%s is not a struct pointer", genericType.PkgPath(), genericType.Name())
}
defaults.Set(config)
if configFile != "" {
if !util.FileExists(configFile) {
return errors.New(fmt.Sprintf("given configuration file %s cannot be found", configFile))
}
} else {
if method := reflect.ValueOf(config).MethodByName("appName"); !method.IsNil() {
result := method.String()
if result != "" {
configFile = GetConfigurationFile(result)
}
}
resolvedConfigFile, err := resolveConfigFile(config, configFile)
if err != nil {
return err
}
if configFile == "" {
if resolvedConfigFile == "" {
return nil
}
ymldata, err := ioutil.ReadFile(configFile)
ymldata, err := os.ReadFile(resolvedConfigFile)
if err != nil {
return errors.New(fmt.Sprintf("cannot read configuration file %s. %v", configFile, err))
return fmt.Errorf("cannot read configuration file %s: %w", resolvedConfigFile, err)
}
err = yaml.Unmarshal(ymldata, config)
if err != nil {
return errors.New(fmt.Sprintf("error unmarshalling configuration data: %v", err))
return fmt.Errorf("error unmarshalling configuration data: %w", err)
}
return nil
}