Files
git-auto-comment/git-auto-comment.py
T
Trez.One 0f936a6047
Renovate / renovate (push) Has been cancelled
...
2025-10-23 14:23:49 -04:00

118 lines
4.0 KiB
Python
Executable File

#!/usr/bin/env python3
import os
import sys
import re
import json
import requests
# --- ANSI color helpers ---
def color(text, code):
return f"\033[{code}m{text}\033[0m"
def green(text): return color(text, "32")
def red(text): return color(text, "31")
def yellow(text): return color(text, "33")
def cyan(text): return color(text, "36")
def bold(text): return color(text, "1")
# --- Inputs ---
platform = os.environ.get("PLATFORM", "github").lower()
token = os.environ.get("TOKEN")
owner = os.environ.get("REPO_OWNER", os.environ.get("GITHUB_REPOSITORY_OWNER"))
repo = os.environ.get("REPO_NAME", os.environ.get("GITHUB_REPOSITORY"))
pr_index = os.environ.get("PR_INDEX")
api_url = os.environ.get("API_URL", os.environ.get("GITHUB_API_URL"))
diff_text = os.environ.get("DIFF")
comment_template = os.environ.get("COMMENT_TEMPLATE", "Auto-comment: changed line -> {line}")
debug_mode = os.environ.get("DEBUG", "false").lower() == "true"
if not token or not pr_index:
print(red("❌ TOKEN and PR_INDEX are required."))
sys.exit(1)
# --- Build URLs and headers ---
def build_comment_url():
if platform == "github":
return f"https://api.github.com/repos/{owner}/{repo}/issues/{pr_index}/comments"
elif platform == "gitea":
if not api_url:
print(red("❌ API_URL required for Gitea platform."))
sys.exit(1)
return f"{api_url}/repos/{owner}/{repo}/pulls/{pr_index}/reviews"
else:
print(red(f"❌ Unsupported platform: {platform}"))
sys.exit(1)
def build_headers():
return {
"Authorization": f"token {token}",
"Content-Type": "application/json",
"Accept": "application/json",
}
# --- POST comment ---
def post_comment(body_text):
url = build_comment_url()
headers = build_headers()
payload = {"body": body_text}
if debug_mode:
preview = (body_text[:400] + "... [truncated]") if len(body_text) > 400 else body_text
print(bold(cyan("🧩 DEBUG MODE ENABLED")))
print(f" {yellow('Platform:')} {platform}")
print(f" {yellow('Repo:')} {owner}/{repo}")
print(f" {yellow('PR Index:')} {pr_index}")
print(f" {yellow('Endpoint:')} {url}")
print(f" {yellow('Comment size:')} {len(body_text)} characters")
print(f" {yellow('Payload preview:')} {json.dumps(payload)[:200]}{'... [truncated]' if len(json.dumps(payload))>200 else ''}")
print(f" {yellow('Comment preview:')}\n{preview}\n{'-'*60}")
try:
resp = requests.post(url, headers=headers, json=payload, timeout=60)
if resp.status_code in (200, 201):
print(green(f"✅ Comment posted successfully to {platform.capitalize()}!"))
else:
print(red(f"❌ Failed to post comment ({resp.status_code}):"))
print(resp.text)
sys.exit(1)
except requests.exceptions.RequestException as e:
print(red(f"❌ Request error: {e}"))
sys.exit(1)
# --- No diff provided ---
if not diff_text:
body = comment_template.replace("{line}", "").replace("{lines}", "")
post_comment(body)
sys.exit(0)
# --- Parse unified diff ---
diff_files = {}
current_file = None
new_line_num = 0
for line in diff_text.splitlines():
if line.startswith("+++ b/"):
current_file = line[6:].strip()
diff_files[current_file] = []
new_line_num = 0
elif line.startswith("@@"):
m = re.match(r"@@ -\d+(?:,\d+)? \+(\d+)(?:,(\d+))? @@", line)
if m:
new_line_num = int(m.group(1)) - 1
elif line.startswith("+") and not line.startswith("+++"):
new_line_num += 1
content = line[1:]
diff_files[current_file].append((new_line_num, content))
elif not line.startswith("-"):
new_line_num += 1
# --- Post combined comment per file ---
for file_path, lines in diff_files.items():
if not lines:
continue
all_lines_content = "\n".join([line_content for _, line_content in lines])
body = comment_template.replace("{lines}", all_lines_content)
post_comment(body)
print(green("🎉 All comments posted successfully."))