Skip to content

Commit 2841254

Browse files
Improve statistics
1 parent d89c8bf commit 2841254

File tree

1 file changed

+118
-1
lines changed

1 file changed

+118
-1
lines changed

.github/workflows/python-tests.yml

Lines changed: 118 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,14 @@ on:
77
pull_request:
88
branches: [ main ]
99

10+
concurrency:
11+
group: ${{ github.workflow }}-${{ github.ref }}
12+
cancel-in-progress: true
13+
14+
defaults:
15+
run:
16+
shell: bash
17+
1018
permissions:
1119
contents: read
1220
checks: write
@@ -15,7 +23,14 @@ permissions:
1523
jobs:
1624
test:
1725
runs-on: ubuntu-latest
26+
timeout-minutes: 30
27+
env:
28+
COVERAGE_THRESHOLD: "85"
29+
PIP_DISABLE_PIP_VERSION_CHECK: "1"
30+
PIP_PROGRESS_BAR: "off"
31+
PYTHONUNBUFFERED: "1"
1832
strategy:
33+
fail-fast: false
1934
matrix:
2035
python-version: [ '3.12', '3.13' , '3.14' ]
2136
steps:
@@ -31,7 +46,11 @@ jobs:
3146
- name: Install dependencies
3247
run: |
3348
python -m pip install --upgrade pip
34-
pip install -r requirements.txt
49+
python -m pip install -r requirements.txt
50+
51+
- name: Validate dependency metadata
52+
run: |
53+
python -m pip check
3554
3655
- name: Run pylint analysis
3756
run: |
@@ -62,6 +81,7 @@ jobs:
6281
with:
6382
name: coverage-html-${{ matrix.python-version }}
6483
path: tests/python/htmlcov-${{ matrix.python-version }}/
84+
if-no-files-found: warn
6585

6686
- name: Upload JUnit test results
6787
if: always()
@@ -70,6 +90,103 @@ jobs:
7090
with:
7191
name: junit-results-${{ matrix.python-version }}
7292
path: tests/python/junit-${{ matrix.python-version }}.xml
93+
if-no-files-found: warn
94+
95+
- name: Append pylint summary to job summary
96+
if: always()
97+
run: |
98+
REPORT_JSON="tests/python/pylint/reports/latest.json"
99+
{
100+
echo "### Python ${{ matrix.python-version }} – Pylint summary"
101+
echo ""
102+
if [ -f "$REPORT_JSON" ] && command -v jq >/dev/null; then
103+
TOTAL=$(jq 'length' "$REPORT_JSON")
104+
echo "- Diagnostics: $TOTAL"
105+
echo ""
106+
jq -r '
107+
group_by(.type) |
108+
map({label: (.[0].type), count: length}) |
109+
.[] | " - \(.label): \(.count)"
110+
' "$REPORT_JSON"
111+
else
112+
echo "Pylint summary unavailable (install jq for statistics)."
113+
fi
114+
echo ""
115+
echo "- Reports artifact: pylint-reports-${{ matrix.python-version }}"
116+
echo ""
117+
} >> "$GITHUB_STEP_SUMMARY"
118+
119+
- name: Append coverage summary to job summary
120+
if: always()
121+
run: |
122+
COVERAGE_FILE="tests/python/.coverage-${{ matrix.python-version }}"
123+
HTML_DIR="tests/python/htmlcov-${{ matrix.python-version }}"
124+
COVERAGE_TXT="$(mktemp)"
125+
if [ -f "$COVERAGE_FILE" ]; then
126+
python -m coverage report --data-file="$COVERAGE_FILE" --rcfile=tests/python/.coveragerc --skip-covered --fail-under=0 > "$COVERAGE_TXT" || true
127+
fi
128+
OVERALL=""
129+
if [ -s "$COVERAGE_TXT" ]; then
130+
OVERALL=$(tail -n 1 "$COVERAGE_TXT" | awk '{print $NF}')
131+
fi
132+
{
133+
echo "### Python ${{ matrix.python-version }} – Coverage summary"
134+
echo ""
135+
echo "- Overall: ${OVERALL:-Unavailable}"
136+
echo ""
137+
echo "- HTML coverage artifact: coverage-html-${{ matrix.python-version }}"
138+
if [ -d "$HTML_DIR" ]; then
139+
echo "- Local path: $HTML_DIR/index.html"
140+
fi
141+
echo ""
142+
} >> "$GITHUB_STEP_SUMMARY"
143+
rm -f "$COVERAGE_TXT"
144+
145+
- name: Enforce coverage threshold
146+
if: steps.pytest.outcome == 'success'
147+
env:
148+
COVERAGE_FILE: tests/python/.coverage-${{ matrix.python-version }}
149+
run: |
150+
if [ ! -f "$COVERAGE_FILE" ]; then
151+
echo "Coverage file not found; skipping threshold enforcement."
152+
exit 0
153+
fi
154+
python - <<'PY'
155+
import os
156+
import re
157+
import subprocess
158+
import sys
159+
160+
threshold = float(os.getenv("COVERAGE_THRESHOLD", "0"))
161+
coverage_file = os.environ["COVERAGE_FILE"]
162+
rcfile = "tests/python/.coveragerc"
163+
164+
result = subprocess.run([
165+
sys.executable,
166+
"-m",
167+
"coverage",
168+
"report",
169+
f"--data-file={coverage_file}",
170+
f"--rcfile={rcfile}",
171+
"--skip-covered",
172+
"--fail-under=0",
173+
], capture_output=True, text=True, check=False)
174+
175+
output = result.stdout.strip().splitlines()
176+
if not output:
177+
sys.exit(0)
178+
179+
match = re.search(r"(\d+(?:\.\d+)?)%$", output[-1])
180+
if not match:
181+
sys.exit(0)
182+
183+
percent = float(match.group(1))
184+
if percent < threshold:
185+
print(f"::error ::Coverage {percent:.2f}% is below required threshold {threshold:.2f}%.")
186+
sys.exit(1)
187+
188+
print(f"Coverage {percent:.2f}% meets the threshold {threshold:.2f}%.")
189+
PY
73190

74191
- name: Publish Unit Test Results to PR
75192
if: always()

0 commit comments

Comments
 (0)