Files
gastown/internal/rig/manager_test.go
Steve Yegge b67141f3fc feat: add .beads-ephemeral/ creation to gt rig add
During rig initialization, now creates a .beads-ephemeral/ directory:
- Initialized as a git repo (for local versioning)
- Contains config.yaml with ephemeral: true
- Automatically added to rig .gitignore

This provides a local-only beads database for runtime tracking of
wisps and molecules, separate from the synced .beads/ database.

Closes gt-3x0z.1

Generated with Claude Code

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-21 15:49:09 -08:00

300 lines
7.9 KiB
Go

package rig
import (
"os"
"path/filepath"
"testing"
"github.com/steveyegge/gastown/internal/config"
"github.com/steveyegge/gastown/internal/git"
)
func setupTestTown(t *testing.T) (string, *config.RigsConfig) {
t.Helper()
root := t.TempDir()
rigsConfig := &config.RigsConfig{
Version: 1,
Rigs: make(map[string]config.RigEntry),
}
return root, rigsConfig
}
func createTestRig(t *testing.T, root, name string) {
t.Helper()
rigPath := filepath.Join(root, name)
if err := os.MkdirAll(rigPath, 0755); err != nil {
t.Fatalf("mkdir rig: %v", err)
}
// Create agent dirs
for _, dir := range AgentDirs {
dirPath := filepath.Join(rigPath, dir)
if err := os.MkdirAll(dirPath, 0755); err != nil {
t.Fatalf("mkdir %s: %v", dir, err)
}
}
// Create witness state.json (witnesses don't have clones, just state)
witnessState := filepath.Join(rigPath, "witness", "state.json")
if err := os.WriteFile(witnessState, []byte(`{"role":"witness"}`), 0644); err != nil {
t.Fatalf("write witness state: %v", err)
}
// Create some polecats
polecatsDir := filepath.Join(rigPath, "polecats")
for _, polecat := range []string{"Toast", "Cheedo"} {
if err := os.MkdirAll(filepath.Join(polecatsDir, polecat), 0755); err != nil {
t.Fatalf("mkdir polecat: %v", err)
}
}
}
func TestDiscoverRigs(t *testing.T) {
root, rigsConfig := setupTestTown(t)
// Create test rig
createTestRig(t, root, "gastown")
rigsConfig.Rigs["gastown"] = config.RigEntry{
GitURL: "git@github.com:test/gastown.git",
}
manager := NewManager(root, rigsConfig, git.NewGit(root))
rigs, err := manager.DiscoverRigs()
if err != nil {
t.Fatalf("DiscoverRigs: %v", err)
}
if len(rigs) != 1 {
t.Errorf("rigs count = %d, want 1", len(rigs))
}
rig := rigs[0]
if rig.Name != "gastown" {
t.Errorf("Name = %q, want gastown", rig.Name)
}
if len(rig.Polecats) != 2 {
t.Errorf("Polecats count = %d, want 2", len(rig.Polecats))
}
if !rig.HasWitness {
t.Error("expected HasWitness = true")
}
if !rig.HasRefinery {
t.Error("expected HasRefinery = true")
}
}
func TestGetRig(t *testing.T) {
root, rigsConfig := setupTestTown(t)
createTestRig(t, root, "test-rig")
rigsConfig.Rigs["test-rig"] = config.RigEntry{
GitURL: "git@github.com:test/test-rig.git",
}
manager := NewManager(root, rigsConfig, git.NewGit(root))
rig, err := manager.GetRig("test-rig")
if err != nil {
t.Fatalf("GetRig: %v", err)
}
if rig.Name != "test-rig" {
t.Errorf("Name = %q, want test-rig", rig.Name)
}
}
func TestGetRigNotFound(t *testing.T) {
root, rigsConfig := setupTestTown(t)
manager := NewManager(root, rigsConfig, git.NewGit(root))
_, err := manager.GetRig("nonexistent")
if err != ErrRigNotFound {
t.Errorf("GetRig = %v, want ErrRigNotFound", err)
}
}
func TestRigExists(t *testing.T) {
root, rigsConfig := setupTestTown(t)
rigsConfig.Rigs["exists"] = config.RigEntry{}
manager := NewManager(root, rigsConfig, git.NewGit(root))
if !manager.RigExists("exists") {
t.Error("expected RigExists = true for existing rig")
}
if manager.RigExists("nonexistent") {
t.Error("expected RigExists = false for nonexistent rig")
}
}
func TestRemoveRig(t *testing.T) {
root, rigsConfig := setupTestTown(t)
rigsConfig.Rigs["to-remove"] = config.RigEntry{}
manager := NewManager(root, rigsConfig, git.NewGit(root))
if err := manager.RemoveRig("to-remove"); err != nil {
t.Fatalf("RemoveRig: %v", err)
}
if manager.RigExists("to-remove") {
t.Error("rig should not exist after removal")
}
}
func TestRemoveRigNotFound(t *testing.T) {
root, rigsConfig := setupTestTown(t)
manager := NewManager(root, rigsConfig, git.NewGit(root))
err := manager.RemoveRig("nonexistent")
if err != ErrRigNotFound {
t.Errorf("RemoveRig = %v, want ErrRigNotFound", err)
}
}
func TestListRigNames(t *testing.T) {
root, rigsConfig := setupTestTown(t)
rigsConfig.Rigs["rig1"] = config.RigEntry{}
rigsConfig.Rigs["rig2"] = config.RigEntry{}
manager := NewManager(root, rigsConfig, git.NewGit(root))
names := manager.ListRigNames()
if len(names) != 2 {
t.Errorf("names count = %d, want 2", len(names))
}
}
func TestRigSummary(t *testing.T) {
rig := &Rig{
Name: "test",
Polecats: []string{"a", "b", "c"},
HasWitness: true,
HasRefinery: false,
}
summary := rig.Summary()
if summary.Name != "test" {
t.Errorf("Name = %q, want test", summary.Name)
}
if summary.PolecatCount != 3 {
t.Errorf("PolecatCount = %d, want 3", summary.PolecatCount)
}
if !summary.HasWitness {
t.Error("expected HasWitness = true")
}
if summary.HasRefinery {
t.Error("expected HasRefinery = false")
}
}
func TestInitEphemeralBeads(t *testing.T) {
root, rigsConfig := setupTestTown(t)
manager := NewManager(root, rigsConfig, git.NewGit(root))
rigPath := filepath.Join(root, "test-rig")
if err := os.MkdirAll(rigPath, 0755); err != nil {
t.Fatalf("mkdir: %v", err)
}
if err := manager.initEphemeralBeads(rigPath); err != nil {
t.Fatalf("initEphemeralBeads: %v", err)
}
// Verify directory was created
ephemeralPath := filepath.Join(rigPath, ".beads-ephemeral")
if _, err := os.Stat(ephemeralPath); os.IsNotExist(err) {
t.Error(".beads-ephemeral/ was not created")
}
// Verify it's a git repo
gitPath := filepath.Join(ephemeralPath, ".git")
if _, err := os.Stat(gitPath); os.IsNotExist(err) {
t.Error(".beads-ephemeral/ was not initialized as git repo")
}
// Verify config.yaml was created with ephemeral: true
configPath := filepath.Join(ephemeralPath, "config.yaml")
content, err := os.ReadFile(configPath)
if err != nil {
t.Fatalf("reading config.yaml: %v", err)
}
if string(content) != "ephemeral: true\n# No sync-branch - ephemeral is local only\n" {
t.Errorf("config.yaml content = %q, want ephemeral: true with comment", string(content))
}
// Verify .gitignore was updated
gitignorePath := filepath.Join(rigPath, ".gitignore")
ignoreContent, err := os.ReadFile(gitignorePath)
if err != nil {
t.Fatalf("reading .gitignore: %v", err)
}
if string(ignoreContent) != ".beads-ephemeral/\n" {
t.Errorf(".gitignore content = %q, want .beads-ephemeral/", string(ignoreContent))
}
}
func TestEnsureGitignoreEntry_AddsEntry(t *testing.T) {
root, rigsConfig := setupTestTown(t)
manager := NewManager(root, rigsConfig, git.NewGit(root))
gitignorePath := filepath.Join(root, ".gitignore")
if err := manager.ensureGitignoreEntry(gitignorePath, ".test-entry/"); err != nil {
t.Fatalf("ensureGitignoreEntry: %v", err)
}
content, _ := os.ReadFile(gitignorePath)
if string(content) != ".test-entry/\n" {
t.Errorf("content = %q, want .test-entry/", string(content))
}
}
func TestEnsureGitignoreEntry_DoesNotDuplicate(t *testing.T) {
root, rigsConfig := setupTestTown(t)
manager := NewManager(root, rigsConfig, git.NewGit(root))
gitignorePath := filepath.Join(root, ".gitignore")
// Pre-populate with the entry
if err := os.WriteFile(gitignorePath, []byte(".test-entry/\n"), 0644); err != nil {
t.Fatalf("writing .gitignore: %v", err)
}
if err := manager.ensureGitignoreEntry(gitignorePath, ".test-entry/"); err != nil {
t.Fatalf("ensureGitignoreEntry: %v", err)
}
content, _ := os.ReadFile(gitignorePath)
if string(content) != ".test-entry/\n" {
t.Errorf("content = %q, want single .test-entry/", string(content))
}
}
func TestEnsureGitignoreEntry_AppendsToExisting(t *testing.T) {
root, rigsConfig := setupTestTown(t)
manager := NewManager(root, rigsConfig, git.NewGit(root))
gitignorePath := filepath.Join(root, ".gitignore")
// Pre-populate with existing entries
if err := os.WriteFile(gitignorePath, []byte("node_modules/\n*.log\n"), 0644); err != nil {
t.Fatalf("writing .gitignore: %v", err)
}
if err := manager.ensureGitignoreEntry(gitignorePath, ".test-entry/"); err != nil {
t.Fatalf("ensureGitignoreEntry: %v", err)
}
content, _ := os.ReadFile(gitignorePath)
expected := "node_modules/\n*.log\n.test-entry/\n"
if string(content) != expected {
t.Errorf("content = %q, want %q", string(content), expected)
}
}