cli/pkg/devops/config.go
Snider e081869ba2 feat(devops): migrate filesystem operations to io.Local abstraction
Migrate config.go:
- os.ReadFile → io.Local.Read

Migrate devops.go:
- os.Stat → io.Local.IsFile

Migrate images.go:
- os.MkdirAll → io.Local.EnsureDir
- os.Stat → io.Local.IsFile
- os.ReadFile → io.Local.Read
- os.WriteFile → io.Local.Write

Migrate test.go:
- os.ReadFile → io.Local.Read
- os.Stat → io.Local.IsFile

Migrate claude.go:
- os.Stat → io.Local.IsDir

Updated tests to reflect improved behavior:
- Manifest.Save() now creates parent directories
- hasFile() correctly returns false for directories

Part of #101 (io.Medium migration tracking issue).

Closes #107

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-02 05:00:10 +00:00

87 lines
2 KiB
Go

package devops
import (
"os"
"path/filepath"
"github.com/host-uk/core/pkg/io"
"gopkg.in/yaml.v3"
)
// Config holds global devops configuration from ~/.core/config.yaml.
type Config struct {
Version int `yaml:"version"`
Images ImagesConfig `yaml:"images"`
}
// ImagesConfig holds image source configuration.
type ImagesConfig struct {
Source string `yaml:"source"` // auto, github, registry, cdn
GitHub GitHubConfig `yaml:"github,omitempty"`
Registry RegistryConfig `yaml:"registry,omitempty"`
CDN CDNConfig `yaml:"cdn,omitempty"`
}
// GitHubConfig holds GitHub Releases configuration.
type GitHubConfig struct {
Repo string `yaml:"repo"` // owner/repo format
}
// RegistryConfig holds container registry configuration.
type RegistryConfig struct {
Image string `yaml:"image"` // e.g., ghcr.io/host-uk/core-devops
}
// CDNConfig holds CDN/S3 configuration.
type CDNConfig struct {
URL string `yaml:"url"` // base URL for downloads
}
// DefaultConfig returns sensible defaults.
func DefaultConfig() *Config {
return &Config{
Version: 1,
Images: ImagesConfig{
Source: "auto",
GitHub: GitHubConfig{
Repo: "host-uk/core-images",
},
Registry: RegistryConfig{
Image: "ghcr.io/host-uk/core-devops",
},
},
}
}
// ConfigPath returns the path to the config file.
func ConfigPath() (string, error) {
home, err := os.UserHomeDir()
if err != nil {
return "", err
}
return filepath.Join(home, ".core", "config.yaml"), nil
}
// LoadConfig loads configuration from ~/.core/config.yaml.
// Returns default config if file doesn't exist.
func LoadConfig() (*Config, error) {
configPath, err := ConfigPath()
if err != nil {
return DefaultConfig(), nil
}
content, err := io.Local.Read(configPath)
if err != nil {
if os.IsNotExist(err) {
return DefaultConfig(), nil
}
return nil, err
}
cfg := DefaultConfig()
if err := yaml.Unmarshal([]byte(content), cfg); err != nil {
return nil, err
}
return cfg, nil
}