Skip to content

feat: Add infinity threshold support for PR size labels#898

Merged
myakove merged 2 commits intomainfrom
fix/pr-size-infinity-thresholds
Nov 10, 2025
Merged

feat: Add infinity threshold support for PR size labels#898
myakove merged 2 commits intomainfrom
fix/pr-size-infinity-thresholds

Conversation

@myakove
Copy link
Copy Markdown
Collaborator

@myakove myakove commented Nov 10, 2025

Enable custom PR size configurations to use 'inf' for unbounded largest categories, matching the behavior of static default thresholds.

Changes:

  • Accept both int and float types for thresholds
  • Convert string "inf" to float("inf") for YAML compatibility
  • Update validation to support infinity thresholds
  • Add 5 comprehensive test cases (all 75 tests passing, 94% coverage)
  • Update README.md with infinity examples and documentation
  • Update example config files to demonstrate infinity usage
  • Update JSON Schema to accept integer or "inf" string

Fixes: Custom configs can now define infinite thresholds like static
defaults (e.g., XXL: threshold: inf)

Summary by CodeRabbit

  • New Features

    • Support for unbounded PR-size categories using "inf" (always sorted last); added example categories (Massive, Extreme, Ultimate) that use infinity thresholds.
  • Documentation

    • Expanded configuration guide and examples to document "inf" semantics, updated label name/color examples, and noted fallback to a default color for invalid names.
  • Tests

    • Added tests covering infinity thresholds, sorting, size categorization, and label color mapping.
  • Chores

    • Updated config/schema to accept "inf" as a valid threshold value.

Enable custom PR size configurations to use 'inf' for unbounded largest
categories, matching the behavior of static default thresholds.

Changes:
- Accept both int and float types for thresholds
- Convert string "inf" to float("inf") for YAML compatibility
- Update validation to support infinity thresholds
- Add 5 comprehensive test cases (all 75 tests passing, 94% coverage)
- Update README.md with infinity examples and documentation
- Update example config files to demonstrate infinity usage
- Update JSON Schema to accept integer or "inf" string

Fixes: Custom configs can now define infinite thresholds like static
defaults (e.g., XXL: threshold: inf)
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Nov 10, 2025

Walkthrough

Adds support for an unbounded "inf" PR-size threshold across docs, examples, JSON Schema, label-handling logic, and tests; converts string "inf" to a numeric infinity value and ensures such thresholds are sorted last and accepted in per-repository overrides.

Changes

Cohort / File(s) Summary
Docs & Examples
README.md, examples/.github-webhook-server.yaml, examples/config.yaml
Introduced new infinite-size labels (e.g., Massive, Extreme) with threshold: inf; updated configuration examples and wording to allow threshold as a positive integer or the string "inf", added color-name examples and fallback note for invalid names.
Schema Definition
webhook_server/config/schema.yaml
Changed pr-size-thresholds.*.threshold in three locations to oneOf: [{type: integer, minimum: 1}, {type: string, enum: ["inf"]}] and updated descriptions to document the inf semantics and sorting.
Label Handler
webhook_server/libs/handlers/labels_handler.py
_get_custom_pr_size_thresholds now accepts "inf" by converting it to float("inf"), broadened numeric type checks to allow int or float, validates threshold > 0, and skips invalid entries.
Tests
webhook_server/tests/test_labels_handler.py
Added tests covering "inf" thresholds (string and converted float), ordering with mixed thresholds (ensuring inf last), PR size categorization across extreme sizes, and label color mapping for infinity-based categories.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

  • Verify schema oneOf entries are consistent across all three locations and descriptions accurately document semantics.
  • Inspect _get_custom_pr_size_thresholds conversion/validation (string "inf" → float("inf")) and ensure sorting/integration with existing logic.
  • Review new tests for coverage of edge cases and correct mocking of configurations.

Possibly related issues

Possibly related PRs

Suggested labels

size/XXL, verified

Suggested reviewers

  • rnetser

Pre-merge checks and finishing touches

✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely summarizes the main change: adding support for infinity thresholds in PR size label configuration, which is the primary focus across all modified files.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
✨ Finishing touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch fix/pr-size-infinity-thresholds

