Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions docs/repository-overrides.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ For runtime settings that the webhook reads from the repository, precedence is:
| `github-tokens` | No | Yes | Needed before the repo-local file can be read. |
| `protected-branches` and branch protection sync | No | Yes | Applied by the server when it configures repositories. |
| `branch-protection.required_conversation_resolution` | Yes | Yes | Also affects the runtime `can-be-merged` gate. |
| `default-status-checks` | No | Yes | Override global default-status-checks for this repository. |
| `events`, `test-oracle`, `allow-commands-on-draft-prs` | No | Yes | Current code reads these from `config.yaml`. |

## Labels
Expand Down
4 changes: 4 additions & 0 deletions examples/config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,10 @@ repositories:
log-level: DEBUG # Override global log-level for repository
log-file: my-repository.log # Override global log-file for repository
mask-sensitive-data: false # Override global setting - disable masking for debugging this specific repo (NOT recommended in production)
default-status-checks: # Override global default-status-checks for this repository
- "WIP"
- "can-be-merged"
- "ci/my-external-check"
slack-webhook-url: <Slack webhook url> # Send notification to slack on several operations
verified-job: true
pypi:
Expand Down
5 changes: 5 additions & 0 deletions webhook_server/config/schema.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -333,6 +333,11 @@ properties:
type: boolean
description: Override global mask-sensitive-data setting for this repository
default: true
default-status-checks:
type: array
items:
type: string
description: Override global default-status-checks for this repository
Comment thread
rnetser marked this conversation as resolved.
slack-webhook-url:
type: string
description: Slack webhook URL
Expand Down
83 changes: 83 additions & 0 deletions webhook_server/tests/test_config_schema.py
Original file line number Diff line number Diff line change
Expand Up @@ -274,6 +274,89 @@ def test_repository_structure_validation(self, valid_minimal_config: dict[str, A
finally:
shutil.rmtree(temp_dir)

def test_per_repo_default_status_checks(
self, valid_minimal_config: dict[str, Any], monkeypatch: pytest.MonkeyPatch
) -> None:
"""Test that default-status-checks is accepted at per-repo level and resolved at runtime."""
config = valid_minimal_config.copy()
config["repositories"] = {
"repo1": {
"name": "org/repo1",
"default-status-checks": ["WIP", "can-be-merged", "ci/my-external-check"],
},
}

temp_dir = self.create_temp_config_dir_and_data(config)

try:
monkeypatch.setenv("WEBHOOK_SERVER_DATA_DIR", temp_dir)

repo_config = Config(repository="repo1")
assert repo_config.get_value("default-status-checks") == [
"WIP",
"can-be-merged",
"ci/my-external-check",
]
Comment thread
rnetser marked this conversation as resolved.
finally:
shutil.rmtree(temp_dir)
Comment thread
rnetser marked this conversation as resolved.

def test_per_repo_default_status_checks_falls_back_to_global(
self, valid_minimal_config: dict[str, Any], monkeypatch: pytest.MonkeyPatch
) -> None:
"""Test that repo without default-status-checks falls back to global value."""
config = valid_minimal_config.copy()
config["default-status-checks"] = ["WIP", "global-check"]
config["repositories"] = {
"repo1": {
"name": "org/repo1",
},
}

temp_dir = self.create_temp_config_dir_and_data(config)

try:
monkeypatch.setenv("WEBHOOK_SERVER_DATA_DIR", temp_dir)

repo_config = Config(repository="repo1")
assert repo_config.get_value("default-status-checks") == ["WIP", "global-check"]
finally:
shutil.rmtree(temp_dir)

def test_per_repo_default_status_checks_overrides_global(
self, valid_minimal_config: dict[str, Any], monkeypatch: pytest.MonkeyPatch
) -> None:
"""Test that per-repo default-status-checks overrides global value."""
config = valid_minimal_config.copy()
config["default-status-checks"] = ["WIP", "global-check"]
config["repositories"] = {
"repo1": {
"name": "org/repo1",
"default-status-checks": ["WIP", "repo-specific-check"],
},
}

temp_dir = self.create_temp_config_dir_and_data(config)

try:
monkeypatch.setenv("WEBHOOK_SERVER_DATA_DIR", temp_dir)

repo_config = Config(repository="repo1")
result = repo_config.get_value("default-status-checks")
assert result == ["WIP", "repo-specific-check"]
assert "global-check" not in result
finally:
shutil.rmtree(temp_dir)

def test_schema_allows_per_repo_default_status_checks(self) -> None:
"""Test that schema.yaml defines default-status-checks in per-repo properties."""
schema_path = os.path.join(os.path.dirname(__file__), "..", "config", "schema.yaml")
with open(schema_path) as f:
schema = yaml.safe_load(f)
repo_props = schema["properties"]["repositories"]["additionalProperties"]["properties"]
assert "default-status-checks" in repo_props
assert repo_props["default-status-checks"]["type"] == "array"
assert repo_props["default-status-checks"]["items"]["type"] == "string"

def test_tox_configuration_flexibility(self, valid_minimal_config: dict[str, Any]) -> None:
"""Test that tox configuration accepts both string and array values."""
config = valid_minimal_config.copy()
Expand Down
1 change: 1 addition & 0 deletions webhook_server/tests/test_schema_validator.py
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,7 @@ def _validate_single_repository(self, repo_name: str, repo_config: Any) -> None:
array_fields = [
"events",
"auto-verified-and-merged-users",
"default-status-checks",
"github-tokens",
"set-auto-merge-prs",
"can-be-merged-required-labels",
Expand Down