From cecec996724ff2ab2a115a4285970cbf3ae59d37 Mon Sep 17 00:00:00 2001 From: Steve Yegge Date: Mon, 3 Nov 2025 15:01:46 -0800 Subject: [PATCH] Fix: bd init --no-db now sets no-db: true in config.yaml GH #210: bd init --no-db was creating config.yaml but leaving no-db commented out, forcing users to pass --no-db on every command. Changes: - Modified createConfigYaml() to accept noDbMode parameter - When true, writes 'no-db: true' instead of '# no-db: false' - Added TestInitNoDbMode() to verify end-to-end workflow The config reading logic was already in place (main.go:122), just needed to write the correct value during init. Fixes bd-5cny Amp-Thread-ID: https://ampcode.com/threads/T-2c569435-6291-40e8-b39b-c33fd317d853 Co-authored-by: Amp --- cmd/bd/init.go | 19 ++++++---- cmd/bd/init_test.go | 88 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 100 insertions(+), 7 deletions(-) diff --git a/cmd/bd/init.go b/cmd/bd/init.go index b4aa2444..337c3de8 100644 --- a/cmd/bd/init.go +++ b/cmd/bd/init.go @@ -124,8 +124,8 @@ With --no-db: creates .beads/ directory and issues.jsonl file instead of SQLite // Non-fatal - continue anyway } - // Create config.yaml template - if err := createConfigYaml(localBeadsDir, quiet); err != nil { + // Create config.yaml with no-db: true + if err := createConfigYaml(localBeadsDir, quiet, true); err != nil { fmt.Fprintf(os.Stderr, "Warning: failed to create config.yaml: %v\n", err) // Non-fatal - continue anyway } @@ -248,7 +248,7 @@ bd.db } // Create config.yaml template - if err := createConfigYaml(localBeadsDir, quiet); err != nil { + if err := createConfigYaml(localBeadsDir, quiet, false); err != nil { fmt.Fprintf(os.Stderr, "Warning: failed to create config.yaml: %v\n", err) // Non-fatal - continue anyway } @@ -544,7 +544,7 @@ func migrateOldDatabases(targetPath string, quiet bool) error { } // createConfigYaml creates the config.yaml template in the specified directory -func createConfigYaml(beadsDir string, quiet bool) error { +func createConfigYaml(beadsDir string, quiet bool, noDbMode bool) error { configYamlPath := filepath.Join(beadsDir, "config.yaml") // Skip if already exists @@ -552,7 +552,12 @@ func createConfigYaml(beadsDir string, quiet bool) error { return nil } - configYamlTemplate := `# Beads Configuration File + noDbLine := "# no-db: false" + if noDbMode { + noDbLine = "no-db: true # JSONL-only mode, no SQLite database" + } + + configYamlTemplate := fmt.Sprintf(`# Beads Configuration File # This file configures default behavior for all bd commands in this repository # All settings can also be set via environment variables (BD_* prefix) # or overridden with command-line flags @@ -565,7 +570,7 @@ func createConfigYaml(beadsDir string, quiet bool) error { # Use no-db mode: load from JSONL, no SQLite, write back after each command # When true, bd will use .beads/issues.jsonl as the source of truth # instead of SQLite database -# no-db: false +%s # Disable daemon for RPC communication (forces direct database access) # no-daemon: false @@ -600,7 +605,7 @@ func createConfigYaml(beadsDir string, quiet bool) error { # - github.org # - github.repo # - sync.branch - Git branch for beads commits (use BEADS_SYNC_BRANCH env var or bd config set) -` +`, noDbLine) if err := os.WriteFile(configYamlPath, []byte(configYamlTemplate), 0600); err != nil { return fmt.Errorf("failed to write config.yaml: %w", err) diff --git a/cmd/bd/init_test.go b/cmd/bd/init_test.go index 55dcefa0..65c465e0 100644 --- a/cmd/bd/init_test.go +++ b/cmd/bd/init_test.go @@ -389,3 +389,91 @@ func TestInitWithCustomDBPath(t *testing.T) { } }) } + +func TestInitNoDbMode(t *testing.T) { + // Reset global state + origDBPath := dbPath + origNoDb := noDb + defer func() { + dbPath = origDBPath + noDb = origNoDb + }() + dbPath = "" + noDb = false + + tmpDir := t.TempDir() + originalWd, err := os.Getwd() + if err != nil { + t.Fatalf("Failed to get working directory: %v", err) + } + defer os.Chdir(originalWd) + + if err := os.Chdir(tmpDir); err != nil { + t.Fatalf("Failed to change to temp directory: %v", err) + } + + // Initialize with --no-db flag + rootCmd.SetArgs([]string{"init", "--no-db", "--no-daemon", "--prefix", "test", "--quiet"}) + + if err := rootCmd.Execute(); err != nil { + t.Fatalf("Init with --no-db failed: %v", err) + } + + // Verify issues.jsonl was created + jsonlPath := filepath.Join(tmpDir, ".beads", "issues.jsonl") + if _, err := os.Stat(jsonlPath); os.IsNotExist(err) { + t.Error("issues.jsonl was not created in --no-db mode") + } + + // Verify config.yaml was created with no-db: true + configPath := filepath.Join(tmpDir, ".beads", "config.yaml") + configContent, err := os.ReadFile(configPath) + if err != nil { + t.Fatalf("Failed to read config.yaml: %v", err) + } + + configStr := string(configContent) + if !strings.Contains(configStr, "no-db: true") { + t.Error("config.yaml should contain 'no-db: true' in --no-db mode") + } + + // Verify subsequent command works without --no-db flag + rootCmd.SetArgs([]string{"create", "test issue", "--json"}) + + // Capture output to verify it worked + var buf bytes.Buffer + oldStdout := os.Stdout + r, w, _ := os.Pipe() + os.Stdout = w + + err = rootCmd.Execute() + + // Restore stdout and read output + w.Close() + buf.ReadFrom(r) + os.Stdout = oldStdout + + if err != nil { + t.Fatalf("create command failed in no-db mode: %v", err) + } + + // Verify issue was written to JSONL + jsonlContent, err := os.ReadFile(jsonlPath) + if err != nil { + t.Fatalf("Failed to read issues.jsonl: %v", err) + } + + if len(jsonlContent) == 0 { + t.Error("issues.jsonl should not be empty after creating issue") + } + + if !strings.Contains(string(jsonlContent), "test issue") { + t.Error("issues.jsonl should contain the created issue") + } + + // Verify no SQLite database was created + dbPath := filepath.Join(tmpDir, ".beads", "beads.db") + if _, err := os.Stat(dbPath); err == nil { + t.Error("SQLite database should not be created in --no-db mode") + } +}