feat: scaffold project with config, store, health endpoint, CI, and Dockerfile
Phase 1 of foreman: initialize the Go module, project layout, and core infrastructure. Includes env-based configuration (FOREMAN_* namespace), SQLite-backed durable job queue with WAL mode via modernc.org/sqlite, stdlib HTTP server with /healthz and optional bearer-token auth middleware, subcommand dispatch (serve + stubs), Gitea CI workflow, multi-stage distroless Dockerfile, and comprehensive tests for all packages. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,96 @@
|
||||
package config
|
||||
|
||||
import (
|
||||
"os"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
func TestLoad_Defaults(t *testing.T) {
|
||||
// Set required env var, leave optional ones at defaults.
|
||||
t.Setenv("FOREMAN_OLLAMA_URL", "http://localhost:11434")
|
||||
// Clear any other vars that might be set.
|
||||
t.Setenv("FOREMAN_ADDR", "")
|
||||
t.Setenv("FOREMAN_DB_PATH", "")
|
||||
t.Setenv("FOREMAN_POLL_INTERVAL", "")
|
||||
|
||||
cfg, err := Load()
|
||||
if err != nil {
|
||||
t.Fatalf("Load() error: %v", err)
|
||||
}
|
||||
|
||||
if cfg.Addr != ":8080" {
|
||||
t.Errorf("Addr = %q, want %q", cfg.Addr, ":8080")
|
||||
}
|
||||
if cfg.OllamaURL != "http://localhost:11434" {
|
||||
t.Errorf("OllamaURL = %q, want %q", cfg.OllamaURL, "http://localhost:11434")
|
||||
}
|
||||
if cfg.DBPath != "foreman.db" {
|
||||
t.Errorf("DBPath = %q, want %q", cfg.DBPath, "foreman.db")
|
||||
}
|
||||
if cfg.PollInterval != 30*time.Second {
|
||||
t.Errorf("PollInterval = %v, want %v", cfg.PollInterval, 30*time.Second)
|
||||
}
|
||||
}
|
||||
|
||||
func TestLoad_AllEnvVars(t *testing.T) {
|
||||
t.Setenv("FOREMAN_ADDR", ":9090")
|
||||
t.Setenv("FOREMAN_OLLAMA_URL", "http://mac.tail:11434")
|
||||
t.Setenv("FOREMAN_OLLAMA_TOKEN", "ollama-secret")
|
||||
t.Setenv("FOREMAN_TOKEN", "my-token")
|
||||
t.Setenv("FOREMAN_EMBED_MODEL", "nomic-embed-text")
|
||||
t.Setenv("FOREMAN_DB_PATH", "/data/foreman.db")
|
||||
t.Setenv("FOREMAN_POLL_INTERVAL", "1m")
|
||||
t.Setenv("FOREMAN_WEBHOOK_SECRET", "hmac-key")
|
||||
|
||||
cfg, err := Load()
|
||||
if err != nil {
|
||||
t.Fatalf("Load() error: %v", err)
|
||||
}
|
||||
|
||||
if cfg.Addr != ":9090" {
|
||||
t.Errorf("Addr = %q, want %q", cfg.Addr, ":9090")
|
||||
}
|
||||
if cfg.OllamaURL != "http://mac.tail:11434" {
|
||||
t.Errorf("OllamaURL = %q", cfg.OllamaURL)
|
||||
}
|
||||
if cfg.OllamaToken != "ollama-secret" {
|
||||
t.Errorf("OllamaToken = %q", cfg.OllamaToken)
|
||||
}
|
||||
if cfg.Token != "my-token" {
|
||||
t.Errorf("Token = %q", cfg.Token)
|
||||
}
|
||||
if cfg.EmbedModel != "nomic-embed-text" {
|
||||
t.Errorf("EmbedModel = %q", cfg.EmbedModel)
|
||||
}
|
||||
if cfg.DBPath != "/data/foreman.db" {
|
||||
t.Errorf("DBPath = %q", cfg.DBPath)
|
||||
}
|
||||
if cfg.PollInterval != time.Minute {
|
||||
t.Errorf("PollInterval = %v, want %v", cfg.PollInterval, time.Minute)
|
||||
}
|
||||
if cfg.WebhookSecret != "hmac-key" {
|
||||
t.Errorf("WebhookSecret = %q", cfg.WebhookSecret)
|
||||
}
|
||||
}
|
||||
|
||||
func TestLoad_MissingOllamaURL(t *testing.T) {
|
||||
// Ensure FOREMAN_OLLAMA_URL is unset.
|
||||
os.Unsetenv("FOREMAN_OLLAMA_URL")
|
||||
t.Setenv("FOREMAN_OLLAMA_URL", "")
|
||||
|
||||
_, err := Load()
|
||||
if err == nil {
|
||||
t.Fatal("Load() should fail when FOREMAN_OLLAMA_URL is empty")
|
||||
}
|
||||
}
|
||||
|
||||
func TestLoad_InvalidPollInterval(t *testing.T) {
|
||||
t.Setenv("FOREMAN_OLLAMA_URL", "http://localhost:11434")
|
||||
t.Setenv("FOREMAN_POLL_INTERVAL", "not-a-duration")
|
||||
|
||||
_, err := Load()
|
||||
if err == nil {
|
||||
t.Fatal("Load() should fail with invalid FOREMAN_POLL_INTERVAL")
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user