Skip to content

refactor: migrate conventional-title config from string to dict#1028

Merged
myakove merged 2 commits intomainfrom
refactor/issue-1027-conventional-title-dict
Mar 12, 2026
Merged

refactor: migrate conventional-title config from string to dict#1028
myakove merged 2 commits intomainfrom
refactor/issue-1027-conventional-title-dict

Conversation

@myakove
Copy link
Copy Markdown
Collaborator

@myakove myakove commented Mar 12, 2026

Summary

Migrate ai-features.conventional-title from string enum ("true"/"false"/"fix") to dict format with enabled, mode, and timeout-minutes. Consistent with resolve-cherry-pick-conflicts-with-ai dict pattern.

Closes #1027

Changes

Old format

ai-features:
  conventional-title: "true"  # "true" | "false" | "fix"

New format

ai-features:
  conventional-title:
    enabled: true
    mode: suggest  # suggest | fix
    timeout-minutes: 10  # default: 10

Files changed

File Change
webhook_server/config/schema.yaml conventional-title from string enum to object
webhook_server/libs/handlers/runner_handler.py Read dict config, pass timeout to AI CLI
webhook_server/tests/test_runner_handler.py Update test fixtures to dict format
examples/config.yaml Update example
examples/.github-webhook-server.yaml Update example
README.md Update AI Features docs

Tests

All 1353 tests pass, 90.10% coverage.

Summary by CodeRabbit

  • Documentation

    • AI conventional title config changed from a scalar string to a structured object with enabled, mode (suggest/fix), and timeout-minutes; docs and examples updated.
  • New Features

    • Added configurable timeout for AI PR title suggestions (default 10 minutes).
    • Added selectable AI mode: "suggest" (recommend titles) or "fix" (auto-apply formatted titles).

Change ai-features.conventional-title from string enum (true/false/fix)
to dict with enabled, mode (suggest/fix), and timeout-minutes.

Config:
  ai-features:
    conventional-title:
      enabled: true
      mode: suggest  # suggest | fix
      timeout-minutes: 10

Signed-off-by: Meni Yakove <myakove@gmail.com>
@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
  • Issue Creation: Disabled for this repository
  • 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
  • Labels: All label categories are enabled (default configuration)

📋 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)
  • /regenerate-welcome - Regenerate this welcome message

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, has-conflicts labels and PR must be mergeable (no conflicts)
  5. Verified: PR must be marked as verified

📊 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.

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Mar 12, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: 190869f1-3cb0-4966-a095-e5c43829d1b0

📥 Commits

Reviewing files that changed from the base of the PR and between 2470c3b and 984c332.

📒 Files selected for processing (2)
  • webhook_server/libs/handlers/runner_handler.py
  • webhook_server/tests/test_runner_handler.py

Walkthrough

This PR migrates the ai-features.conventional-title setting from a scalar string to a structured object with enabled, mode and timeout-minutes, and updates schema, examples, handler logic, and tests to read and enforce the new shape and behavior.

Changes

Cohort / File(s) Summary
Configuration Schema
webhook_server/config/schema.yaml
Replaced conventional-title string enum with an object schema: required enabled (boolean), mode (enum: suggest/fix, default suggest), timeout-minutes (integer min 1, default 10). Adds descriptions and additionalProperties: false.
Top-level Docs / Examples
README.md, examples/config.yaml, examples/.github-webhook-server.yaml
Updated README and example configs to show nested ai-features.conventional-title object with enabled, mode, and timeout-minutes fields; replaced previous Mode/Behavior table with Setting/Value/Description format and updated example block.
Handler Implementation
webhook_server/libs/handlers/runner_handler.py
Refactored to accept dict-based config: reads enabled, validates mode (suggest/fix), uses timeout-minutes when invoking AI, runs AI suggestion inside a worktree checkout, updates title on fix mode, and appends suggestions in suggest mode. Signature of _get_ai_title_suggestion updated to accept pull_request.
Tests
webhook_server/tests/test_runner_handler.py
Updated fixtures and assertions to use object config shapes; patched worktree checkout in tests; added expectations for worktree-based AI calls and timeout propagation; adjusted success/failure and message assertions for suggest vs fix modes.