📜 Recent review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 2510f9d and 97d078b.

📒 Files selected for processing (2)
  • examples/.github-webhook-server.yaml (2 hunks)
  • examples/config.yaml (2 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • examples/config.yaml
🔇 Additional comments (2)
examples/.github-webhook-server.yaml (2)

107-110: Well-documented infinity threshold feature.

The updated comments clearly explain that thresholds accept "inf" for unbounded categories and note the sorting behavior. The documentation is accurate and helpful for users adopting this feature.


111-126: Example correctly demonstrates infinity threshold usage.

The PR-size-thresholds configuration properly showcases the new feature with:

  • A logical threshold progression (Quick → Normal → Complex → Critical → Extreme)
  • Correct YAML syntax for both finite (integers) and infinite (inf) thresholds
  • A meaningful color scheme (black for Extreme/unbounded category)
  • Clear explanation that Extreme captures all PRs with 1000+ lines

Ensure that the handler code (webhook_server/libs/handlers/labels_handler.py) correctly sorts infinity thresholds last during processing, as documented in the comments (lines 109–110). This is critical for the documented behavior to match runtime behavior.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@myakove-bot
Copy link
Copy Markdown
Collaborator

Report bugs in Issues

Welcome! 🎉

This pull request will be automatically processed with the following features:

🔄 Automatic Actions

  • Reviewer Assignment: Reviewers are automatically assigned based on the "
    "OWNERS file in the repository root
    "
    "* Size Labeling: PR size labels (XS, S, M, L, XL, XXL) are "
    "automatically applied based on changes
    "
    f"* Issue Creation: A tracking issue is created for this PR and will be closed when the PR is merged or closed
    "
    "* Pre-commit Checks: pre-commit runs "
    "automatically if .pre-commit-config.yaml exists
    "
  • Branch Labeling: Branch-specific labels are applied to track the target branch
  • Auto-verification: Auto-verified users have their PRs automatically marked as verified

📋 Available Commands

PR Status Management

  • /wip - Mark PR as work in progress (adds WIP: prefix to title)
  • /wip cancel - Remove work in progress status
  • /hold - Block PR merging (approvers only)
  • /hold cancel - Unblock PR merging
  • /verified - Mark PR as verified
  • /verified cancel - Remove verification status
  • /reprocess - Trigger complete PR workflow reprocessing (useful if webhook failed or configuration changed)

Review & Approval

  • /lgtm - Approve changes (looks good to me)
  • /approve - Approve PR (approvers only)
  • /automerge - Enable automatic merging when all requirements are met (maintainers and approvers only)
  • /assign-reviewers - Assign reviewers based on OWNERS file
  • /assign-reviewer @username - Assign specific reviewer
  • /check-can-merge - Check if PR meets merge requirements

Testing & Validation

  • /retest tox - Run Python test suite with tox
  • /retest build-container - Rebuild and test container image
  • /retest python-module-install - Test Python package installation
  • /retest pre-commit - Run pre-commit hooks and checks
  • /retest conventional-title - Validate commit message format
  • /retest all - Run all available tests

Container Operations

  • /build-and-push-container - Build and push container image (tagged with PR number)
    • Supports additional build arguments: /build-and-push-container --build-arg KEY=value

Cherry-pick Operations

  • /cherry-pick <branch> - Schedule cherry-pick to target branch when PR is merged
    • Multiple branches: /cherry-pick branch1 branch2 branch3

Label Management

  • /<label-name> - Add a label to the PR
  • /<label-name> cancel - Remove a label from the PR

✅ Merge Requirements

This PR will be automatically approved when the following conditions are met:

  1. Approval: /approve from at least one approver
  2. LGTM Count: Minimum 1 /lgtm from reviewers
  3. Status Checks: All required status checks must pass
  4. No Blockers: No WIP, hold, or conflict labels
  5. Verified: PR must be marked as verified (if verification is enabled)

📊 Review Process

Approvers and Reviewers

Approvers:

  • myakove
  • rnetser

Reviewers:

  • myakove
  • rnetser
Available Labels
  • hold
  • verified
  • wip
  • lgtm
  • approve
  • automerge

💡 Tips

  • WIP Status: Use /wip when your PR is not ready for review
  • Verification: The verified label is automatically removed on each new commit
  • Cherry-picking: Cherry-pick labels are processed when the PR is merged
  • Container Builds: Container images are automatically tagged with the PR number
  • Permission Levels: Some commands require approver permissions
  • Auto-verified Users: Certain users have automatic verification and merge privileges

For more information, please refer to the project documentation or contact the maintainers.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (2)
examples/.github-webhook-server.yaml (1)

124-126: Clarify the infinity threshold comment.

The comment "Optional: using 'inf' ensures no PR exceeds thresholds" is somewhat redundant since infinity by definition cannot be exceeded. Consider clarifying to better explain the practical benefit:

-    threshold: inf     # PRs with 1000+ lines changed (unbounded largest category)
-    color: black       # Optional: using 'inf' ensures no PR exceeds thresholds
+    threshold: inf     # PRs with 1000+ lines changed (unbounded largest category)
+    color: black       # Infinity captures all PRs beyond the largest finite threshold
examples/config.yaml (1)

54-55: Same comment clarification needed.

Similar to the .github-webhook-server.yaml file, the comment "Optional: using 'inf' ensures no PR exceeds thresholds" is redundant. Consider using clearer wording that explains the practical use case.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 4439ff4 and 2510f9d.

📒 Files selected for processing (6)
  • README.md (3 hunks)
  • examples/.github-webhook-server.yaml (2 hunks)
  • examples/config.yaml (2 hunks)
  • webhook_server/config/schema.yaml (2 hunks)
  • webhook_server/libs/handlers/labels_handler.py (1 hunks)
  • webhook_server/tests/test_labels_handler.py (1 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
webhook_server/tests/test_labels_handler.py (2)
webhook_server/libs/handlers/labels_handler.py (3)
  • _get_custom_pr_size_thresholds (198-241)
  • get_size (243-266)
  • _get_label_color (158-182)
webhook_server/tests/conftest.py (4)
  • github_webhook (120-140)
  • owners_file_handler (149-150)
  • pull_request (115-116)
  • PullRequest (99-111)
🔇 Additional comments (14)
webhook_server/libs/handlers/labels_handler.py (1)

219-227: LGTM! Elegant handling of infinity thresholds.

The implementation correctly:

  • Converts YAML string "inf" to Python float("inf") with case-insensitive handling
  • Accepts both int and float types while maintaining backward compatibility
  • Validates threshold > 0 (which correctly passes for float("inf"))
  • Relies on Python's natural sort order to place infinity last
  • Ensures the size < threshold comparison in get_size() works correctly (any finite size < infinity evaluates to True)

This enables unbounded largest categories without special-casing infinity in the comparison logic.

examples/.github-webhook-server.yaml (1)

107-110: Clear documentation of infinity threshold behavior.

The comments accurately explain that 'inf' creates an unbounded largest category and is always sorted last, providing users with the information needed to use this feature effectively.

examples/config.yaml (1)

36-40: Consistent and clear documentation.

The threshold documentation matches the other example file and accurately describes the infinity behavior and sorting semantics.

webhook_server/tests/test_labels_handler.py (5)

1025-1047: Comprehensive test for float infinity threshold.

The test correctly verifies that float("inf") is accepted, sorted last, and properly mapped to the expected label name and color.

Consider adding a test case for multiple infinity thresholds to verify behavior when users accidentally define multiple unbounded categories. The current sorting would keep all infinity values together at the end, but the behavior should be documented or validated:

def test_get_custom_pr_size_thresholds_multiple_infinities(self, mock_github_webhook: Mock) -> None:
    """Test handling of multiple infinity thresholds."""
    mock_github_webhook.config.get_value.return_value = {
        "L": {"threshold": 300, "color": "orange"},
        "XXL": {"threshold": float("inf"), "color": "red"},
        "XXXL": {"threshold": float("inf"), "color": "darkred"},
    }
    
    labels_handler = LabelsHandler(github_webhook=mock_github_webhook, owners_file_handler=Mock())
    thresholds = labels_handler._get_custom_pr_size_thresholds()
    
    # Both infinity thresholds should be at the end
    assert thresholds[-2][0] == float("inf")
    assert thresholds[-1][0] == float("inf")

1049-1071: Good YAML compatibility test.

The test correctly verifies that the string "inf" is converted to float("inf"), maintaining YAML compatibility where infinity can't be represented as a float literal.

Consider adding a test case for case-insensitive infinity string handling, since the implementation uses .lower():

def test_get_custom_pr_size_thresholds_with_infinity_case_insensitive(self, mock_github_webhook: Mock) -> None:
    """Test case-insensitive handling of 'inf' string."""
    mock_github_webhook.config.get_value.return_value = {
        "S": {"threshold": 100, "color": "green"},
        "XXL_lower": {"threshold": "inf", "color": "red"},
        "XXL_upper": {"threshold": "INF", "color": "darkred"},
        "XXL_mixed": {"threshold": "Inf", "color": "crimson"},
    }
    
    labels_handler = LabelsHandler(github_webhook=mock_github_webhook, owners_file_handler=Mock())
    thresholds = labels_handler._get_custom_pr_size_thresholds()
    
    # All infinity variations should be converted to float("inf")
    infinity_thresholds = [t for t in thresholds if t[0] == float("inf")]
    assert len(infinity_thresholds) == 3

1073-1097: Excellent test for mixed threshold sorting.

The test uses unsorted input and validates that the sorting algorithm correctly orders numeric values before placing infinity last. The loop at lines 1096-1097 is particularly good for verifying all adjacent pairs are in ascending order.


1099-1127: Thorough test of size categorization with infinity.

The test cases cover the full range from small PRs to extremely large ones (15,000 lines), verifying that the infinity threshold correctly captures all PRs beyond the largest finite threshold without special-casing.


1129-1143: Essential test for color mapping with infinity thresholds.

Validates that the color lookup logic works correctly for infinity-based categories, ensuring labels are created with the correct colors.

README.md (4)

345-358: Clear documentation of infinity threshold in global config.

The example and description effectively communicate how to use 'inf' for unbounded largest categories, with practical context.


374-377: Good repository-level override example.

The Ultimate category example effectively demonstrates that repository-specific configurations can override global settings and use different category names and colors.


381-392: Comprehensive configuration rules documentation.

The section clearly explains:

  • Threshold types (integer or 'inf')
  • Infinity behavior and sorting semantics
  • Updated color examples matching the new categories
  • Backward compatibility assurance

This provides users with all the information needed to confidently use the feature.


394-401: Helpful color name documentation updates.

The additions of darkred and crimson align with the example configurations, and the fallback behavior note helps users understand what happens with invalid color names.

webhook_server/config/schema.yaml (2)

85-90: Correct schema definition for infinity thresholds.

The oneOf schema correctly allows either a positive integer or the string "inf", with a clear description. This provides IDE support and validation for users.


273-278: Consistent schema for repository-level overrides.

The repository-level threshold schema correctly mirrors the top-level schema, ensuring consistent validation across global and repository-specific configurations.

Updated comments in both configuration files to better explain
the practical benefit of using 'inf' for PR size thresholds.

Changed from: "Optional: using 'inf' ensures no PR exceeds thresholds"
Changed to: "'inf' means no upper limit - catches all PRs above X lines"

This makes it clear that 'inf' creates an unbounded category for the
largest PRs, rather than stating the obvious about infinity.

Addresses CodeRabbit review feedback.
@myakove
Copy link
Copy Markdown
Collaborator Author

myakove commented Nov 10, 2025

/verified
/approve

@myakove myakove merged commit 9968e6f into main Nov 10, 2025
8 of 9 checks passed
@myakove myakove deleted the fix/pr-size-infinity-thresholds branch November 10, 2025 14:25
@myakove-bot
Copy link
Copy Markdown
Collaborator

New container for ghcr.io/myk-org/github-webhook-server:latest published

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants