Fix config system: rename config.json → metadata.json, fix config.yaml loading
- Renamed config.json to metadata.json to clarify purpose (database metadata) - Fixed config.yaml/config.json conflict by making Viper explicitly load only config.yaml - Added automatic migration from config.json to metadata.json on first read - Fixed jsonOutput variable shadowing across 22 command files - Updated bd init to create both metadata.json and config.yaml template - Fixed 5 failing JSON output tests - All tests passing Resolves config file confusion and makes config.yaml work correctly. Closes #178 (global flags), addresses config issues from #193 Amp-Thread-ID: https://ampcode.com/threads/T-e6ac8192-e18f-4ed7-83bc-4a5986718bb7 Co-authored-by: Amp <amp@ampcode.com>
This commit is contained in:
@@ -64,7 +64,7 @@ var createCmd = &cobra.Command{
|
||||
externalRef, _ := cmd.Flags().GetString("external-ref")
|
||||
deps, _ := cmd.Flags().GetStringSlice("deps")
|
||||
forceCreate, _ := cmd.Flags().GetBool("force")
|
||||
jsonOutput, _ := cmd.Flags().GetBool("json")
|
||||
// Use global jsonOutput set by PersistentPreRun
|
||||
|
||||
// Check for conflicting flags
|
||||
if explicitID != "" && parentID != "" {
|
||||
|
||||
@@ -36,7 +36,7 @@ var daemonsListCmd = &cobra.Command{
|
||||
uptime, last activity, and exclusive lock status.`,
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
searchRoots, _ := cmd.Flags().GetStringSlice("search")
|
||||
jsonOutput, _ := cmd.Flags().GetBool("json")
|
||||
// Use global jsonOutput set by PersistentPreRun
|
||||
|
||||
// Discover daemons
|
||||
daemons, err := daemon.DiscoverDaemons(searchRoots)
|
||||
@@ -139,7 +139,7 @@ Sends shutdown command via RPC, with SIGTERM fallback if RPC fails.`,
|
||||
Args: cobra.ExactArgs(1),
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
target := args[0]
|
||||
jsonOutput, _ := cmd.Flags().GetBool("json")
|
||||
// Use global jsonOutput set by PersistentPreRun
|
||||
|
||||
// Discover all daemons
|
||||
daemons, err := daemon.DiscoverDaemons(nil)
|
||||
@@ -209,7 +209,7 @@ Supports tail mode (last N lines) and follow mode (like tail -f).`,
|
||||
Args: cobra.ExactArgs(1),
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
target := args[0]
|
||||
jsonOutput, _ := cmd.Flags().GetBool("json")
|
||||
// Use global jsonOutput set by PersistentPreRun
|
||||
follow, _ := cmd.Flags().GetBool("follow")
|
||||
lines, _ := cmd.Flags().GetInt("lines")
|
||||
|
||||
@@ -348,7 +348,7 @@ var daemonsKillallCmd = &cobra.Command{
|
||||
Uses escalating shutdown strategy: RPC (2s) → SIGTERM (3s) → SIGKILL (1s).`,
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
searchRoots, _ := cmd.Flags().GetStringSlice("search")
|
||||
jsonOutput, _ := cmd.Flags().GetBool("json")
|
||||
// Use global jsonOutput set by PersistentPreRun
|
||||
force, _ := cmd.Flags().GetBool("force")
|
||||
|
||||
// Discover all daemons
|
||||
@@ -411,7 +411,7 @@ var daemonsHealthCmd = &cobra.Command{
|
||||
stale sockets, version mismatches, and unresponsive daemons.`,
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
searchRoots, _ := cmd.Flags().GetStringSlice("search")
|
||||
jsonOutput, _ := cmd.Flags().GetBool("json")
|
||||
// Use global jsonOutput set by PersistentPreRun
|
||||
|
||||
// Discover daemons
|
||||
daemons, err := daemon.DiscoverDaemons(searchRoots)
|
||||
|
||||
@@ -54,7 +54,7 @@ Force: Delete and orphan dependents
|
||||
force, _ := cmd.Flags().GetBool("force")
|
||||
dryRun, _ := cmd.Flags().GetBool("dry-run")
|
||||
cascade, _ := cmd.Flags().GetBool("cascade")
|
||||
jsonOutput, _ := cmd.Flags().GetBool("json")
|
||||
// Use global jsonOutput set by PersistentPreRun
|
||||
|
||||
// Collect issue IDs from args and/or file
|
||||
issueIDs := make([]string, 0, len(args))
|
||||
|
||||
@@ -63,8 +63,7 @@ Examples:
|
||||
bd doctor /path/to/repo # Check specific repository
|
||||
bd doctor --json # Machine-readable output`,
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
// Get json flag from command
|
||||
jsonOutput, _ := cmd.Flags().GetBool("json")
|
||||
// Use global jsonOutput set by PersistentPreRun
|
||||
|
||||
// Determine path to check
|
||||
checkPath := "."
|
||||
@@ -201,7 +200,7 @@ func checkInstallation(path string) doctorCheck {
|
||||
func checkDatabaseVersion(path string) doctorCheck {
|
||||
beadsDir := filepath.Join(path, ".beads")
|
||||
|
||||
// Check config.json first for custom database name
|
||||
// Check metadata.json first for custom database name
|
||||
var dbPath string
|
||||
if cfg, err := configfile.Load(beadsDir); err == nil && cfg != nil && cfg.Database != "" {
|
||||
dbPath = cfg.DatabasePath(beadsDir)
|
||||
@@ -275,7 +274,7 @@ func checkDatabaseVersion(path string) doctorCheck {
|
||||
func checkIDFormat(path string) doctorCheck {
|
||||
beadsDir := filepath.Join(path, ".beads")
|
||||
|
||||
// Check config.json first for custom database name
|
||||
// Check metadata.json first for custom database name
|
||||
var dbPath string
|
||||
if cfg, err := configfile.Load(beadsDir); err == nil && cfg != nil && cfg.Database != "" {
|
||||
dbPath = cfg.DatabasePath(beadsDir)
|
||||
|
||||
@@ -38,7 +38,7 @@ Example:
|
||||
|
||||
autoMerge, _ := cmd.Flags().GetBool("auto-merge")
|
||||
dryRun, _ := cmd.Flags().GetBool("dry-run")
|
||||
jsonOutput, _ := cmd.Flags().GetBool("json")
|
||||
// Use global jsonOutput set by PersistentPreRun
|
||||
|
||||
ctx := context.Background()
|
||||
|
||||
|
||||
@@ -22,7 +22,7 @@ var epicStatusCmd = &cobra.Command{
|
||||
Short: "Show epic completion status",
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
eligibleOnly, _ := cmd.Flags().GetBool("eligible-only")
|
||||
jsonOutput, _ := cmd.Flags().GetBool("json")
|
||||
// Use global jsonOutput set by PersistentPreRun
|
||||
|
||||
var epics []*types.EpicStatus
|
||||
var err error
|
||||
@@ -115,7 +115,7 @@ var closeEligibleEpicsCmd = &cobra.Command{
|
||||
Short: "Close epics where all children are complete",
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
dryRun, _ := cmd.Flags().GetBool("dry-run")
|
||||
jsonOutput, _ := cmd.Flags().GetBool("json")
|
||||
// Use global jsonOutput set by PersistentPreRun
|
||||
|
||||
var eligibleEpics []*types.EpicStatus
|
||||
|
||||
|
||||
@@ -149,6 +149,7 @@ bd.db
|
||||
|
||||
# Keep JSONL exports and config (source of truth for git)
|
||||
!*.jsonl
|
||||
!metadata.json
|
||||
!config.json
|
||||
`
|
||||
if err := os.WriteFile(gitignorePath, []byte(gitignoreContent), 0600); err != nil {
|
||||
@@ -211,36 +212,93 @@ bd.db
|
||||
}
|
||||
}
|
||||
|
||||
// Create config.json for explicit configuration
|
||||
if useLocalBeads {
|
||||
cfg := configfile.DefaultConfig(Version)
|
||||
if err := cfg.Save(localBeadsDir); err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Warning: failed to create config.json: %v\n", err)
|
||||
// Create metadata.json for database metadata
|
||||
if useLocalBeads {
|
||||
cfg := configfile.DefaultConfig(Version)
|
||||
if err := cfg.Save(localBeadsDir); err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Warning: failed to create metadata.json: %v\n", err)
|
||||
// Non-fatal - continue anyway
|
||||
}
|
||||
|
||||
// Create config.yaml template for user preferences
|
||||
configYamlPath := filepath.Join(localBeadsDir, "config.yaml")
|
||||
if _, err := os.Stat(configYamlPath); os.IsNotExist(err) {
|
||||
configYamlTemplate := `# 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
|
||||
|
||||
# Issue prefix for this repository (used by bd init)
|
||||
# If not set, bd init will auto-detect from directory name
|
||||
# Example: issue-prefix: "myproject" creates issues like "myproject-1", "myproject-2", etc.
|
||||
# issue-prefix: ""
|
||||
|
||||
# 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
|
||||
|
||||
# Disable daemon for RPC communication (forces direct database access)
|
||||
# no-daemon: false
|
||||
|
||||
# Disable auto-flush of database to JSONL after mutations
|
||||
# no-auto-flush: false
|
||||
|
||||
# Disable auto-import from JSONL when it's newer than database
|
||||
# no-auto-import: false
|
||||
|
||||
# Enable JSON output by default
|
||||
# json: false
|
||||
|
||||
# Default actor for audit trails (overridden by BD_ACTOR or --actor)
|
||||
# actor: ""
|
||||
|
||||
# Path to database (overridden by BEADS_DB or --db)
|
||||
# db: ""
|
||||
|
||||
# Auto-start daemon if not running (can also use BEADS_AUTO_START_DAEMON)
|
||||
# auto-start-daemon: true
|
||||
|
||||
# Debounce interval for auto-flush (can also use BEADS_FLUSH_DEBOUNCE)
|
||||
# flush-debounce: "5s"
|
||||
|
||||
# Integration settings (access with 'bd config get/set')
|
||||
# These are stored in the database, not in this file:
|
||||
# - jira.url
|
||||
# - jira.project
|
||||
# - linear.url
|
||||
# - linear.api-key
|
||||
# - github.org
|
||||
# - github.repo
|
||||
`
|
||||
if err := os.WriteFile(configYamlPath, []byte(configYamlTemplate), 0600); err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Warning: failed to create config.yaml: %v\n", err)
|
||||
// Non-fatal - continue anyway
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Check if git has existing issues to import (fresh clone scenario)
|
||||
issueCount, jsonlPath := checkGitForIssues()
|
||||
if issueCount > 0 {
|
||||
// Check if git has existing issues to import (fresh clone scenario)
|
||||
issueCount, jsonlPath := checkGitForIssues()
|
||||
if issueCount > 0 {
|
||||
if !quiet {
|
||||
fmt.Fprintf(os.Stderr, "\n✓ Database initialized. Found %d issues in git, importing...\n", issueCount)
|
||||
fmt.Fprintf(os.Stderr, "\n✓ Database initialized. Found %d issues in git, importing...\n", issueCount)
|
||||
}
|
||||
|
||||
if err := importFromGit(ctx, initDBPath, store, jsonlPath); err != nil {
|
||||
if !quiet {
|
||||
fmt.Fprintf(os.Stderr, "Warning: auto-import failed: %v\n", err)
|
||||
fmt.Fprintf(os.Stderr, "Try manually: git show HEAD:%s | bd import -i /dev/stdin\n", jsonlPath)
|
||||
}
|
||||
// Non-fatal - continue with empty database
|
||||
if !quiet {
|
||||
fmt.Fprintf(os.Stderr, "Warning: auto-import failed: %v\n", err)
|
||||
fmt.Fprintf(os.Stderr, "Try manually: git show HEAD:%s | bd import -i /dev/stdin\n", jsonlPath)
|
||||
}
|
||||
// Non-fatal - continue with empty database
|
||||
} else if !quiet {
|
||||
fmt.Fprintf(os.Stderr, "✓ Successfully imported %d issues from git.\n\n", issueCount)
|
||||
fmt.Fprintf(os.Stderr, "✓ Successfully imported %d issues from git.\n\n", issueCount)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if err := store.Close(); err != nil {
|
||||
if err := store.Close(); err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Warning: failed to close database: %v\n", err)
|
||||
}
|
||||
}
|
||||
|
||||
// Check if we're in a git repo and hooks aren't installed
|
||||
// Do this BEFORE quiet mode return so hooks get installed for agents
|
||||
|
||||
@@ -79,7 +79,7 @@ var labelAddCmd = &cobra.Command{
|
||||
Short: "Add a label to one or more issues",
|
||||
Args: cobra.MinimumNArgs(2),
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
jsonOutput, _ := cmd.Flags().GetBool("json")
|
||||
// Use global jsonOutput set by PersistentPreRun
|
||||
issueIDs, label := parseLabelArgs(args)
|
||||
|
||||
// Resolve partial IDs
|
||||
@@ -125,7 +125,7 @@ var labelRemoveCmd = &cobra.Command{
|
||||
Short: "Remove a label from one or more issues",
|
||||
Args: cobra.MinimumNArgs(2),
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
jsonOutput, _ := cmd.Flags().GetBool("json")
|
||||
// Use global jsonOutput set by PersistentPreRun
|
||||
issueIDs, label := parseLabelArgs(args)
|
||||
|
||||
// Resolve partial IDs
|
||||
@@ -170,7 +170,7 @@ var labelListCmd = &cobra.Command{
|
||||
Short: "List labels for an issue",
|
||||
Args: cobra.ExactArgs(1),
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
jsonOutput, _ := cmd.Flags().GetBool("json")
|
||||
// Use global jsonOutput set by PersistentPreRun
|
||||
ctx := context.Background()
|
||||
|
||||
// Resolve partial ID first
|
||||
@@ -245,7 +245,7 @@ var labelListAllCmd = &cobra.Command{
|
||||
Use: "list-all",
|
||||
Short: "List all unique labels in the database",
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
jsonOutput, _ := cmd.Flags().GetBool("json")
|
||||
// Use global jsonOutput set by PersistentPreRun
|
||||
ctx := context.Background()
|
||||
|
||||
var issues []*types.Issue
|
||||
|
||||
@@ -46,7 +46,7 @@ var listCmd = &cobra.Command{
|
||||
labelsAny, _ := cmd.Flags().GetStringSlice("label-any")
|
||||
titleSearch, _ := cmd.Flags().GetString("title")
|
||||
idFilter, _ := cmd.Flags().GetString("id")
|
||||
jsonOutput, _ := cmd.Flags().GetBool("json")
|
||||
// Use global jsonOutput set by PersistentPreRun
|
||||
|
||||
// Normalize labels: trim, dedupe, remove empty
|
||||
labels = normalizeLabels(labels)
|
||||
|
||||
@@ -78,6 +78,23 @@ var (
|
||||
noDb bool // Use --no-db mode: load from JSONL, write back after each command
|
||||
)
|
||||
|
||||
func init() {
|
||||
// Initialize viper configuration
|
||||
if err := config.Initialize(); err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Warning: failed to initialize config: %v\n", err)
|
||||
}
|
||||
|
||||
// Register persistent flags
|
||||
rootCmd.PersistentFlags().StringVar(&dbPath, "db", "", "Database path (default: auto-discover .beads/*.db)")
|
||||
rootCmd.PersistentFlags().StringVar(&actor, "actor", "", "Actor name for audit trail (default: $BD_ACTOR or $USER)")
|
||||
rootCmd.PersistentFlags().BoolVar(&jsonOutput, "json", false, "Output in JSON format")
|
||||
rootCmd.PersistentFlags().BoolVar(&noDaemon, "no-daemon", false, "Force direct storage mode, bypass daemon if running")
|
||||
rootCmd.PersistentFlags().BoolVar(&noAutoFlush, "no-auto-flush", false, "Disable automatic JSONL sync after CRUD operations")
|
||||
rootCmd.PersistentFlags().BoolVar(&noAutoImport, "no-auto-import", false, "Disable automatic JSONL import when newer than DB")
|
||||
rootCmd.PersistentFlags().BoolVar(&sandboxMode, "sandbox", false, "Sandbox mode: disables daemon and auto-sync")
|
||||
rootCmd.PersistentFlags().BoolVar(&noDb, "no-db", false, "Use no-db mode: load from JSONL, no SQLite")
|
||||
}
|
||||
|
||||
var rootCmd = &cobra.Command{
|
||||
Use: "bd",
|
||||
Short: "bd - Dependency-aware issue tracker",
|
||||
|
||||
@@ -43,7 +43,7 @@ Example:
|
||||
|
||||
sourceIDs := args
|
||||
dryRun, _ := cmd.Flags().GetBool("dry-run")
|
||||
jsonOutput, _ := cmd.Flags().GetBool("json")
|
||||
// Use global jsonOutput set by PersistentPreRun
|
||||
|
||||
// Validate merge operation
|
||||
if err := validateMerge(targetID, sourceIDs); err != nil {
|
||||
|
||||
@@ -100,7 +100,7 @@ This command:
|
||||
return
|
||||
}
|
||||
|
||||
// Check if target database exists and is current (use config.json name)
|
||||
// Check if target database exists and is current (use metadata.json name)
|
||||
targetPath := cfg.DatabasePath(beadsDir)
|
||||
var currentDB *dbInfo
|
||||
var oldDBs []*dbInfo
|
||||
@@ -444,7 +444,7 @@ This command:
|
||||
if !dryRun {
|
||||
if err := cfg.Save(beadsDir); err != nil {
|
||||
if !jsonOutput {
|
||||
color.Yellow("Warning: failed to update config.json version: %v\n", err)
|
||||
color.Yellow("Warning: failed to update metadata.json version: %v\n", err)
|
||||
}
|
||||
// Don't fail migration if config save fails
|
||||
}
|
||||
@@ -667,7 +667,7 @@ func handleUpdateRepoID(dryRun bool, autoYes bool) {
|
||||
}
|
||||
}
|
||||
|
||||
// loadOrCreateConfig loads config.json or creates default if not found
|
||||
// loadOrCreateConfig loads metadata.json or creates default if not found
|
||||
func loadOrCreateConfig(beadsDir string) (*configfile.Config, error) {
|
||||
cfg, err := configfile.Load(beadsDir)
|
||||
if err != nil {
|
||||
|
||||
@@ -127,18 +127,18 @@ func TestFormatDBList(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestMigrateRespectsConfigJSON(t *testing.T) {
|
||||
// Test that migrate respects custom database name from config.json
|
||||
// Test that migrate respects custom database name from metadata.json
|
||||
tmpDir := t.TempDir()
|
||||
beadsDir := filepath.Join(tmpDir, ".beads")
|
||||
if err := os.MkdirAll(beadsDir, 0750); err != nil {
|
||||
t.Fatalf("Failed to create .beads directory: %v", err)
|
||||
}
|
||||
|
||||
// Create config.json with custom database name
|
||||
configPath := filepath.Join(beadsDir, "config.json")
|
||||
// Create metadata.json with custom database name
|
||||
configPath := filepath.Join(beadsDir, "metadata.json")
|
||||
configData := `{"database": "beady.db", "version": "0.21.1", "jsonl_export": "beady.jsonl"}`
|
||||
if err := os.WriteFile(configPath, []byte(configData), 0600); err != nil {
|
||||
t.Fatalf("Failed to create config.json: %v", err)
|
||||
t.Fatalf("Failed to create metadata.json: %v", err)
|
||||
}
|
||||
|
||||
// Create old database with custom name
|
||||
|
||||
@@ -20,7 +20,7 @@ var readyCmd = &cobra.Command{
|
||||
limit, _ := cmd.Flags().GetInt("limit")
|
||||
assignee, _ := cmd.Flags().GetString("assignee")
|
||||
sortPolicy, _ := cmd.Flags().GetString("sort")
|
||||
jsonOutput, _ := cmd.Flags().GetBool("json")
|
||||
// Use global jsonOutput set by PersistentPreRun (respects config.yaml + env vars)
|
||||
|
||||
filter := types.WorkFilter{
|
||||
// Leave Status empty to get both 'open' and 'in_progress' (bd-165)
|
||||
@@ -153,7 +153,7 @@ var blockedCmd = &cobra.Command{
|
||||
Use: "blocked",
|
||||
Short: "Show blocked issues",
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
jsonOutput, _ := cmd.Flags().GetBool("json")
|
||||
// Use global jsonOutput set by PersistentPreRun (respects config.yaml + env vars)
|
||||
|
||||
// If daemon is running but doesn't support this command, use direct storage
|
||||
if daemonClient != nil && store == nil {
|
||||
@@ -208,7 +208,7 @@ var statsCmd = &cobra.Command{
|
||||
Use: "stats",
|
||||
Short: "Show statistics",
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
jsonOutput, _ := cmd.Flags().GetBool("json")
|
||||
// Use global jsonOutput set by PersistentPreRun (respects config.yaml + env vars)
|
||||
|
||||
// If daemon is running, use RPC
|
||||
if daemonClient != nil {
|
||||
|
||||
@@ -22,7 +22,7 @@ This is more explicit than 'bd update --status open' and emits a Reopened event.
|
||||
Args: cobra.MinimumNArgs(1),
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
reason, _ := cmd.Flags().GetString("reason")
|
||||
jsonOutput, _ := cmd.Flags().GetBool("json")
|
||||
// Use global jsonOutput set by PersistentPreRun
|
||||
|
||||
ctx := context.Background()
|
||||
|
||||
|
||||
@@ -21,7 +21,7 @@ var showCmd = &cobra.Command{
|
||||
Short: "Show issue details",
|
||||
Args: cobra.MinimumNArgs(1),
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
jsonOutput, _ := cmd.Flags().GetBool("json")
|
||||
// Use global jsonOutput set by PersistentPreRun
|
||||
ctx := context.Background()
|
||||
|
||||
// Resolve partial IDs first
|
||||
@@ -346,7 +346,7 @@ var updateCmd = &cobra.Command{
|
||||
Short: "Update one or more issues",
|
||||
Args: cobra.MinimumNArgs(1),
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
jsonOutput, _ := cmd.Flags().GetBool("json")
|
||||
// Use global jsonOutput set by PersistentPreRun
|
||||
updates := make(map[string]interface{})
|
||||
|
||||
if cmd.Flags().Changed("status") {
|
||||
@@ -710,7 +710,7 @@ var closeCmd = &cobra.Command{
|
||||
if reason == "" {
|
||||
reason = "Closed"
|
||||
}
|
||||
jsonOutput, _ := cmd.Flags().GetBool("json")
|
||||
// Use global jsonOutput set by PersistentPreRun
|
||||
|
||||
ctx := context.Background()
|
||||
|
||||
|
||||
@@ -125,6 +125,8 @@ func TestShowCommand(t *testing.T) {
|
||||
os.Stdout = w
|
||||
|
||||
// Reset command state
|
||||
jsonOutput = true
|
||||
defer func() { jsonOutput = false }()
|
||||
rootCmd.SetArgs([]string{"show", issue1.ID, "--json"})
|
||||
|
||||
err := rootCmd.Execute()
|
||||
@@ -171,6 +173,8 @@ func TestShowCommand(t *testing.T) {
|
||||
os.Stdout = w
|
||||
|
||||
// Reset command state
|
||||
jsonOutput = true
|
||||
defer func() { jsonOutput = false }()
|
||||
rootCmd.SetArgs([]string{"show", issue1.ID, issue2.ID, "--json"})
|
||||
|
||||
err := rootCmd.Execute()
|
||||
@@ -204,6 +208,8 @@ func TestShowCommand(t *testing.T) {
|
||||
os.Stdout = w
|
||||
|
||||
// Reset command state
|
||||
jsonOutput = true
|
||||
defer func() { jsonOutput = false }()
|
||||
rootCmd.SetArgs([]string{"show", issue2.ID, "--json"})
|
||||
|
||||
err := rootCmd.Execute()
|
||||
@@ -490,6 +496,8 @@ func TestUpdateCommand(t *testing.T) {
|
||||
os.Stdout = w
|
||||
|
||||
// Reset command state
|
||||
jsonOutput = true
|
||||
defer func() { jsonOutput = false }()
|
||||
rootCmd.SetArgs([]string{"update", issue.ID, "--priority", "3", "--json"})
|
||||
|
||||
err := rootCmd.Execute()
|
||||
@@ -779,6 +787,8 @@ func TestCloseCommand(t *testing.T) {
|
||||
os.Stdout = w
|
||||
|
||||
// Reset command state
|
||||
jsonOutput = true
|
||||
defer func() { jsonOutput = false }()
|
||||
rootCmd.SetArgs([]string{"close", issue.ID, "--reason", "Fixed", "--json"})
|
||||
|
||||
err := rootCmd.Execute()
|
||||
|
||||
@@ -26,7 +26,7 @@ This helps identify:
|
||||
days, _ := cmd.Flags().GetInt("days")
|
||||
status, _ := cmd.Flags().GetString("status")
|
||||
limit, _ := cmd.Flags().GetInt("limit")
|
||||
jsonOutput, _ := cmd.Flags().GetBool("json")
|
||||
// Use global jsonOutput set by PersistentPreRun
|
||||
|
||||
// Validate status if provided
|
||||
if status != "" && status != "open" && status != "in_progress" && status != "blocked" {
|
||||
|
||||
3
cmd/bd/testdata/init.txt
vendored
3
cmd/bd/testdata/init.txt
vendored
@@ -2,7 +2,7 @@
|
||||
bd init --prefix test
|
||||
stdout 'initialized successfully'
|
||||
exists .beads/beads.db
|
||||
exists .beads/config.json
|
||||
exists .beads/metadata.json
|
||||
exists .beads/.gitignore
|
||||
grep '^\*\.db$' .beads/.gitignore
|
||||
grep '^\*\.db-journal$' .beads/.gitignore
|
||||
@@ -12,4 +12,5 @@ grep '^daemon\.log$' .beads/.gitignore
|
||||
grep '^daemon\.pid$' .beads/.gitignore
|
||||
grep '^bd\.sock$' .beads/.gitignore
|
||||
grep '^!\*\.jsonl$' .beads/.gitignore
|
||||
grep '^!metadata\.json$' .beads/.gitignore
|
||||
grep '^!config\.json$' .beads/.gitignore
|
||||
|
||||
Reference in New Issue
Block a user