Skip to content

Commit

Permalink
feat: WhitespaceChecker, expandable summary sections
Browse files Browse the repository at this point in the history
  • Loading branch information
FHeilmann committed Nov 29, 2023
1 parent 4442039 commit bbcf8da
Show file tree
Hide file tree
Showing 8 changed files with 208 additions and 52 deletions.
18 changes: 9 additions & 9 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v2.3.0
hooks:
- id: check-yaml
- id: check-toml
- id: mixed-line-ending
args: [ --fix=lf ]
- id: end-of-file-fixer
- id: trailing-whitespace
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v2.3.0
hooks:
- id: check-yaml
- id: check-toml
- id: mixed-line-ending
args: [ --fix=lf ]
- id: end-of-file-fixer
- id: trailing-whitespace
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.1.6
hooks:
Expand Down
3 changes: 2 additions & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,8 @@ ignore_missing_imports = true
[tool.poetry.scripts]
check-stl-corruption = "voron_ci.tools.stl_corruption_checker:main"
check-stl-rotation = "voron_ci.tools.stl_rotation_checker:main"
check-files = "voron_ci.tools.file_checker:main"
check-mod-structure = "voron_ci.tools.mod_structure_checker:main"
check-whitespace = "voron_ci.tools.whitespace_checker:main"
upload-images = "voron_ci.tools.imagekit_uploader:main"
generate-readme = "voron_ci.tools.readme_generator:main"
debug-container = "voron_ci.utils.debug_container:print_container_info"
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,6 @@
logger = init_logging(__name__)


STEP_SUMMARY_PREAMBLE = """
## Folder check
"""


class FileErrors(StrEnum):
file_outside_mod_folder = "The file '{}' is located outside the expected folder structure of `printer_mods/user/mod`"
mod_missing_metadata = "The mod '{}' does not have a metadata.yml file"
Expand All @@ -30,7 +24,7 @@ class FileErrors(StrEnum):
MOD_DEPTH = 2


class FileChecker:
class ModStructureChecker:
def __init__(self: Self, args: argparse.Namespace) -> None:
self.input_dir: Path = Path(Path.cwd(), args.input_dir)
self.verbosity: bool = args.verbose
Expand Down Expand Up @@ -84,14 +78,16 @@ def run(self: Self) -> None:

if self.print_gh_step_summary:
self.check_summary = [(path.relative_to(self.input_dir).as_posix(), reason) for path, reason in self.errors.items()]
GithubActionHelper.print_summary_table(
preamble=STEP_SUMMARY_PREAMBLE,
columns=[
"File/Folder",
"Reason",
],
rows=self.check_summary,
)
with GithubActionHelper.expandable_section(
title=f"Mod structure check (errors: {len(self.errors)})", default_open=self.return_status == ReturnStatus.SUCCESS
):
GithubActionHelper.print_summary_table(
columns=[
"File/Folder",
"Reason",
],
rows=self.check_summary,
)

GithubActionHelper.write_output(output={"extended-outcome": EXTENDED_OUTCOME[self.return_status]})

Expand Down Expand Up @@ -138,7 +134,7 @@ def main() -> None:
default=False,
)
args: argparse.Namespace = parser.parse_args()
FileChecker(args=args).run()
ModStructureChecker(args=args).run()


if __name__ == "__main__":
Expand Down
6 changes: 2 additions & 4 deletions voron_ci/tools/readme_generator.py
Original file line number Diff line number Diff line change
Expand Up @@ -70,10 +70,8 @@ def run(self: Self) -> None:
)
)
prev_username = mod["creator"]

GithubActionHelper.print_summary_table(
preamble="# Printer Readme Preview", columns=["Creator", "Mod title", "Description", "Printer compatibility", "Last Changed"], rows=readme_rows
)
with GithubActionHelper.expandable_section(title="README.md preview", default_open=True):
GithubActionHelper.print_summary_table(columns=["Creator", "Mod title", "Description", "Printer compatibility", "Last Changed"], rows=readme_rows)

if self.json_path:
logger.info("Writing json file to '%s'", self.json_path)
Expand Down
15 changes: 10 additions & 5 deletions voron_ci/tools/stl_corruption_checker.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ def __init__(self: Self, args: argparse.Namespace) -> None:
self.print_gh_step_summary: bool = args.github_step_summary
self.return_status: ReturnStatus = ReturnStatus.SUCCESS
self.check_summary: list[tuple[str, ...]] = []
self.error_count: int = 0

