Thank you for your interest in contributing to PR Auto-Labeler! This document provides guidelines for adding new rules and contributing to the project.
Contributing is now incredibly simple:
- Fork the repository on GitHub
- Create a new file in
src/rules/or appropriate category folder (e.g.,src/rules/frontend/my-rule.jsorsrc/rules/environment/my-rule.js) - Copy the template from
src/rules/RULE_TEMPLATE.js - Implement your logic - just the detection code!
- Submit a PR with ONLY your new file
That's it! No need to modify any other files. The workflow automatically discovers and loads your rule from any subdirectory.
- Fork the repository on GitHub
- Clone your fork locally
- Create a new branch for your rule:
git checkout -b add-rule-your-rule-name - Add your rule following the steps below
- Test your rule (see Testing section)
- Submit a pull request with a clear description
Create a new file in the appropriate category folder:
- Frontend rules:
src/rules/frontend/your-rule-name.js - Environment rules:
src/rules/environment/your-rule-name.js - Infrastructure rules:
src/rules/infrastructure/your-rule-name.js - Database rules:
src/rules/database/your-rule-name.js - New category: Create
src/rules/your-category/your-rule-name.js
Use the template as a starting point:
cp src/rules/RULE_TEMPLATE.js src/rules/frontend/your-rule-name.js
# or
cp src/rules/RULE_TEMPLATE.js src/rules/environment/your-rule-name.js
# or
cp src/rules/RULE_TEMPLATE.js src/rules/infrastructure/your-rule-name.jsNote: Rules are organized by category, but you can place a rule anywhere in src/rules/ - the workflow will find it automatically.
Edit your rule file to implement the detection logic. A rule is a function that receives a context object and returns an array of labels.
/**
* Your Rule Description
*/
function yourRuleNameRule({ files, pr, enableDebug }) {
const labels = [];
// Your logic here
for (const file of files) {
if (someCondition(file)) {
labels.push('your-label');
}
}
return labels;
}
// Don't forget to add metadata!
yourRuleNameRule.metadata = {
name: 'Your Rule Name',
description: 'What your rule does',
labels: [
{
name: 'your-label',
color: 'FBCA04',
description: 'Description of the label'
}
],
author: 'your-github-username',
version: '1.0.0'
};
module.exports = yourRuleNameRule;Before submitting, test your rule works correctly:
- Enable debug mode in your test repository
- Create a test PR with files that should trigger your rule
- Verify the correct labels are applied
- Check the workflow logs for any errors
That's it! You only need to submit your new rule file. The workflow automatically discovers and loads all rules from the src/rules/ directory.
What to include in your PR:
- ✅ Your new rule file in
src/rules/(or category subfolder) - ✅ Test file in
__tests__/(matching the folder structure) - ❌ No changes to
.github/workflows/pr-auto-labeler.ymlneeded! - ❌ No changes to
src/rules/index.jsneeded!
The system is fully automatic - just add your rule file and tests!
Every rule must follow this structure:
function ruleName({ files, pr, enableDebug }) {
// 1. Initialize labels array
const labels = [];
// 2. Analyze PR data
// ... your logic ...
// 3. Add labels based on conditions
if (condition) {
labels.push('label-name');
}
// 4. Debug logging (optional but recommended)
if (enableDebug && labels.length > 0) {
console.log(`[Rule Name] Labels: ${labels.join(', ')}`);
}
// 5. Return labels array
return labels;
}
// REQUIRED: Add metadata
ruleName.metadata = {
name: 'Human Readable Rule Name',
description: 'Brief description',
labels: [/* label definitions */],
author: 'github-username',
version: '1.0.0'
};Your rule receives a context object with:
-
files: Array of changed files{ filename: 'path/to/file.js', status: 'added' | 'modified' | 'removed', additions: 10, deletions: 5, changes: 15, patch: '@@diff content@@' }
-
pr: Pull request information{ number: 123, title: 'PR Title', body: 'PR description', user: { login: 'username' }, labels: [/* existing labels */] }
-
enableDebug: Boolean flag for debug mode
Each label must have:
name: Label name (lowercase, use hyphens)color: Hex color code without#(e.g.,'FBCA04')description: Short description of what the label means
Color Palette Suggestions:
- 🔴 Red (
D93F0B): Risky/dangerous changes - 🟡 Yellow (
FBCA04): Warnings/attention needed - 🟢 Green (
0E8A16): Safe changes/improvements - 🔵 Blue (
0075CA): Information/documentation - 🟣 Purple (
D4C5F9): Style/formatting - ⚫ Gray (
7F8C8D): Metadata/configuration
- Keep it simple: One rule should do one thing well
- Be specific: Clear detection criteria reduce false positives
- Add debug logging: Help users understand rule behavior
- Handle edge cases: Consider empty files, special characters, etc.
- Document your logic: Add comments explaining complex conditions
- Test thoroughly: Test with various file types and scenarios
const filename = file.filename.toLowerCase();
const ext = filename.substring(filename.lastIndexOf('.'));
if (ext === '.md') {
labels.push('documentation');
}if (file.filename.startsWith('test/')) {
labels.push('test');
}
if (file.filename.includes('/migrations/')) {
labels.push('migration');
}if (file.patch && file.patch.includes('DROP TABLE')) {
labels.push('risky-migration');
}if (pr.title.toLowerCase().includes('[wip]')) {
labels.push('work-in-progress');
}const totalChanges = files.reduce((sum, f) => sum + f.changes, 0);
if (totalChanges > 500) {
labels.push('large-pr');
}There are two main approaches to test your rule changes in a real GitHub environment before merging:
If you have write access to the repository, you can test directly using a feature branch:
Step 1: Push your changes to a feature branch
git checkout -b feat/my-new-rule
git add src/rules/my-new-rule.js __tests__/my-new-rule.test.js
git commit -m "feat: add my new rule"
git push origin feat/my-new-ruleStep 2: Update the workflow in a test repository to use your branch
# In your test repository's .github/workflows/pr-labeler.yml
jobs:
label:
uses: workflow-kit/pr-auto-labeler/.github/workflows/pr-auto-labeler.yml@feat/my-new-rule # Use your branch
with:
enabled_rules: '["my-new-rule"]'
enable_debug: true # Enable debug mode to see logsStep 3: Create a test PR in your test repository
- Make changes that should trigger your rule
- Check the GitHub Actions logs to verify the rule works
- Verify the correct labels are applied
Step 4: Iterate if needed
# Make changes to your rule
git add -A
git commit -m "fix: improve rule detection"
git push origin feat/my-new-rule
# Create another test PR to verify the changesIf you're contributing from a fork (most common for external contributors):
Step 1: Fork the repository and clone your fork
git clone https://github.com/YOUR-USERNAME/pr-auto-labeler.git
cd pr-auto-labelerStep 2: Create your feature branch and make changes
git checkout -b feat/my-new-rule
# Add your rule file
# Add tests
git add -A
git commit -m "feat: add my new rule"
git push origin feat/my-new-ruleStep 3: Set up a test repository to use your fork
In your test repository, create .github/workflows/pr-labeler.yml:
name: Test My New Rule
on:
pull_request:
types: [opened, synchronize, reopened]
permissions:
contents: read
pull-requests: write
jobs:
label:
# Point to YOUR fork and branch
uses: YOUR-USERNAME/pr-auto-labeler/.github/workflows/pr-auto-labeler.yml@feat/my-new-rule
with:
enabled_rules: '["my-new-rule"]'
enable_debug: true # Important: see what's happeningStep 4: Create test PRs in your test repository
- Make changes that should trigger your rule
- Check the Actions tab to see workflow execution
- Verify labels are applied correctly
Step 5: Iterate and refine
# Make improvements to your rule
git add -A
git commit -m "fix: handle edge case"
git push origin feat/my-new-rule
# The next test PR will use the updated codeStep 6: Submit your PR to the main repository Once satisfied with testing:
# Create a PR from your fork to workflow-kit/pr-auto-labeler
# GitHub will show you the "Contribute" button✅ Enable Debug Mode: Always use enable_debug: true when testing
with:
enabled_rules: '["my-rule"]'
enable_debug: true # Shows detailed execution logs✅ Test Multiple Scenarios: Create test PRs with different file combinations
- Positive case: Files that should trigger the rule
- Negative case: Files that should NOT trigger the rule
- Edge cases: Empty files, special characters, large files
✅ Check GitHub Actions Logs:
- Go to the "Actions" tab in your test repository
- Click on the latest workflow run
- Expand the logs to see debug output
- Look for your rule's debug messages
✅ Verify Labels:
- Check the PR's label section
- Ensure only expected labels are applied
- Test label overrides if using custom names
We use Jest for unit testing. Before submitting your rule, add tests for it:
-
Create a test file matching your rule's folder structure:
- Rule in
src/rules/frontend/my-rule.js→ Test in__tests__/frontend/my-rule.test.js - Rule in
src/rules/environment/my-rule.js→ Test in__tests__/environment/my-rule.test.js - Rule in
src/rules/my-rule.js→ Test in__tests__/my-rule.test.js
- Rule in
-
Write test cases covering:
const myRule = require('../src/rules/my-rule'); describe('My Rule', () => { it('should detect condition X', () => { const files = [{ filename: 'test.txt' }]; const labels = myRule({ files, pr: {}, enableDebug: false }); expect(labels).toContain('my-label'); }); it('should not detect condition Y', () => { const files = [{ filename: 'other.txt' }]; const labels = myRule({ files, pr: {}, enableDebug: false }); expect(labels).not.toContain('my-label'); }); });
-
Run tests locally:
npm install npm test -
Check coverage:
npm run test:coverage
-
Enable debug mode to see rule execution:
with: enable_debug: true
-
Create a test PR with files that should trigger your rule
-
Check the workflow logs to verify:
- Your rule executed
- Correct labels were applied
- Debug output is helpful
- Unit tests written and passing
- Test coverage >= 80%
- Rule applies labels for positive cases
- Rule doesn't apply labels for negative cases
- Debug logging is clear and helpful
- Edge cases are handled (empty files, special chars, etc.)
- Performance is acceptable for large PRs
- Rule doesn't conflict with existing rules
When users adopt your rule, they enable it and all labels from that rule are applied automatically.
Users must explicitly enable your rule to use it:
# Enable the rule
enabled_rules: '["your-rule-name"]'Important: All rules are disabled by default. When a user enables your rule, all labels returned by your rule will be applied to matching PRs.
If your rule returns 3 labels: db-change, migration, risky-migration
When enabled:
enabled_rules: '["database"]'
# All 3 labels from the rule will be applied automaticallyNote: If users want fewer labels, they should enable fewer rules or create custom rules that return only the labels they need.
-
Provide Multiple Labels: Different labels for different scenarios
- ✅ Good:
ui-change,style-change(2 labels, different scenarios) - ✅ Also good: Single label rules are fine if they serve a specific purpose
- ✅ Good:
-
Use Descriptive Names: Help users understand what each label means
- ✅ Good:
potential-secret-leak,env-change - ❌ Unclear:
flag,warning
- ✅ Good:
-
Document Each Label: In your metadata, explain when each label applies
labels: [ { name: 'db-change', color: 'FBCA04', description: 'Database files modified' }, { name: 'risky-migration', color: 'D93F0B', description: 'Potentially destructive migration (DROP/ALTER)' } ]
-
Think About Use Cases: Different teams may want different labels
- Security teams: Only
potential-secret-leak - Frontend teams:
ui-changeandstyle-change - Full-stack teams: All labels
- Security teams: Only
Use conventional commit style:
feat(rules): add [Rule Name] detection
Examples:
feat(rules): add database migration detectionfeat(rules): add test coverage analysisfix(rules): improve UI detection accuracy
## Description
Brief description of the rule and what it detects.
## Rule Details
- **Rule Name**: Your Rule Name
- **Labels Applied**: `label-1`, `label-2`
- **Detection Criteria**:
- Condition 1
- Condition 2
## Testing
- [ ] Tested with positive cases
- [ ] Tested with negative cases
- [ ] Debug logging verified
- [ ] Tested with demo-app repo
## Example PR
Link to a test PR that demonstrates the rule: #123
## Additional Notes
Any additional context or considerations.Here are some rule ideas you can implement:
- Database & Migration Rules (DROP TABLE, ALTER TABLE, etc.)
- Test Coverage Rules (missing tests, test-only changes)
- Dependency Changes (package.json, requirements.txt, etc.)
- Environment & Configuration (
.env, config files) - Large PR Detection (>500 lines changed)
- CI/CD Changes (workflow files, Jenkinsfile)
- Docker Changes (Dockerfile, docker-compose) - Implemented:
docker-changerule - Detect Migration File Changes - Implemented:
migrationrule - Documentation Changes (README, docs/)
- Security Changes (auth, encryption, secrets)
- Infrastructure Changes (terraform, ansible)
- Refactoring Detection (rename/move operations)
- Breaking Changes (based on PR title/body)
- Work in Progress (WIP in title)
- Missing Issue Link (no "Fixes #" or "Closes #")
- Missing Description (empty or short PR body)
- Questions? Open a GitHub Discussion
- Bug Report? Open an Issue
- Need Examples? Check out existing rules in
src/rules/
- Be respectful and inclusive
- Provide constructive feedback
- Help others learn and grow
- Keep discussions focused and professional
Thank you for contributing! 🎉