Add --json flag support to more bd commands

- stats: Added --json flag for programmatic output
- show, update: Added --json flag for issue details
- close, reopen: Added --json flag for bulk operations
- dep (add, remove, tree, cycles): Added --json flags
- label (add, remove, list, list-all): Added --json flags
- duplicates, merge: Added --json flags

Closes bd-4dcd2d09
This commit is contained in:
Steve Yegge
2025-10-31 14:36:20 -07:00
parent b2b0373d08
commit 118d7541dd
7 changed files with 43 additions and 5 deletions

View File

@@ -25,6 +25,7 @@ var depAddCmd = &cobra.Command{
Args: cobra.ExactArgs(2),
Run: func(cmd *cobra.Command, args []string) {
depType, _ := cmd.Flags().GetString("type")
jsonOutput, _ := cmd.Flags().GetBool("json")
ctx := context.Background()
@@ -147,6 +148,7 @@ var depRemoveCmd = &cobra.Command{
Short: "Remove a dependency",
Args: cobra.ExactArgs(2),
Run: func(cmd *cobra.Command, args []string) {
jsonOutput, _ := cmd.Flags().GetBool("json")
ctx := context.Background()
// Resolve partial IDs first
@@ -238,6 +240,7 @@ var depTreeCmd = &cobra.Command{
Short: "Show dependency tree",
Args: cobra.ExactArgs(1),
Run: func(cmd *cobra.Command, args []string) {
jsonOutput, _ := cmd.Flags().GetBool("json")
ctx := context.Background()
// Resolve partial ID first
@@ -338,6 +341,8 @@ var depCyclesCmd = &cobra.Command{
Use: "cycles",
Short: "Detect dependency cycles",
Run: func(cmd *cobra.Command, args []string) {
jsonOutput, _ := cmd.Flags().GetBool("json")
// If daemon is running but doesn't support this command, use direct storage
if daemonClient != nil && store == nil {
var err error
@@ -385,9 +390,17 @@ var depCyclesCmd = &cobra.Command{
func init() {
depAddCmd.Flags().StringP("type", "t", "blocks", "Dependency type (blocks|related|parent-child|discovered-from)")
depAddCmd.Flags().Bool("json", false, "Output JSON format")
depRemoveCmd.Flags().Bool("json", false, "Output JSON format")
depTreeCmd.Flags().Bool("show-all-paths", false, "Show all paths to nodes (no deduplication for diamond dependencies)")
depTreeCmd.Flags().IntP("max-depth", "d", 50, "Maximum tree depth to display (safety limit)")
depTreeCmd.Flags().Bool("reverse", false, "Show dependent tree (what was discovered from this) instead of dependency tree (what blocks this)")
depTreeCmd.Flags().Bool("json", false, "Output JSON format")
depCyclesCmd.Flags().Bool("json", false, "Output JSON format")
depCmd.AddCommand(depAddCmd)
depCmd.AddCommand(depRemoveCmd)
depCmd.AddCommand(depTreeCmd)

View File

@@ -38,6 +38,7 @@ Example:
autoMerge, _ := cmd.Flags().GetBool("auto-merge")
dryRun, _ := cmd.Flags().GetBool("dry-run")
jsonOutput, _ := cmd.Flags().GetBool("json")
ctx := context.Background()
@@ -174,6 +175,7 @@ Example:
func init() {
duplicatesCmd.Flags().Bool("auto-merge", false, "Automatically merge all duplicates")
duplicatesCmd.Flags().Bool("dry-run", false, "Show what would be merged without making changes")
duplicatesCmd.Flags().Bool("json", false, "Output JSON format")
rootCmd.AddCommand(duplicatesCmd)
}

View File

@@ -22,7 +22,7 @@ var labelCmd = &cobra.Command{
}
// Helper function to process label operations for multiple issues
func processBatchLabelOperation(issueIDs []string, label string, operation string,
func processBatchLabelOperation(issueIDs []string, label string, operation string, jsonOut bool,
daemonFunc func(string, string) error, storeFunc func(context.Context, string, string, string) error) {
ctx := context.Background()
results := []map[string]interface{}{}
@@ -40,7 +40,7 @@ func processBatchLabelOperation(issueIDs []string, label string, operation strin
continue
}
if jsonOutput {
if jsonOut {
results = append(results, map[string]interface{}{
"status": operation,
"issue_id": issueID,
@@ -62,7 +62,7 @@ func processBatchLabelOperation(issueIDs []string, label string, operation strin
markDirtyAndScheduleFlush()
}
if jsonOutput && len(results) > 0 {
if jsonOut && len(results) > 0 {
outputJSON(results)
}
}
@@ -79,6 +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")
issueIDs, label := parseLabelArgs(args)
// Resolve partial IDs
@@ -107,7 +108,7 @@ var labelAddCmd = &cobra.Command{
}
issueIDs = resolvedIDs
processBatchLabelOperation(issueIDs, label, "added",
processBatchLabelOperation(issueIDs, label, "added", jsonOutput,
func(issueID, lbl string) error {
_, err := daemonClient.AddLabel(&rpc.LabelAddArgs{ID: issueID, Label: lbl})
return err
@@ -124,6 +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")
issueIDs, label := parseLabelArgs(args)
// Resolve partial IDs
@@ -152,7 +154,7 @@ var labelRemoveCmd = &cobra.Command{
}
issueIDs = resolvedIDs
processBatchLabelOperation(issueIDs, label, "removed",
processBatchLabelOperation(issueIDs, label, "removed", jsonOutput,
func(issueID, lbl string) error {
_, err := daemonClient.RemoveLabel(&rpc.LabelRemoveArgs{ID: issueID, Label: lbl})
return err
@@ -168,6 +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")
ctx := context.Background()
// Resolve partial ID first
@@ -242,6 +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")
ctx := context.Background()
var issues []*types.Issue
@@ -342,6 +346,11 @@ var labelListAllCmd = &cobra.Command{
}
func init() {
labelAddCmd.Flags().Bool("json", false, "Output JSON format")
labelRemoveCmd.Flags().Bool("json", false, "Output JSON format")
labelListCmd.Flags().Bool("json", false, "Output JSON format")
labelListAllCmd.Flags().Bool("json", false, "Output JSON format")
labelCmd.AddCommand(labelAddCmd)
labelCmd.AddCommand(labelRemoveCmd)
labelCmd.AddCommand(labelListCmd)

View File

@@ -43,6 +43,7 @@ Example:
sourceIDs := args
dryRun, _ := cmd.Flags().GetBool("dry-run")
jsonOutput, _ := cmd.Flags().GetBool("json")
// Validate merge operation
if err := validateMerge(targetID, sourceIDs); err != nil {
@@ -96,6 +97,7 @@ Example:
func init() {
mergeCmd.Flags().String("into", "", "Target issue ID to merge into (required)")
mergeCmd.Flags().Bool("dry-run", false, "Validate without making changes")
mergeCmd.Flags().Bool("json", false, "Output JSON format")
rootCmd.AddCommand(mergeCmd)
}

View File

@@ -206,6 +206,8 @@ var statsCmd = &cobra.Command{
Use: "stats",
Short: "Show statistics",
Run: func(cmd *cobra.Command, args []string) {
jsonOutput, _ := cmd.Flags().GetBool("json")
// If daemon is running, use RPC
if daemonClient != nil {
resp, err := daemonClient.Stats()
@@ -296,6 +298,8 @@ func init() {
readyCmd.Flags().StringP("sort", "s", "hybrid", "Sort policy: hybrid (default), priority, oldest")
readyCmd.Flags().Bool("json", false, "Output JSON format")
statsCmd.Flags().Bool("json", false, "Output JSON format")
rootCmd.AddCommand(readyCmd)
rootCmd.AddCommand(blockedCmd)
rootCmd.AddCommand(statsCmd)

View File

@@ -22,6 +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")
ctx := context.Background()
@@ -146,5 +147,6 @@ This is more explicit than 'bd update --status open' and emits a Reopened event.
func init() {
reopenCmd.Flags().StringP("reason", "r", "", "Reason for reopening")
reopenCmd.Flags().Bool("json", false, "Output JSON format")
rootCmd.AddCommand(reopenCmd)
}

View File

@@ -20,6 +20,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")
ctx := context.Background()
// Resolve partial IDs first
@@ -329,6 +330,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")
updates := make(map[string]interface{})
if cmd.Flags().Changed("status") {
@@ -691,6 +693,7 @@ var closeCmd = &cobra.Command{
if reason == "" {
reason = "Closed"
}
jsonOutput, _ := cmd.Flags().GetBool("json")
ctx := context.Background()
@@ -776,6 +779,7 @@ var closeCmd = &cobra.Command{
}
func init() {
showCmd.Flags().Bool("json", false, "Output JSON format")
rootCmd.AddCommand(showCmd)
updateCmd.Flags().StringP("status", "s", "", "New status")
@@ -789,6 +793,7 @@ func init() {
updateCmd.Flags().String("acceptance-criteria", "", "DEPRECATED: use --acceptance")
_ = updateCmd.Flags().MarkHidden("acceptance-criteria")
updateCmd.Flags().String("external-ref", "", "External reference (e.g., 'gh-9', 'jira-ABC')")
updateCmd.Flags().Bool("json", false, "Output JSON format")
rootCmd.AddCommand(updateCmd)
editCmd.Flags().Bool("title", false, "Edit the title")
@@ -799,5 +804,6 @@ func init() {
rootCmd.AddCommand(editCmd)
closeCmd.Flags().StringP("reason", "r", "", "Reason for closing")
closeCmd.Flags().Bool("json", false, "Output JSON format")
rootCmd.AddCommand(closeCmd)
}