From b54facdbd8eb6b5e3919dbba5e14010b73e41af4 Mon Sep 17 00:00:00 2001 From: Tyler Wilding Date: Sun, 22 May 2022 21:09:50 -0400 Subject: [PATCH] ci: catch duplicate YAML keys in the GameDB --- .github/workflows/lint_gamedb.yml | 12 +++++++++--- .../lint-gamedb.py => lint/gamedb/lint.py} | 17 ++++++++++++++--- .../gamedb}/requirements.txt | 0 3 files changed, 23 insertions(+), 6 deletions(-) rename .github/workflows/scripts/{validation/lint-gamedb/lint-gamedb.py => lint/gamedb/lint.py} (93%) rename .github/workflows/scripts/{validation/lint-gamedb => lint/gamedb}/requirements.txt (100%) diff --git a/.github/workflows/lint_gamedb.yml b/.github/workflows/lint_gamedb.yml index cd55e5324b..2675f99005 100644 --- a/.github/workflows/lint_gamedb.yml +++ b/.github/workflows/lint_gamedb.yml @@ -19,9 +19,15 @@ jobs: - name: Checkout Repository uses: actions/checkout@v3 - - name: Validate GameDB + - name: Validate Contents env: - SCRIPT_DIR: .github/workflows/scripts/validation/lint-gamedb + GAMEDB_PATH: ./bin/resources/GameIndex.yaml + SCRIPT_DIR: .github/workflows/scripts/lint/gamedb run: | pip install -r "${SCRIPT_DIR}/requirements.txt" - python "${SCRIPT_DIR}/lint-gamedb.py" + python "${SCRIPT_DIR}/lint.py" + + - name: Check Formatting + run: | + npm install -g prettier + prettier --check ./bin/Resources/GameIndex.yaml diff --git a/.github/workflows/scripts/validation/lint-gamedb/lint-gamedb.py b/.github/workflows/scripts/lint/gamedb/lint.py similarity index 93% rename from .github/workflows/scripts/validation/lint-gamedb/lint-gamedb.py rename to .github/workflows/scripts/lint/gamedb/lint.py index 37cf353e4a..bae239c3db 100644 --- a/.github/workflows/scripts/validation/lint-gamedb/lint-gamedb.py +++ b/.github/workflows/scripts/lint/gamedb/lint.py @@ -1,7 +1,8 @@ +import os import yaml # Assumes this is ran from the root of the repository -file_path = "./bin/resources/GameIndex.yaml" +file_path = os.environ['GAMEDB_PATH'] # These settings have to be manually kept in sync with the emulator code unfortunately. # up to date validation should ALWAYS be provided via the application! @@ -209,11 +210,21 @@ option_validation_handlers = { "patches": (lambda serial, key, value: validate_patches(serial, key, value)), } +class UniqueKeyLoader(yaml.FullLoader): + def construct_mapping(self, node, deep=False): + mapping = set() + for key_node, value_node in node.value: + key = self.construct_object(key_node, deep=deep) + if key in mapping: + raise ValueError(f"Duplicate {key!r} key found in YAML.") + mapping.add(key) + return super().construct_mapping(node, deep) + print("Opening {}...".format(file_path)) -with open(file_path) as f: +with open(file_path, encoding="utf-8") as f: try: print("Attempting to parse GameDB file...") - gamedb = yaml.load(f, Loader=yaml.FullLoader) + gamedb = yaml.load(f, Loader=UniqueKeyLoader) except Exception as err: print(err) print( diff --git a/.github/workflows/scripts/validation/lint-gamedb/requirements.txt b/.github/workflows/scripts/lint/gamedb/requirements.txt similarity index 100% rename from .github/workflows/scripts/validation/lint-gamedb/requirements.txt rename to .github/workflows/scripts/lint/gamedb/requirements.txt