mirror of
https://github.com/ivuorinen/gh-action-readme.git
synced 2026-01-26 03:04:10 +00:00
* feat: ignore vendored directories * chore: cr tweaks * fix: sonarcloud detected issues * fix: sonarcloud detected issues
124 lines
4.4 KiB
Go
124 lines
4.4 KiB
Go
package internal
|
|
|
|
import (
|
|
"fmt"
|
|
"os"
|
|
"path/filepath"
|
|
"strings"
|
|
|
|
"github.com/adrg/xdg"
|
|
"github.com/spf13/viper"
|
|
|
|
"github.com/ivuorinen/gh-action-readme/appconstants"
|
|
)
|
|
|
|
// initializeViperInstance creates and configures a new viper instance with standard settings.
|
|
// This includes XDG-compliant configuration paths, environment variable support,
|
|
// and standard search paths for configuration files.
|
|
func initializeViperInstance() (*viper.Viper, error) {
|
|
v := viper.New()
|
|
|
|
// Set configuration file name and type
|
|
v.SetConfigName(appconstants.ConfigFileName)
|
|
v.SetConfigType(appconstants.OutputFormatYAML)
|
|
|
|
// Add XDG-compliant configuration directory
|
|
configDir, err := xdg.ConfigFile(appconstants.PathXDGConfig)
|
|
if err != nil {
|
|
return nil, fmt.Errorf(appconstants.ErrFailedToGetXDGConfigDir, err)
|
|
}
|
|
v.AddConfigPath(filepath.Dir(configDir))
|
|
|
|
// Add additional search paths
|
|
v.AddConfigPath(".") // current directory
|
|
|
|
// Expand home directory for fallback config path
|
|
if home, err := os.UserHomeDir(); err == nil {
|
|
v.AddConfigPath(filepath.Join(home, ".config", appconstants.AppName)) // fallback
|
|
}
|
|
|
|
v.AddConfigPath(appconstants.PathEtcConfig) // system-wide
|
|
|
|
// Set environment variable prefix
|
|
v.SetEnvPrefix(appconstants.EnvPrefix)
|
|
v.SetEnvKeyReplacer(strings.NewReplacer("-", "_", ".", "_"))
|
|
v.AutomaticEnv()
|
|
|
|
return v, nil
|
|
}
|
|
|
|
// setConfigDefaults sets all default configuration values in the viper instance.
|
|
// This ensures consistent default values across all configuration loading scenarios.
|
|
func setConfigDefaults(v *viper.Viper, defaults *AppConfig) {
|
|
v.SetDefault(appconstants.ConfigKeyOrganization, defaults.Organization)
|
|
v.SetDefault(appconstants.ConfigKeyRepository, defaults.Repository)
|
|
v.SetDefault(appconstants.ConfigKeyVersion, defaults.Version)
|
|
v.SetDefault(appconstants.ConfigKeyTheme, defaults.Theme)
|
|
v.SetDefault(appconstants.ConfigKeyOutputFormat, defaults.OutputFormat)
|
|
v.SetDefault(appconstants.ConfigKeyOutputDir, defaults.OutputDir)
|
|
v.SetDefault(appconstants.ConfigKeyTemplate, defaults.Template)
|
|
v.SetDefault(appconstants.ConfigKeyHeader, defaults.Header)
|
|
v.SetDefault(appconstants.ConfigKeyFooter, defaults.Footer)
|
|
v.SetDefault(appconstants.ConfigKeySchema, defaults.Schema)
|
|
v.SetDefault(appconstants.ConfigKeyAnalyzeDependencies, defaults.AnalyzeDependencies)
|
|
v.SetDefault(appconstants.ConfigKeyShowSecurityInfo, defaults.ShowSecurityInfo)
|
|
v.SetDefault(appconstants.ConfigKeyVerbose, defaults.Verbose)
|
|
v.SetDefault(appconstants.ConfigKeyQuiet, defaults.Quiet)
|
|
v.SetDefault(appconstants.ConfigKeyIgnoredDirectories, defaults.IgnoredDirectories)
|
|
v.SetDefault(appconstants.ConfigKeyDefaultsName, defaults.Defaults.Name)
|
|
v.SetDefault(appconstants.ConfigKeyDefaultsDescription, defaults.Defaults.Description)
|
|
v.SetDefault(appconstants.ConfigKeyDefaultsBrandingIcon, defaults.Defaults.Branding.Icon)
|
|
v.SetDefault(appconstants.ConfigKeyDefaultsBrandingColor, defaults.Defaults.Branding.Color)
|
|
}
|
|
|
|
// loadConfigFromViper loads an AppConfig from a specified YAML config file using viper.
|
|
func loadConfigFromViper(configPath string) (*AppConfig, error) {
|
|
v := viper.New()
|
|
v.SetConfigFile(configPath)
|
|
v.SetConfigType(appconstants.OutputFormatYAML)
|
|
|
|
if err := v.ReadInConfig(); err != nil {
|
|
return nil, fmt.Errorf("failed to read config %s: %w", configPath, err)
|
|
}
|
|
|
|
var config AppConfig
|
|
if err := v.Unmarshal(&config); err != nil {
|
|
return nil, fmt.Errorf(appconstants.ErrFailedToUnmarshalConfig, err)
|
|
}
|
|
|
|
return &config, nil
|
|
}
|
|
|
|
// loadAndUnmarshalConfig initializes viper with defaults, reads config file,
|
|
// and unmarshals into AppConfig with proper error handling.
|
|
// Returns *AppConfig with resolved template paths.
|
|
func loadAndUnmarshalConfig(configFile string, v *viper.Viper) (*AppConfig, error) {
|
|
// Set defaults
|
|
defaults := DefaultAppConfig()
|
|
setConfigDefaults(v, defaults)
|
|
|
|
// Use specific config file if provided
|
|
if configFile != "" {
|
|
v.SetConfigFile(configFile)
|
|
}
|
|
|
|
// Read configuration
|
|
if err := v.ReadInConfig(); err != nil {
|
|
if _, ok := err.(viper.ConfigFileNotFoundError); !ok {
|
|
return nil, fmt.Errorf(appconstants.ErrFailedToReadConfigFile, err)
|
|
}
|
|
// Config file not found is not an error - we'll use defaults and env vars
|
|
}
|
|
|
|
// Unmarshal configuration into struct
|
|
var config AppConfig
|
|
if err := v.Unmarshal(&config); err != nil {
|
|
return nil, fmt.Errorf(appconstants.ErrFailedToUnmarshalConfig, err)
|
|
}
|
|
|
|
// Resolve template paths relative to binary if they're not absolute
|
|
resolveAllTemplatePaths(&config)
|
|
|
|
return &config, nil
|
|
}
|