mirror of
https://github.com/kevinveenbirkenbach/computer-playbook.git
synced 2025-07-17 14:04:24 +02:00
Added variable usage test
This commit is contained in:
parent
f02ca50f88
commit
fff06d52b8
97
tests/integration/test_variable_usage.py
Normal file
97
tests/integration/test_variable_usage.py
Normal file
@ -0,0 +1,97 @@
|
||||
import unittest
|
||||
import os
|
||||
import yaml
|
||||
from glob import glob
|
||||
import re
|
||||
|
||||
class TestTopLevelVariableUsage(unittest.TestCase):
|
||||
def setUp(self):
|
||||
self.project_root = os.path.abspath(
|
||||
os.path.join(os.path.dirname(__file__), '../../')
|
||||
)
|
||||
# Braces werden von glob nicht unterstützt – also einzeln sammeln:
|
||||
self.roles_vars_paths = (
|
||||
glob(os.path.join(self.project_root, 'roles/*/vars/main.yml')) +
|
||||
glob(os.path.join(self.project_root, 'roles/*/defaults/main.yml'))
|
||||
)
|
||||
self.group_vars_paths = glob(
|
||||
os.path.join(self.project_root, 'group_vars/all/*.yml')
|
||||
)
|
||||
self.all_variable_files = self.roles_vars_paths + self.group_vars_paths
|
||||
self.valid_extensions = {
|
||||
'.yml', '.yaml', '.j2', '.py', '.sh', '.conf',
|
||||
'.env', '.xml', '.html', '.txt'
|
||||
}
|
||||
|
||||
def get_top_level_keys(self, file_path):
|
||||
with open(file_path, 'r') as f:
|
||||
try:
|
||||
data = yaml.safe_load(f)
|
||||
if isinstance(data, dict):
|
||||
return list(data.keys())
|
||||
except yaml.YAMLError:
|
||||
pass
|
||||
return []
|
||||
|
||||
def find_declaration_line(self, file_path, varname):
|
||||
"""
|
||||
Findet die Zeilennummer (1-basiert), in der der Top-Level-Key wirklich deklariert wird.
|
||||
"""
|
||||
pattern = re.compile(rf"^\s*{re.escape(varname)}\s*:")
|
||||
with open(file_path, 'r', encoding='utf-8', errors='ignore') as f:
|
||||
for i, line in enumerate(f, 1):
|
||||
if pattern.match(line) and not line.lstrip().startswith('#'):
|
||||
return i
|
||||
return None
|
||||
|
||||
def find_usage_in_project(self, varname, definition_path):
|
||||
"""
|
||||
Sucht im gesamten Projekt nach varname, überspringt dabei
|
||||
nur die eine Deklarationszeile in definition_path.
|
||||
"""
|
||||
decl_line = self.find_declaration_line(definition_path, varname)
|
||||
|
||||
for root, _, files in os.walk(self.project_root):
|
||||
for fn in files:
|
||||
path = os.path.join(root, fn)
|
||||
ext = os.path.splitext(path)[1]
|
||||
if ext not in self.valid_extensions:
|
||||
continue
|
||||
try:
|
||||
with open(path, 'r', encoding='utf-8', errors='ignore') as f:
|
||||
for i, line in enumerate(f, 1):
|
||||
if (path == definition_path and
|
||||
decl_line is not None and
|
||||
i == decl_line):
|
||||
# genau die Deklarationszeile überspringen
|
||||
continue
|
||||
if varname in line:
|
||||
return True
|
||||
except Exception:
|
||||
continue
|
||||
return False
|
||||
|
||||
def test_top_level_variable_usage(self):
|
||||
"""
|
||||
Stellt sicher, dass jede Top-Level-Variable in roles/*/{vars,defaults}/main.yml
|
||||
und group_vars/all/*.yml irgendwo im Projekt (außer in ihrer eigenen
|
||||
Deklarationszeile) verwendet wird.
|
||||
"""
|
||||
unused = []
|
||||
for varfile in self.all_variable_files:
|
||||
keys = self.get_top_level_keys(varfile)
|
||||
for key in keys:
|
||||
if not self.find_usage_in_project(key, varfile):
|
||||
unused.append((varfile, key))
|
||||
|
||||
if unused:
|
||||
msg = "\n".join(
|
||||
f"{path}: unused top-level key '{key}'"
|
||||
for path, key in unused
|
||||
)
|
||||
self.fail(
|
||||
"The following top-level variables are defined but never used:\n" + msg
|
||||
)
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
Loading…
x
Reference in New Issue
Block a user