Repository: myk-org/github-webhook-server
Pull request #670: read branch protection rules from config files
Author: login: dbasunag
Labels: name: size/L
name: branch-main
name: approved-myakove
Created: 2025-02-27T23:40:07Z | Merged: 2025-03-06T11:19:22Z



<!-- This is an auto-generated comment: release notes by coderabbit.ai -->
## Summary by CodeRabbit

- **Tests**
  - Added a comprehensive suite of tests to verify branch protection behaviors under multiple configuration scenarios, ensuring reliable repository safeguards.

- **New Features**
  - Enhanced branch protection settings by introducing flexible, configurable parameters for features such as strict enforcement and review requirements, improving overall repository security.
  - Introduced a new configuration section for branch protection settings at both global and repository levels.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->


Diff:
diff --git a/example.config.yaml b/example.config.yaml
index 0364ee56..fe6e9c2a 100644
--- a/example.config.yaml
+++ b/example.config.yaml
@@ -30,6 +30,14 @@ jira:
   user-mapping:
     <GITHUB USER>: <JIRA USER> # if github user is not the same as jira
 
+branch_protection:
+  strict: True
+  require_code_owner_reviews: True
+  dismiss_stale_reviews: False
+  required_approving_review_count: 1
+  required_linear_history: True
+  required_conversation_resolution: True
+
 repositories:
   my-repository:
     name: my-org/my-repository
@@ -94,3 +102,10 @@ repositories:
         <GITHUB USER>: <JIRA USER> # if github user is not the same as jira
 
     conventional-title: "ci,docs,feat,fix,refactor,test,release" # Check PR title start with any of these words + :
+    branch_protection:
+      strict: True
+      require_code_owner_reviews: True
+      dismiss_stale_reviews: False
+      required_approving_review_count: 1
+      required_linear_history: True
+      required_conversation_resolution: True
diff --git a/webhook_server_container/config/schema.yaml b/webhook_server_container/config/schema.yaml
index b27e042f..80373275 100644
--- a/webhook_server_container/config/schema.yaml
+++ b/webhook_server_container/config/schema.yaml
@@ -51,6 +51,21 @@ properties:
       token:
         type: string
         format: password
+  branch_protection:
+    type: object
+    properties:
+      strict:
+        type: boolean
+      require_code_owner_reviews:
+        type: boolean
+      dismiss_stale_reviews:
+        type: boolean
+      required_approving_review_count:
+        type: integer
+      required_linear_history:
+        type: boolean
+      required_conversation_resolution:
+        type: boolean
   repositories:
     type: object
     properties:
@@ -141,6 +156,21 @@ properties:
           type: array
           items:
             type: string
+        branch_protection:
+          type: object
+          properties:
+            strict:
+              type: boolean
+            require_code_owner_reviews:
+              type: boolean
+            dismiss_stale_reviews:
+              type: boolean
+            required_approving_review_count:
+              type: integer
+            required_linear_history:
+              type: boolean
+            required_conversation_resolution:
+              type: boolean
   can-be-merged-required-labels:
     type: array
     items:
diff --git a/webhook_server_container/tests/test_branch_protection.py b/webhook_server_container/tests/test_branch_protection.py
new file mode 100644
index 00000000..71160038
--- /dev/null
+++ b/webhook_server_container/tests/test_branch_protection.py
@@ -0,0 +1,95 @@
+import os
+import pytest
+from webhook_server_container.libs.config import Config
+from webhook_server_container.utils.github_repository_settings import (
+    get_repo_branch_protection_rules,
+    DEFAULT_BRANCH_PROTECTION,
+)
+
+
+@pytest.fixture()
+def branch_protection_rules(request, mocker):
+    os.environ["WEBHOOK_SERVER_DATA_DIR"] = "webhook_server_container/tests/manifests"
+    config = Config()
+    repo_name = "test-repo"
+    data = config.data
+    data.setdefault("branch_protection", request.param.get("global", {}))
+    data["repositories"][repo_name].setdefault("branch_protection", request.param.get("repo", {}))
+    mocker.patch(
+        "webhook_server_container.libs.config.Config.data", new_callable=mocker.PropertyMock, return_value=data
+    )
+    return get_repo_branch_protection_rules(config_data=config.data, repo_data=config.data["repositories"][repo_name])[
+        "branch_protection"
+    ]
+
+
+@pytest.mark.parametrize(
+    "branch_protection_rules, expected",
+    [
+        pytest.param(
+            {
+                "global": {
+                    "strict": True,
+                },
+                "repo": {
+                    "strict": False,
+                },
+            },
+            {
+                "strict": False,
+            },
+            id="test_repo_branch_protection_rule",
+        ),
+        pytest.param(
+            {
+                "global": {
+                    "strict": False,
+                },
+            },
+            {
+                "strict": False,
+            },
+            id="test_global_branch_protection_rule",
+        ),
+        pytest.param(
+            {
+                "global": {
+                    "strict": False,
+                    "require_code_owner_reviews": True,
+                    "dismiss_stale_reviews": False,
+                    "required_approving_review_count": 2,
+                    "required_linear_history": False,
+                },
+                "repo": {
+                    "strict": True,
+                    "require_code_owner_reviews": True,
+                    "dismiss_stale_reviews": False,
+                    "required_approving_review_count": 1,
+                    "required_linear_history": True,
+                },
+            },
+            {
+                "strict": True,
+                "require_code_owner_reviews": True,
+                "dismiss_stale_reviews": False,
+                "required_approving_review_count": 1,
+                "required_linear_history": True,
+            },
+            id="test_repo_multiple_branch_protection_rule",
+        ),
+        pytest.param(
+            {},
+            {
+                **DEFAULT_BRANCH_PROTECTION,
+            },
+            id="test_default_branch_protection_rule",
+        ),
+    ],
+    indirect=["branch_protection_rules"],
+)
+def test_branch_protection_setup(branch_protection_rules, expected):
+    mismatch = {}
+    for key in expected:
+        if branch_protection_rules[key] != expected[key]:
+            mismatch[key] = f"Expected value for {key}: {expected[key]}, actual: {branch_protection_rules[key]}"
+    assert not mismatch, f"Following mismatches are found: {mismatch}"
diff --git a/webhook_server_container/utils/github_repository_settings.py b/webhook_server_container/utils/github_repository_settings.py
index 200071e2..d2391be8 100644
--- a/webhook_server_container/utils/github_repository_settings.py
+++ b/webhook_server_container/utils/github_repository_settings.py
@@ -28,8 +28,18 @@
     get_api_with_highest_rate_limit,
     get_future_results,
     get_logger_with_params,
+    get_value_from_dicts,
 )
 
+DEFAULT_BRANCH_PROTECTION = {
+    "strict": True,
+    "require_code_owner_reviews": False,
+    "dismiss_stale_reviews": True,
+    "required_approving_review_count": 0,
+    "required_linear_history": True,
+    "required_conversation_resolution": True,
+}
+
 
 def _get_github_repo_api(github_api: github.Github, repository: int | str) -> Repository | None:
     logger = get_logger_with_params(name="github-repository-settings")
