Skip to content

Commit

Permalink
Run cpplint add messages as github annotations
Browse files Browse the repository at this point in the history
  • Loading branch information
MDW committed Dec 19, 2023
1 parent 5e0dbf5 commit 79f7505
Show file tree
Hide file tree
Showing 3 changed files with 195 additions and 3 deletions.
177 changes: 177 additions & 0 deletions .github/logToCs.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,177 @@
#!/usr/bin/python3
"""
Convert a log to CheckStyle format.
Url: https://github.com/mdeweerd/LogToCheckStyle
The log can then be used for generating annotations in a github action.
Note: this script is very young and "quick and dirty".
Patterns can be added to "PATTERNS" to match more messages.
# Examples
Assumes that logToCs.py is available as .github/logToCs.py.
## Example 1:
```yaml
- run: |
pre-commit run -all-files | tee pre-commit.log
.github/logToCs.py pre-commit.log pre-commit.xml
- uses: staabm/annotate-pull-request-from-checkstyle-action@v1
with:
files: pre-commit.xml
notices-as-warnings: true # optional
```
## Example 2:
```yaml
- run: |
pre-commit run --all-files | tee pre-commit.log
- name: Add results to PR
if: ${{ always() }}
run: |
.github/logToCs.py pre-commit.log | cs2pr
```
Author(s):
- https://github.com/mdeweerd
License: MIT License
"""

import argparse
import re
import sys
import xml.etree.ElementTree as ET


def convert_to_checkstyle(messages):
root = ET.Element("checkstyle")
for message in messages:
fields = parse_message(message)
if fields:
add_error_entry(root, **fields)
return ET.tostring(root, encoding="utf-8").decode("utf-8")


ANY_REGEX = r".*?"
FILE_REGEX = r"\s*(?P<file_name>\S.*?)\s*?"
LINE_REGEX = r"\s*(?P<line_number>\d+?)\s*?"
COLUMN_REGEX = r"\s*(?P<column>\d+?)\s*?"
SEVERITY_REGEX = r"\s*(?P<severity>error|warning|notice)\s*?"
MSG_REGEX = r"\s*(?P<message>.+?)\s*?"


# List of message patterns, add more specific patterns earlier in the list
# Creating patterns by using constants makes them easier to define and read.
PATTERNS = [
re.compile(f"^{FILE_REGEX}:{LINE_REGEX}:{COLUMN_REGEX}:{MSG_REGEX}$"),
re.compile(f"^{FILE_REGEX}:{LINE_REGEX}:{MSG_REGEX}$"),
# re.compile(f"^{ANY_REGEX}:{LINE_REGEX}:{MSG_REGEX}$"),
]


def parse_message(message):
"""
Parse message until it matches a pattern.
Returns the fields in a dict.
"""
for pattern in PATTERNS:
m = pattern.match(message)
if not m:
continue
result = m.groupdict()
if len(result) == 0:
continue

if "severity" not in result:
result["severity"] = "error"
else:
result["severity"] = result["severity"].lower()

return result

# Nothing matched
return None


def add_error_entry(
root, severity, file_name, line_number=None, message=None, source=None
):
file_element = find_or_create_file_element(root, file_name)
error_element = ET.SubElement(file_element, "error")
error_element.set("severity", severity)
if line_number:
error_element.set("line", line_number)
if message:
error_element.set("message", message)
if source:
# To verify if this is a valid attribute
error_element.set("source", source)


def find_or_create_file_element(root, file_name):
for file_element in root.findall("file"):
if file_element.get("name") == file_name:
return file_element
file_element = ET.SubElement(root, "file")
file_element.set("name", file_name)
return file_element


def main():
parser = argparse.ArgumentParser(
description="Convert messages to Checkstyle XML format."
)
parser.add_argument(
"input", help="Input file. Use '-' for stdin.", nargs="?", default="-"
)
parser.add_argument(
"output",
help="Output file. Use '-' for stdout.",
nargs="?",
default="-",
)
parser.add_argument(
"-i",
"--input-named",
help="Named input file. Overrides positional input.",
)
parser.add_argument(
"-o",
"--output-named",
help="Named output file. Overrides positional output.",
)

args = parser.parse_args()

if args.input == "-" and args.input_named:
with open(args.input_named) as input_file:
messages = input_file.readlines()
elif args.input != "-":
with open(args.input) as input_file:
messages = input_file.readlines()
else:
messages = sys.stdin.readlines()

checkstyle_xml = convert_to_checkstyle(messages)

if args.output == "-" and args.output_named:
with open(args.output_named, "w") as output_file:
output_file.write(checkstyle_xml)
elif args.output != "-":
with open(args.output, "w") as output_file:
output_file.write(checkstyle_xml)
else:
print(checkstyle_xml)


if __name__ == "__main__":
main()
18 changes: 17 additions & 1 deletion .github/workflows/pre-commit.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@ on:
jobs:
pre-commit:
runs-on: ubuntu-latest
env:
LOG_TO_CS: .github/logToCs.py
RAW_LOG: pre-commit.log
CS_XML: pre-commit.xml
steps:
- run: sudo apt-get update && sudo apt-get install cppcheck
- uses: actions/checkout@v4
Expand All @@ -19,7 +23,19 @@ jobs:
path: ~/.cache/pre-commit/
key: pre-commit-4|${{ env.pythonLocation }}|${{ hashFiles('.pre-commit-config.yaml')
}}
- run: pre-commit run --show-diff-on-failure --color=always --all-files
- run: |
set -o pipefail
pre-commit run --show-diff-on-failure --color=always --all-files | tee ${RAW_LOG}
- if: ${{ failure() }}
run: |
${LOG_TO_CS} ${RAW_LOG} ${CS_XML}
cat ${CS_XML}
- uses: staabm/annotate-pull-request-from-checkstyle-action@v1
if: ${{ failure() }}
with:
files: ${{ env.CS_XML }}
notices-as-warnings: true # optional
prepend-filename: true # optional
- uses: actions/cache/save@v3
if: ${{ always() }}
with:
Expand Down
3 changes: 1 addition & 2 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
files: ^(.*\.(py|json|md|sh|yaml|txt|h|hpp|c|cpp)|setup.cfg)$
exclude:
(?x)^(
.cache/.*|
\.cache/.*|
.*\.hex
)$
repos:
Expand Down Expand Up @@ -84,7 +84,6 @@ repos:
- '--template={file}({line}): {severity} ({id}): {message}'
#exclude: (SevenSegment_defs.h|stm32[^/]*|sysmem\.*)$
- id: cpplint
stages: [manual]
args: ["--filter=-build/header_guard,-build/include,-build/include_subdir,-legal/copyright,-readability/braces,-readability/casting,-readability/fn_size,-readability/multiline_comment,-readability/multiline_string,-readability/todo,-whitespace/blank_line,-whitespace/braces,-whitespace/comma,-whitespace/comments,-whitespace/line_length,-whitespace/newline,-whitespace/operators,-whitespace/parens,-whitespace/semicolon,-whitespace/tab,-whitespace/todo"]
exclude: (mongoose.*\.[ch])$
additional_dependencies:
Expand Down

0 comments on commit 79f7505

Please sign in to comment.