Repository: conda-forge/conda-smithy

Issue:
optionally make schema validation errors a warning instead of erroring out during rerenders
This feature is stopping the bot from making PRs on effected feedstocks. As @isuruf has pointed out, the linter will error on the CI checks anyways, so letting the rerender go through is fine. 

At minimum, we can add an optional override to only warn.


Discussion:
Yeah warning on re-rendering seems like a better default

Having an option to convert warnings to errors in conda-smithy could be useful, but maybe that is not needed given the linter already errors. If we do add such an option, it would be good to cover on CI (to catch any false positives early)
Agreed on this strategy.

* `conda-smithy rerender` will warn about validation errors. If they are critical, they'll fail later in the job anyway.
* `conda-smithy recipe-lint` will error out.

Resolving patch:
diff --git a/conda_smithy/configure_feedstock.py b/conda_smithy/configure_feedstock.py
--- a/conda_smithy/configure_feedstock.py
+++ b/conda_smithy/configure_feedstock.py
@@ -9,7 +9,6 @@
 import pprint
 import textwrap
 import time
-import jsonschema
 import yaml
 import warnings
 from collections import Counter, OrderedDict, namedtuple
@@ -1999,11 +1998,15 @@ def _read_forge_config(forge_dir, forge_yml=None):
 
     # Validate loaded configuration against a JSON schema.
     validate_lints, validate_hints = validate_json_schema(file_config)
-    for err in validate_lints:
-        raise ExceptionGroup("lints", [*map(ValueError, validate_lints)])
-
-    for hint in validate_hints:
-        logger.info(hint.message)
+    for err in chain(validate_lints, validate_hints):
+        logger.warn(
+            "%s: %s = %s -> %s",
+            os.path.relpath(forge_yml, forge_dir),
+            err.json_path,
+            err.instance,
+            err.message,
+        )
+        logger.debug("Relevant schema:\n%s", json.dumps(err.schema, indent=2))
 
     # The config is just the union of the defaults, and the overridden
     # values.
diff --git a/conda_smithy/validate_schema.py b/conda_smithy/validate_schema.py
--- a/conda_smithy/validate_schema.py
+++ b/conda_smithy/validate_schema.py
@@ -1,6 +1,6 @@
 import json
 from pathlib import Path
-
+from typing import Tuple, List
 from jsonschema import Draft202012Validator, validators
 from jsonschema.exceptions import ValidationError
 
@@ -36,7 +36,9 @@ def get_validator_class():
 _VALIDATOR_CLASS = get_validator_class()
 
 
-def validate_json_schema(config, schema_file: str = None):
+def validate_json_schema(
+    config, schema_file: str = None
+) -> Tuple[List[ValidationError], List[ValidationError]]:
     # Validate the merged configuration against a JSON schema
     if not schema_file:
         schema_file = CONDA_FORGE_YAML_SCHEMA_FILE


Test patch:
diff --git a/tests/test_configure_feedstock.py b/tests/test_configure_feedstock.py
--- a/tests/test_configure_feedstock.py
+++ b/tests/test_configure_feedstock.py
@@ -1,11 +1,12 @@
+import copy
+import logging
 import os
-
-from conda_smithy import configure_feedstock
+import textwrap
 
 import pytest
-import copy
 import yaml
-import textwrap
+
+from conda_smithy import configure_feedstock
 
 
 def test_noarch_skips_appveyor(noarch_recipe, jinja_env):
@@ -762,7 +763,7 @@ def test_conda_forge_yaml_empty(config_yaml):
     assert load_forge_config()["recipe_dir"] == "recipe"
 
 
-def test_noarch_platforms_bad_yaml(config_yaml):
+def test_noarch_platforms_bad_yaml(config_yaml, caplog):
     load_forge_config = lambda: configure_feedstock._load_forge_config(  # noqa
         config_yaml,
         exclusive_config_file=os.path.join(
@@ -773,10 +774,10 @@ def test_noarch_platforms_bad_yaml(config_yaml):
     with open(os.path.join(config_yaml, "conda-forge.yml"), "a+") as fp:
         fp.write("noarch_platforms: [eniac, zx80]")
 
-    with pytest.raises(configure_feedstock.ExceptionGroup) as excinfo:
+    with caplog.at_level(logging.WARNING):
         load_forge_config()
 
-    assert "eniac" in repr(excinfo.value)
+    assert "eniac" in caplog.text
 
 
 def test_forge_yml_alt_path(config_yaml):
@@ -867,7 +868,7 @@ def test_cuda_enabled_render(cuda_enabled_recipe, jinja_env):
                 del os.environ["CF_CUDA_ENABLED"]
 
 
-def test_conda_build_tools(config_yaml):
+def test_conda_build_tools(config_yaml, caplog):
     load_forge_config = lambda: configure_feedstock._load_forge_config(  # noqa
         config_yaml,
         exclusive_config_file=os.path.join(
@@ -900,8 +901,9 @@ def test_conda_build_tools(config_yaml):
         fp.write(unmodified)
         fp.write("conda_build_tool: does-not-exist")
 
-    with pytest.raises(configure_feedstock.ExceptionGroup):
+    with caplog.at_level(logging.WARNING):
         assert load_forge_config()
+    assert "does-not-exist" in caplog.text
 
 
 def test_remote_ci_setup(config_yaml):