mirror of
https://github.com/spantaleev/matrix-docker-ansible-deploy.git
synced 2026-10-22 14:24:17 +00:00
Check group-vars Jinja syntax in pre-commit
Port the syntax-only checker from MASH PR #3613, including its hook triggers and YAML diagnostics. Check both group_vars/matrix_servers and group_vars/jitsi_jvb_servers when either file, the checker, or the hook configuration changes. Source: https://github.com/mother-of-all-self-hosting/mash-playbook/pull/3613 Co-authored-by: QEDeD <pope-jellied-hull@duck.com>
This commit is contained in:
@@ -32,6 +32,14 @@ repos:
|
||||
pass_filenames: false
|
||||
- repo: local
|
||||
hooks:
|
||||
- id: check-group-vars-jinja
|
||||
name: Check the Jinja syntax in group_vars
|
||||
entry: bin/check-group-vars-jinja.py
|
||||
language: python
|
||||
additional_dependencies: ['jinja2==3.1.6', 'pyyaml==6.0.3']
|
||||
files: '^(group_vars/(matrix_servers|jitsi_jvb_servers)|bin/check-group-vars-jinja\.py|\.pre-commit-config\.yaml)$'
|
||||
args: ['group_vars/matrix_servers', 'group_vars/jitsi_jvb_servers']
|
||||
pass_filenames: false
|
||||
- id: check-examples-vars-migration-version
|
||||
name: Check examples/vars.yml migration version matches expected
|
||||
entry: bin/check-examples-vars-migration-version.sh
|
||||
|
||||
Executable
+65
@@ -0,0 +1,65 @@
|
||||
#!/usr/bin/env python3
|
||||
# SPDX-FileCopyrightText: 2026 MASH project contributors
|
||||
# SPDX-FileCopyrightText: 2026 Slavi Pantaleev
|
||||
#
|
||||
# SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
|
||||
# Checks that the Jinja expressions in the playbook's group_vars files can be parsed.
|
||||
#
|
||||
# Ansible renders a `{{ ... }}` expression in group_vars only when something uses that value,
|
||||
# usually a role's task. A typo such as a missing `)` or `'` can therefore pass `--syntax-check`
|
||||
# and the ansible-lint hook (which only lints roles/custom), and the playbook run fails where the
|
||||
# value is first used.
|
||||
# This script reads the file as YAML, parses every string value with Jinja2 (as Ansible does before
|
||||
# evaluating it), and prints the variable name and line of each value that does not parse.
|
||||
# It checks syntax only: it does not know which variables or filters exist.
|
||||
#
|
||||
# Usage: bin/check-group-vars-jinja.py group_vars/matrix_servers group_vars/jitsi_jvb_servers
|
||||
|
||||
import sys
|
||||
|
||||
import jinja2
|
||||
import yaml
|
||||
|
||||
|
||||
def string_values(node, variable):
|
||||
"""Yields (variable, node) for every string value below a YAML node."""
|
||||
if node.tag == "!unsafe": # Ansible never evaluates values tagged !unsafe
|
||||
return
|
||||
if isinstance(node, yaml.MappingNode):
|
||||
for key, value in node.value:
|
||||
yield from string_values(value, variable or key.value)
|
||||
elif isinstance(node, yaml.SequenceNode):
|
||||
for value in node.value:
|
||||
yield from string_values(value, variable)
|
||||
else:
|
||||
yield variable, node
|
||||
|
||||
|
||||
def main(paths):
|
||||
environment = jinja2.Environment()
|
||||
failed = False
|
||||
for path in paths:
|
||||
try:
|
||||
with open(path, encoding="utf-8") as file:
|
||||
document = yaml.compose(file, Loader=yaml.SafeLoader)
|
||||
except yaml.YAMLError as error:
|
||||
print(f"{path}: invalid YAML: {error}")
|
||||
failed = True
|
||||
continue
|
||||
if document is None:
|
||||
print(f"{path}:1: empty YAML document")
|
||||
failed = True
|
||||
continue
|
||||
for variable, node in string_values(document, None):
|
||||
try:
|
||||
environment.parse(node.value)
|
||||
except jinja2.TemplateSyntaxError as error:
|
||||
line = node.start_mark.line + 1
|
||||
print(f"{path}:{line}: {variable}: {error.message} (line {error.lineno} of the value)")
|
||||
failed = True
|
||||
return 1 if failed else 0
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
sys.exit(main(sys.argv[1:]))
|
||||
Reference in New Issue
Block a user