Skip to content

Commit 9f4ebf9

Browse files
feat(cli): add manifest delete command
Implement manifest delete subcommand to allow users to remove flags from their manifest file via the CLI. This complements the existing add subcommand and provides complete flag lifecycle management. Features: - Command validates flag exists before deletion - Uses atomic temp file pattern for safe I/O operations - Provides clear success/error feedback - Follows existing CLI patterns and conventions - Includes comprehensive unit tests (9 test cases) - Handles edge cases (empty manifest, non-existent flags, etc.) Fixes #154 Signed-off-by: Liam <[email protected]>
1 parent b255228 commit 9f4ebf9

File tree

4 files changed

+559
-0
lines changed

4 files changed

+559
-0
lines changed

internal/cmd/manifest.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ func GetManifestCmd() *cobra.Command {
2121
// Add subcommands
2222
manifestCmd.AddCommand(GetManifestAddCmd())
2323
manifestCmd.AddCommand(GetManifestListCmd())
24+
manifestCmd.AddCommand(GetManifestDeleteCmd())
2425

2526
addStabilityInfo(manifestCmd)
2627

internal/cmd/manifest_delete.go

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
package cmd
2+
3+
import (
4+
"fmt"
5+
6+
"github.com/open-feature/cli/internal/config"
7+
"github.com/open-feature/cli/internal/filesystem"
8+
"github.com/open-feature/cli/internal/logger"
9+
"github.com/open-feature/cli/internal/manifest"
10+
"github.com/pterm/pterm"
11+
"github.com/spf13/afero"
12+
"github.com/spf13/cobra"
13+
)
14+
15+
func GetManifestDeleteCmd() *cobra.Command {
16+
manifestDeleteCmd := &cobra.Command{
17+
Use: "delete <flag-name>",
18+
Short: "Delete a flag from the manifest",
19+
Long: `Delete a flag from the manifest file by its key.
20+
21+
Examples:
22+
# Delete a flag named 'old-feature'
23+
openfeature manifest delete old-feature
24+
25+
# Delete a flag from a specific manifest file
26+
openfeature manifest delete old-feature --manifest path/to/flags.json`,
27+
Args: cobra.ExactArgs(1),
28+
PreRunE: func(cmd *cobra.Command, args []string) error {
29+
return initializeConfig(cmd, "manifest.delete")
30+
},
31+
RunE: func(cmd *cobra.Command, args []string) error {
32+
flagName := args[0]
33+
manifestPath := config.GetManifestPath(cmd)
34+
35+
// Check if manifest exists
36+
exists, err := afero.Exists(filesystem.FileSystem(), manifestPath)
37+
if err != nil {
38+
return fmt.Errorf("failed to check manifest existence: %w", err)
39+
}
40+
41+
if !exists {
42+
return fmt.Errorf("manifest file does not exist: %s", manifestPath)
43+
}
44+
45+
// Load existing manifest
46+
fs, err := manifest.LoadFlagSet(manifestPath)
47+
if err != nil {
48+
return fmt.Errorf("failed to load manifest: %w", err)
49+
}
50+
51+
// Check if manifest has any flags
52+
if len(fs.Flags) == 0 {
53+
return fmt.Errorf("manifest contains no flags")
54+
}
55+
56+
// Check if flag exists
57+
flagIndex := -1
58+
for i, flag := range fs.Flags {
59+
if flag.Key == flagName {
60+
flagIndex = i
61+
break
62+
}
63+
}
64+
65+
if flagIndex == -1 {
66+
return fmt.Errorf("flag '%s' not found in manifest", flagName)
67+
}
68+
69+
// Remove the flag by creating a new slice without it
70+
fs.Flags = append(fs.Flags[:flagIndex], fs.Flags[flagIndex+1:]...)
71+
72+
// Write updated manifest
73+
if err := manifest.Write(manifestPath, *fs); err != nil {
74+
return fmt.Errorf("failed to write manifest: %w", err)
75+
}
76+
77+
// Success message
78+
pterm.Success.Printfln("Flag '%s' deleted successfully from %s", flagName, manifestPath)
79+
logger.Default.Debug(fmt.Sprintf("Deleted flag: name=%s, manifestPath=%s", flagName, manifestPath))
80+
81+
return nil
82+
},
83+
}
84+
85+
// Add command-specific flags
86+
config.AddManifestDeleteFlags(manifestDeleteCmd)
87+
addStabilityInfo(manifestDeleteCmd)
88+
89+
return manifestDeleteCmd
90+
}

0 commit comments

Comments
 (0)