(#13274) linters: Add annotations for YAML lint + add schema verification for config.yml and conandata.yml

* first attempt at a yaml linter wit github actions output

* This is less strict but has more information

* fixup message

* run config linter in Action

* better ux feedback

* try to use newlines

https://github.com/actions/toolkit/issues/193#issuecomment-605394935

* clean up

* fixup file name

* trying custom class for quoted str

* underlying yaml parser does not keep quotes

* trying to catch ints as problems

* remove test code

* and to "linter testing"

* install deps

* run new linter unconditionally

* revert testing changes

* new script for conandata (this one is much harder to spec)

* debugging

* lets see all the errors

* yamale -s ../linter/config_yaml_schema.yml aaf/config.yml

from linters folder as a test

* adjust script to match meeting discussion

* make sure the docs and linters match

* fix link

* Update conandata.yml

* exit 1 is not needed with annotations

* add annotation matchers for yaml since those do do much

* fix search for type

* fix whitespace

* tryout a yamllint file with a better looking matcher

* copy syntax from readme

* test if it's running in the wrong dir 🤔

* try with debug output

* bump since i dont have permissions

* bump - dont glob star

* bump

* less star globs

* also add action to conandata way

* bump

* drop action for cli + matcher

* more docs around linters

* fix file and name

* cleanup
This commit is contained in:
Chris Mc
2022-10-25 05:25:05 -07:00
committed by GitHub
parent 12a158a68e
commit 70d9c6b69e
13 changed files with 359 additions and 147 deletions

View File

@@ -0,0 +1,82 @@
import argparse
from strictyaml import (
load,
Map,
Str,
YAMLValidationError,
MapPattern,
Optional,
Seq,
Enum,
Any,
)
from yaml_linting import file_path
def main():
parser = argparse.ArgumentParser(
description="Validate Conan's 'conandata.yaml' file to ConanCenterIndex's requirements."
)
parser.add_argument(
"path",
nargs="?",
type=file_path,
help="file to validate.",
)
args = parser.parse_args()
patch_fields = Map(
{
"patch_file": Str(),
"patch_description": Str(),
"patch_type": Enum(
["official", "conan", "portability", "backport", "vulnerability"]
),
Optional("patch_source"): Str(),
Optional("sha256"): Str(), # Really uncommon
# No longer required for v2 recipes with layouts
Optional("base_path"): Str(),
}
)
schema = Map(
{
"sources": MapPattern(Str(), Any(), minimum_keys=1),
Optional("patches"): MapPattern(Str(), Seq(patch_fields), minimum_keys=1),
}
)
with open(args.path) as f:
content = f.read()
try:
parsed = load(content, schema)
if "patches" in parsed:
for version in parsed["patches"]:
patches = parsed["patches"][version]
for i, patch in enumerate(patches):
type = parsed["patches"][version][i]["patch_type"]
if (
type in ["official", "backport", "vulnerability"]
and not "patch_source" in patch
):
print(
f"::warning file={args.path},line={type.start_line},endline={type.end_line},"
f"title='patch_type' should have 'patch_source'"
"::As per https://github.com/conan-io/conan-center-index/blob/master/docs/conandata_yml_format.md#patches-fields"
" it is expected to have a source (e.g. a URL) to where it originates from to help with reviewing and consumers to evaluate patches\n"
)
except YAMLValidationError as error:
e = error.__str__().replace("\n", "%0A")
print(
f"::error file={args.path},line={error.context_mark.line},endline={error.problem_mark.line},"
f"title=config.yml schema error"
f"::{e}\n"
)
except error:
e = error.__str__().replace("\n", "%0A")
print(f"::error ::{e}")
if __name__ == "__main__":
main()