From 0e59d35129755cd677bb896957aca3b27089ea71 Mon Sep 17 00:00:00 2001 From: Kevin Veen-Birkenbach Date: Mon, 11 Aug 2025 13:23:20 +0200 Subject: [PATCH] Update RunOnceSchemaTest to skip files with deactivated run_once variables via comment https://chatgpt.com/share/6899d297-4bec-800f-a748-6816398d8c7e --- tests/integration/test_run_once_schema.py | 30 +++++++++++++---------- 1 file changed, 17 insertions(+), 13 deletions(-) diff --git a/tests/integration/test_run_once_schema.py b/tests/integration/test_run_once_schema.py index 7415b55e..392fa0ee 100644 --- a/tests/integration/test_run_once_schema.py +++ b/tests/integration/test_run_once_schema.py @@ -7,43 +7,47 @@ import unittest class RunOnceSchemaTest(unittest.TestCase): """ Ensure that any occurrence of 'run_once_' in roles/*/tasks/main.yml - matches the pattern 'run_once_' + (role_name with '-' replaced by '_'). + matches the pattern 'run_once_' + (role_name with '-' replaced by '_'), + unless the file explicitly deactivates its own run_once var via: + # run_once_: deactivated """ RUN_ONCE_PATTERN = re.compile(r"run_once_([A-Za-z0-9_]+)") + # Will be compiled per-file with the expected suffix: + # r"^\s*#\s*run_once_\s*:\s*deactivated\s*$" (flags=MULTILINE|IGNORECASE) def test_run_once_suffix_matches_role(self): - # Determine project root: two levels up from this test file (tests/integration -> tests -> project) project_root = os.path.abspath( os.path.join(os.path.dirname(__file__), '..', '..') ) violations = [] - # Find all roles/*/tasks/main.yml files pattern = os.path.join(project_root, 'roles', '*', 'tasks', 'main.yml') for filepath in glob.glob(pattern): - # Extract role name from path parts = os.path.normpath(filepath).split(os.sep) try: role_index = parts.index('roles') + 1 role_name = parts[role_index] except ValueError: - continue # skip unexpected path + continue - # Compute expected suffix expected_suffix = role_name.lower().replace('-', '_') - # Read file content with open(filepath, 'r', encoding='utf-8') as f: content = f.read() - # Find all run_once_ suffixes - matches = self.RUN_ONCE_PATTERN.findall(content) - if not matches: - # No run_once_ in this file, skip + # Skip this file entirely if it explicitly deactivates its own run_once var + deactivated_re = re.compile( + rf"^\s*#\s*run_once_{re.escape(expected_suffix)}\s*:\s*deactivated\s*$", + flags=re.IGNORECASE | re.MULTILINE, + ) + if deactivated_re.search(content): + continue + + matches = self.RUN_ONCE_PATTERN.findall(content) + if not matches: continue - # Check each occurrence for suffix in matches: if suffix != expected_suffix: violations.append( @@ -55,4 +59,4 @@ class RunOnceSchemaTest(unittest.TestCase): if __name__ == '__main__': - unittest.main() \ No newline at end of file + unittest.main()