def run(self: Self) -> None:
if self.verbosity:
Expand All @@ -46,11 +47,13 @@ def run(self: Self) -> None:
self.return_status = ReturnStatus.SUCCESS

if self.print_gh_step_summary:
GithubActionHelper.print_summary_table(
preamble=STEP_SUMMARY_PREAMBLE,
columns=["Filename", "Result", "Edges Fixed", "Backwards Edges", "Degenerate Facets", "Facets Removed", "Facets Added", "Facets Reversed"],
rows=self.check_summary,
)
with GithubActionHelper.expandable_section(
title=f"STL corruption check (errors: {self.error_count})", default_open=self.return_status == ReturnStatus.SUCCESS
):
GithubActionHelper.print_summary_table(
columns=["Filename", "Result", "Edges Fixed", "Backwards Edges", "Degenerate Facets", "Facets Removed", "Facets Added", "Facets Reversed"],
rows=self.check_summary,
)

GithubActionHelper.write_output(output={"extended-outcome": EXTENDED_OUTCOME[self.return_status]})

Expand Down Expand Up @@ -94,6 +97,7 @@ def _check_stl(self: Self, stl_file_path: Path) -> ReturnStatus:
stl=stl,
path=Path(self.output_dir, stl_file_path.relative_to(self.input_dir)),
)
self.error_count += 1
return ReturnStatus.FAILURE
logger.info("STL '%s' does not contain any errors!", stl_file_path.relative_to(self.input_dir).as_posix())
self.check_summary.append(
Expand All @@ -105,6 +109,7 @@ def _check_stl(self: Self, stl_file_path: Path) -> ReturnStatus:
self.check_summary.append(
(stl_file_path.name, SummaryStatus.EXCEPTION, "0", "0", "0", "0", "0", "0"),
)
self.error_count += 1
return ReturnStatus.EXCEPTION


Expand Down
24 changes: 12 additions & 12 deletions voron_ci/tools/stl_rotation_checker.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,6 @@

logger = init_logging(__name__)


STEP_SUMMARY_PREAMBLE = """
## STL rotation check summary
"""

TWEAK_THRESHOLD = 0.1


Expand All @@ -39,6 +33,7 @@ def __init__(self: Self, args: argparse.Namespace) -> None:
self.file_handler: FileHandler.FileHandler = FileHandler.FileHandler()
self.return_status: ReturnStatus = ReturnStatus.SUCCESS
self.check_summary: list[tuple[str, ...]] = []
self.error_count: int = 0

@staticmethod
def get_random_string(length: int) -> str:
Expand Down Expand Up @@ -78,17 +73,19 @@ def run(self: Self) -> None:

with ThreadPoolExecutor() as pool:
return_statuses: list[ReturnStatus] = list(pool.map(self._check_stl, stl_paths))

if return_statuses:
self.return_status = max(*return_statuses, self.return_status)
else:
self.return_status = ReturnStatus.SUCCESS

if self.print_gh_step_summary:
GithubActionHelper.print_summary_table(
preamble=STEP_SUMMARY_PREAMBLE,
columns=["Filename", "Result", "Current orientation", "Suggested orientation"],
rows=self.check_summary,
)
with GithubActionHelper.expandable_section(
title=f"STL rotation check (errors: {self.error_count})", default_open=self.return_status == ReturnStatus.SUCCESS
):
GithubActionHelper.print_summary_table(
columns=["Filename", "Result", "Current orientation", "Suggested orientation"],
rows=self.check_summary,
)

GithubActionHelper.write_output(output={"extended-outcome": EXTENDED_OUTCOME[self.return_status]})

Expand All @@ -112,6 +109,7 @@ def _check_stl(self: Self, stl_file_path: Path) -> ReturnStatus:
if len(mesh_objects.items()) > 1:
logger.warning("File '%s' contains multiple objects and is therefore skipped!", stl_file_path.relative_to(self.input_dir).as_posix())
self.check_summary.append((stl_file_path.name, SummaryStatus.WARNING, "", ""))
self.error_count += 1
return ReturnStatus.WARNING
rotated_mesh: Tweak = Tweak(mesh_objects[0]["mesh"], extended_mode=True, verbose=False, min_volume=True)
original_image_url: str = self.make_markdown_image(base_dir=self.input_dir, stl_file_path=stl_file_path.relative_to(self.input_dir))
Expand All @@ -131,12 +129,14 @@ def _check_stl(self: Self, stl_file_path: Path) -> ReturnStatus:
rotated_image_url,
),
)
self.error_count += 1
return ReturnStatus.WARNING
self.check_summary.append((stl_file_path.name, SummaryStatus.SUCCESS, original_image_url, ""))
return ReturnStatus.SUCCESS
except Exception as e:
logger.exception("A fatal error occurred during rotation checking", exc_info=e)
self.check_summary.append((stl_file_path.name, SummaryStatus.EXCEPTION, "", ""))
self.error_count += 1
return ReturnStatus.EXCEPTION


