Overview
Validators in envcheck are modular components that check specific aspects of your development environment. Each validator implements theValidator trait and returns validation results.
Understanding the Validator Trait
All validators implement this trait (defined insrc/validators/mod.rs:52):
ValidationResult Structure
Validators returnValidationResult objects (defined in src/validators/mod.rs:20):
ValidationStatus::Success- Check passedValidationStatus::Warning- Optional check failedValidationStatus::Error- Required check failed
Helper Methods
Use these helper methods to create results:Step-by-Step Guide
Step 1: Create the Validator File
Create a new file insrc/validators/ for your validator. For example, to add a database validator:
Step 2: Define the Configuration Structure
First, add a configuration struct insrc/config.rs. This defines what users can configure:
Config struct:
Step 3: Implement the Validator
Here’s a complete example based on theEnvValidator pattern (src/validators/env.rs:1):
Step 4: Register the Validator Module
Add your validator tosrc/validators/mod.rs:5:
Step 5: Integrate Into Validation Runner
Add your validator to therun_all_validations function in src/validators/mod.rs:56:
Real-World Example: EnvValidator
Let’s examine theEnvValidator (src/validators/env.rs:1) as a complete example:
- Required vs Optional: Check
self.check.requiredto return errors vs warnings - Helpful suggestions: Always provide actionable suggestions in error/warning messages
- Multiple results: You can push multiple
ValidationResultobjects for complex checks
Real-World Example: FileValidator
TheFileValidator (src/validators/file.rs:1) shows more complex validation:
- Multiple validation steps: First check existence, then type, then permissions
- Conditional checks: Only check permissions if the file exists and is the right type
- Platform-specific code: Using
#[cfg(unix)]for Unix-only features - Specific error messages: Different messages for different failure modes
Adding Tests
Always add tests for your validator. Here’s an example pattern:Best Practices
1. Clear Error Messages
Always provide clear, actionable error messages:2. Respect the Required Flag
Always check therequired field and return appropriate status:
3. Return Multiple Results When Appropriate
Don’t hesitate to return multiple validation results for complex checks:4. Use Rust Idioms
- Use pattern matching instead of if-else chains
- Leverage the
?operator for error propagation - Use descriptive variable names
- Keep functions focused and small
5. Handle Edge Cases
Consider edge cases in your validation:- Missing dependencies
- Permission issues
- Platform differences (Windows vs Unix)
- Network timeouts
- Malformed input
Documentation
After implementing your validator, update the documentation:- Add examples to
README.mdshowing how to use your validator - Document the configuration options
- Provide real-world use cases
Checklist
Before submitting your validator:- Created validator file in
src/validators/ - Added configuration struct to
src/config.rs - Implemented the
Validatortrait - Registered module in
src/validators/mod.rs - Integrated into
run_all_validations - Added unit tests
- Tested with real configuration
- Ran
cargo fmtandcargo clippy - Updated documentation
- All tests pass (
cargo test)
Getting Help
If you’re stuck:- Look at existing validators for patterns
- Open a draft PR and ask for feedback
- Create an issue with your questions
- Check for
good first issuelabels for simpler starting points