@@ -49,19 +59,25 @@ def set_branch_protection(
     repository: Repository,
     required_status_checks: List[str],
     github_api: Github,
+    strict: bool,
+    require_code_owner_reviews: bool,
+    dismiss_stale_reviews: bool,
+    required_approving_review_count: int,
+    required_linear_history: bool,
+    required_conversation_resolution: bool,
 ) -> bool:
     logger = get_logger_with_params(name="github-repository-settings")
 
     api_user = github_api.get_user().login
     logger.info(f"Set branch {branch} setting for {repository.name}. enabled checks: {required_status_checks}")
     branch.edit_protection(
-        strict=True,
-        required_conversation_resolution=True,
+        strict=strict,
+        required_conversation_resolution=required_conversation_resolution,
         contexts=required_status_checks,
-        require_code_owner_reviews=False,
-        dismiss_stale_reviews=True,
-        required_approving_review_count=0,
-        required_linear_history=True,
+        require_code_owner_reviews=require_code_owner_reviews,
+        dismiss_stale_reviews=dismiss_stale_reviews,
+        required_approving_review_count=required_approving_review_count,
+        required_linear_history=required_linear_history,
         users_bypass_pull_request_allowances=[api_user],
         teams_bypass_pull_request_allowances=[api_user],
         apps_bypass_pull_request_allowances=[api_user],
@@ -168,6 +184,18 @@ def set_repository_labels(repository: Repository) -> str:
     return f"{repository}: Setting repository labels is done"
 
 
+def get_repo_branch_protection_rules(config_data: dict[str, Any], repo_data: dict[str, Any]) -> dict[str, Any]:
+    for rule_name in DEFAULT_BRANCH_PROTECTION:
+        repo_data.setdefault("branch_protection", {})
+        repo_data["branch_protection"][rule_name] = get_value_from_dicts(
+            primary_dict=repo_data["branch_protection"],
+            secondary_dict=config_data.get("branch_protection", {}),
+            key=rule_name,
+            return_on_none=DEFAULT_BRANCH_PROTECTION[rule_name],
+        )
+    return repo_data
+
+
 def set_repositories_settings(config_: Config, github_api: Github) -> None:
     logger = get_logger_with_params(name="github-repository-settings")
 
@@ -186,6 +214,7 @@ def set_repositories_settings(config_: Config, github_api: Github) -> None:
     futures = []
     with ThreadPoolExecutor() as executor:
         for _, data in config_data["repositories"].items():
+            data = get_repo_branch_protection_rules(config_data=config_data, repo_data=data)
             futures.append(
                 executor.submit(
                     set_repository,
@@ -208,6 +237,7 @@ def set_repository(
     repository: str = data["name"]
     logger.info(f"Processing repository {repository}")
     protected_branches: Dict[str, Any] = data.get("protected-branches", {})
+    repo_branch_protection_rules: Dict[str, Any] = data["branch_protection"]
     repo = _get_github_repo_api(github_api=github_api, repository=repository)
     if not repo:
         return False, f"{repository}: Failed to get repository", logger.error
@@ -241,7 +271,6 @@ def set_repository(
                     default_status_checks=_default_status_checks,
                     exclude_status_checks=exclude_status_checks,
                 )
-
                 futures.append(
                     executor.submit(
                         set_branch_protection,
@@ -251,6 +280,7 @@ def set_repository(
                             "required_status_checks": required_status_checks,
                             "github_api": github_api,
                         },
+                        **repo_branch_protection_rules,
                     )
                 )
 


Reviews:
user: login: coderabbitai[bot]
body: > [!CAUTION]
> Inline review comments failed to post. This is likely due to GitHub's limits when posting large numbers of comments.  If you are seeing this consistently it is likely a permissions issue. Please check "Moderation" -> "Code review limits" under your organization settings.

**Actionable comments posted: 1**

<details>
<summary>🧹 Nitpick comments (4)</summary><blockquote>

<details>
<summary>webhook_server_container/tests/test_branch_protection.py (2)</summary><blockquote>

`90-90`: **Simplify dictionary unpacking.**

The `**DEFAULT_BRANCH_PROTECTION` syntax is unnecessary in this context since you're creating a new dictionary. Consider using the constant directly.


```diff
            {
-                **DEFAULT_BRANCH_PROTECTION,
+                "strict": True,
+                "require_code_owner_reviews": False,
+                "dismiss_stale_reviews": True,
+                "required_approving_review_count": 0,
+                "required_linear_history": True,
+                "required_conversation_resolution": True,
            },
```

Or more simply:

```diff
            {
-                **DEFAULT_BRANCH_PROTECTION,
+                "strict": DEFAULT_BRANCH_PROTECTION["strict"],
+                "require_code_owner_reviews": DEFAULT_BRANCH_PROTECTION["require_code_owner_reviews"],
+                "dismiss_stale_reviews": DEFAULT_BRANCH_PROTECTION["dismiss_stale_reviews"],
+                "required_approving_review_count": DEFAULT_BRANCH_PROTECTION["required_approving_review_count"],
+                "required_linear_history": DEFAULT_BRANCH_PROTECTION["required_linear_history"],
+                "required_conversation_resolution": DEFAULT_BRANCH_PROTECTION["required_conversation_resolution"],
            },
```

---

`26-96`: **Consider adding a docstring to the test module.**

Adding a module-level docstring would help clarify the purpose and structure of these tests for future developers.


```diff
import os
import pytest
from webhook_server_container.libs.config import Config
from webhook_server_container.utils.github_repository_settings import (
    get_repo_branch_protection_rules,
    DEFAULT_BRANCH_PROTECTION,
)

+"""
+Tests for branch protection rules functionality.
+
+This module validates the behavior of the branch protection rules mechanism,
+ensuring that rules are correctly applied from repository-specific, global,
+and default configurations in the expected priority order.
+"""

@pytest.fixture()
def branch_protection_rules(request, mocker):
```

</blockquote></details>
<details>
<summary>webhook_server_container/utils/github_repository_settings.py (2)</summary><blockquote>

`186-197`: **Consider input validation and simplification.**

The get_repo_branch_protection_rules function works as expected, but could benefit from:
1. Type validation for the branch protection values
2. Simplification using a dictionary comprehension



```diff
def get_repo_branch_protection_rules(config_data: Dict[str, Any], repo_data: Dict[str, Any]) -> Dict[str, Any]:
-    for key in DEFAULT_BRANCH_PROTECTION:
-        branch_protection_rule = None
-        if key in repo_data:
-            branch_protection_rule = repo_data[key]
-        elif key in config_data:
-            branch_protection_rule = config_data[key]
-        else:
-            branch_protection_rule = DEFAULT_BRANCH_PROTECTION[key]
-        repo_data[key] = branch_protection_rule
+    # Use repository-specific rules, fall back to global rules, then to defaults
+    for key, default_value in DEFAULT_BRANCH_PROTECTION.items():
+        value = repo_data.get(key, config_data.get(key, default_value))
+        
+        # Validate types to prevent runtime errors
+        if key == "required_approving_review_count" and not isinstance(value, int):
+            repo_data[key] = default_value
+        elif key != "required_approving_review_count" and not isinstance(value, bool):
+            repo_data[key] = default_value
+        else:
+            repo_data[key] = value
    return repo_data
```

---

`186-197`: **Consider adding error logging for configuration issues.**

When merging configuration from different sources, it's useful to log warnings if unexpected values are encountered.


```diff
def get_repo_branch_protection_rules(config_data: Dict[str, Any], repo_data: Dict[str, Any]) -> Dict[str, Any]:
+    logger = get_logger_with_params(name="github-repository-settings")
    for key in DEFAULT_BRANCH_PROTECTION:
        branch_protection_rule = None
        if key in repo_data:
            branch_protection_rule = repo_data[key]
+            # Add type validation
+            if key == "required_approving_review_count" and not isinstance(branch_protection_rule, int):
+                logger.warning(f"Repository config for '{key}' has incorrect type. Expected int, got {type(branch_protection_rule).__name__}. Using default.")
+                branch_protection_rule = DEFAULT_BRANCH_PROTECTION[key]
+            elif key != "required_approving_review_count" and not isinstance(branch_protection_rule, bool):
+                logger.warning(f"Repository config for '{key}' has incorrect type. Expected bool, got {type(branch_protection_rule).__name__}. Using default.")
+                branch_protection_rule = DEFAULT_BRANCH_PROTECTION[key]
        elif key in config_data:
            branch_protection_rule = config_data[key]
+            # Add type validation
+            if key == "required_approving_review_count" and not isinstance(branch_protection_rule, int):
+                logger.warning(f"Global config for '{key}' has incorrect type. Expected int, got {type(branch_protection_rule).__name__}. Using default.")
+                branch_protection_rule = DEFAULT_BRANCH_PROTECTION[key]
+            elif key != "required_approving_review_count" and not isinstance(branch_protection_rule, bool):
+                logger.warning(f"Global config for '{key}' has incorrect type. Expected bool, got {type(branch_protection_rule).__name__}. Using default.")
+                branch_protection_rule = DEFAULT_BRANCH_PROTECTION[key]
        else:
            branch_protection_rule = DEFAULT_BRANCH_PROTECTION[key]
        repo_data[key] = branch_protection_rule
    return repo_data
```

</blockquote></details>

</blockquote></details>

<details>
<summary>🛑 Comments failed to post (1)</summary><blockquote>

<details>
<summary>webhook_server_container/tests/test_branch_protection.py (1)</summary><blockquote>

42-49: _:warning: Potential issue_

**Fix duplicate test ID.**

There are two test cases with the identical ID "test_default_branch_protection_rule" (lines 48 and 92). This could cause confusion when running specific tests by ID.


```diff
        pytest.param(
            {},
            {
                "strict": True,
            },
-            id="test_default_branch_protection_rule",
+            id="test_default_single_branch_protection_rule",
        ),
```


Also applies to: 88-93

</blockquote></details>

</blockquote></details>

<!-- This is an auto-generated comment by CodeRabbit for review status -->
state: COMMENTED
author_association: NONE
submitted_at: 2025-02-27T23:43:09Z
user: login: coderabbitai[bot]
body: **Actionable comments posted: 2**

<details>
<summary>🧹 Nitpick comments (4)</summary><blockquote>

<details>
<summary>webhook_server_container/tests/test_branch_protection.py (4)</summary><blockquote>

`10-24`: **Add docstring to describe the fixture's purpose and parameters.**

The `branch_protection_rules` fixture lacks documentation explaining its purpose, parameters, and return value. This would improve readability and maintainability.

```diff
 @pytest.fixture()
 def branch_protection_rules(request, mocker):
+    """
+    Fixture to prepare and return branch protection rules based on test parameters.
+    
+    Args:
+        request: pytest request object containing parameters for the test case
+        mocker: pytest-mock fixture for patching
+    
+    Parameters format:
+        {
+            "global": {key: value, ...},  # Global branch protection settings
+            "repo": {key: value, ...}     # Repository-specific settings that override global ones
+        }
+    
+    Returns:
+        dict: The effective branch protection rules for the repository
+    """
     os.environ["WEBHOOK_SERVER_DATA_DIR"] = "webhook_server_container/tests/manifests"
     config = Config()
     repo_name = next(iter(config.data["repositories"]))
```

---

`97-102`: **Add docstring to describe the test function.**

The `test_branch_protection_setup` function would benefit from a docstring explaining its purpose and parameters.

```diff
 def test_branch_protection_setup(branch_protection_rules, expected):
+    """
+    Test that branch protection rules are correctly determined from global and repository-specific configurations.
+    
+    Args:
+        branch_protection_rules: Actual branch protection rules from the fixture
+        expected: Expected branch protection rules for the test case
+    
+    Verifies that there are no mismatches between expected and actual branch protection rules.
+    """
     mismatch = {}
     for key in expected:
         if branch_protection_rules[key] != expected[key]:
```

---

`99-101`: **Use assertDictEqual for clearer dictionary comparison results.**

The current comparison implementation manually builds a mismatch dictionary. Consider using pytest's built-in dictionary comparison for cleaner test output.

```diff
-    mismatch = {}
-    for key in expected:
-        if branch_protection_rules[key] != expected[key]:
-            mismatch[key] = f"Expected value for {key}: {expected[key]}, actual: {branch_protection_rules[key]}"
-    assert not mismatch, f"Following mismatches are found: {mismatch}"
+    # Filter branch_protection_rules to only include keys in expected
+    actual = {k: branch_protection_rules[k] for k in expected}
+    assert actual == expected, f"Branch protection rules mismatch.\nExpected: {expected}\nActual: {actual}"
```

---

`26-96`: **Add test case for missing configuration keys.**

The current test cases don't verify behavior when certain branch protection keys are present in one level but missing in another. Consider adding a test case to ensure proper fallback behavior.

```diff
         pytest.param(
             {},
             {
                 **DEFAULT_BRANCH_PROTECTION,
             },
             id="test_default_branch_protection_rule",
         ),
+        pytest.param(
+            {
+                "global": {
+                    "strict": True,
+                    "require_code_owner_reviews": True,
+                },
+                "repo": {
+                    "required_approving_review_count": 2,
+                    "required_linear_history": True,
+                },
+            },
+            {
+                "strict": True,
+                "require_code_owner_reviews": True,
+                "required_approving_review_count": 2,
+                "required_linear_history": True,
+            },
+            id="test_mixed_branch_protection_rules",
+        ),
     ],
     indirect=["branch_protection_rules"],
 )
```

</blockquote></details>

</blockquote></details>

<details>
<summary>📜 Review details</summary>

**Configuration used: CodeRabbit UI**
**Review profile: CHILL**
**Plan: Pro**

<details>
<summary>📥 Commits</summary>

Reviewing files that changed from the base of the PR and between 9db9c9f897652703945dce51b6864f31d2a921ff and 98818a90ef78f1f703fc64701e4fcf15ebb4869f.

</details>

<details>
<summary>📒 Files selected for processing (2)</summary>

* `webhook_server_container/tests/test_branch_protection.py` (1 hunks)
* `webhook_server_container/utils/github_repository_settings.py` (5 hunks)

</details>

<details>
<summary>🚧 Files skipped from review as they are similar to previous changes (1)</summary>

* webhook_server_container/utils/github_repository_settings.py

</details>

<details>
<summary>⏰ Context from checks skipped due to timeout of 90000ms (4)</summary>

* GitHub Check: pre-commit
* GitHub Check: tox
* GitHub Check: python-module-install
* GitHub Check: build-container

</details>

</details>

<!-- This is an auto-generated comment by CodeRabbit for review status -->
state: COMMENTED
author_association: NONE
submitted_at: 2025-02-27T23:45:51Z
user: login: myakove
state: CHANGES_REQUESTED
author_association: COLLABORATOR
submitted_at: 2025-02-28T08:56:32Z
user: login: coderabbitai[bot]
body: **Actionable comments posted: 0**

<details>
<summary>🧹 Nitpick comments (3)</summary><blockquote>

<details>
<summary>webhook_server_container/config/schema.yaml (2)</summary><blockquote>

`54-65`: **New Branch Protection Properties at Root Level**  
The new properties (`strict`, `require_code_owner_reviews`, `dismiss_stale_reviews`, `required_approving_review_count`, `required_linear_history`, `required_conversation_resolution`) are correctly added at the root level to reflect the new branch protection settings. This aligns with the PR objective of reading branch protection rules from configuration files.  
Consider adding descriptive fields for each property to improve clarity for users editing the config file.

---

`156-167`: **Repository-Specific Branch Protection Enhancements**  
The branch protection properties have been duplicated under the `my-repository` object within `repositories`, mirroring the root-level properties. This consistency is beneficial for granular configuration per repository.  
It would be helpful to also include descriptions for these properties as done for other settings in the schema, so administrators understand their purpose at a glance.

</blockquote></details>
<details>
<summary>webhook_server_container/tests/test_branch_protection.py (1)</summary><blockquote>

`90-95`: **Enhance test robustness by checking for unexpected keys.**

The current test only checks if expected keys have the correct values, but doesn't verify if there are unexpected keys in the actual result. This could hide potential issues where extra configuration options are being returned unexpectedly.

```diff
def test_branch_protection_setup(branch_protection_rules, expected):
    mismatch = {}
    for key in expected:
        if branch_protection_rules[key] != expected[key]:
            mismatch[key] = f"Expected value for {key}: {expected[key]}, actual: {branch_protection_rules[key]}"
+    # Check for unexpected keys
+    unexpected = set(branch_protection_rules.keys()) - set(expected.keys())
+    if unexpected:
+        mismatch["unexpected_keys"] = f"Found unexpected keys in result: {unexpected}"
    assert not mismatch, f"Following mismatches are found: {mismatch}"
```

</blockquote></details>

</blockquote></details>

<details>
<summary>📜 Review details</summary>

**Configuration used: CodeRabbit UI**
**Review profile: CHILL**
**Plan: Pro**

<details>
<summary>📥 Commits</summary>

Reviewing files that changed from the base of the PR and between 98818a90ef78f1f703fc64701e4fcf15ebb4869f and eee17a584071d6d27b3fbc2e241bc019dc976a59.

</details>

<details>
<summary>📒 Files selected for processing (3)</summary>

* `webhook_server_container/config/schema.yaml` (2 hunks)
* `webhook_server_container/tests/test_branch_protection.py` (1 hunks)
* `webhook_server_container/utils/github_repository_settings.py` (5 hunks)

</details>

<details>
<summary>🚧 Files skipped from review as they are similar to previous changes (1)</summary>

* webhook_server_container/utils/github_repository_settings.py

</details>

<details>
<summary>⏰ Context from checks skipped due to timeout of 90000ms (4)</summary>

* GitHub Check: tox
* GitHub Check: python-module-install
* GitHub Check: pre-commit
* GitHub Check: build-container

</details>

<details>
<summary>🔇 Additional comments (3)</summary><blockquote>

<details>
<summary>webhook_server_container/tests/test_branch_protection.py (3)</summary>

`14-14`: **Use the real repo name from the test config file.**

As mentioned in a previous comment, you should use the actual repository name from the test configuration file instead of hardcoding "test-repo". This ensures tests are based on real data and avoids maintenance issues when the test configuration changes.

```diff
-    repo_name = "test-repo"
+    repo_name = next(iter(config.data["repositories"]))
```

---

`15-19`: **Add error handling for empty repositories list.**

The code assumes that `config.data["repositories"]` is non-empty. If there are no repositories defined in the configuration, this will raise an exception. Add appropriate error handling before accessing repository data.

```diff
    data = config.data
+    if not data.get("repositories"):
+        raise ValueError("No repositories found in the test configuration")
+    repo_name = next(iter(data["repositories"]))
    for key in request.param.get("global", {}):
        data[key] = request.param["global"][key]
    for key in request.param.get("repo", {}):
        data["repositories"][repo_name][key] = request.param["repo"][key]
```

---

`26-89`: **LGTM! Good use of parameterized tests.**

The test cases cover a good range of scenarios for branch protection rules, including global settings, repository-specific settings, and their interactions. The use of pytest's parameterization with the `indirect` parameter is well implemented.

</details>

</blockquote></details>

</details>

<!-- This is an auto-generated comment by CodeRabbit for review status -->
state: COMMENTED
author_association: NONE
submitted_at: 2025-02-28T19:32:10Z
user: login: myakove
body: Also update config.example with the changes
state: CHANGES_REQUESTED
author_association: COLLABORATOR
submitted_at: 2025-03-02T07:22:19Z
user: login: dbasunag
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-03T11:56:40Z
user: login: myakove
state: CHANGES_REQUESTED
author_association: COLLABORATOR
submitted_at: 2025-03-03T17:59:22Z
user: login: coderabbitai[bot]
body: **Actionable comments posted: 1**

<details>
<summary>🧹 Nitpick comments (1)</summary><blockquote>

<details>
<summary>webhook_server_container/utils/github_repository_settings.py (1)</summary><blockquote>

`279-289`: **Verify fields exist in branch_protection before accessing.**

The code directly accesses fields in the `branch_protection` dictionary without checking if they exist. While the `get_repo_branch_protection_rules` function should ensure these fields are populated, it would be more robust to use `data.get("branch_protection", {}).get("field_name", default_value)` pattern to handle potential missing fields gracefully.


```diff
-                            "strict": data["branch_protection"]["strict"],
-                            "require_code_owner_reviews": data["branch_protection"]["require_code_owner_reviews"],
-                            "dismiss_stale_reviews": data["branch_protection"]["dismiss_stale_reviews"],
-                            "required_approving_review_count": data["branch_protection"][
-                                "required_approving_review_count"
-                            ],
-                            "required_linear_history": data["branch_protection"]["required_linear_history"],
-                            "required_conversation_resolution": data["branch_protection"][
-                                "required_conversation_resolution"
-                            ],
+                            "strict": data.get("branch_protection", {}).get("strict", DEFAULT_BRANCH_PROTECTION["strict"]),
+                            "require_code_owner_reviews": data.get("branch_protection", {}).get("require_code_owner_reviews", DEFAULT_BRANCH_PROTECTION["require_code_owner_reviews"]),
+                            "dismiss_stale_reviews": data.get("branch_protection", {}).get("dismiss_stale_reviews", DEFAULT_BRANCH_PROTECTION["dismiss_stale_reviews"]),
+                            "required_approving_review_count": data.get("branch_protection", {}).get("required_approving_review_count", DEFAULT_BRANCH_PROTECTION["required_approving_review_count"]),
+                            "required_linear_history": data.get("branch_protection", {}).get("required_linear_history", DEFAULT_BRANCH_PROTECTION["required_linear_history"]),
+                            "required_conversation_resolution": data.get("branch_protection", {}).get("required_conversation_resolution", DEFAULT_BRANCH_PROTECTION["required_conversation_resolution"]),
```

</blockquote></details>

</blockquote></details>

<details>
<summary>📜 Review details</summary>

**Configuration used: CodeRabbit UI**
**Review profile: CHILL**
**Plan: Pro**

<details>
<summary>📥 Commits</summary>

Reviewing files that changed from the base of the PR and between eee17a584071d6d27b3fbc2e241bc019dc976a59 and 34097ac5deeb9f9bb4918d4a1610c3dbc751da1f.

</details>

<details>
<summary>📒 Files selected for processing (4)</summary>

* `example.config.yaml` (2 hunks)
* `webhook_server_container/config/schema.yaml` (2 hunks)
* `webhook_server_container/tests/test_branch_protection.py` (1 hunks)
* `webhook_server_container/utils/github_repository_settings.py` (5 hunks)

</details>

<details>
<summary>🚧 Files skipped from review as they are similar to previous changes (1)</summary>

* webhook_server_container/tests/test_branch_protection.py

</details>

<details>
<summary>⏰ Context from checks skipped due to timeout of 90000ms (4)</summary>

* GitHub Check: python-module-install
* GitHub Check: tox
* GitHub Check: build-container
* GitHub Check: pre-commit

</details>

<details>
<summary>🔇 Additional comments (10)</summary><blockquote>

<details>
<summary>example.config.yaml (2)</summary>

`33-38`: **Consider using `branch-protection` instead of `branch_protection` for consistency.**

Previous review comments indicate that the configuration should use hyphenated naming (`branch-protection`) rather than underscore naming (`branch_protection`). There appears to be an ongoing discussion about this naming convention.

---

`104-109`: **Add missing `required_conversation_resolution` field to match implementation.**

Same as the global configuration, the repository-specific branch protection configuration is missing the `required_conversation_resolution` field that is defined in the `DEFAULT_BRANCH_PROTECTION` constant.

</details>
<details>
<summary>webhook_server_container/utils/github_repository_settings.py (5)</summary>

`34-41`: **The default configuration looks good.**

The `DEFAULT_BRANCH_PROTECTION` constant provides sensible defaults for branch protection settings.

---

`57-68`: **Updated function signature to support branch protection parameters.**

The function signature has been appropriately updated to include all the branch protection parameters needed for the GitHub API.

---

`74-81`: **Branch protection parameters correctly applied.**

The branch protection parameters are correctly passed to the `edit_protection` method.

---

`187-196`: **Good use of helper function for determining effective branch protection rules.**

The `get_repo_branch_protection_rules` function correctly uses `get_value_from_dicts` to prioritize repository-specific settings over global ones, with defaults from `DEFAULT_BRANCH_PROTECTION`.

---

`217-217`: **Correctly apply branch protection rules at repository setup.**

The call to `get_repo_branch_protection_rules` within the repository setup loop ensures that each repository gets the correct branch protection settings based on both global and repository-specific configurations.

</details>
<details>
<summary>webhook_server_container/config/schema.yaml (3)</summary>

`54-68`: **Consider using `branch-protection` instead of `branch_protection` for consistency.**

Based on previous review comments, the schema should use hyphenated naming (`branch-protection`) rather than underscore naming (`branch_protection`). Consider updating the field name for consistency with other fields in the schema (like `log-level`, `github-app-id`, etc.).



```shell
#!/bin/bash
# Look for naming patterns in the schema file to verify consistency
echo "Fields with hyphens:"
grep -E '^ +[a-z]+-[a-z]+:' webhook_server_container/config/schema.yaml | sort | uniq

echo -e "\nFields with underscores:"
grep -E '^ +[a-z]+_[a-z]+:' webhook_server_container/config/schema.yaml | sort | uniq
```

---

`54-68`: **Add missing `required_conversation_resolution` documentation.**

The schema defines `required_conversation_resolution` but this field is missing from the example configuration in `example.config.yaml`. Ensure that documentation is updated to include all fields.

---

`159-173`: **Consider using `branch-protection` instead of `branch_protection` for consistency.**

Same issue as in the root-level schema definition. Consider updating for consistency with other hyphenated field names.

</details>

</blockquote></details>

</details>

<!-- This is an auto-generated comment by CodeRabbit for review status -->
state: COMMENTED
author_association: NONE
submitted_at: 2025-03-04T17:36:25Z
user: login: dbasunag
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-04T17:53:55Z
user: login: myakove
state: CHANGES_REQUESTED
author_association: COLLABORATOR
submitted_at: 2025-03-05T07:31:42Z
user: login: coderabbitai[bot]
state: COMMENTED
author_association: NONE
submitted_at: 2025-03-05T07:31:48Z
user: login: dbasunag
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-05T22:20:05Z
user: login: dbasunag
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-05T22:27:09Z
user: login: coderabbitai[bot]
body: **Actionable comments posted: 0**

<details>
<summary>🔭 Outside diff range comments (1)</summary><blockquote>

<details>
<summary>example.config.yaml (1)</summary><blockquote>

`7-9`: _⚠️ Potential issue_

**Fix typo in configuration key.**

There's a typo in the GitHub tokens configuration key.


```diff
-github-toekns:
+github-tokens:
```

</blockquote></details>

</blockquote></details>

<details>
<summary>🧹 Nitpick comments (1)</summary><blockquote>

<details>
<summary>webhook_server_container/utils/github_repository_settings.py (1)</summary><blockquote>

`275-285`: **Consider adding type annotations to dictionary unpacking.**

To improve code readability and type-safety, consider adding type annotations for the branch protection parameters in the `executor.submit` call.


```diff
futures.append(
    executor.submit(
        set_branch_protection,
        **{
            "branch": branch,
            "repository": repo,
            "required_status_checks": required_status_checks,
            "github_api": github_api,
-        },
+        } : dict[str, Any],
        **repo_branch_protection_rules,
    )
)
```

</blockquote></details>

</blockquote></details>

<details>
<summary>📜 Review details</summary>

**Configuration used: CodeRabbit UI**
**Review profile: CHILL**
**Plan: Pro**

<details>
<summary>📥 Commits</summary>

Reviewing files that changed from the base of the PR and between 34097ac5deeb9f9bb4918d4a1610c3dbc751da1f and 71bf62d6e02d7e6718675503712a804cd7d2a9cf.

</details>

<details>
<summary>📒 Files selected for processing (2)</summary>

* `example.config.yaml` (2 hunks)
* `webhook_server_container/utils/github_repository_settings.py` (6 hunks)

</details>

<details>
<summary>⏰ Context from checks skipped due to timeout of 90000ms (4)</summary>

* GitHub Check: python-module-install
* GitHub Check: tox
* GitHub Check: pre-commit
* GitHub Check: build-container

</details>

<details>
<summary>🔇 Additional comments (10)</summary><blockquote>

<details>
<summary>example.config.yaml (2)</summary>

`33-39`: **Configuration matches implementation, good job!**

The branch protection settings at the root level align well with the `DEFAULT_BRANCH_PROTECTION` constant in `github_repository_settings.py`. The `required_conversation_resolution: True` field has been properly added as requested in previous feedback.

---

`105-111`: **Consistent repository-specific branch protection configuration.**

The repository-specific branch protection configuration correctly mirrors the global configuration, allowing for repository-level customization if needed while maintaining the same structure.

</details>
<details>
<summary>webhook_server_container/utils/github_repository_settings.py (8)</summary>

`31-31`: **Appropriate import for helper function.**

The `get_value_from_dicts` import is correctly added to support the new branch protection logic.

---

`34-41`: **Well-structured default branch protection configuration.**

The `DEFAULT_BRANCH_PROTECTION` constant provides good default values for branch protection settings. The values are sensible and align with the example configuration.

---

`57-68`: **Function signature properly expanded to support branch protection parameters.**

The function signature for `set_branch_protection` has been correctly expanded to include all the branch protection parameters needed for the GitHub API.

---

`74-81`: **Correct use of branch protection parameters in API call.**

The branch protection parameters are properly passed to the `edit_protection` method, ensuring that all settings are applied to the branch.

---

`187-197`: **Well-implemented branch protection rules resolution.**

The `get_repo_branch_protection_rules` function effectively resolves branch protection rules by prioritizing repository-specific settings over global ones and falling back to defaults when needed. The use of `get_value_from_dicts` is appropriate here.

---

`217-217`: **Correctly integrates branch protection rules into repository settings.**

The implementation now properly integrates branch protection rules by calling `get_repo_branch_protection_rules` before passing the data to `set_repository`.

---

`240-240`: **Good use of descriptive variable name.**

The variable name `repo_branch_protection_rules` is descriptive and clearly indicates what the data represents, as suggested in previous feedback.

---

`283-283`: **Efficient parameter passing using dictionary unpacking.**

The use of `**repo_branch_protection_rules` to unpack the branch protection parameters is efficient and matches the suggestion from previous feedback.

</details>

</blockquote></details>

</details>

<!-- This is an auto-generated comment by CodeRabbit for review status -->
state: COMMENTED
author_association: NONE
submitted_at: 2025-03-05T23:14:19Z
user: login: myakove
state: APPROVED
author_association: COLLABORATOR
submitted_at: 2025-03-06T11:18:09Z

Review comments:
diff_hunk: @@ -0,0 +1,102 @@
+import os
+import pytest
+from webhook_server_container.libs.config import Config
+from webhook_server_container.utils.github_repository_settings import (
+    get_repo_branch_protection_rules,
+    DEFAULT_BRANCH_PROTECTION,
+)
+
+
+@pytest.fixture()
+def branch_protection_rules(request, mocker):
+    os.environ["WEBHOOK_SERVER_DATA_DIR"] = "webhook_server_container/tests/manifests"
+    config = Config()
+    repo_name = next(iter(config.data["repositories"]))
+    data = config.data
+    for key in request.param.get("global", {}):
+        data[key] = request.param["global"][key]
+    for key in request.param.get("repo", {}):
+        data["repositories"][repo_name][key] = request.param["repo"][key]
+    mocker.patch(
+        "webhook_server_container.libs.config.Config.data", new_callable=mocker.PropertyMock, return_value=data
+    )
+    return get_repo_branch_protection_rules(config_data=config.data, repo_data=config.data["repositories"][repo_name])
+
+
+@pytest.mark.parametrize(
+    "branch_protection_rules, expected",
+    [
+        pytest.param(
+            {
+                "global": {
+                    "strict": True,
+                },
+                "repo": {
+                    "strict": False,
+                },
+            },
+            {
+                "strict": False,
+            },
+            id="test_repo_branch_protection_rule",
+        ),
+        pytest.param(
+            {},
+            {
+                "strict": True,
+            },
+            id="test_default_branch_protection_rule",
+        ),
path: webhook_server_container/tests/test_branch_protection.py
user: login: coderabbitai[bot]
body: _:hammer_and_wrench: Refactor suggestion_

**Remove duplicate test cases with identical IDs.**

There are two test cases with the same ID "test_default_branch_protection_rule" (lines 48 and 92), but they're implemented differently:
- Lines 43-49: Explicitly sets `{"strict": True}` as the expected value
- Lines 87-93: Uses the imported `DEFAULT_BRANCH_PROTECTION` constant

These appear to be testing the same behavior in different ways. Consider consolidating these into a single test case that uses the `DEFAULT_BRANCH_PROTECTION` constant for clarity and maintainability.

```diff
-        pytest.param(
-            {},
-            {
-                "strict": True,
-            },
-            id="test_default_branch_protection_rule",
-        ),
         pytest.param(
             {},
             {
                 **DEFAULT_BRANCH_PROTECTION,
             },
             id="test_default_branch_protection_rule",
         ),
```


Also applies to: 87-93

<!-- This is an auto-generated comment by CodeRabbit -->
created_at: 2025-02-27T23:45:50Z
author_association: NONE
diff_hunk: @@ -0,0 +1,102 @@
+import os
+import pytest
+from webhook_server_container.libs.config import Config
+from webhook_server_container.utils.github_repository_settings import (
+    get_repo_branch_protection_rules,
+    DEFAULT_BRANCH_PROTECTION,
+)
+
+
+@pytest.fixture()
+def branch_protection_rules(request, mocker):
+    os.environ["WEBHOOK_SERVER_DATA_DIR"] = "webhook_server_container/tests/manifests"
+    config = Config()
+    repo_name = next(iter(config.data["repositories"]))
+    data = config.data
path: webhook_server_container/tests/test_branch_protection.py
user: login: coderabbitai[bot]
body: _:bulb: Verification agent_

<details>
<summary>🧩 Analysis chain</summary>

**Consider adding error handling for empty repositories list.**

The code assumes `config.data["repositories"]` is not empty. If there are no repositories in the test data, this will raise an exception.

---

🏁 Script executed:

```shell
#!/bin/bash
# Check if test manifest file exists and has repositories defined
manifest_file="webhook_server_container/tests/manifests/config.yaml"
if [ -f "$manifest_file" ]; then
  echo "Test manifest file exists. Checking for repositories:"
  grep -A 5 "repositories:" "$manifest_file"
else
  echo "Test manifest file not found at: $manifest_file"
fi
```

Length of output: 612

---



</details>

**Action Required: Add error handling before iterating over repositories**

While the current test manifest in `webhook_server_container/tests/manifests/config.yaml` includes repository data, the code still assumes that `config.data["repositories"]` is non-empty. If the repositories mapping were ever empty—due to a misconfiguration or an intentional test for edge cases—using `next(iter(config.data["repositories"]))` would raise a `StopIteration` exception. Consider introducing a guard clause to handle such cases. For example:

```python
if not config.data.get("repositories"):
    raise ValueError("No repositories found in the test configuration")
repo_name = next(iter(config.data["repositories"]))
```

This proactive check will make the test more robust against empty configurations.

<!-- This is an auto-generated comment by CodeRabbit -->
created_at: 2025-02-27T23:45:50Z
author_association: NONE
diff_hunk: @@ -0,0 +1,102 @@
+import os
+import pytest
+from webhook_server_container.libs.config import Config
+from webhook_server_container.utils.github_repository_settings import (
+    get_repo_branch_protection_rules,
+    DEFAULT_BRANCH_PROTECTION,
+)
+
+
+@pytest.fixture()
+def branch_protection_rules(request, mocker):
+    os.environ["WEBHOOK_SERVER_DATA_DIR"] = "webhook_server_container/tests/manifests"
+    config = Config()
+    repo_name = next(iter(config.data["repositories"]))
path: webhook_server_container/tests/test_branch_protection.py
user: login: myakove
body: Please use the real repo name from the test config file.

created_at: 2025-02-28T08:51:33Z
author_association: COLLABORATOR
diff_hunk: @@ -168,6 +183,19 @@ def set_repository_labels(repository: Repository) -> str:
     return f"{repository}: Setting repository labels is done"
 
 
+def get_repo_branch_protection_rules(config_data: dict[str, Any], repo_data: dict[str, Any]) -> dict[str, Any]:
+    for key in DEFAULT_BRANCH_PROTECTION:
path: webhook_server_container/utils/github_repository_settings.py
user: login: myakove
body: Use `get_value_from_dicts`
created_at: 2025-02-28T08:54:54Z
author_association: COLLABORATOR
diff_hunk: @@ -51,6 +51,18 @@ properties:
       token:
         type: string
         format: password
+  strict:
path: webhook_server_container/config/schema.yaml
user: login: myakove
body: Should be under `branch-protection` section.

created_at: 2025-03-02T07:20:32Z
author_association: COLLABORATOR
diff_hunk: @@ -141,6 +153,18 @@ properties:
           type: array
           items:
             type: string
+        strict:
path: webhook_server_container/config/schema.yaml
user: login: myakove
body: ditto
created_at: 2025-03-02T07:20:44Z
author_association: COLLABORATOR
diff_hunk: @@ -51,6 +51,18 @@ properties:
       token:
         type: string
         format: password
+  strict:
path: webhook_server_container/config/schema.yaml
user: login: dbasunag
body: Current code expects them to be similar to other global config option. Do you want that to change? How about repo ones? Should they be under branch protection section too?
created_at: 2025-03-03T11:56:40Z
author_association: CONTRIBUTOR
diff_hunk: @@ -51,6 +51,18 @@ properties:
       token:
         type: string
         format: password
+  strict:
path: webhook_server_container/config/schema.yaml
user: login: myakove
body: Yes, it should be under `branch-protection`.
What are `repo ones` that you mansion?
created_at: 2025-03-03T17:55:58Z
author_association: COLLABORATOR
diff_hunk: @@ -30,6 +30,13 @@ jira:
   user-mapping:
     <GITHUB USER>: <JIRA USER> # if github user is not the same as jira
 
+branch_protection:
+  strict: True
+  require_code_owner_reviews: True
+  dismiss_stale_reviews: False
+  required_approving_review_count: 1
+  required_linear_history: True
path: example.config.yaml
user: login: coderabbitai[bot]
body: _💡 Verification agent_

<details>
<summary>🧩 Analysis chain</summary>

**Add missing `required_conversation_resolution` field to match implementation.**

The branch protection configuration is missing the `required_conversation_resolution` field that is defined in the `DEFAULT_BRANCH_PROTECTION` constant in `github_repository_settings.py`. This field is used when setting branch protection in the `set_branch_protection` function.

---

🏁 Script executed:

```shell
#!/bin/bash
# Verify the DEFAULT_BRANCH_PROTECTION constant includes required_conversation_resolution
grep -A 10 "DEFAULT_BRANCH_PROTECTION" webhook_server_container/utils/github_repository_settings.py
```

Length of output: 1191

---



</details>

**Action Required: Update branch protection configuration**

The YAML configuration is missing the `required_conversation_resolution` field. The `DEFAULT_BRANCH_PROTECTION` constant in `webhook_server_container/utils/github_repository_settings.py` defines it as `True`, so please add it to ensure consistency. For example, update the branch protection section in `example.config.yaml` as follows:

```yaml
branch_protection:
  strict: True
  require_code_owner_reviews: True
  dismiss_stale_reviews: False
  required_approving_review_count: 1
  required_linear_history: True
  required_conversation_resolution: True
```

<!-- This is an auto-generated reply by CodeRabbit -->
created_at: 2025-03-04T17:36:24Z
author_association: NONE
diff_hunk: @@ -51,6 +51,18 @@ properties:
       token:
         type: string
         format: password
+  strict:
path: webhook_server_container/config/schema.yaml
user: login: dbasunag
body: ok, I moved them under branch_protection for both global and repo settings
created_at: 2025-03-04T17:53:55Z
author_association: CONTRIBUTOR
diff_hunk: @@ -30,6 +30,13 @@ jira:
   user-mapping:
     <GITHUB USER>: <JIRA USER> # if github user is not the same as jira
 
+branch_protection:
+  strict: True
+  require_code_owner_reviews: True
+  dismiss_stale_reviews: False
+  required_approving_review_count: 1
+  required_linear_history: True
path: example.config.yaml
user: login: myakove
body: @dbasunag please fix this
created_at: 2025-03-05T07:26:57Z
author_association: COLLABORATOR
diff_hunk: @@ -186,6 +214,7 @@ def set_repositories_settings(config_: Config, github_api: Github) -> None:
     futures = []
     with ThreadPoolExecutor() as executor:
         for _, data in config_data["repositories"].items():
+            data = get_repo_branch_protection_rules(config_data=config_data, repo_data=data)
path: webhook_server_container/utils/github_repository_settings.py
user: login: myakove
body: please rename `data` to name that describe the data (`repo_branch_protection_rules`?)

created_at: 2025-03-05T07:31:03Z
author_association: COLLABORATOR
diff_hunk: @@ -247,6 +276,16 @@ def set_repository(
                         set_branch_protection,
                         **{
                             "branch": branch,
+                            "strict": data["branch_protection"]["strict"],
path: webhook_server_container/utils/github_repository_settings.py
user: login: myakove
body: you can send here `**repo_branch_protection_rules` 
created_at: 2025-03-05T07:31:36Z
author_association: COLLABORATOR
diff_hunk: @@ -30,6 +30,13 @@ jira:
   user-mapping:
     <GITHUB USER>: <JIRA USER> # if github user is not the same as jira
 
+branch_protection:
+  strict: True
+  require_code_owner_reviews: True
+  dismiss_stale_reviews: False
+  required_approving_review_count: 1
+  required_linear_history: True
path: example.config.yaml
user: login: coderabbitai[bot]
body: > Seems like the humans are having a chat. I'll hop back into my burrow for now. If you need me again, just tag @coderabbitai in a new comment, and I'll come hopping out!

<!-- This is an auto-generated mute comment by CodeRabbit -->
created_at: 2025-03-05T07:31:48Z
author_association: NONE
diff_hunk: @@ -186,6 +214,7 @@ def set_repositories_settings(config_: Config, github_api: Github) -> None:
     futures = []
     with ThreadPoolExecutor() as executor:
         for _, data in config_data["repositories"].items():
+            data = get_repo_branch_protection_rules(config_data=config_data, repo_data=data)
path: webhook_server_container/utils/github_repository_settings.py
user: login: dbasunag
body: But this is the entire data dict including repo branch protection (get_repo_branch_protection_rules() returns the entire repo_data dict). Do you want me to just separate it?
created_at: 2025-03-05T22:20:05Z
author_association: CONTRIBUTOR
diff_hunk: @@ -30,6 +30,13 @@ jira:
   user-mapping:
     <GITHUB USER>: <JIRA USER> # if github user is not the same as jira
 
+branch_protection:
+  strict: True
+  require_code_owner_reviews: True
+  dismiss_stale_reviews: False
+  required_approving_review_count: 1
+  required_linear_history: True
path: example.config.yaml
user: login: dbasunag
body: Done.
created_at: 2025-03-05T22:27:09Z
author_association: CONTRIBUTOR
diff_hunk: @@ -186,6 +214,7 @@ def set_repositories_settings(config_: Config, github_api: Github) -> None:
     futures = []
     with ThreadPoolExecutor() as executor:
         for _, data in config_data["repositories"].items():
+            data = get_repo_branch_protection_rules(config_data=config_data, repo_data=data)
path: webhook_server_container/utils/github_repository_settings.py
user: login: myakove
body: what you did is good.
created_at: 2025-03-06T11:17:46Z
author_association: COLLABORATOR

PR comments:
user: login: myakove-bot
created_at: 2025-02-27T23:40:15Z
body: 
Report bugs in [Issues](https://github.com/myakove/github-webhook-server/issues)

The following are automatically added:
 * Add reviewers from OWNER file (in the root of the repository) under reviewers section.
 * Set PR size label.
 * New issue is created for the PR. (Closed when PR is merged/closed)
 * Run [pre-commit](https://pre-commit.ci/) if `.pre-commit-config.yaml` exists in the repo.

Available user actions:
 * To mark PR as WIP comment `/wip` to the PR, To remove it from the PR comment `/wip cancel` to the PR.
 * To block merging of PR comment `/hold`, To un-block merging of PR comment `/hold cancel`.
 * To mark PR as verified comment `/verified` to the PR, to un-verify comment `/verified cancel` to the PR.
        verified label removed on each new commit push.
 * To cherry pick a merged PR comment `/cherry-pick <target branch to cherry-pick to>` in the PR.
    * Multiple target branches can be cherry-picked, separated by spaces. (`/cherry-pick branch1 branch2`)
    * Cherry-pick will be started when PR is merged
 * To build and push container image command `/build-and-push-container` in the PR (tag will be the PR number).
    * You can add extra args to the Podman build command
        * Example: `/build-and-push-container --build-arg OPENSHIFT_PYTHON_WRAPPER_COMMIT=<commit_hash>`
 * To add a label by comment use `/<label name>`, to remove, use `/<label name> cancel`
 * To assign reviewers based on OWNERS file use `/assign-reviewers`
 * To check if PR can be merged use `/check-can-merge`
 * to assign reviewer to PR use `/assign-reviewer @<reviewer>`

<details>
<summary>Supported /retest check runs</summary>

 * `/retest tox`: Retest tox
 * `/retest build-container`: Retest build-container
 * `/retest python-module-install`: Retest python-module-install
 * `/retest pre-commit`: Retest pre-commit
 * `/retest all`: Retest all

</details>

<details>
<summary>Supported labels</summary>

 * hold
 * verified
 * wip
 * lgtm

</details>
    
author_association: COLLABORATOR
user: login: coderabbitai[bot]
created_at: 2025-02-27T23:40:15Z
body: <!-- This is an auto-generated comment: summarize by coderabbit.ai -->
<!-- walkthrough_start -->

## Walkthrough
This pull request introduces a new test file for validating branch protection rules and updates the repository settings utility to support dynamic branch protection configurations. The new test module uses a parameterized test function to check different branch protection scenarios based on both global and repository-specific configurations. In the utility, a default branch protection constant is defined, the branch protection function signature is updated to accept multiple parameters, and a helper function is added to determine effective branch protection rules using configuration and repository data. Additionally, the JSON schema is expanded to include new properties related to branch protection settings.

## Changes

| File(s)                                                     | Change Summary                                                                                                                                                                                                                  |
|-------------------------------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `webhook_server_container/tests/test_branch_protection.py`  | Added a new test module with a parameterized test function `test_branch_protection_setup` to validate branch protection rules using a dedicated fixture and environment configuration.                                   |
| `webhook_server_container/utils/github_repository_settings.py` | Introduced the `DEFAULT_BRANCH_PROTECTION` constant; updated `set_branch_protection` to accept additional branch protection parameters; added `get_repo_branch_protection_rules` to derive settings dynamically; updated `set_repositories_settings` accordingly. |
| `webhook_server_container/config/schema.yaml`               | Added new properties `branch_protection`, `strict`, `require_code_owner_reviews`, `dismiss_stale_reviews`, `required_approving_review_count`, `required_linear_history`, and `required_conversation_resolution` at the root level and under `my-repository` for enhanced configuration options. |
| `example.config.yaml`                                       | Introduced a new `branch_protection` section at the root level and within the `my-repository` block, defining parameters for branch protection rules such as `strict`, `require_code_owner_reviews`, `dismiss_stale_reviews`, `required_approving_review_count`, and `required_linear_history`. |

## Suggested labels
`verified`, `size/S`, `can-be-merged`, `approved-rnetser`, `commented-coderabbitai[bot]`

## Suggested reviewers
- rnetser

<!-- walkthrough_end -->
<!-- internal state start -->


<!-- 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 -->

<!-- internal state end -->
<!-- finishing_touch_checkbox_start -->

<details>
<summary>✨ Finishing Touches</summary>

- [ ] <!-- {"checkboxId": "7962f53c-55bc-4827-bfbf-6a18da830691"} --> 📝 Generate Docstrings

</details>

<!-- finishing_touch_checkbox_end -->
<!-- tips_start -->

---

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.

<details>
<summary>❤️ Share</summary>

- [X](https://twitter.com/intent/tweet?text=I%20just%20used%20%40coderabbitai%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20the%20proprietary%20code.%20Check%20it%20out%3A&url=https%3A//coderabbit.ai)
- [Mastodon](https://mastodon.social/share?text=I%20just%20used%20%40coderabbitai%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20the%20proprietary%20code.%20Check%20it%20out%3A%20https%3A%2F%2Fcoderabbit.ai)
- [Reddit](https://www.reddit.com/submit?title=Great%20tool%20for%20code%20review%20-%20CodeRabbit&text=I%20just%20used%20CodeRabbit%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20proprietary%20code.%20Check%20it%20out%3A%20https%3A//coderabbit.ai)
- [LinkedIn](https://www.linkedin.com/sharing/share-offsite/?url=https%3A%2F%2Fcoderabbit.ai&mini=true&title=Great%20tool%20for%20code%20review%20-%20CodeRabbit&summary=I%20just%20used%20CodeRabbit%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20proprietary%20code)

</details>

<details>
<summary>🪧 Tips</summary>

### Chat

There are 3 ways to chat with [CodeRabbit](https://coderabbit.ai?utm_source=oss&utm_medium=github&utm_campaign=myk-org/github-webhook-server&utm_content=670):

- Review comments: Directly reply to a review comment made by CodeRabbit. Example:
  - `I pushed a fix in commit <commit_id>, please review it.`
  - `Generate unit testing code for this file.`
  - `Open a follow-up GitHub issue for this discussion.`
- Files and specific lines of code (under the "Files changed" tab): Tag `@coderabbitai` in a new review comment at the desired location with your query. Examples:
  - `@coderabbitai generate unit testing code for this file.`
  -	`@coderabbitai modularize this function.`
- PR comments: Tag `@coderabbitai` in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
  - `@coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.`
  - `@coderabbitai read src/utils.ts and generate unit testing code.`
  - `@coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.`
  - `@coderabbitai help me debug CodeRabbit configuration file.`

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

### CodeRabbit Commands (Invoked using PR comments)

- `@coderabbitai pause` to pause the reviews on a PR.
- `@coderabbitai resume` to resume the paused reviews.
- `@coderabbitai review` to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
- `@coderabbitai full review` to do a full review from scratch and review all the files again.
- `@coderabbitai summary` to regenerate the summary of the PR.
- `@coderabbitai generate docstrings` to [generate docstrings](https://docs.coderabbit.ai/finishing-touches/docstrings) for this PR.
- `@coderabbitai resolve` resolve all the CodeRabbit review comments.
- `@coderabbitai configuration` to show the current CodeRabbit configuration for the repository.
- `@coderabbitai help` to get help.

### Other keywords and placeholders

- Add `@coderabbitai ignore` anywhere in the PR description to prevent this PR from being reviewed.
- Add `@coderabbitai summary` to generate the high-level summary at a specific location in the PR description.
- Add `@coderabbitai` anywhere in the PR title to generate the title automatically.

### CodeRabbit Configuration File (`.coderabbit.yaml`)

- You can programmatically configure CodeRabbit by adding a `.coderabbit.yaml` file to the root of your repository.
- Please see the [configuration documentation](https://docs.coderabbit.ai/guides/configure-coderabbit) for more information.
- If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: `# yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json`

### Documentation and Community

- Visit our [Documentation](https://docs.coderabbit.ai) for detailed information on how to use CodeRabbit.
- Join our [Discord Community](http://discord.gg/coderabbit) to get help, request features, and share feedback.
- Follow us on [X/Twitter](https://twitter.com/coderabbitai) for updates and announcements.

</details>

<!-- tips_end -->
author_association: NONE
user: login: myakove
created_at: 2025-02-28T08:56:48Z
body: https://github.com/myk-org/github-webhook-server/blob/main/webhook_server_container/config/schema.yaml needs to be updated too
author_association: COLLABORATOR
user: login: myakove
created_at: 2025-03-06T11:18:55Z
body: /lgtm
author_association: COLLABORATOR
user: login: myakove-bot
created_at: 2025-03-06T11:21:08Z
body: New container for ghcr.io/myk-org/github-webhook-server:latest published
author_association: COLLABORATOR