Go Installer Development
Development guide for the dotfiles-installer Go codebase.
Project Structure
installer/
├── main.go # Entry point (version injection)
├── cmd/ # CLI commands (Cobra)
│ ├── root.go # Root command, global setup
│ ├── install.go # Main installation workflow
│ ├── checkCompatibility.go # Compatibility check command
│ └── version.go # Version display
├── lib/ # Core business logic
│ ├── compatibility/ # OS/distro detection
│ ├── pkgmanager/ # Package manager interface
│ ├── brew/ # Homebrew implementation
│ ├── apt/ # APT implementation
│ ├── dnf/ # DNF implementation
│ ├── gpg/ # GPG key management
│ ├── shell/ # Shell installation
│ ├── dotfilesmanager/ # Chezmoi integration
│ └── packageresolver/ # Package name resolution
├── utils/ # Shared utilities
│ ├── logger/ # Logging with progress display
│ ├── osmanager/ # OS operations interface
│ ├── privilege/ # Sudo/doas escalation
│ ├── commander.go # Command execution
│ ├── filesystem.go # File operations
│ └── httpclient/ # HTTP client interface
├── cli/ # Interactive UI components
├── internal/config/ # Embedded YAML configs
├── Taskfile.yml # Task runner commands
└── .goreleaser.yaml # Release configuration
Key Interfaces
Commander (utils/commander.go)
Execute system commands with functional options:
result, err := commander.RunCommand(ctx, "brew", []string{"install", pkg},
WithCaptureOutput(),
WithEnv(env),
WithTimeout(5 * time.Minute),
)
Available options: WithEnv(), WithDir(), WithInput(), WithCaptureOutput(), WithDiscardOutput(), WithInteractive(), WithTimeout(), WithStdout(), WithStderr()
Logger (utils/logger/)
Logging with progress tracking:
logger.StartProgress("Installing packages")
logger.UpdateProgress("Installing git")
logger.FinishProgress()
// or
logger.FailProgress(err)
Methods: Trace, Debug, Info, Success, Warning, Error
FileSystem (utils/filesystem.go)
File operations interface for testability:
exists, err := fs.PathExists(path)
data, err := fs.ReadFile(path)
err = fs.WriteFile(path, data, 0644)
err = fs.CreateDirectory(path)
OsManager (utils/osmanager/)
OS-level operations (user management, environment, program queries, permissions).
Privilege Escalator (utils/privilege/)
Smart privilege escalation (prefers sudo, falls back to doas):
escalatedCmd, escalatedArgs, err := escalator.EscalateCommand("apt-get", []string{"install", "git"})
isRoot := escalator.IsRunningAsRoot()
Optional Types
Use samber/mo for safer nil handling:
import "github.com/samber/mo"
type Config struct {
Shell mo.Option[string]
}
if shell, ok := config.Shell.Get(); ok {
// use shell
}
Code Style & Testing
For all coding conventions and patterns: See Code Style Reference
For all testing conventions: See Test Style Reference
Development Commands
| Command | Purpose |
|---|---|
task build |
Build binary via goreleaser |
task test |
Run tests with race detection |
task fmt |
Format code (gofumpt, goimports, golines) |
task lint |
Run golangci-lint and typos |
task check |
Run tests + lint |
task cov |
Generate coverage report |
task bench |
Run benchmarks |
task sloc |
Print lines of code stats |
Adding Features
New Package Manager
- Create package in
lib/{managername}/ - Implement
PackageManagerinterface (see lib/pkgmanager/pkgmanager.go) - Add installer interface if installation needed
- Add unit and integration tests (see Test Style Reference)
- Update
internal/config/packagemap.yamlfor package name mappings
New Utility Interface
- Define interface in
utils/ - Create implementation with constructor (see Code Style Reference)
- Generate mock: run
mockeryin project root - Inject via constructors where needed
New CLI Command
- Create file in
cmd/ - Define
cobra.Commandwith flags - Register in
root.goinit() - Implement run logic using injected dependencies
Configuration Files
compatibility.yaml (internal/config/)
Defines supported OS/distros, architectures, and prerequisites:
supported_os:
darwin:
name: macOS
distros:
- name: macOS
architectures: [amd64, arm64]
prerequisites: [git, curl]
packagemap.yaml (internal/config/)
Maps generic package codes to manager-specific names:
packages:
git:
brew: git
apt: git
dnf: git
neovim:
brew: neovim
apt: neovim
dnf: neovim
Reference Files
- Code Style Reference - All Go coding conventions, formatting rules, patterns
- Test Style Reference - All testing patterns, naming conventions, mock usage