From 27225f8d60190fada2faad8a93a2bf4bf87af9cd Mon Sep 17 00:00:00 2001 From: Roxedus Date: Thu, 21 Mar 2024 10:46:19 +0100 Subject: [PATCH] Automate checks --- .github/scripts/check.py | 130 ++++++++++++++++++++++++++++++++++ .github/workflows/xmllint.yml | 32 ++++++--- .gitignore | 1 + 3 files changed, 152 insertions(+), 11 deletions(-) create mode 100644 .github/scripts/check.py create mode 100644 .gitignore diff --git a/.github/scripts/check.py b/.github/scripts/check.py new file mode 100644 index 00000000..7ca40130 --- /dev/null +++ b/.github/scripts/check.py @@ -0,0 +1,130 @@ +#!/usr/bin/env python3 +import sys + +sys.modules['_elementtree'] = None + +import xml.etree.ElementTree as ET +import re +import os +import argparse + +blacklistedChars: list = ["<", ">", "&", "\"", "'"] +bloatTags: list = ["DateInstalled", "Networking", "Data", "Environment"] +noticeTags: list = ["Category", "Registry", "Icon"] +userInputTags: list = ["Description", "Overview", "Config", "Changelog"] + +class LineNumberingParser(ET.XMLParser): # https://stackoverflow.com/a/36430270 + def _start_list(self, *args, **kwargs): + # Here we assume the default XML parser which is expat + # and copy its element position attributes into output Elements + element = super(self.__class__, self)._start_list(*args, **kwargs) + element._start_line_number = self.parser.CurrentLineNumber + element._start_column_number = self.parser.CurrentColumnNumber + element._start_byte_index = self.parser.CurrentByteIndex + return element + + def _end(self, *args, **kwargs): + element = super(self.__class__, self)._end(*args, **kwargs) + element._end_line_number = self.parser.CurrentLineNumber + element._end_column_number = self.parser.CurrentColumnNumber + element._end_byte_index = self.parser.CurrentByteIndex + return element + +def check_xml(filename: str): + webUiPort: dict = { "port": None, "line": None } + targetPorts: list = [] + + tree = ET.parse(filename, parser=LineNumberingParser()) + + root = tree.getroot() + + # Errors + + if root.find("Support") is None or root.find("Project") is None: + title = "Missing Support or Project Link" + message = "No Support or Project Link Present" + print(f"::error file={filename},title={title}::{message}") + + for overview in root.iter('Overview'): + if "Converted By Community Applications" in overview.text: + title = "Converted By Community Applications" + message = "Blacklisted: Obvious CA conversion templates are disallowed" + line = overview._end_line_number + print(f"::error file={filename},line={line},title={title}::{message}") + + for tag in userInputTags: + for element in root.iter(tag): + texts = [element.text, element.attrib.get("Default"), element.attrib.get("Description")] + if any(char in texts for char in blacklistedChars): + title = f"Blacklisted Character" + message = f"Blacklisted Character in {tag}" + line = element._end_line_number + print(f"::error file={filename},line={line},title={title}::{message}") + + for tag in bloatTags: + if root.find(tag) is not None: + title = f"Unnecessary Tag" + message = f"Unnecessary {tag} Tag Present" + print(f"::error file={filename},title={title}::{message}") + + # Notices + + if (postArg := root.find("PostArgs")) is not None: + if postArg.text: + if len(postArg) != 0: + title = "PostArgs Present" + message = "PostArgs are to be used with care" + print(f"::notice file={filename},title={title}::{message}") + + for tag in noticeTags: + if root.find(tag) is None: + title = f"Missing Tag" + message = f"No {tag} entry present." + print(f"::notice file={filename},title={title}::{message}") + + # Webport logic + + for web in root.iter('WebUI'): + if not web.text: + continue + ex = re.search(r"\[PORT:(\d+)\]", web.text, re.IGNORECASE) + if ex: + webUiPort["port"] = ex.group(1) + webUiPort["line"] = web._end_line_number + + for config in root.iter('Config'): + if config.attrib.get("Type") == "Port": + targetPorts.append(config.attrib.get("Target")) + + if webUiPort.get("port"): + if webUiPort.get("port") not in targetPorts: + title = "WebUI Port not in Config" + message = f"WebUI Port {webUiPort.get('port')} is not a target in Config" + line = webUiPort.get("line") + print(f"::error file={filename},line={line},title={title}::{message}") + +if __name__ == "__main__": + parser = argparse.ArgumentParser(description="Template Checker") + parser.add_argument('-f', '--files', nargs='+', help="Runs only on file") + + args = parser.parse_args() + + if args.files: + _files: list = [] + for fileargs in args.files: + if os.path.isfile(fileargs): + _files.append(fileargs) + else: + print(f"{fileargs} is not a file") + if len(_files) != 0: + [check_xml(filename = file) for file in _files] + else: + print("No files found") + + else: + directory = "templates" + for filename in os.scandir(directory): + if filename.name.endswith(".xml") and filename.is_file(): + if filename.name == "ca_profile.xml": + pass + check_xml(filename = filename.path) \ No newline at end of file diff --git a/.github/workflows/xmllint.yml b/.github/workflows/xmllint.yml index 1dc1a7af..8bdb2c10 100644 --- a/.github/workflows/xmllint.yml +++ b/.github/workflows/xmllint.yml @@ -13,17 +13,27 @@ jobs: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v1 - - name: Prep Enviroment - run: sudo apt-get update -q && sudo apt-get install -qy libxml2-utils + - uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Get changed files + id: changed-files + uses: tj-actions/changed-files@v43 + with: + files: | + templates/*.xml - name: Run linter - env: - sha: ${{ github.sha }} run: | - for file in $(git diff-tree --no-commit-id --name-only -r $sha ); do - if [[ ${file} == *.xml ]] && [[ -f ${file} ]] - then - xmllint $file - fi - done; + sudo apt-get update -q && sudo apt-get install -qy libxml2-utils + xmllint ${{ steps.changed-files.outputs.all_changed_files }} + + - name: Set up Python 3.11 + uses: actions/setup-python@v5 + with: + python-version: 3.11 + + - name: Run template check + shell: bash + run: python .github/scripts/check.py --files ${{ steps.changed-files.outputs.all_changed_files }} diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000..b694934f --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +.venv \ No newline at end of file