CLI tool for enforcing development guidelines
Project description
DevRulesAutomate your internal rules. Reduce errors. Accelerate onboarding. |
📜 License
DevRules is licensed under the Business Source License 1.1 (BSL).
What this means:
- ✅ Free for small companies - Organizations with < 100 employees can use in production
- ✅ Free for non-production - Anyone can use for development, testing, and evaluation
- ✅ Source available - Full source code is visible and modifiable
- ✅ Becomes open source - Converts to Apache 2.0 license on 2029-12-06 (4 years)
- 💼 Commercial license available - For larger organizations or production use beyond the grant
Need a commercial license? Contact pedroifgonzalez@gmail.com
See LICENSE for full details.
🎬 Demo
Branch Name Validation
Run Custom Rules
Custom Rules with Lifecycle Hooks
🚀 Features
- ✅ Branch naming validation - Enforce consistent branch naming conventions
- ✅ Commit message format checking - Validate commit message structure with GPG signing support
- ✅ Pull Request validation - Check PR size and title format
- ✅ Deployment workflow - Manage deployments across environments with Jenkins integration
- ⚙️ Configurable via TOML - Customize all rules to match your workflow
- 🔌 Git hooks integration - Automatic validation with pre-commit support
- 🎨 Interactive mode with Gum - Beautiful terminal UI with arrow-key selection and styled prompts
- 🌐 GitHub API integration - Manage issues, projects, and PRs directly
- 📊 TUI Dashboard - Interactive terminal dashboard for metrics and issue tracking
- 🏢 Enterprise builds - Create custom packages with embedded corporate configuration
- 🛠️ Custom Rules Engine - Define and run your own validation functions
- 🪝 Lifecycle Hooks - Attach custom rules to events (pre-commit, pre-deploy, etc.)
📦 Installation
pip install devrules
Optional: Install Gum for Enhanced UI
DevRules integrates with Gum for a beautiful interactive terminal experience. Install it for:
- Arrow-key selection menus
- Styled input prompts
- Formatted tables
- Colorful output
# macOS
brew install gum
# Linux (Debian/Ubuntu)
sudo mkdir -p /etc/apt/keyrings
curl -fsSL https://repo.charm.sh/apt/gpg.key | sudo gpg --dearmor -o /etc/apt/keyrings/charm.gpg
echo "deb [signed-by=/etc/apt/keyrings/charm.gpg] https://repo.charm.sh/apt/ * *" | sudo tee /etc/apt/sources.list.d/charm.list
sudo apt update && sudo apt install gum
# Windows (Scoop)
scoop install charm-gum
Note: Gum is optional. DevRules falls back to standard prompts if Gum is not installed.
🎯 Quick Start
- Initialize configuration:
devrules init-config
- Create a branch interactively:
devrules create-branch
- Validate a branch name:
devrules check-branch feature/123-new-feature
- Validate a commit message:
devrules check-commit .git/COMMIT_EDITMSG
- Validate a Pull Request:
export GH_TOKEN=your_github_token
devrules check-pr 42 --owner your-org --repo your-repo
# Or configure owner/repo in .devrules.toml and just run:
devrules check-pr 42
- Deploy to an environment:
# Configure deployment settings in .devrules.toml first
devrules deploy dev --branch feature/123-new-feature
# Or check deployment readiness without deploying
devrules check-deployment staging
- Launch the TUI Dashboard:
# Install with TUI support first
pip install "devrules[tui]"
# Run the dashboard
devrules dashboard
- Manage GitHub Issues:
# List issues from a project
devrules list-issues --project 6
# View issue details
devrules describe-issue 123
# Update issue status
devrules update-issue-status 123 --status "In Progress" --project 6
- Commit with validation:
devrules commit "[FTR] Add new feature"
⚙️ Configuration
Create a .devrules.toml file in your project root:
[branch]
pattern = "^(feature|bugfix|hotfix|release|docs)/(\\d+-)?[a-z0-9-]+"
prefixes = ["feature", "bugfix", "hotfix", "release", "docs"]
[commit]
tags = ["WIP", "FTR", "FIX", "DOCS", "TST"]
pattern = "^\\[({tags})\\].+"
min_length = 10
max_length = 100
gpg_sign = false # Sign commits with GPG
protected_branch_prefixes = ["staging-"] # Block direct commits to these branches
enable_ai_suggestions = false # Generate AI-powered commit message suggestions (requires diny)
[pr]
max_loc = 400
max_files = 20
require_title_tag = true
[github]
owner = "your-org"
repo = "your-repo"
For a complete configuration example, run devrules init-config.
AI-Powered Commit Messages
⚠️ Security Notice: When enable_ai_suggestions = true, your staged changes, diffs, and repository metadata may be sent to an external AI service (diny). Ensure you review the data handling policies and have appropriate consent before enabling this feature. Sensitive content such as credentials, secrets, or PII should not be present in your staged changes when using AI suggestions.
When enable_ai_suggestions = true is set in the [commit] section, DevRules can generate AI-powered commit message suggestions using the diny tool.
How it works:
- During commits, DevRules automatically generates a commit message suggestion based on your staged changes
- The AI-generated message appears as a default value that you can edit or replace
- Requires
dinyto be installed and available in your PATH - Default is disabled for security - you must explicitly enable it
Security Considerations:
- Review diny's privacy policy and data handling practices
- Ensure no sensitive information is in staged changes when using AI suggestions
- Consider using AI suggestions only for non-sensitive repositories
- The feature is opt-in and disabled by default for your security
🔗 Git Hooks Integration
Automatic Installation
Install git hooks with a single command:
devrules install-hooks
This creates a commit-msg hook that:
- Validates commit messages using devrules
- Runs any existing pre-commit hooks (if
pre-commitis installed)
To uninstall:
devrules uninstall-hooks
Manual Setup
Commit message validation:
# .git/hooks/commit-msg
#!/bin/bash
devrules check-commit "$1" || exit 1
Branch validation before push:
# .git/hooks/pre-push
#!/bin/bash
current_branch=$(git symbolic-ref --short HEAD)
devrules check-branch "$current_branch" || exit 1
⌨️ Command Aliases
Most commands have short aliases for convenience:
| Command | Alias | Description |
|---|---|---|
check-branch |
cb |
Validate branch name |
check-commit |
cc |
Validate commit message |
check-pr |
cpr |
Validate pull request |
create-branch |
nb |
Create new branch (interactive with Gum) |
commit |
ci |
Commit with validation |
icommit |
ic |
Interactive commit with tag selection |
create-pr |
pr |
Create pull request |
ipr |
- | Interactive PR with target selection |
init-config |
init |
Generate config file |
install-hooks |
ih |
Install git hooks |
uninstall-hooks |
uh |
Remove git hooks |
list-issues |
li |
List GitHub issues |
describe-issue |
di |
Show issue details |
update-issue-status |
uis |
Update issue status |
list-owned-branches |
lob |
List your branches |
delete-branch |
db |
Delete a branch |
delete-merged |
dm |
Delete merged branches |
dashboard |
dash |
Open TUI dashboard |
deploy |
dep |
Deploy to environment |
check-deployment |
cd |
Check deployment status |
build-enterprise |
be |
Build enterprise package |
rules |
- | Manage custom rules |
🏢 Enterprise Builds
Create custom packages with embedded corporate configuration:
# Install enterprise dependencies
pip install "devrules[enterprise]"
# Build enterprise package
devrules build-enterprise \
--config .devrules.enterprise.toml \
--name devrules-mycompany \
--sensitive github.api_url,github.owner
See Enterprise Build Guide for more details.
🛠️ Custom Validation Rules
Extend DevRules with your own Python validation logic and attach them to lifecycle events.
Basic Rule Definition
- Define a rule:
from devrules.core.rules_engine import rule
@rule(name="check-env", description="Verify .env exists")
def check_env():
# Return (success, message)
return True, "Environment valid"
- Configure:
[custom_rules]
paths = ["./custom_checks.py"]
- Run manually:
devrules list-rules
devrules run-rule (selects rules interactively)
devrules run-rule <rule_name>
Lifecycle Hooks
Attach custom rules to specific lifecycle events for automatic execution:
Available Events
PRE_COMMIT- Before committing changes (blocking)POST_COMMIT- After successful commit (non-blocking)PRE_PUSH- Before pushing to remote (blocking)PRE_PR- Before creating a pull request (blocking)PRE_DEPLOY- Before deployment (blocking)POST_DEPLOY- After successful deployment (non-blocking)
Hook Registration
from devrules.core.enum import DevRulesEvent
from devrules.core.rules_engine import rule
@rule(
name="validate_no_breakpoints",
description="Ensure no debugging statements in code",
hooks=[DevRulesEvent.PRE_COMMIT], # Auto-run before commits
ignore_defaults=True, # Skip interactive prompts when run as hook
)
def validate_no_breakpoints() -> tuple[bool, str]:
"""Check for debugging breakpoints in staged changes."""
# Your validation logic here
return True, "No breakpoints found"
Example: Multi-Language Breakpoint Detection
import re
import subprocess
from devrules.core.enum import DevRulesEvent
from devrules.core.rules_engine import rule
@rule(
name="validate_no_breakpoints",
description="Validate that there are no breakpoints in the code.",
hooks=[DevRulesEvent.PRE_COMMIT],
ignore_defaults=True,
)
def validate_no_breakpoints() -> tuple[bool, str]:
"""Check for debugging statements in staged changes."""
patterns = [
r"\bbreakpoint\(\)", # Python
r"\bpdb\.set_trace\(\)", # Python pdb
r"\bdebugger;", # JavaScript/TypeScript
r"\bconsole\.log\(", # JavaScript console
r"\bbinding\.pry\b", # Ruby pry
]
combined = re.compile("|".join(patterns))
# Get staged diff
diff = subprocess.run(
["git", "diff", "--cached", "--unified=0"],
capture_output=True,
text=True,
check=True,
).stdout
offending = {}
current_file = None
for line in diff.splitlines():
if line.startswith("+++ b/"):
current_file = line[6:]
elif current_file and line.startswith("+") and not line.startswith("+++"):
if combined.search(line[1:]):
offending.setdefault(current_file, []).append(line[1:].strip())
if offending:
msg = "Debugging statements detected:\n\n"
for file, lines in offending.items():
msg += f"{file}\n"
for line in lines[:5]:
msg += f" • {line}\n"
return False, msg
return True, "No debugging statements found."
Example: Documentation Coverage Check
import subprocess
from devrules.core.enum import DevRulesEvent
from devrules.core.rules_engine import rule
@rule(
name="validate_docstrings",
description="Validate docstrings in the code.",
hooks=[DevRulesEvent.PRE_COMMIT],
ignore_defaults=True,
)
def check_docstrings(path: str = "src", fail_under: int = 98) -> tuple[bool, str]:
"""Validate docstrings coverage using interrogate."""
result = subprocess.run(
["interrogate", path, "--fail-under", str(fail_under)],
capture_output=True,
text=True,
)
valid = "PASSED" in result.stdout
return valid, result.stdout
How Hooks Work
- Automatic Execution: When you run
devrules icommitordevrules commit, all rules registered withPRE_COMMIThooks are automatically executed - Blocking Behavior: Pre-hooks (PRE_*) block the operation if validation fails
- Non-Interactive: Rules with
ignore_defaults=Trueuse default parameter values instead of prompting - Clear Feedback: Hook execution shows which rules are running and their results
Configuration
[custom_rules]
# Paths to Python files or directories containing rules
paths = ["./custom_rules/", "./checks.py"]
# Python packages to import (rules will auto-register)
packages = ["mycompany.devrules"]
Best Practices
- Use
ignore_defaults=Truefor hook-triggered rules to avoid interactive prompts - Return clear messages - Users see these when rules fail
- Keep rules fast - They run on every commit/deploy
- Test independently - Use
devrules run-rule <rule-name>to test - Handle errors gracefully - Return
(False, error_message)instead of raising exceptions
📚 Documentation
For full documentation, visit GitHub.
🤝 Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
🙏 Acknowledgments
Built with:
📧 Contact
- GitHub: @pedroifgonzalez
- Email: pedroifgonzalez@gmail.com
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file devrules-0.1.9.tar.gz.
File metadata
- Download URL: devrules-0.1.9.tar.gz
- Upload date:
- Size: 3.8 MB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.11.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
4a96626243a44eda2b130ff64c14414c7f5d749fd4f2ae8d90cd941327dfb8cf
|
|
| MD5 |
6b49a2dac555ee7b024288875caafbca
|
|
| BLAKE2b-256 |
5f1eaacd158ebe02bebd86458000b88b06dff199abf746ebda30a82c3eaa7fc3
|
File details
Details for the file devrules-0.1.9-py3-none-any.whl.
File metadata
- Download URL: devrules-0.1.9-py3-none-any.whl
- Upload date:
- Size: 194.6 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.11.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
b5c214128ab26f79314ffc63d7cfa86d6ea19aa158823ba34a30f88cb91d432b
|
|
| MD5 |
2b24f5db8a8e1a252cb2c88e0a5f4c08
|
|
| BLAKE2b-256 |
751b9610b3e8b51c89070359f33b513b406cd2e6fe86c690a584b917217dc25e
|