feat(bd): add --ephemeral and --persistent flags to bd update (#1263)
Adds --ephemeral and --persistent flags to bd update command. Author: aleiby
This commit is contained in:
@@ -312,6 +312,94 @@ func TestCLI_UpdateLabels(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestCLI_UpdateEphemeral(t *testing.T) {
|
||||
if testing.Short() {
|
||||
t.Skip("skipping slow CLI test in short mode")
|
||||
}
|
||||
// Note: Not using t.Parallel() because inProcessMutex serializes execution anyway
|
||||
tmpDir := setupCLITestDB(t)
|
||||
out := runBDInProcess(t, tmpDir, "create", "Issue for ephemeral testing", "-p", "2", "--json")
|
||||
|
||||
var issue map[string]interface{}
|
||||
if err := json.Unmarshal([]byte(out), &issue); err != nil {
|
||||
t.Fatalf("Failed to parse create output: %v", err)
|
||||
}
|
||||
id := issue["id"].(string)
|
||||
|
||||
// Mark as ephemeral
|
||||
runBDInProcess(t, tmpDir, "update", id, "--ephemeral")
|
||||
|
||||
out = runBDInProcess(t, tmpDir, "show", id, "--json")
|
||||
var updated []map[string]interface{}
|
||||
if err := json.Unmarshal([]byte(out), &updated); err != nil {
|
||||
t.Fatalf("Failed to parse show output: %v", err)
|
||||
}
|
||||
if updated[0]["ephemeral"] != true {
|
||||
t.Errorf("Expected ephemeral to be true after --ephemeral, got: %v", updated[0]["ephemeral"])
|
||||
}
|
||||
}
|
||||
|
||||
func TestCLI_UpdatePersistent(t *testing.T) {
|
||||
if testing.Short() {
|
||||
t.Skip("skipping slow CLI test in short mode")
|
||||
}
|
||||
// Note: Not using t.Parallel() because inProcessMutex serializes execution anyway
|
||||
tmpDir := setupCLITestDB(t)
|
||||
|
||||
// Create ephemeral issue directly
|
||||
out := runBDInProcess(t, tmpDir, "create", "Ephemeral issue", "-p", "2", "--ephemeral", "--json")
|
||||
|
||||
var issue map[string]interface{}
|
||||
if err := json.Unmarshal([]byte(out), &issue); err != nil {
|
||||
t.Fatalf("Failed to parse create output: %v", err)
|
||||
}
|
||||
id := issue["id"].(string)
|
||||
|
||||
// Verify it's ephemeral
|
||||
out = runBDInProcess(t, tmpDir, "show", id, "--json")
|
||||
var initial []map[string]interface{}
|
||||
if err := json.Unmarshal([]byte(out), &initial); err != nil {
|
||||
t.Fatalf("Failed to parse show output: %v", err)
|
||||
}
|
||||
if initial[0]["ephemeral"] != true {
|
||||
t.Fatalf("Expected issue to be ephemeral initially, got: %v", initial[0]["ephemeral"])
|
||||
}
|
||||
|
||||
// Promote to persistent
|
||||
runBDInProcess(t, tmpDir, "update", id, "--persistent")
|
||||
|
||||
out = runBDInProcess(t, tmpDir, "show", id, "--json")
|
||||
var updated []map[string]interface{}
|
||||
if err := json.Unmarshal([]byte(out), &updated); err != nil {
|
||||
t.Fatalf("Failed to parse show output after persistent: %v", err)
|
||||
}
|
||||
if updated[0]["ephemeral"] == true {
|
||||
t.Errorf("Expected ephemeral to be false after --persistent, got: %v", updated[0]["ephemeral"])
|
||||
}
|
||||
}
|
||||
|
||||
func TestCLI_UpdateEphemeralMutualExclusion(t *testing.T) {
|
||||
if testing.Short() {
|
||||
t.Skip("skipping slow CLI test in short mode")
|
||||
}
|
||||
// Note: Not using t.Parallel() because inProcessMutex serializes execution anyway
|
||||
tmpDir := setupCLITestDB(t)
|
||||
out := runBDInProcess(t, tmpDir, "create", "Issue for mutual exclusion test", "-p", "2", "--json")
|
||||
|
||||
var issue map[string]interface{}
|
||||
json.Unmarshal([]byte(out), &issue)
|
||||
id := issue["id"].(string)
|
||||
|
||||
// Both flags should error
|
||||
_, stderr, err := runBDInProcessAllowError(t, tmpDir, "update", id, "--ephemeral", "--persistent")
|
||||
if err == nil {
|
||||
t.Errorf("Expected error when both flags specified, got none")
|
||||
}
|
||||
if !strings.Contains(stderr, "cannot specify both") {
|
||||
t.Errorf("Expected mutual exclusion error message, got: %v", stderr)
|
||||
}
|
||||
}
|
||||
|
||||
func TestCLI_Close(t *testing.T) {
|
||||
if testing.Short() {
|
||||
t.Skip("skipping slow CLI test in short mode")
|
||||
|
||||
@@ -165,6 +165,19 @@ create, update, show, or close operation).`,
|
||||
updates["defer_until"] = t
|
||||
}
|
||||
}
|
||||
// Ephemeral/persistent flags
|
||||
// Note: storage layer uses "wisp" field name, maps to "ephemeral" column
|
||||
ephemeralChanged := cmd.Flags().Changed("ephemeral")
|
||||
persistentChanged := cmd.Flags().Changed("persistent")
|
||||
if ephemeralChanged && persistentChanged {
|
||||
FatalErrorRespectJSON("cannot specify both --ephemeral and --persistent flags")
|
||||
}
|
||||
if ephemeralChanged {
|
||||
updates["wisp"] = true
|
||||
}
|
||||
if persistentChanged {
|
||||
updates["wisp"] = false
|
||||
}
|
||||
|
||||
// Get claim flag
|
||||
claimFlag, _ := cmd.Flags().GetBool("claim")
|
||||
@@ -278,6 +291,10 @@ create, update, show, or close operation).`,
|
||||
empty := ""
|
||||
updateArgs.DeferUntil = &empty
|
||||
}
|
||||
// Ephemeral/persistent
|
||||
if wisp, ok := updates["wisp"].(bool); ok {
|
||||
updateArgs.Ephemeral = &wisp
|
||||
}
|
||||
|
||||
// Set claim flag for atomic claim operation
|
||||
updateArgs.Claim = claimFlag
|
||||
@@ -613,6 +630,9 @@ func init() {
|
||||
updateCmd.Flags().String("defer", "", "Defer until date (empty to clear). Issue hidden from bd ready until then")
|
||||
// Gate fields (bd-z6kw)
|
||||
updateCmd.Flags().String("await-id", "", "Set gate await_id (e.g., GitHub run ID for gh:run gates)")
|
||||
// Ephemeral/persistent flags
|
||||
updateCmd.Flags().Bool("ephemeral", false, "Mark issue as ephemeral (wisp) - not exported to JSONL")
|
||||
updateCmd.Flags().Bool("persistent", false, "Mark issue as persistent (promote wisp to regular issue)")
|
||||
updateCmd.ValidArgsFunction = issueIDCompletion
|
||||
rootCmd.AddCommand(updateCmd)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user