Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,19 @@ Manage multiple environments (dev, staging, prod) using profiles.
| `execution task-poll <type>` | Poll for tasks | task type | `orkes execution task-poll my_task --count 5` |
| `execution task-update` | Update task by ref name | workflow-id, task-ref-name, status | `orkes execution task-update --workflow-id abc --task-ref-name task1 --status COMPLETED` |

### Config Commands

| Command | Description | Required Args | Optional Flags | Example |
|---------|-------------|---------------|----------------|---------|
| `config save` | Save current configuration | None | `--profile` | `orkes --server http://localhost:8080/api --auth-key key --profile production config save` |
| `config list` | List all configuration profiles | None | None | `orkes config list` |
| `config delete [profile]` | Delete configuration file | None | `--profile`, `-y` | `orkes config delete production` or `orkes config delete --profile production -y` |

**Notes:**
- `config save`: Use `--profile <name>` to save to a named profile (e.g., `config-production.yaml`). Without it, saves to default `config.yaml`.
- `config list`: Shows all profiles. Default config shown as "default", named profiles show as profile name only.
- `config delete`: Profile can be specified as positional arg or via `--profile` flag. Use `-y` to skip confirmation prompt.

### Webhook Commands

| Command | Description | Required Args | Example |
Expand Down
74 changes: 69 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -163,17 +163,29 @@ Profiles allow you to manage multiple Conductor environments (e.g., development,

**Creating a Profile:**

Save your current flags to a named profile:
Save your current flags to a named profile using the `config save` command:

```bash
# Save to default profile (~/.conductor-cli/config.yaml)
orkes --server https://dev.example.com --auth-key key123 --save-config workflow list
orkes --server https://dev.example.com --auth-key key123 config save

# Save to named profile (~/.conductor-cli/config-production.yaml)
orkes --server https://prod.example.com --auth-token token --save-config=production workflow list
orkes --server https://prod.example.com --auth-token token --profile production config save
```

**Deleting a Profile:**

# Create multiple profiles
orkes --server https://staging.example.com --auth-key key --save-config=staging workflow list
Delete a configuration file using the `config delete` command:

```bash
# Delete default config (with confirmation prompt)
orkes config delete

# Delete named profile (with confirmation prompt)
orkes config delete production

# Delete without confirmation
orkes config delete production -y
```

**Using a Profile:**
Expand Down Expand Up @@ -211,6 +223,58 @@ orkes --profile nonexistent workflow list
# Error: Profile 'nonexistent' doesn't exist (expected file: ~/.conductor-cli/config-nonexistent.yaml)
```

## Config Management Commands

The CLI provides dedicated commands for managing configuration files:

### Save Configuration

```bash
# Save to default config file
orkes --server http://localhost:8080/api --auth-key key123 config save

# Save to a named profile (using --profile flag)
orkes --server https://prod.example.com --auth-token token --profile production config save

# Flags can be placed before or after the command
orkes config save --server http://localhost:8080/api --auth-key key123 --profile staging
```

### List Configurations

```bash
# List all configuration profiles
orkes config list
```

This shows:
- `default` - for the default `config.yaml` file
- Profile names (e.g., `production`, `staging`) - for named profiles like `config-production.yaml`

### Delete Configuration

```bash
# Delete default config (with confirmation prompt)
orkes config delete

# Delete named profile using positional argument
orkes config delete production

# Delete named profile using --profile flag
orkes config delete --profile production

# Delete without confirmation using -y flag
orkes config delete production -y
orkes config delete --profile staging -y
```

**Notes:**
- The `--profile` flag specifies which profile to save/delete
- Without `--profile`, operations affect the default `config.yaml`
- `config list` shows all available profiles in `~/.conductor-cli/` directory
- Delete operations require confirmation unless `-y` flag is used
- Both positional argument and `--profile` flag work for delete command

## Workflow Metadata Management

```shell
Expand Down
201 changes: 184 additions & 17 deletions cmd/config.go
Original file line number Diff line number Diff line change
@@ -1,28 +1,195 @@
package cmd

import (
"bufio"
"fmt"
"os"
"path/filepath"
"strings"

"github.com/spf13/cobra"
)

const CONDUCTOR_SERVER_URL = "CONDUCTOR_SERVER_URL"
const CONDUCTOR_AUTH_KEY = "CONDUCTOR_AUTH_KEY"
const CONDUCTOR_AUTH_SECRET = "CONDUCTOR_AUTH_SECRET"
const CONDUCTOR_AUTH_TOKEN = "CONDUCTOR_AUTH_TOKEN"
var configCmd = &cobra.Command{
Use: "config",
Short: "CLI configuration management",
}

var configSaveCmd = &cobra.Command{
Use: "save",
Short: "Save current configuration to file",
Long: `Save the current server and authentication settings to a configuration file.

The configuration will be saved to ~/.conductor-cli/config.yaml by default,
or to a profile-specific file if --profile is specified.

Examples:
# Save to default config file
orkes --server http://localhost:8080/api --auth-key key123 config save

type Config struct {
URL string `json:url`
Token string `json:token`
Key string `json:token`
Secret string `json:token`
# Save to a named profile
orkes --server https://prod.example.com --auth-token token123 --profile production config save
`,
RunE: func(cmd *cobra.Command, args []string) error {
profileName := profile

if err := saveConfigFile(profileName); err != nil {
return fmt.Errorf("failed to save config: %w", err)
}

configFileName := "config.yaml"
if profileName != "" {
configFileName = fmt.Sprintf("config-%s.yaml", profileName)
}

fmt.Fprintf(os.Stderr, "✓ Configuration saved to ~/.conductor-cli/%s\n", configFileName)
return nil
},
SilenceUsage: true,
}

func getActiveConfig() *Config {
var configListCmd = &cobra.Command{
Use: "list",
Short: "List all configuration profiles",
Long: `List all configuration profiles in ~/.conductor-cli directory.

Shows the default config.yaml and all named profiles (config-<profile>.yaml).

Examples:
# List all config profiles
orkes config list
`,
RunE: func(cmd *cobra.Command, args []string) error {
home, err := os.UserHomeDir()
if err != nil {
return err
}

configDir := filepath.Join(home, ".conductor-cli")

// Check if config directory exists
if _, err := os.Stat(configDir); os.IsNotExist(err) {
fmt.Println("No configuration files found")
return nil
}

// Read all files in config directory
files, err := os.ReadDir(configDir)
if err != nil {
return fmt.Errorf("failed to read config directory: %w", err)
}

hasConfigs := false
for _, file := range files {
if file.IsDir() {
continue
}

name := file.Name()

// Handle default config.yaml
if name == "config.yaml" {
fmt.Println("default")
hasConfigs = true
continue
}

// Handle named profiles: config-<profile>.yaml
if strings.HasPrefix(name, "config-") && strings.HasSuffix(name, ".yaml") {
profileName := strings.TrimPrefix(name, "config-")
profileName = strings.TrimSuffix(profileName, ".yaml")
fmt.Println(profileName)
hasConfigs = true
}
}

if !hasConfigs {
fmt.Println("No configuration files found")
}

return nil
},
SilenceUsage: true,
}

var configDeleteCmd = &cobra.Command{
Use: "delete [profile]",
Short: "Delete a configuration file",
Long: `Delete a configuration file.

If no profile is specified, the default config.yaml will be deleted.
Profile can be specified either as a positional argument or via --profile flag.

Examples:
# Delete default config file (requires confirmation)
orkes config delete

# Delete a named profile using positional argument
orkes config delete production

# Delete a named profile using --profile flag
orkes config delete --profile production

# Delete without confirmation
orkes config delete production -y
`,
RunE: func(cmd *cobra.Command, args []string) error {
home, err := os.UserHomeDir()
if err != nil {
return err
}

configDir := filepath.Join(home, ".conductor-cli")

// Get profile name from either positional arg or --profile flag
var profileName string
if len(args) > 0 {
profileName = args[0]
} else if profile != "" {
profileName = profile
}

configFileName := "config.yaml"
if profileName != "" {
configFileName = fmt.Sprintf("config-%s.yaml", profileName)
}

configPath := filepath.Join(configDir, configFileName)

// Check if config file exists
if _, err := os.Stat(configPath); os.IsNotExist(err) {
return fmt.Errorf("config file does not exist: %s", configPath)
}

// Ask for confirmation unless -y flag is set
if !yes {
reader := bufio.NewReader(os.Stdin)
fmt.Fprintf(os.Stderr, "Are you sure you want to delete %s? [y/N]: ", configPath)
response, err := reader.ReadString('\n')
if err != nil {
return err
}
response = strings.ToLower(strings.TrimSpace(response))
if response != "y" && response != "yes" {
fmt.Fprintf(os.Stderr, "Deletion cancelled\n")
return nil
}
}

// Delete the file
if err := os.Remove(configPath); err != nil {
return fmt.Errorf("failed to delete config file: %w", err)
}

fmt.Fprintf(os.Stderr, "✓ Configuration deleted: %s\n", configPath)
return nil
},
SilenceUsage: true,
}

config := Config{
URL: os.Getenv(CONDUCTOR_SERVER_URL),
Token: os.Getenv(CONDUCTOR_AUTH_TOKEN),
Key: os.Getenv(CONDUCTOR_AUTH_KEY),
Secret: os.Getenv(CONDUCTOR_AUTH_SECRET),
}
return &config
func init() {
rootCmd.AddCommand(configCmd)
configCmd.AddCommand(configSaveCmd)
configCmd.AddCommand(configListCmd)
configCmd.AddCommand(configDeleteCmd)
}
Loading
Loading