chore: import upstream snapshot with attribution

This commit is contained in:
wehub-resource-sync
2026-07-13 12:42:18 +08:00
commit 05f60106aa
288 changed files with 76871 additions and 0 deletions
+62
View File
@@ -0,0 +1,62 @@
#!/usr/bin/env python3
"""Check whether this Python can reach PyPI (same path pip/pipx use for hatchling, etc.).
If TLS to pypi.org fails (e.g. Errno 9 in some IDE terminals), a user-wide
install from a git checkout may still work via uv (different downloader):
uv tool install /path/to/code-review-graph --force
Run: python3 scripts/diagnose_pypi_connectivity.py
"""
from __future__ import annotations
import json
import os
import socket
import ssl
import sys
import time
import urllib.error
import urllib.request
def main() -> int:
ok_tls = _try_tls_pypi()
ok_url = _try_urllib()
if ok_tls and ok_url:
print("PyPI check: OK (this Python can use HTTPS to pypi.org).")
return 0
print("PyPI check: FAILED (pip/pipx may be unable to download build deps like hatchling).")
print("Workaround: from the repo root, with https://github.com/astral-sh/uv installed:")
print(' uv tool install . --force')
print("Or run pipx from macOS Terminal.app (outside the IDE) if the failure is terminal-specific.")
return 1
def _try_tls_pypi() -> bool:
try:
ctx = ssl.create_default_context()
with socket.create_connection(("pypi.org", 443), timeout=15) as sock:
with ctx.wrap_socket(sock, server_hostname="pypi.org") as tsock:
return bool(tsock.version())
except OSError as e:
print(f" TLS pypi.org:443 -> {e!r}", file=sys.stderr)
return False
def _try_urllib() -> bool:
try:
req = urllib.request.Request(
"https://pypi.org/simple/hatchling/",
headers={"User-Agent": "code-review-graph-diagnostic/1.0"},
)
with urllib.request.urlopen(req, timeout=30) as resp:
resp.read(256)
return True
except (urllib.error.URLError, OSError) as e:
print(f" urllib hatchling index -> {e!r}", file=sys.stderr)
return False
if __name__ == "__main__":
raise SystemExit(main())
+333
View File
@@ -0,0 +1,333 @@
#!/usr/bin/env python3
"""Render a risk-scored PR comment from ``code-review-graph detect-changes`` JSON.
Reads the JSON document printed by ``code-review-graph detect-changes
--base <ref>`` (the full, non ``--brief`` output) and emits GitHub-flavoured
markdown suitable for a sticky pull-request comment. Also implements the
risk gate behind the composite action's ``fail-on-risk`` input.
The first line of the rendered body is a hidden HTML marker so the action
can find and update its own comment instead of posting a new one each run.
Exit codes:
0 rendered successfully (gate passed or disabled)
2 the input file could not be read
3 risk gate breached (``--fail-on-risk high|critical``)
"""
from __future__ import annotations
import argparse
import json
import logging
import re
import sys
from pathlib import Path
from typing import Any
logger = logging.getLogger("render_pr_comment")
MARKER = "<!-- code-review-graph-report -->"
REPO_URL = "https://github.com/tirth8205/code-review-graph"
FOOTER = (
f"*Powered by [code-review-graph]({REPO_URL}) — "
"local-first analysis; no code leaves the CI runner.*"
)
# Risk-level cutoffs over analyze_changes' 0.0-1.0 risk_score.
RISK_THRESHOLDS: dict[str, float] = {"critical": 0.85, "high": 0.7, "medium": 0.4}
_CONTROL_CHARS = re.compile(r"[\x00-\x08\x0b\x0c\x0e-\x1f\x7f]")
_MAX_CELL = 120
# GitHub rejects comment bodies over 65,536 characters; leave headroom.
_MAX_BODY = 60_000
def risk_level(score: float) -> str:
"""Map a 0.0-1.0 risk score to a named level."""
if score >= RISK_THRESHOLDS["critical"]:
return "critical"
if score >= RISK_THRESHOLDS["high"]:
return "high"
if score >= RISK_THRESHOLDS["medium"]:
return "medium"
return "low"
def md_escape(value: Any, limit: int = _MAX_CELL) -> str:
"""Escape a value for safe inclusion in markdown tables and lists.
Strips control characters, collapses newlines, escapes table/markup
characters, and caps the length. Graph node names are already sanitized
by ``_sanitize_name`` server-side; this is the defensive second layer
for fields (like file paths) that are not.
"""
text = str(value)
text = _CONTROL_CHARS.sub("", text)
text = text.replace("\r", " ").replace("\n", " ")
text = text.replace("\\", "\\\\")
for ch in ("|", "`", "*", "_", "[", "]", "<", ">"):
text = text.replace(ch, "\\" + ch)
if len(text) > limit:
text = text[: limit - 3] + "..."
return text
def _location(entry: dict[str, Any]) -> str:
"""Format ``file:line`` for a node-ish dict (file_path/file + line_start)."""
file_path = entry.get("file_path") or entry.get("file") or "?"
line_start = entry.get("line_start")
if line_start:
return f"{md_escape(file_path)}:{line_start}"
return md_escape(file_path)
def _functions_table(
priorities: list[dict[str, Any]],
gap_names: set[str],
max_functions: int,
) -> list[str]:
lines = [
"### Risk-scored changes",
"",
"| Risk | Level | Symbol | Location | Tested |",
"| ---: | :--- | :--- | :--- | :---: |",
]
for entry in priorities[:max_functions]:
score = float(entry.get("risk_score") or 0.0)
name = entry.get("qualified_name") or entry.get("name") or "?"
if entry.get("is_test"):
tested = "(test)"
elif name in gap_names:
tested = "no"
else:
tested = "yes"
lines.append(
f"| {score:.2f} | {risk_level(score)} | {md_escape(name)} "
f"| {_location(entry)} | {tested} |"
)
if len(priorities) > max_functions:
lines.append("")
lines.append(f"...and {len(priorities) - max_functions} more changed symbol(s).")
return lines
def _flows_section(flows: list[dict[str, Any]], max_flows: int) -> list[str]:
lines = ["### Affected execution flows", ""]
for flow in flows[:max_flows]:
name = md_escape(flow.get("name") or "?")
criticality = flow.get("criticality")
crit_txt = (
f"criticality {float(criticality):.2f}"
if criticality is not None
else "criticality n/a"
)
node_count = flow.get("node_count", "?")
file_count = flow.get("file_count", "?")
lines.append(
f"- **{name}** — {crit_txt}, {node_count} node(s) across {file_count} file(s)"
)
if len(flows) > max_flows:
lines.append(f"- ...and {len(flows) - max_flows} more affected flow(s)")
return lines
def _gaps_section(gaps: list[dict[str, Any]], max_gaps: int = 5) -> list[str]:
lines = ["### Test gaps", ""]
seen: set[str] = set()
shown: list[dict[str, Any]] = []
for gap in gaps:
name = str(gap.get("qualified_name") or gap.get("name") or "?")
if name in seen:
continue
seen.add(name)
shown.append(gap)
if len(shown) >= max_gaps:
break
for gap in shown:
name = gap.get("qualified_name") or gap.get("name") or "?"
lines.append(f"- {md_escape(name)} ({_location(gap)})")
remaining = len(gaps) - len(shown)
if remaining > 0:
lines.append(f"- ...and {remaining} more without direct tests")
return lines
def render_markdown(
report: dict[str, Any],
*,
max_functions: int = 10,
max_flows: int = 5,
) -> str:
"""Render the detect-changes JSON report as a markdown PR comment."""
score = float(report.get("risk_score") or 0.0)
changed = report.get("changed_functions") or []
flows = report.get("affected_flows") or []
gaps = report.get("test_gaps") or []
priorities = report.get("review_priorities") or changed
gap_names = {
str(g.get("qualified_name") or g.get("name") or "") for g in gaps
}
lines: list[str] = [MARKER, "", "## code-review-graph review", ""]
lines.append(
f"**Overall risk: {score:.2f} ({risk_level(score).upper()})** — "
f"{len(changed)} changed function(s)/class(es), "
f"{len(flows)} affected flow(s), {len(gaps)} test gap(s)"
)
if priorities:
lines.append("")
lines.extend(_functions_table(priorities, gap_names, max_functions))
if flows:
lines.append("")
lines.extend(_flows_section(flows, max_flows))
if gaps:
lines.append("")
lines.extend(_gaps_section(gaps))
savings = report.get("context_savings") or {}
saved_tokens = savings.get("saved_tokens")
saved_percent = savings.get("saved_percent")
if saved_tokens and saved_percent is not None:
lines.append("")
lines.append(
f"**Token savings:** this graph-backed report used ~{int(saved_tokens):,} "
f"fewer tokens (~{int(saved_percent)}%) than reading every changed file in "
"full (estimated, chars/4 approximation)."
)
if report.get("functions_truncated"):
lines.append("")
lines.append(
"> Note: analysis was capped at the configured maximum number of "
"changed functions (set `CRG_MAX_CHANGED_FUNCS` to adjust)."
)
lines.extend(["", "---", "", FOOTER])
body = "\n".join(lines)
if len(body) > _MAX_BODY:
body = body[:_MAX_BODY] + "\n\n*Report truncated.*\n\n" + FOOTER
return body
def render_no_changes() -> str:
"""Fallback comment for when detect-changes finds nothing analyzable."""
return "\n".join(
[
MARKER,
"",
"## code-review-graph review",
"",
"No analyzable code changes detected against the base branch.",
"",
"---",
"",
FOOTER,
]
)
def load_report(text: str) -> dict[str, Any] | None:
"""Parse detect-changes output; None when it is not a JSON object.
``detect-changes`` prints the plain string ``No changes detected.``
instead of JSON when the diff is empty, so non-JSON input is expected.
"""
try:
data = json.loads(text)
except json.JSONDecodeError:
return None
if not isinstance(data, dict):
return None
return data
def build_arg_parser() -> argparse.ArgumentParser:
parser = argparse.ArgumentParser(description=__doc__.splitlines()[0])
parser.add_argument(
"--input",
default="-",
help="Path to detect-changes JSON output, or '-' for stdin (default).",
)
parser.add_argument(
"--output",
default="-",
help="Path to write the markdown comment, or '-' for stdout (default).",
)
parser.add_argument(
"--fail-on-risk",
choices=("none", "high", "critical"),
default="none",
help="Exit 3 when the overall risk score reaches this level "
"(high >= 0.70, critical >= 0.85). Default: none.",
)
parser.add_argument(
"--max-functions",
type=int,
default=10,
help="Maximum rows in the risk table (default: 10).",
)
parser.add_argument(
"--max-flows",
type=int,
default=5,
help="Maximum affected flows listed (default: 5).",
)
parser.add_argument(
"--quiet",
action="store_true",
help="Skip writing the markdown body (gate-only mode).",
)
return parser
def main(argv: list[str] | None = None) -> int:
logging.basicConfig(level=logging.INFO, format="%(levelname)s: %(message)s")
args = build_arg_parser().parse_args(argv)
if args.input == "-":
text = sys.stdin.read()
else:
try:
text = Path(args.input).read_text(encoding="utf-8")
except OSError as exc:
logger.error("Cannot read input file %s: %s", args.input, exc)
return 2
report = load_report(text)
if report is None:
body = render_no_changes()
else:
body = render_markdown(
report,
max_functions=args.max_functions,
max_flows=args.max_flows,
)
if not args.quiet:
if args.output == "-":
sys.stdout.write(body + "\n")
else:
try:
Path(args.output).write_text(body + "\n", encoding="utf-8")
except OSError as exc:
logger.error("Cannot write output file %s: %s", args.output, exc)
return 2
if args.fail_on_risk != "none" and report is not None:
score = float(report.get("risk_score") or 0.0)
threshold = RISK_THRESHOLDS[args.fail_on_risk]
if score >= threshold:
logger.error(
"Risk gate breached: overall risk %.2f >= %s threshold %.2f",
score,
args.fail_on_risk,
threshold,
)
return 3
return 0
if __name__ == "__main__":
sys.exit(main())