Skip to content

Commit

Permalink
Merge pull request #2040 from conda-forge/lint-dup-cfyaml-keys
Browse files Browse the repository at this point in the history
feat: add lint for duplicate keys in conda-forge.yml
  • Loading branch information
xhochy committed Aug 22, 2024
2 parents 2dc51df + a89f029 commit f82b58f
Show file tree
Hide file tree
Showing 4 changed files with 66 additions and 2 deletions.
17 changes: 17 additions & 0 deletions conda_smithy/lint_recipe.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
import github
import jsonschema
import requests
from ruamel.yaml.constructor import DuplicateKeyError

from conda_smithy.linter import conda_recipe_v1_linter
from conda_smithy.linter.hints import (
Expand Down Expand Up @@ -571,6 +572,22 @@ def run_conda_forge_specific(
"The feedstock has no `.ci_support` files and thus will not build any packages."
)

# 9: No duplicates in conda-forge.yml
if (
not is_staged_recipes
and recipe_dir is not None
and os.path.exists(
cfyml_pth := os.path.join(recipe_dir, "..", "conda-forge.yml")
)
):
try:
with open(cfyml_pth) as fh:
get_yaml(allow_duplicate_keys=False).load(fh)
except DuplicateKeyError:
lints.append(
"The ``conda-forge.yml`` file is not allowed to have duplicate keys."
)


def _format_validation_msg(error: jsonschema.ValidationError):
"""Use the data on the validation error to generate improved reporting.
Expand Down
4 changes: 2 additions & 2 deletions conda_smithy/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -75,14 +75,14 @@ def get_feedstock_about_from_meta(meta) -> dict:
return dict(meta.meta["about"])


def get_yaml():
def get_yaml(allow_duplicate_keys: bool = True):
# define global yaml API
# roundrip-loader and allowing duplicate keys
# for handling # [filter] / # [not filter]
# Don't use a global variable for this as a global
# variable will make conda-smithy thread unsafe.
yaml = ruamel.yaml.YAML(typ="rt")
yaml.allow_duplicate_keys = True
yaml.allow_duplicate_keys = allow_duplicate_keys
return yaml


Expand Down
3 changes: 3 additions & 0 deletions news/cfyaml-duplicate-keys.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
**Added:**

* Added a lint for duplicate keys in the ``conda-forge.yml`` file. (#2040)
44 changes: 44 additions & 0 deletions tests/test_lint_recipe.py
Original file line number Diff line number Diff line change
Expand Up @@ -2519,6 +2519,50 @@ def test_lint_no_builds():
assert not any(lint.startswith(expected_message) for lint in lints)


@unittest.skipUnless(is_gh_token_set(), "GH_TOKEN not set")
def test_lint_duplicate_cfyml():
expected_message = (
"The ``conda-forge.yml`` file is not allowed to have duplicate keys."
)

with tmp_directory() as feedstock_dir:
cfyml = os.path.join(feedstock_dir, "conda-forge.yml")
recipe_dir = os.path.join(feedstock_dir, "recipe")
os.makedirs(recipe_dir, exist_ok=True)
with open(os.path.join(recipe_dir, "meta.yaml"), "w") as fh:
fh.write(
"""
package:
name: foo
"""
)

with open(cfyml, "w") as fh:
fh.write(
textwrap.dedent(
"""
blah: 1
blah: 2
"""
)
)

lints = linter.main(recipe_dir, conda_forge=True)
assert any(lint.startswith(expected_message) for lint in lints)

with open(cfyml, "w") as fh:
fh.write(
textwrap.dedent(
"""
blah: 1
"""
)
)

lints = linter.main(recipe_dir, conda_forge=True)
assert not any(lint.startswith(expected_message) for lint in lints)


@pytest.mark.parametrize(
"yaml_block,annotation",
[
Expand Down

0 comments on commit f82b58f

Please sign in to comment.