import json import os from pathlib import Path import subprocess import xml.etree.ElementTree as ET import yaml paths = subprocess.check_output(['git', 'ls-files', '-z']).decode('utf-8').split('\0') paths = [Path(name) for name in paths if name] if not paths: raise SystemExit('No tracked policy files') names = {'LICENSE', 'NOTICE', 'COPYING', 'CODEOWNERS', '.gitignore', '.gitattributes', '.editorconfig', 'mvnw', 'mvnw.cmd'} shell_checks = os.environ.get('QQQ_POLICY_SHELL') == 'true' suffixes = {'.md', '.rst', '.txt', '.adoc', '.yml', '.yaml', '.json', '.properties'} manifests = {'pom.xml', 'package.json', 'cargo.toml', 'pyproject.toml', 'go.mod', 'build.gradle', 'build.gradle.kts', 'settings.gradle', 'settings.gradle.kts'} for path in paths: if path.is_symlink() or path.name.lower() in manifests: raise SystemExit(f'Application or symlink requires a build profile: {path}') if path.as_posix() == '.mvn/wrapper/maven-wrapper.jar': continue if path.as_posix() == 'checkstyle/config.xml': ET.fromstring(path.read_text(encoding='utf-8')) continue if shell_checks and path.suffix.lower() == '.sh': subprocess.run(['bash', '-n', '--', str(path)], check=True) subprocess.run(['shellcheck', '--severity=warning', '--', str(path)], check=True) continue if shell_checks and path.suffix.lower() == '.mmd': path.read_text(encoding='utf-8') continue if path.name not in names and path.suffix.lower() not in suffixes: raise SystemExit(f'Unsupported policy file; select a build profile: {path}') text = path.read_text(encoding='utf-8') if path.suffix.lower() in ('.yml', '.yaml'): list(yaml.safe_load_all(text)) elif path.suffix.lower() == '.json': json.loads(text) print(f'Validated {len(paths)} tracked policy/documentation files; no application build or publication')