fix coverage badge: use .woodpecker/ci.yml and stdlib urllib (no curl)
This commit is contained in:
@@ -23,11 +23,17 @@ steps:
|
|||||||
environment:
|
environment:
|
||||||
UV_PYTHON_PREFERENCE: only-system
|
UV_PYTHON_PREFERENCE: only-system
|
||||||
UV_LINK_MODE: copy
|
UV_LINK_MODE: copy
|
||||||
|
GITEA_TOKEN:
|
||||||
|
from_secret: gitea_token
|
||||||
|
GITEA_URL:
|
||||||
|
from_secret: gitea_url
|
||||||
commands:
|
commands:
|
||||||
- uv python pin 3.13.11
|
- uv python pin 3.13.11
|
||||||
- uv sync --dev
|
- uv sync --dev
|
||||||
- uv pip install -e .
|
- uv pip install -e .
|
||||||
- uv run pytest tests/ --no-cov --tb=short -q
|
- uv run pytest tests/ --cov=src --cov-report=term-missing --cov-fail-under=99 -q 2>&1 | tee pytest.out
|
||||||
|
- uv run python dev/scripts/coverage_badge.py < pytest.out > coverage.svg
|
||||||
|
- uv run python dev/scripts/coverage_badge.py --post pytest.out
|
||||||
|
|
||||||
- name: validate-compose
|
- name: validate-compose
|
||||||
image: docker:cli
|
image: docker:cli
|
||||||
|
|||||||
@@ -1,16 +1,21 @@
|
|||||||
"""Generate a coverage badge SVG from pytest-cov output.
|
"""Generate a coverage badge SVG and optionally post status to Gitea.
|
||||||
|
|
||||||
Usage:
|
Usage:
|
||||||
uv run python -m pytest --cov=src ... | uv run python dev/scripts/coverage_badge.py
|
# Generate badge SVG to stdout from piped pytest-cov output:
|
||||||
|
uv run pytest --cov=src ... | uv run python dev/scripts/coverage_badge.py
|
||||||
|
|
||||||
Reads stdin for a pytest-cov summary line like "TOTAL 1234 56 95%",
|
# Post coverage as a Gitea commit status (reads GITEA_TOKEN, GITEA_URL,
|
||||||
extracts the percentage, writes a badge SVG to stdout.
|
# CI_COMMIT_SHA from environment):
|
||||||
|
uv run python dev/scripts/coverage_badge.py --post pytest.out
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
|
import json
|
||||||
|
import os
|
||||||
import re
|
import re
|
||||||
import sys
|
import sys
|
||||||
|
import urllib.request
|
||||||
|
|
||||||
TEMPLATE = """\
|
TEMPLATE = """\
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" width="116" height="20">
|
<svg xmlns="http://www.w3.org/2000/svg" width="116" height="20">
|
||||||
@@ -45,14 +50,47 @@ def color_for(pct: int) -> str:
|
|||||||
return "#e05d44"
|
return "#e05d44"
|
||||||
|
|
||||||
|
|
||||||
def main() -> None:
|
def extract_pct(text: str) -> int:
|
||||||
text = sys.stdin.read()
|
|
||||||
m = re.search(r"^TOTAL\s+\d+\s+\d+\s+(\d+)%", text, re.MULTILINE)
|
m = re.search(r"^TOTAL\s+\d+\s+\d+\s+(\d+)%", text, re.MULTILINE)
|
||||||
if not m:
|
if not m:
|
||||||
print("ERROR: could not find coverage percentage in input", file=sys.stderr)
|
print("ERROR: could not find coverage percentage in input", file=sys.stderr)
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
pct = int(m.group(1))
|
return int(m.group(1))
|
||||||
print(TEMPLATE.format(pct=pct, color=color_for(pct)))
|
|
||||||
|
|
||||||
|
def post_status(pct: int) -> None:
|
||||||
|
token = os.environ["GITEA_TOKEN"]
|
||||||
|
url = os.environ["GITEA_URL"]
|
||||||
|
sha = os.environ["CI_COMMIT_SHA"]
|
||||||
|
endpoint = f"{url}/api/v1/repos/homelab/stack/statuses/{sha}"
|
||||||
|
body = json.dumps({
|
||||||
|
"state": "success",
|
||||||
|
"description": f"{pct}% coverage",
|
||||||
|
"context": "coverage",
|
||||||
|
}).encode()
|
||||||
|
req = urllib.request.Request(
|
||||||
|
endpoint,
|
||||||
|
data=body,
|
||||||
|
headers={
|
||||||
|
"Authorization": f"token {token}",
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
},
|
||||||
|
method="POST",
|
||||||
|
)
|
||||||
|
with urllib.request.urlopen(req) as resp:
|
||||||
|
print(f"Posted coverage status: {pct}% (HTTP {resp.status})")
|
||||||
|
|
||||||
|
|
||||||
|
def main() -> None:
|
||||||
|
if "--post" in sys.argv:
|
||||||
|
path = sys.argv[sys.argv.index("--post") + 1]
|
||||||
|
text = open(path).read()
|
||||||
|
pct = extract_pct(text)
|
||||||
|
post_status(pct)
|
||||||
|
else:
|
||||||
|
text = sys.stdin.read()
|
||||||
|
pct = extract_pct(text)
|
||||||
|
print(TEMPLATE.format(pct=pct, color=color_for(pct)))
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
|
|||||||
Reference in New Issue
Block a user