Guide for adding new YAML linting rules to yaml-lint-rs. Use when implementing a new validation rule, creating a linting feature, or when the user mentions adding rules like "truthy", "comments", "braces", etc.
설치
Codex 또는 Claude로 설치 이 Prompt를 복사해 Codex, Claude 또는 다른 어시스턴트에 붙여 넣으면 Skill 페이지를 검토하고 설치를 진행할 수 있습니다.
Guide for adding new YAML linting rules to yaml-lint-rs. Use when implementing a new validation rule, creating a linting feature, or when the user mentions adding rules like "truthy", "comments", "braces", etc.
Adding New Validation Rules
This skill provides step-by-step guidance for implementing new YAML linting rules in the yaml-lint-rs project.
Quick Checklist
When adding a new rule, complete these steps in order:
Create rule file: core/src/rules/<rule_name>.rs
Register in core/src/rules/mod.rs
Add to presets in core/src/config.rs
Add unit tests (minimum 10+ test cases)
Create test fixture: tests/fixtures/invalid/<rule-name>.yaml
Add integration test in core/tests/integration_tests.rs
Update docs/RULES.md
Update README.md rule list
Run make ci and make validate-fixtures to verify
Create PR
Step 1: Create Rule File
Create core/src/rules/<rule_name>.rs with this template:
// In with_default_preset():
config.rules.insert("<rule-name>".to_string(), RuleLevel::Error);
// or RuleLevel::Warning for less critical rules// In with_relaxed_preset():
config.rules.insert("<rule-name>".to_string(), RuleLevel::Warning);
Create an invalid YAML fixture file at tests/fixtures/invalid/<rule-name>.yaml:
# File demonstrating <rule-name> violations# This file should trigger the rule multiple times# Example for truthy rule:enabled:yesdisabled:noflag:on# Example for trailing-spaces rule:key:valueanother:test
Fixture Guidelines:
Include a comment at the top explaining the violations
Include multiple violations (3+ recommended)
Cover different scenarios the rule checks
Keep it focused on ONE rule per fixture file
Directory Structure:
tests/fixtures/
├── invalid/ # Files with lint errors
│ ├── <rule-name>.yaml
│ ├── trailing-spaces.yaml
│ └── ...
└── valid/ # Files that should pass all rules
├── simple.yaml
└── ...
Step 6: Add Integration Test
Edit core/tests/integration_tests.rs to add a test for the new rule:
#[test]fntest_<rule_name>_detected() {
letlinter = Linter::with_defaults();
letpath = fixture_path("invalid/<rule-name>.yaml");
letproblems = linter.lint_file(&path).expect("Failed to lint file");
assert!(!problems.is_empty(), "Expected to find <rule-name> violations");
// Verify expected number of problemsletrule_problems: Vec<_> = problems
.iter()
.filter(|p| p.rule == "<rule-name>")
.collect();
assert_eq!(
rule_problems.len(),
3, // Adjust based on your fixture"Expected 3 <rule-name> problems"
);
// Verify rule nameforproblemin &rule_problems {
assert_eq!(problem.rule, "<rule-name>");
}
}
Also update:
- Preset documentation (if rule is in default/relaxed)
- Remove from "Future Rules" section if listed there
## Step 8: Update README.md
Add to the "Implemented Rules" section:
```markdown
N. **<rule-name>** - <Brief description>
- Level: Error/Warning
- Options: `option1`, `option2` (if configurable)
Update "Future Rules" section if needed.
Step 9: Run CI
make ci # fmt-check + clippy + test
make validate-fixtures # Validate test fixtures
Fix any issues:
make fmt for formatting
Address clippy warnings
Fix failing tests
Fixture Validation:
make validate-fixtures runs the linter on all fixtures and verifies:
Valid fixtures produce 0 errors
Invalid fixtures produce expected errors
Step 10: Create PR
git checkout -b feature/<issue-number>-<rule-name>-rule
git add -A
git commit -m "feat: Add \`<rule-name>\` rule
<Description of what the rule does>
Closes #<issue-number>"
git push -u origin feature/<issue-number>-<rule-name>-rule
gh pr create --title "feat: Add \`<rule-name>\` rule" --body "..."
Common Patterns
Handling Quoted Strings
Use peekable iterator for proper YAML string parsing: