Skip to content

Commit

Permalink
Merge pull request #485 from selfhosters/ci
Browse files Browse the repository at this point in the history
  • Loading branch information
Roxedus authored Mar 21, 2024
2 parents 28f0e8e + 27225f8 commit 5980ec3
Show file tree
Hide file tree
Showing 3 changed files with 152 additions and 11 deletions.
130 changes: 130 additions & 0 deletions .github/scripts/check.py
Original file line number Diff line number Diff line change
@@ -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)
32 changes: 21 additions & 11 deletions .github/workflows/xmllint.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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 }}
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
.venv

0 comments on commit 5980ec3

Please sign in to comment.