Expand Down
133 changes: 133 additions & 0 deletions voron_ci/tools/whitespace_checker.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
import argparse
import os
import string
import sys
from typing import Self

from voron_ci.contants import EXTENDED_OUTCOME, ReturnStatus
from voron_ci.utils.github_action_helper import GithubActionHelper
from voron_ci.utils.logging import init_logging

logger = init_logging(__name__)

STEP_SUMMARY_PREAMBLE = """
## Whitespace check errors
"""


class WhitespaceChecker:
def __init__(self: Self, args: argparse.Namespace) -> None:
self.input_env_var: str = args.input_env_var
self.output_gh_var: str = args.output_gh_var
self.verbosity: bool = args.verbose
self.fail_on_error: bool = args.fail_on_error
self.print_gh_step_summary: bool = args.github_step_summary
self.return_status: ReturnStatus = ReturnStatus.SUCCESS
self.check_summary: list[tuple[str, ...]] = []
self.error_count: int = 0

def _check_for_whitespace(self: Self) -> None:
input_file_list = os.environ.get(self.input_env_var, "").splitlines()

for input_file in input_file_list:
if not input_file:
continue
logger.info("Checking file '%s' for whitespace!", input_file)
for c in input_file:
if c in string.whitespace:
logger.error("File '%s' contains whitespace!", input_file)
self.check_summary.append((input_file, "This file contains whitespace!"))
self.error_count += 1
self.return_status = ReturnStatus.FAILURE
break

def _write_sanitized_output(self: Self) -> None:
input_file_list = os.environ.get(self.input_env_var, "").splitlines()

output_file_list: list[str] = [input_file.replace("[", "\\[").replace("]", "\\]") for input_file in input_file_list]

GithubActionHelper.write_output_multiline(output={self.output_gh_var: output_file_list})

def run(self: Self) -> None:
if self.verbosity:
logger.setLevel("INFO")

logger.info("Starting files check from env var '%s'", self.input_env_var)

self._check_for_whitespace()

if self.output_gh_var:
self._write_sanitized_output()

if self.print_gh_step_summary:
with GithubActionHelper.expandable_section(
title=f"Whitespace checks (errors: {self.error_count})", default_open=self.return_status != ReturnStatus.SUCCESS
):
GithubActionHelper.print_summary_table(
columns=[
"File/Folder",
"Reason",
],
rows=self.check_summary,
)

GithubActionHelper.write_output(output={"extended-outcome": EXTENDED_OUTCOME[self.return_status]})

if self.return_status > ReturnStatus.SUCCESS and self.fail_on_error:
logger.error("Error detected during whitespace checking!")
sys.exit(255)


def main() -> None:
parser: argparse.ArgumentParser = argparse.ArgumentParser(
prog="VoronDesign VoronUsers whitespace checker",
description="This tool is used to check changed files inside an env var for whitespace. The list is also prepared for sparse-checkout",
)
parser.add_argument(
"-i",
"--input_env_var",
required=True,
action="store",
type=str,
help="Environment variable name containing a newline separated list of files to be checked",
)
parser.add_argument(
"-v",
"--verbose",
required=False,
action="store_true",
help="Print debug output to stdout",
default=False,
)
parser.add_argument(
"-f",
"--fail_on_error",
required=False,
action="store_true",
help="Whether to return an error exit code if one of the files contains whitespace",
default=False,
)
parser.add_argument(
"-o",
"--output_gh_var",
required=False,
action="store",
type=str,
help="Github output variable to store a sanitized list of files into",
default="",
)
parser.add_argument(
"-g",
"--github_step_summary",
required=False,
action="store_true",
help="Whether to output a step summary when running inside a github action",
default=False,
)
args: argparse.Namespace = parser.parse_args()
WhitespaceChecker(args=args).run()


if __name__ == "__main__":
main()
Loading

0 comments on commit bbcf8da

Please sign in to comment.