Success Predicate Examples¶
Coverage Validation Predicate Examples¶
This directory contains example coverage validation predicates for use with the validate subcommand.
⚠️ SECURITY WARNING
Success predicates execute as arbitrary Ruby code with full system privileges. They have unrestricted access to: - File system operations (read, write, delete) - Network operations (HTTP requests, sockets) - System commands (via backticks,
system(),exec(), etc.) - Environment variables and sensitive dataOnly use predicate files from trusted sources. Treat them like any other executable code in your project. - Never use predicates from untrusted or unknown sources - Review predicates before use, especially in CI/CD environments - Store predicates in version control with code review - Be cautious when copying examples from the internet
Usage¶
File mode:
String mode:
The predicate receives a CoverageModel instance and returns: - Truthy value → Exit code 0 (success) - Falsy value → Exit code 1 (failure) - Exception → Exit code 2 (error)
Available Examples¶
all_files_above_threshold_predicate.rb¶
All files must have >= 80% coverage.
project_coverage_minimum_predicate.rb¶
Total project coverage must be >= 85%.
directory_specific_thresholds_predicate.rb¶
Different thresholds for different directories: - lib/api/ - 90% required - lib/core/ - 85% required - lib/legacy/ - 60% required
Creating Custom Predicates¶
A predicate must be a callable object (lambda, proc, or class with #call method):
Lambda example:
Class method example:
class MyPolicy
def self.call(model)
model.list['files'].all? { |f| f['percentage'] >= @threshold }
end
end
MyPolicy # The class itself
Instance method example:
class MyPolicy
def initialize(threshold = 80)
@threshold = threshold
end
def call(model)
model.list['files'].all? { |f| f['percentage'] >= @threshold }
end
end
MyPolicy
CoverageModel API¶
The model parameter provides:
# Get all files
files = model.list['files']
# => [{ "file" => "...", "covered" => 12, "total" => 14, "percentage" => 85.71, "stale" => false }, ...]
# Filter by globs
api_files = model.list(tracked_globs: ['lib/api/**/*.rb'])['files']
# Get specific file data
summary = model.summary_for('lib/model.rb')
uncovered = model.uncovered_for('lib/model.rb')
See docs/user/LIBRARY_API.md for the complete API.
When to Use Standalone Scripts Instead¶
For more complex scenarios, you may prefer writing a standalone Ruby script that uses the cov-loupe library directly instead of using the validate subcommand.
Use a standalone script when: - External dependencies needed - Your policy requires other gems or libraries - Complex setup required - You need custom logging, database connections, or API calls - Easier testing desired - Standalone scripts can be tested like any Ruby code - More explicit control - You want full control over model initialization and error handling - Sophisticated logic - Multi-step analysis, data aggregation, or integration with other tools
Predicate approach is better when: - Policy is simple and self-contained (most common use case) - You want the tool to handle option parsing (--resultset, --raise-on-stale, etc.) - Consistent error handling and exit codes are desired - Less boilerplate is preferred
Example standalone script:
#!/usr/bin/env ruby
require 'cov_loupe'
require 'httparty' # External gem
# Custom initialization
model = CovLoupe::CoverageModel.new(
resultset: ENV['COVERAGE_PATH'],
raise_on_stale: true
)
# Complex logic with external API
files = model.list['files']
low_coverage_files = files.select { |f| f['percentage'] < 80 }
# Post to Slack
if low_coverage_files.any?
HTTParty.post(
ENV['SLACK_WEBHOOK_URL'],
body: { text: "#{low_coverage_files.size} files below 80%" }.to_json
)
exit 1
else
exit 0
end
Both approaches execute arbitrary code with full system privileges, so the security considerations are identical. Choose the approach that best fits your use case.
CI/CD Integration¶
GitHub Actions:
GitLab CI:
Jenkins:
Exit Codes¶
- 0 - Predicate returned truthy (success)
- 1 - Predicate returned falsy (failure)
- 2 - Predicate raised an error
Use exit code 1 to fail CI/CD builds when coverage doesn't meet policy.