-
Notifications
You must be signed in to change notification settings - Fork 2
Open
Labels
enhancementNew feature or requestNew feature or request
Description
Command Flow Guardrails: Dependency Management for CLI Commands
Overview
Command Flow Guardrails detect when CLI commands are run out of expected sequence and provide context-aware error messages to guide users. This feature ensures commands like avs call
(which depends on avs contract-deploy
) fail gracefully with helpful guidance.
Key Components
- Command Dependency Definitions: Map of commands to their prerequisites
- Command History Tracking: In-memory registry of executed commands
- Dependency Checking Middleware: Validates dependencies before execution
- Contextual Error Messages: Guides users to the correct next actions
Implementation
1. Command Dependency Definition
// CommandDependency defines a command dependency relationship
type CommandDependency struct {
Command string // Command that has dependencies
DependsOn []string // Commands that must be run before this command
ErrorMessage string // Helpful message when dependency isn't met
CheckFunc func() bool // Optional additional validation
}
// Sample dependencies
var CommandFlowDependencies = []CommandDependency{
{
Command: "call",
DependsOn: []string{"deploy-contracts"},
ErrorMessage: "The 'avs call' command requires contract deployment. " +
"Please run 'devkit avs devnet start' or 'devkit avs devnet deploy-contracts' first.",
CheckFunc: checkContractsDeployed,
},
// Other dependencies...
}
2. Command Execution Tracking
// Track command execution history
var commandHistory = struct {
executedCommands map[string]bool
mu sync.Mutex
}{
executedCommands: make(map[string]bool),
}
// Record successful command execution
func recordCommandExecution(command string) {
commandHistory.mu.Lock()
defer commandHistory.mu.Unlock()
commandHistory.executedCommands[command] = true
}
3. Dependency Checking Middleware
// Middleware that enforces command dependencies
func WithCommandDependencyCheck(action cli.ActionFunc) cli.ActionFunc {
return func(ctx *cli.Context) error {
cmdName := ctx.Command.Name
// Skip checks for create command (entry point)
if cmdName == "create" {
result := action(ctx)
if result == nil {
recordCommandExecution(cmdName)
}
return result
}
// Check dependencies
for _, dep := range CommandFlowDependencies {
if dep.Command == cmdName {
for _, depCmd := range dep.DependsOn {
if !hasCommandBeenExecuted(depCmd) &&
!(dep.CheckFunc != nil && dep.CheckFunc()) {
return errors.New(dep.ErrorMessage)
}
}
}
}
// Execute command and record success
result := action(ctx)
if result == nil {
recordCommandExecution(cmdName)
}
return result
}
}
4. Integration with CLI Framework
func main() {
actionChain := hooks.NewActionChain()
actionChain.Use(WithCommandDependencyCheck)
hooks.ApplyMiddleware(app.Commands, actionChain)
}
User Experience
When a user attempts to run a command before its prerequisites:
$ devkit avs call signature="(uint256)" args="(5)"
Error: The 'avs call' command requires contract deployment.
Please run 'devkit avs devnet start' or 'devkit avs devnet deploy-contracts' first.
- Users receive clear error message about the correct command sequence and next steps.
Additional Validations
For complex dependencies that can't be verified by simple command history:
// Validation function example
func checkContractsDeployed() bool {
// Check for config files with deployed contract addresses
contextPath := filepath.Join("config", "contexts", "devnet.yaml")
if _, err := os.Stat(contextPath); os.IsNotExist(err) {
return false
}
// Parse YAML and verify contract addresses exist
// [Implementation details...]
return contractsExist
}
Open questions
- Is there any check that should be made for
create
command ?
Example validations
- Check that fork url is set before devnet start is called in the context file
Metadata
Metadata
Assignees
Labels
enhancementNew feature or requestNew feature or request