mirror of
https://github.com/SquidDev-CC/CC-Tweaked
synced 2024-12-11 18:50:30 +00:00
Add problem matchers for Github actions
- Add a basic problem matcher for illuaminate errors. - Add a script (tools/parse-reports.py) which parses the XML reports generated by checkstyle and junit, extracts source locations, and emits them in a manner which can be consumed by another set of matchers. This should make it a little easier to see problems for folks who just rely on CI to test things (though also, please don't do this if you can help it).
This commit is contained in:
parent
e10e30f82b
commit
953b94fd08
17
.github/matchers/checkstyle.json
vendored
Normal file
17
.github/matchers/checkstyle.json
vendored
Normal file
@ -0,0 +1,17 @@
|
||||
{
|
||||
"problemMatcher": [
|
||||
{
|
||||
"owner": "checkstyle",
|
||||
"pattern": [
|
||||
{
|
||||
"regexp": "^([a-z]+) ([\\w./-]+):(\\d+):(\\d+): (.*)$",
|
||||
"severity": 1,
|
||||
"file": 2,
|
||||
"line": 3,
|
||||
"column": 4,
|
||||
"message": 5
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
18
.github/matchers/illuaminate.json
vendored
Normal file
18
.github/matchers/illuaminate.json
vendored
Normal file
@ -0,0 +1,18 @@
|
||||
{
|
||||
"problemMatcher": [
|
||||
{
|
||||
"owner": "illuaminate",
|
||||
"severity": "warning",
|
||||
"pattern": [
|
||||
{
|
||||
"regexp": "^([\\w./-]+):\\[(\\d+):(\\d+)\\-(?:\\d+):(?:\\d+)\\]: (.*) \\[([a-z:-]+)\\]$",
|
||||
"file": 1,
|
||||
"line": 2,
|
||||
"column": 3,
|
||||
"message": 4,
|
||||
"code": 5
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
15
.github/matchers/junit.json
vendored
Normal file
15
.github/matchers/junit.json
vendored
Normal file
@ -0,0 +1,15 @@
|
||||
{
|
||||
"problemMatcher": [
|
||||
{
|
||||
"owner": "junit",
|
||||
"pattern": [
|
||||
{
|
||||
"regexp": "^## ([\\w./-]+):(\\d+): (.*)$",
|
||||
"file": 1,
|
||||
"line": 2,
|
||||
"message": 3
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
8
.github/workflows/main-ci.yml
vendored
8
.github/workflows/main-ci.yml
vendored
@ -41,8 +41,11 @@ jobs:
|
||||
path: build/libs
|
||||
|
||||
- name: Upload Coverage
|
||||
run: bash <(curl -s https://codecov.io/bash)
|
||||
continue-on-error: true
|
||||
uses: codecov/codecov-action@v1
|
||||
|
||||
- name: Parse test reports
|
||||
run: ./tools/parse-reports.py
|
||||
if: ${{ failure() }}
|
||||
|
||||
- name: Cache pre-commit
|
||||
uses: actions/cache@v2
|
||||
@ -51,6 +54,7 @@ jobs:
|
||||
key: ${{ runner.os }}-pre-commit-${{ hashFiles('config/pre-commit/config.yml') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-pre-commit-
|
||||
|
||||
- name: Run linters
|
||||
run: |
|
||||
pip install pre-commit
|
||||
|
@ -5,5 +5,12 @@ test -d bin || mkdir bin
|
||||
test -f bin/illuaminate || curl -s -obin/illuaminate https://squiddev.cc/illuaminate/linux-x86-64/illuaminate
|
||||
chmod +x bin/illuaminate
|
||||
|
||||
if [ -n ${GITHUB_ACTIONS+x} ]; then
|
||||
# Register a problem matcher (see https://github.com/actions/toolkit/blob/master/docs/problem-matchers.md)
|
||||
# for illuaminate.
|
||||
echo "::add-matcher::.github/matchers/illuaminate.json"
|
||||
trap 'echo "::remove-matcher owner=illuaminate::"' EXIT
|
||||
fi
|
||||
|
||||
./gradlew luaJavadoc
|
||||
bin/illuaminate lint
|
||||
|
114
tools/parse-reports.py
Executable file
114
tools/parse-reports.py
Executable file
@ -0,0 +1,114 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Parse reports generated by Gradle and convert them into GitHub annotations.
|
||||
|
||||
See https://github.com/actions/toolkit/blob/master/docs/problem-matchers.md and
|
||||
https://github.com/actions/toolkit/blob/master/docs/commands.md.
|
||||
"""
|
||||
|
||||
from typing import Optional, Tuple
|
||||
import pathlib
|
||||
import xml.etree.ElementTree as ET
|
||||
import re
|
||||
import os.path
|
||||
|
||||
|
||||
LUA_ERROR_LOCATION = re.compile(r"^\s+(/[\w./-]+):(\d+):", re.MULTILINE)
|
||||
JAVA_ERROR_LOCATION = re.compile(r"^\tat ([\w.]+)\.[\w]+\([\w.]+:(\d+)\)$", re.MULTILINE)
|
||||
ERROR_MESSAGE = re.compile(r"(.*)\nstack traceback:", re.DOTALL)
|
||||
|
||||
SPACES = re.compile(r"\s+")
|
||||
|
||||
SOURCE_LOCATIONS = [
|
||||
"src/main/java",
|
||||
"src/main/resources/data/computercraft/lua",
|
||||
"src/test/java",
|
||||
"src/test/resources",
|
||||
]
|
||||
|
||||
|
||||
def find_file(path: str) -> Optional[str]:
|
||||
while len(path) > 0 and path[0] == '/':
|
||||
path = path[1:]
|
||||
|
||||
for source_dir in SOURCE_LOCATIONS:
|
||||
child_path = os.path.join(source_dir, path)
|
||||
if os.path.exists(child_path):
|
||||
return child_path
|
||||
|
||||
return None
|
||||
|
||||
|
||||
def find_location(message: str) -> Optional[Tuple[str, str]]:
|
||||
location = LUA_ERROR_LOCATION.search(message)
|
||||
if location:
|
||||
file = find_file(location[1])
|
||||
if file:
|
||||
return file, location[2]
|
||||
|
||||
for location in JAVA_ERROR_LOCATION.findall(message):
|
||||
file = find_file(location[0].replace(".", "/") + ".java")
|
||||
if file:
|
||||
return file, location[1]
|
||||
|
||||
return None
|
||||
|
||||
|
||||
def parse_junit() -> None:
|
||||
"""
|
||||
Scrape JUnit test reports for errors. We determine the location from the Lua
|
||||
or Java stacktrace.
|
||||
"""
|
||||
print("::add-matcher::.github/matchers/junit.json")
|
||||
|
||||
for path in pathlib.Path("build/test-results/test").glob("TEST-*.xml"):
|
||||
for testcase in ET.parse(path).getroot():
|
||||
if testcase.tag != "testcase":
|
||||
continue
|
||||
|
||||
for result in testcase:
|
||||
if result.tag != "failure":
|
||||
continue
|
||||
|
||||
name = f'{testcase.attrib["classname"]}.{testcase.attrib["name"]}'
|
||||
message = result.attrib.get('message')
|
||||
|
||||
location = find_location(result.text)
|
||||
error = ERROR_MESSAGE.match(message)
|
||||
if error:
|
||||
error = error[1]
|
||||
else:
|
||||
error = message
|
||||
|
||||
if location:
|
||||
print(f'## {location[0]}:{location[1]}: {name} failed: {SPACES.sub(" ", error)}')
|
||||
else:
|
||||
print(f'::error::{name} failed')
|
||||
|
||||
print("::group::Full error message")
|
||||
print(result.text)
|
||||
print("::endgroup")
|
||||
|
||||
print("::remove-matcher owner=junit::")
|
||||
|
||||
|
||||
def parse_checkstyle() -> None:
|
||||
"""
|
||||
Scrape JUnit test reports for errors. We determine the location from the Lua
|
||||
or Java stacktrace.
|
||||
"""
|
||||
print("::add-matcher::.github/matchers/checkstyle.json")
|
||||
|
||||
for path in pathlib.Path("build/reports/checkstyle/").glob("*.xml"):
|
||||
for file in ET.parse(path).getroot():
|
||||
for error in file:
|
||||
filename = os.path.relpath(file.attrib['name'])
|
||||
|
||||
attrib = error.attrib
|
||||
print(f'{attrib["severity"]} {filename}:{attrib["line"]}:{attrib.get("column", 1)}: {SPACES.sub(" ", attrib["message"])}')
|
||||
|
||||
print("::remove-matcher owner=checkstyle::")
|
||||
|
||||
if __name__ == '__main__':
|
||||
parse_junit()
|
||||
parse_checkstyle()
|
Loading…
Reference in New Issue
Block a user