Sequence Diagram(s)

sequenceDiagram
  participant GH as GitHub (PR)
  participant Runner as Runner Handler
  participant WT as Worktree (checkout)
  participant AI as AI CLI
  participant GHAPI as GitHub API

  GH->>Runner: New/updated PR triggers check
  Runner->>WT: checkout worktree for PR (cwd)
  Runner->>AI: run AI suggestion (cwd=WT, timeout=timeout-minutes, prompt)
  AI-->>Runner: suggested_title or error
  alt mode == "fix" and valid
    Runner->>GHAPI: update PR title (apply auto-fix)
    GHAPI-->>Runner: success
  else mode == "suggest" and suggested
    Runner-->>GH: add suggestion message to check output
  end
  Runner-->>GH: post check result (pass/fail with AI messages)
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

Suggested reviewers

  • rnetser
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Linked Issues check ⚠️ Warning The PR fulfills core requirements [#1027]: schema updated to dict format, code updated to handle dict config with timeout support, examples updated, and tests added. However, backward compatibility requirement is not addressed. Add support for old string format ("true"/"false"/"fix") to maintain backward compatibility for existing user configurations, or document migration path explicitly.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately describes the main refactoring: migrating conventional-title config from string to dict, which is the primary change across all modified files.
Out of Scope Changes check ✅ Passed All changes are directly scoped to the conventional-title configuration migration. README, schema, examples, handler logic, and tests all align with the refactoring objective.
Docstring Coverage ✅ Passed Docstring coverage is 88.89% which is sufficient. The required threshold is 80.00%.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch refactor/issue-1027-conventional-title-dict
📝 Coding Plan
  • Generate coding plan for human review comments

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.

@qodo-code-review
Copy link
Copy Markdown

ⓘ You are approaching your monthly quota for Qodo. Upgrade your plan

Review Summary by Qodo

Migrate conventional-title config from string to dict format

✨ Enhancement

Grey Divider

Walkthroughs

Description
• Migrate conventional-title config from string enum to dict format
• Add enabled, mode (suggest/fix), and timeout-minutes properties
• Update config schema, handler logic, and all example configurations
• Pass timeout parameter to AI CLI for conventional title suggestions
Diagram
flowchart LR
  A["String enum config<br/>true/false/fix"] -->|"Refactor"| B["Dict config<br/>enabled/mode/timeout"]
  B -->|"Update schema"| C["schema.yaml"]
  B -->|"Update handler"| D["runner_handler.py"]
  B -->|"Update tests"| E["test_runner_handler.py"]
  B -->|"Update examples"| F["config.yaml files"]
  B -->|"Update docs"| G["README.md"]
Loading

Grey Divider

File Changes

1. webhook_server/config/schema.yaml ⚙️ Configuration changes +25/-10

Schema definition for dict-based conventional-title config

• Changed conventional-title from string enum to object type
• Added enabled (boolean, required), mode (suggest/fix), and timeout-minutes (integer)
 properties
• Updated description to reflect new dict-based configuration
• Set defaults: mode: suggest, timeout-minutes: 10

webhook_server/config/schema.yaml


2. webhook_server/libs/handlers/runner_handler.py ✨ Enhancement +12/-8

Update handler to support dict config and timeout

• Updated _get_ai_conventional_title_mode() to parse dict config instead of string enum
• Changed mode comparison from "true" to "suggest" in check failure logic
• Added extraction of timeout-minutes from config with default value of 10
• Pass timeout_minutes parameter to call_ai_cli() function

webhook_server/libs/handlers/runner_handler.py


3. webhook_server/tests/test_runner_handler.py 🧪 Tests +7/-7

Update test fixtures to dict config format

• Updated 6 test fixtures to use dict format for conventional-title config
• Changed from string values ("true", "false", "fix") to dict with enabled and mode keys
• Updated test docstring for disabled mode test

webhook_server/tests/test_runner_handler.py


View more (3)
4. README.md 📝 Documentation +10/-6

Update documentation for dict config format

• Updated AI Features documentation with new dict-based config format
• Replaced mode behavior table with settings table showing enabled, mode, and timeout-minutes
• Added example configuration showing all three properties

README.md


5. examples/.github-webhook-server.yaml ⚙️ Configuration changes +4/-1

Update example config to dict format

• Migrated conventional-title from string "true" to dict format
• Added enabled: true, mode: suggest, and timeout-minutes: 10 properties

examples/.github-webhook-server.yaml


6. examples/config.yaml ⚙️ Configuration changes +4/-1

Update example config to dict format

• Migrated conventional-title from string "true" to dict format
• Added enabled: true, mode: suggest, and timeout-minutes: 10 properties

examples/config.yaml


Grey Divider

Qodo Logo

@qodo-code-review
Copy link
Copy Markdown

qodo-code-review Bot commented Mar 12, 2026

Code Review by Qodo

🐞 Bugs (2) 📘 Rule violations (0) 📎 Requirement gaps (4)

Grey Divider


Action required

1. Schema drops legacy string values 📎 Requirement gap ✓ Correctness
Description
ai-features.conventional-title schema now only accepts an object, so legacy string configs
("true"/"false"/"fix") will fail validation. This breaks required backward compatibility for
user-facing configuration files.
Code

webhook_server/config/schema.yaml[R21-47]

    conventional-title:
-        type: string
-        enum:
-          - "true"
-          - "false"
-          - "fix"
+        type: object
      description: |
-          AI-powered conventional title suggestions.
-          - "true": Show AI-suggested title in check run output when validation fails
-          - "false": Disabled (default)
-          - "fix": Auto-fix PR title with AI suggestion when validation fails
-        default: "false"
+          AI-powered conventional title configuration.
+          When enabled, suggests or auto-fixes PR titles that don't follow
+          Conventional Commits format.
+        properties:
+          enabled:
+            type: boolean
+            description: Enable AI conventional title suggestions
+          mode:
+            type: string
+            enum:
+              - suggest
+              - fix
+            description: |
+              - suggest: Show AI-suggested title in check run output when validation fails
+              - fix: Auto-fix PR title with AI suggestion when validation fails
+            default: suggest
+          timeout-minutes:
+            type: integer
+            minimum: 1
+            description: Timeout in minutes for the AI CLI process (default 10)
+            default: 10
+        required:
+          - enabled
+        additionalProperties: false
Evidence
PR Compliance requires maintaining backward compatibility for legacy string formats, but the updated
schema defines conventional-title strictly as an object with required enabled and
additionalProperties: false, with no oneOf/union allowing the legacy string enum.

Backward compatibility maintained for legacy string format
CLAUDE.md
webhook_server/config/schema.yaml[21-47]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`webhook_server/config/schema.yaml` changed `ai-features.conventional-title` to `type: object` only, which makes legacy configs using string values (`&amp;amp;quot;true&amp;amp;quot;`, `&amp;amp;quot;false&amp;amp;quot;`, `&amp;amp;quot;fix&amp;amp;quot;`) fail validation.
## Issue Context
Compliance requires backward compatibility for user-facing configs. The schema must accept both the new dict format and the legacy string format (or provide an equivalent migration path).
## Fix Focus Areas
- webhook_server/config/schema.yaml[21-47]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


2. Legacy conventional-title ignored 📎 Requirement gap ✓ Correctness
Description
Runtime parsing now disables AI conventional-title when ai-features.conventional-title is a legacy
string, changing behavior for existing configs. This violates the backward compatibility requirement
for legacy string values.
Code

webhook_server/libs/handlers/runner_handler.py[R587-591]

+        ct_config = ai_config.get("conventional-title")
+        if not isinstance(ct_config, dict) or not ct_config.get("enabled"):
+            return None
+
+        return ct_config.get("mode", "suggest")
Evidence
The compliance checklist requires legacy string formats to keep working, but
_get_ai_conventional_title_mode() now returns None unless conventional-title is a dict with
enabled: true, so legacy string configs will be treated as disabled.

Backward compatibility maintained for legacy string format
CLAUDE.md
webhook_server/libs/handlers/runner_handler.py[587-591]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`RunnerHandler._get_ai_conventional_title_mode()` now only supports dict config and treats non-dict (including legacy strings) as disabled, breaking backward compatibility.
## Issue Context
Legacy values must continue to work: `&amp;amp;quot;true&amp;amp;quot;` should behave like `enabled: true, mode: suggest`; `&amp;amp;quot;fix&amp;amp;quot;` like `enabled: true, mode: fix`; `&amp;amp;quot;false&amp;amp;quot;` like disabled.
## Fix Focus Areas
- webhook_server/libs/handlers/runner_handler.py[577-611]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


3. No legacy config format tests 📎 Requirement gap ⛯ Reliability
Description
Tests were updated to use only the new dict format, but no tests cover legacy
"true"/"false"/"fix" behavior. This leaves required backward compatibility unverified and
prone to regressions.
Code

webhook_server/tests/test_runner_handler.py[R709-715]

      runner_handler.github_webhook.ai_features = {
          "ai-provider": "claude",
          "ai-model": "sonnet",
-            "conventional-title": "true",
+            "conventional-title": {"enabled": True, "mode": "suggest"},
      }
      runner_handler.github_webhook.clone_repo_dir = "/tmp/test-clone"
Evidence
PR Compliance requires tests for both dict and legacy formats; the updated tests in
test_runner_handler.py now only set conventional-title as a dict, providing coverage for the new
format but not legacy string values.

Tests updated/added to cover new and legacy formats
webhook_server/tests/test_runner_handler.py[702-775]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
Automated tests cover the new dict format for `ai-features.conventional-title` but do not verify required backward compatibility with legacy string values (`&amp;amp;quot;true&amp;amp;quot;`, `&amp;amp;quot;false&amp;amp;quot;`, `&amp;amp;quot;fix&amp;amp;quot;`).
## Issue Context
Compliance requires both formats to be supported (or a migration layer). Tests should lock in the expected mapping from legacy strings to the new behavior.
## Fix Focus Areas
- webhook_server/tests/test_runner_handler.py[702-921]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


View more (1)
4. Mode not validated🐞 Bug ✓ Correctness
Description
_get_ai_conventional_title_mode() returns ct_config["mode"] without validating type/value, and
_get_ai_title_suggestion() treats any truthy mode as enabled. With runtime config loading that does
not enforce schema, a mis-typed mode (e.g., boolean true or a typo) will still trigger an AI CLI
call but the suggestion will never be applied because run_conventional_title_check only handles
"fix" and "suggest".
Code

webhook_server/libs/handlers/runner_handler.py[R587-591]

+        ct_config = ai_config.get("conventional-title")
+        if not isinstance(ct_config, dict) or not ct_config.get("enabled"):
+            return None
+
+        return ct_config.get("mode", "suggest")
Evidence
The handler enables the AI path based on a truthy mode and later only applies suggestions for the
exact strings "fix" or "suggest"; since config values are loaded from YAML without schema/type
validation, invalid mode/enabled values can reach this code and cause an AI call whose result is
discarded.

webhook_server/libs/handlers/runner_handler.py[534-575]
webhook_server/libs/handlers/runner_handler.py[587-591]
webhook_server/libs/handlers/runner_handler.py[598-601]
webhook_server/libs/config.py[132-153]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`RunnerHandler._get_ai_conventional_title_mode()` currently returns whatever is stored in `ai-features.conventional-title.mode` without validation, and `enabled` is treated by truthiness. Since runtime config loading does not enforce the JSON schema, common YAML mistakes (e.g., `mode: true`, `enabled: &amp;amp;quot;false&amp;amp;quot;`, typos) can cause the AI CLI to run but the suggestion will never be shown/applied because later logic only checks for the exact strings `&amp;amp;quot;suggest&amp;amp;quot;` and `&amp;amp;quot;fix&amp;amp;quot;`.
### Issue Context
Config is loaded via `Config.get_value()` from YAML and returned as-is (no schema/type enforcement). The PR changes `conventional-title` from a string enum to a dict, increasing the chance of type/value mismatches.
### Fix Focus Areas
- webhook_server/libs/handlers/runner_handler.py[577-602]
### Suggested change (high level)
- Parse `enabled` as a strict boolean (`enabled is True`).
- Parse `mode` as a string; if missing or invalid, default to `&amp;amp;quot;suggest&amp;amp;quot;` and log a warning including the invalid value.
- Ensure `_get_ai_title_suggestion()` is gated on validated mode values (it already calls `_get_ai_conventional_title_mode()`, so fixing that function is usually sufficient).

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools



Remediation recommended

5. README omits legacy behavior 📎 Requirement gap ✓ Correctness
Description
README documents only the new dict format for ai-features.conventional-title and does not explain
how legacy string values are handled. This fails the documentation requirement to describe backward
compatibility expectations.
Code

README.md[R1258-1272]

ai-features:
ai-provider: "claude"
ai-model: "claude-opus-4-6[1m]"
-  conventional-title: "true"   # "true": suggest in check run | "false": disabled | "fix": auto-update PR title
+  conventional-title:
+    enabled: true
+    mode: suggest            # suggest | fix
+    timeout-minutes: 10      # default: 10
Evidence
PR Compliance requires documentation to cover the new keys and explain legacy compatibility; the
updated README section lists only enabled, mode, and timeout-minutes without describing legacy
"true"/"false"/"fix" behavior.

Documentation updated (README.md and/or CLAUDE.md as applicable)
README.md[1253-1272]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
README documents the new dict-based configuration but does not explain backward compatibility handling for legacy string values.
## Issue Context
Compliance requires docs to explain new keys (`enabled`, `mode`, `timeout-minutes`) and how legacy values are handled (or how to migrate).
## Fix Focus Areas
- README.md[1253-1272]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


6. Stale conventional-title docs 🐞 Bug ⛯ Reliability
Description
The PR updates the schema and README to the new dict-based ai-features.conventional-title config,
but CLAUDE.md still documents the deprecated string values ("true"/"false"/"fix"). This mismatch
will lead users to configure the old format, which the new runtime code treats as disabled
(ct_config not a dict).
Code

webhook_server/config/schema.yaml[R21-47]

    conventional-title:
-        type: string
-        enum:
-          - "true"
-          - "false"
-          - "fix"
+        type: object
      description: |
-          AI-powered conventional title suggestions.
-          - "true": Show AI-suggested title in check run output when validation fails
-          - "false": Disabled (default)
-          - "fix": Auto-fix PR title with AI suggestion when validation fails
-        default: "false"
+          AI-powered conventional title configuration.
+          When enabled, suggests or auto-fixes PR titles that don't follow
+          Conventional Commits format.
+        properties:
+          enabled:
+            type: boolean
+            description: Enable AI conventional title suggestions
+          mode:
+            type: string
+            enum:
+              - suggest
+              - fix
+            description: |
+              - suggest: Show AI-suggested title in check run output when validation fails
+              - fix: Auto-fix PR title with AI suggestion when validation fails
+            default: suggest
+          timeout-minutes:
+            type: integer
+            minimum: 1
+            description: Timeout in minutes for the AI CLI process (default 10)
+            default: 10
+        required:
+          - enabled
+        additionalProperties: false
Evidence
The schema in this PR clearly defines the new object shape for ai-features.conventional-title,
while CLAUDE.md continues to describe the previous string enum format, creating conflicting
guidance.

webhook_server/config/schema.yaml[21-47]
CLAUDE.md[676-685]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
CLAUDE.md still documents `ai-features.conventional-title` as a string enum (&amp;amp;quot;true&amp;amp;quot;/&amp;amp;quot;false&amp;amp;quot;/&amp;amp;quot;fix&amp;amp;quot;), but the PR migrates it to an object config. This conflicting guidance can cause users to apply the deprecated format, which the updated code will treat as disabled.
### Issue Context
README.md and the JSON schema were updated to the new dict format, but CLAUDE.md was not.
### Fix Focus Areas
- CLAUDE.md[676-689]
### Suggested change (high level)
- Replace the old description with the new YAML example:
- `conventional-title.enabled: true/false`
- `conventional-title.mode: suggest|fix`
- `conventional-title.timeout-minutes: &amp;amp;lt;int&amp;amp;gt;`
- Ensure any prose describing modes uses `suggest`/`fix` (not `&amp;amp;quot;true&amp;amp;quot;`).

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

ⓘ The new review experience is currently in Beta. Learn more

Grey Divider

Qodo Logo

Comment thread webhook_server/config/schema.yaml
Comment thread webhook_server/libs/handlers/runner_handler.py Outdated
Comment thread webhook_server/tests/test_runner_handler.py
Comment thread webhook_server/libs/handlers/runner_handler.py Outdated
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: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
webhook_server/tests/test_runner_handler.py (1)

703-740: ⚠️ Potential issue | 🟡 Minor

LOW: Lock the new timeout_minutes behavior in this test.

This is the only updated test that inspects call_ai_cli kwargs, but it only checks cwd. If the new timeout_minutes argument gets dropped or renamed, the suite still passes. Please assert the default 10 here and add one non-default case.

Minimal assertion for the default path
                             mock_ai_cli.assert_awaited_once()
                             call_kwargs = mock_ai_cli.call_args[1]
                             assert call_kwargs["cwd"] == "/tmp/test-clone"
+                            assert call_kwargs["timeout_minutes"] == 10
As per coding guidelines, `webhook_server/tests/*.py`: Test files must achieve 90% code coverage - new code without tests fails CI.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@webhook_server/tests/test_runner_handler.py` around lines 703 - 740, The test
test_conventional_title_failure_with_ai_suggestion currently only asserts the
cwd passed to the mocked call_ai_cli; add an assertion that call_ai_cli received
timeout_minutes==10 (the default) by checking
mock_ai_cli.call_args[1]["timeout_minutes"] == 10, and add a second small test
(or extend this test) that configures runner_handler.github_webhook.ai_features
to include a non-default timeout (e.g., "timeout_minutes": 5) and asserts that
mock_ai_cli was awaited with timeout_minutes==5; reference the existing mock
object for call_ai_cli and the run_conventional_title_check invocation to locate
where to add these assertions.
webhook_server/libs/handlers/runner_handler.py (1)

577-591: ⚠️ Potential issue | 🟠 Major

HIGH: Legacy string configs are silently disabled here.

Even if the schema stays backward-compatible, this helper returns None for any non-dict value, so old "true" and "fix" settings never reach suggest/fix mode. Please translate the legacy strings here or normalize them before this method runs, otherwise upgrades change behavior without warning.

Compatibility shim example
         ct_config = ai_config.get("conventional-title")
+        if isinstance(ct_config, str):
+            return {"true": "suggest", "fix": "fix", "false": None}.get(ct_config)
         if not isinstance(ct_config, dict) or not ct_config.get("enabled"):
             return None

-        return ct_config.get("mode", "suggest")
+        return ct_config.get("mode") or "suggest"
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@webhook_server/libs/handlers/runner_handler.py` around lines 577 - 591, The
helper _get_ai_conventional_title_mode currently returns None for non-dict
ct_config, silently dropping legacy string/bool configs; update it to accept and
normalize legacy values from self.github_webhook.ai_features: if ct_config is a
bool True or string "true"/"suggest"/"fix", treat them as {"enabled": True,
"mode": "suggest" or "fix"} (map plain "fix" to mode "fix", any other truthy
string to "suggest"); keep existing dict handling for modern config, and only
return None when enabled is false or missing. Locate ct_config handling in
_get_ai_conventional_title_mode and perform this normalization before the
enabled/mode checks so legacy settings continue to work.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@webhook_server/config/schema.yaml`:
- Around line 21-47: The ai-features.conventional-title node must preserve
legacy string values; update the schema or add a pre-validation migration:
either change the conventional-title definition to accept a union (oneOf) of the
legacy string enum ("true","false","fix") and the new object shape (with
properties enabled, mode, timeout-minutes, default values and
additionalProperties:false), or implement a migration step that rewrites
incoming config values by mapping "true" → {enabled: true, mode: suggest},
"false" → {enabled: false}, and "fix" → {enabled: true, mode: fix} before schema
validation, and document this mapping in the config docs; reference the
ai-features.conventional-title schema and the properties enabled, mode,
timeout-minutes when making the change.

---

Outside diff comments:
In `@webhook_server/libs/handlers/runner_handler.py`:
- Around line 577-591: The helper _get_ai_conventional_title_mode currently
returns None for non-dict ct_config, silently dropping legacy string/bool
configs; update it to accept and normalize legacy values from
self.github_webhook.ai_features: if ct_config is a bool True or string
"true"/"suggest"/"fix", treat them as {"enabled": True, "mode": "suggest" or
"fix"} (map plain "fix" to mode "fix", any other truthy string to "suggest");
keep existing dict handling for modern config, and only return None when enabled
is false or missing. Locate ct_config handling in
_get_ai_conventional_title_mode and perform this normalization before the
enabled/mode checks so legacy settings continue to work.

In `@webhook_server/tests/test_runner_handler.py`:
- Around line 703-740: The test
test_conventional_title_failure_with_ai_suggestion currently only asserts the
cwd passed to the mocked call_ai_cli; add an assertion that call_ai_cli received
timeout_minutes==10 (the default) by checking
mock_ai_cli.call_args[1]["timeout_minutes"] == 10, and add a second small test
(or extend this test) that configures runner_handler.github_webhook.ai_features
to include a non-default timeout (e.g., "timeout_minutes": 5) and asserts that
mock_ai_cli was awaited with timeout_minutes==5; reference the existing mock
object for call_ai_cli and the run_conventional_title_check invocation to locate
where to add these assertions.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: 99b27c18-dab4-4e1b-b2d3-eb3f02125c89

📥 Commits

Reviewing files that changed from the base of the PR and between a60b1ce and 2470c3b.

📒 Files selected for processing (6)
  • README.md
  • examples/.github-webhook-server.yaml
  • examples/config.yaml
  • webhook_server/config/schema.yaml
  • webhook_server/libs/handlers/runner_handler.py
  • webhook_server/tests/test_runner_handler.py

Comment thread webhook_server/config/schema.yaml
coderabbitai[bot]
coderabbitai Bot previously approved these changes Mar 12, 2026
- Validate conventional-title mode against (suggest, fix) with fallback
- Set check to success after valid AI title auto-fix
- Run AI title suggestion in PR worktree for correct context
- Assert timeout_minutes in test

Signed-off-by: Meni Yakove <myakove@gmail.com>
@myakove
Copy link
Copy Markdown
Collaborator Author

myakove commented Mar 12, 2026

/retest all

@myakove myakove merged commit f56f74b into main Mar 12, 2026
7 of 8 checks passed
@myakove myakove deleted the refactor/issue-1027-conventional-title-dict branch March 12, 2026 17:05
@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.

refactor: migrate conventional-title config from string to dict

2 participants