#!/usr/bin/python3 # Version in sysadmin/ci-utilities should be single source of truth # SPDX-FileCopyrightText: 2023 Alexander Lohnau # SPDX-FileCopyrightText: 2024 Johnny Jazeix # SPDX-License-Identifier: BSD-2-Clause import argparse import glob import os import subprocess import yaml parser = argparse.ArgumentParser(description='Check XML files in repository') parser.add_argument('--check-all', default=False, action='store_true', help='If all files should be checked or only the changed files') parser.add_argument('--verbose', default=False, action='store_true') args = parser.parse_args() supported_extensions = (('.xml', '.kcfg', '.ui', '.qrc')) def get_changed_files() -> list[str]: result = subprocess.run(['git', 'diff', '--cached', '--name-only'], capture_output=True, text=True) return [file for file in result.stdout.splitlines() if file.endswith(supported_extensions)] def get_all_files() -> list[str]: files = [] for root, _, filenames in os.walk('.'): for filename in filenames: if filename.endswith(supported_extensions): files.append(os.path.join(root, filename)) return files def filter_excluded_included_xml_files(files: list[str]) -> list[str]: config_file = '.kde-ci.yml' # Check if the file exists if os.path.exists(config_file): with open(config_file, 'r') as file: config = yaml.safe_load(file) else: if args.verbose: print(f'{config_file} does not exist in current directory') config = {} # Extract excluded files, used for tests that intentionally have broken files excluded_files = [] if 'Options' in config and 'xml-validate-ignore' in config['Options']: xml_files_to_ignore = config['Options']['xml-validate-ignore'] for xml in xml_files_to_ignore: excluded_files += glob.glob(xml, recursive=True) # Find XML files filtered_files = [] for file_path in files: if not any(excluded_file in file_path for excluded_file in excluded_files): filtered_files.append(file_path) # "include" overrides the "ignore" files, so if a file is both included and excluded, it will be included if 'Options' in config and 'xml-validate-include' in config['Options']: for filename in config['Options']['xml-validate-include']: if os.path.isfile(filename): filtered_files += [filename] else: print(f"warning: {filename} does not exist, please double check it and either fix the filename or update the .kde-ci.yml file to remove it") return filtered_files if args.check_all: files = get_all_files() else: files = get_changed_files() files = filter_excluded_included_xml_files(files) if files: files_option = ' '.join(files) if args.verbose: print(f"Validating {files_option}") result = subprocess.run(['xmllint', *files], stdout=subprocess.DEVNULL) # Fail the pipeline if command failed if result.returncode != 0: exit(1)