diff --git a/mergify_cli/ci/scopes/config/scopes.py b/mergify_cli/ci/scopes/config/scopes.py index 3e171b4..b784783 100644 --- a/mergify_cli/ci/scopes/config/scopes.py +++ b/mergify_cli/ci/scopes/config/scopes.py @@ -15,6 +15,8 @@ class FileFilters(pydantic.BaseModel): + model_config = pydantic.ConfigDict(extra="forbid") + include: tuple[str, ...] = pydantic.Field( default_factory=lambda: ("**/*",), description=( @@ -34,6 +36,8 @@ class FileFilters(pydantic.BaseModel): class SourceFiles(pydantic.BaseModel): + model_config = pydantic.ConfigDict(extra="forbid") + files: dict[ScopeName, FileFilters] = pydantic.Field( description=( "Mapping of scope name to its file filters. " @@ -44,6 +48,8 @@ class SourceFiles(pydantic.BaseModel): class SourceManual(pydantic.BaseModel): + model_config = pydantic.ConfigDict(extra="forbid") + manual: None = pydantic.Field( description="Scopes are manually sent via API or `mergify scopes-send`", ) diff --git a/mergify_cli/tests/ci/scopes/test_cli.py b/mergify_cli/tests/ci/scopes/test_cli.py index 4bf0a89..1ad1e0a 100644 --- a/mergify_cli/tests/ci/scopes/test_cli.py +++ b/mergify_cli/tests/ci/scopes/test_cli.py @@ -106,7 +106,7 @@ def test_from_yaml_invalid_config(tmp_path: pathlib.Path) -> None: ) # Bad name and missing dict - with pytest.raises(config.ConfigInvalidError, match="3 validation errors"): + with pytest.raises(config.ConfigInvalidError, match="4 validation errors"): config.Config.from_yaml(str(config_file)) @@ -481,6 +481,22 @@ def test_detect_no_matches( assert result.scopes == set() +def test_match_scopes_invalid() -> None: + with pytest.raises(config.ConfigInvalidError, match="4 validation errors"): + config.Config.from_dict( + { + "scopes": { + "source": { + "files": { + "backend": {"includes": ("api/**/*.py",)}, + "frontend": {"includes": ("ui/**/*.js",)}, + }, + }, + }, + }, + ) + + @mock.patch("mergify_cli.ci.scopes.changed_files.git_changed_files") def test_detect_debug_output( mock_git_changed: mock.Mock,