Files
Ryan 0557635008 feat: add Docker deployment and application configuration
Add package declarations across the Go scaffold, YAML configuration loading and validation, and a minimal API entry point.

Add development and production Compose files, a multi-stage Docker image, configuration template, and Make targets. Remove the directory scaffolding script.
2026-09-17 11:38:47 +03:30

85 lines
1.9 KiB
Go

package app
import (
"errors"
"fmt"
"os"
"strings"
"gopkg.in/yaml.v3"
)
const defaultConfigPath = "configs/config.example.yaml"
// Config contains the settings required to start the application.
type Config struct {
Environment string `yaml:"environment"`
HTTP HTTPConfig `yaml:"http"`
Database DatabaseConfig `yaml:"database"`
}
type HTTPConfig struct {
Address string `yaml:"address"`
}
type DatabaseConfig struct {
URL string `yaml:"url"`
}
// LoadConfig reads configuration from YAML, applies environment overrides,
// and validates the result. An empty path uses CONFIG_FILE when set.
func LoadConfig(path string) (Config, error) {
if path == "" {
path = os.Getenv("CONFIG_FILE")
}
if path == "" {
path = defaultConfigPath
}
contents, err := os.ReadFile(path)
if err != nil {
return Config{}, fmt.Errorf("read config %q: %w", path, err)
}
var config Config
if err := yaml.Unmarshal(contents, &config); err != nil {
return Config{}, fmt.Errorf("parse config %q: %w", path, err)
}
applyEnvironment(&config)
if err := config.Validate(); err != nil {
return Config{}, fmt.Errorf("validate config: %w", err)
}
return config, nil
}
func (config Config) Validate() error {
var missing []string
if strings.TrimSpace(config.Environment) == "" {
missing = append(missing, "environment")
}
if strings.TrimSpace(config.HTTP.Address) == "" {
missing = append(missing, "http.address")
}
if strings.TrimSpace(config.Database.URL) == "" {
missing = append(missing, "database.url")
}
if len(missing) > 0 {
return errors.New("missing required values: " + strings.Join(missing, ", "))
}
return nil
}
func applyEnvironment(config *Config) {
if value := os.Getenv("APP_ENVIRONMENT"); value != "" {
config.Environment = value
}
if value := os.Getenv("APP_HTTP_ADDRESS"); value != "" {
config.HTTP.Address = value
}
if value := os.Getenv("APP_DATABASE_URL"); value != "" {
config.Database.URL = value
}
}