freeleaps-ops/apps/gitea-webhook-ambassador/internal/config/config.go
zhenyus db590f3f27 refactor: update gitea-webhook-ambassador Dockerfile and configuration
- Changed the build process to include a web UI build stage using Node.js.
- Updated Go build stage to copy web UI files to the correct location.
- Removed the main.go file as it is no longer needed.
- Added SQLite database configuration to example config.
- Updated dependencies in go.mod and go.sum, including new packages for JWT and SQLite.
- Modified .gitignore to include new database and configuration files.

Signed-off-by: zhenyus <zhenyus@mathmast.com>
2025-06-10 16:00:52 +08:00

147 lines
3.8 KiB
Go

package config
import (
"fmt"
"os"
"sync"
"freeleaps.com/gitea-webhook-ambassador/internal/logger"
"github.com/go-playground/validator/v10"
"gopkg.in/yaml.v2"
)
// Configuration holds application configuration
type Configuration struct {
Server struct {
Port int `yaml:"port" validate:"required,gt=0"`
WebhookPath string `yaml:"webhookPath" validate:"required"`
SecretHeader string `yaml:"secretHeader" default:"Authorization"`
SecretKey string `yaml:"secretKey"`
} `yaml:"server"`
Jenkins struct {
URL string `yaml:"url" validate:"required,url"`
Username string `yaml:"username"`
Token string `yaml:"token"`
Timeout int `yaml:"timeout" default:"30"`
} `yaml:"jenkins"`
Database struct {
Path string `yaml:"path" validate:"required"` // Path to SQLite database file
} `yaml:"database"`
Logging struct {
Level string `yaml:"level" default:"info" validate:"oneof=debug info warn error"`
Format string `yaml:"format" default:"text" validate:"oneof=text json"`
File string `yaml:"file"`
} `yaml:"logging"`
Worker struct {
PoolSize int `yaml:"poolSize" default:"10" validate:"gt=0"`
QueueSize int `yaml:"queueSize" default:"100" validate:"gt=0"`
MaxRetries int `yaml:"maxRetries" default:"3" validate:"gte=0"`
RetryBackoff int `yaml:"retryBackoff" default:"1" validate:"gt=0"`
} `yaml:"worker"`
EventCleanup struct {
Interval int `yaml:"interval" default:"3600"`
ExpireAfter int `yaml:"expireAfter" default:"7200"`
} `yaml:"eventCleanup"`
}
// ProjectConfig represents the configuration for a specific repository
type ProjectConfig struct {
DefaultJob string `yaml:"defaultJob"`
BranchJobs map[string]string `yaml:"branchJobs,omitempty"`
BranchPatterns []BranchPattern `yaml:"branchPatterns,omitempty"`
}
// BranchPattern defines a pattern-based branch to job mapping
type BranchPattern struct {
Pattern string `yaml:"pattern"`
Job string `yaml:"job"`
}
var (
config Configuration
configMutex sync.RWMutex
validate = validator.New()
)
// Load reads and parses the configuration file
func Load(file string) error {
logger.Debug("Loading configuration from file: %s", file)
f, err := os.Open(file)
if err != nil {
return fmt.Errorf("cannot open config file: %v", err)
}
defer f.Close()
var newConfig Configuration
decoder := yaml.NewDecoder(f)
if err := decoder.Decode(&newConfig); err != nil {
return fmt.Errorf("cannot decode config: %v", err)
}
setDefaults(&newConfig)
if err := validate.Struct(newConfig); err != nil {
return fmt.Errorf("invalid configuration: %v", err)
}
logger.Debug("Configuration loaded successfully - Server.SecretKey length: %d", len(newConfig.Server.SecretKey))
configMutex.Lock()
config = newConfig
configMutex.Unlock()
return nil
}
// Get returns a copy of the current configuration
func Get() Configuration {
configMutex.RLock()
defer configMutex.RUnlock()
return config
}
// Update atomically updates the configuration
func Update(newConfig Configuration) {
configMutex.Lock()
config = newConfig
configMutex.Unlock()
}
func setDefaults(config *Configuration) {
if config.Server.SecretHeader == "" {
config.Server.SecretHeader = "X-Gitea-Signature"
}
if config.Jenkins.Timeout == 0 {
config.Jenkins.Timeout = 30
}
if config.Worker.PoolSize == 0 {
config.Worker.PoolSize = 10
}
if config.Worker.QueueSize == 0 {
config.Worker.QueueSize = 100
}
if config.Worker.MaxRetries == 0 {
config.Worker.MaxRetries = 3
}
if config.Worker.RetryBackoff == 0 {
config.Worker.RetryBackoff = 1
}
if config.EventCleanup.Interval == 0 {
config.EventCleanup.Interval = 3600
}
if config.EventCleanup.ExpireAfter == 0 {
config.EventCleanup.ExpireAfter = 7200
}
if config.Logging.Level == "" {
config.Logging.Level = "info"
}
if config.Logging.Format == "" {
config.Logging.Format = "text"
}
}