From 5f65ba478405b4dece06292bd56796c73e04b7ee Mon Sep 17 00:00:00 2001 From: rnetser Date: Sun, 14 Jun 2026 16:37:54 +0300 Subject: [PATCH 1/2] feat: support default-status-checks at repository level MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Config.get_value() already resolves per-repo → global config, so the runtime code already supported per-repo default-status-checks. Only the YAML schema was missing the property at the per-repo level, causing schema validation to reject it. Add default-status-checks to the per-repo properties in the schema, add a per-repo example in examples/config.yaml, add a schema validation test that exercises Config() constructor and get_value() resolution, and document the override in repository-overrides.md. Closes #1111 Signed-off-by: rnetser Assisted-by: Claude --- docs/repository-overrides.md | 1 + examples/config.yaml | 4 ++++ webhook_server/config/schema.yaml | 5 +++++ webhook_server/tests/test_config_schema.py | 26 ++++++++++++++++++++++ 4 files changed, 36 insertions(+) diff --git a/docs/repository-overrides.md b/docs/repository-overrides.md index 159bd3b7b..8697e35ca 100644 --- a/docs/repository-overrides.md +++ b/docs/repository-overrides.md @@ -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 diff --git a/examples/config.yaml b/examples/config.yaml index c8529020e..14d219499 100644 --- a/examples/config.yaml +++ b/examples/config.yaml @@ -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: # Send notification to slack on several operations verified-job: true pypi: diff --git a/webhook_server/config/schema.yaml b/webhook_server/config/schema.yaml index 7d0dd7157..bfdf84129 100644 --- a/webhook_server/config/schema.yaml +++ b/webhook_server/config/schema.yaml @@ -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 slack-webhook-url: type: string description: Slack webhook URL diff --git a/webhook_server/tests/test_config_schema.py b/webhook_server/tests/test_config_schema.py index 1ebb9fc6c..59c02381e 100644 --- a/webhook_server/tests/test_config_schema.py +++ b/webhook_server/tests/test_config_schema.py @@ -274,6 +274,32 @@ 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", + ] + finally: + shutil.rmtree(temp_dir) + 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() From 9985cf5ad3b97f285f35395f7400745a7d54290f Mon Sep 17 00:00:00 2001 From: rnetser Date: Sun, 14 Jun 2026 17:06:17 +0300 Subject: [PATCH 2/2] test: add precedence and schema validation tests for per-repo default-status-checks MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Addresses Qodo review findings — adds global fallback, repo-override precedence, and direct schema assertion tests. Also adds default-status-checks to validator array_fields. Signed-off-by: rnetser Assisted-by: Claude --- webhook_server/tests/test_config_schema.py | 57 +++++++++++++++++++ webhook_server/tests/test_schema_validator.py | 1 + 2 files changed, 58 insertions(+) diff --git a/webhook_server/tests/test_config_schema.py b/webhook_server/tests/test_config_schema.py index 59c02381e..6a6002570 100644 --- a/webhook_server/tests/test_config_schema.py +++ b/webhook_server/tests/test_config_schema.py @@ -300,6 +300,63 @@ def test_per_repo_default_status_checks( finally: shutil.rmtree(temp_dir) + 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() diff --git a/webhook_server/tests/test_schema_validator.py b/webhook_server/tests/test_schema_validator.py index 1784e9bf3..d768d6165 100644 --- a/webhook_server/tests/test_schema_validator.py +++ b/webhook_server/tests/test_schema_validator.py @@ -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",