Add reports, integrations, and utils modules
Some checks failed
CI / test (push) Has been cancelled
CI / build (push) Has been cancelled

This commit is contained in:
2026-02-03 07:01:14 +00:00
parent bcd8907ff9
commit 7a9a3d3d11

View File

@@ -0,0 +1,174 @@
"""Report generator for VibeGuard."""
import json
from datetime import datetime
from pathlib import Path
from typing import Any
from jinja2 import Environment, FileSystemLoader
class ReportGenerator:
"""Generates reports in various formats."""
def __init__(self, template_dir: str | None = None) -> None:
"""Initialize report generator with templates."""
self.template_dir = template_dir or str(
Path(__file__).parent.parent / "templates"
)
self._env = Environment(
loader=FileSystemLoader(self.template_dir),
autoescape=True,
)
def generate_json(
self, issues: list[dict[str, Any]], output_path: str
) -> None:
"""Generate JSON report."""
report = {
"version": "0.1.0",
"timestamp": datetime.utcnow().isoformat(),
"summary": self._generate_summary(issues),
"issues": issues,
}
with open(output_path, "w", encoding="utf-8") as f:
json.dump(report, f, indent=2)
def load_json(self, input_path: str) -> list[dict[str, Any]]:
"""Load issues from JSON file."""
with open(input_path, "r", encoding="utf-8") as f:
data = json.load(f)
return data.get("issues", [])
def generate_html(
self,
issues: list[dict[str, Any]],
output_path: str,
summary: dict[str, int] | None = None,
) -> None:
"""Generate HTML report."""
if summary is None:
summary = self._generate_summary(issues)
template = self._env.get_template("report.html")
html_content = template.render(
title="VibeGuard Analysis Report",
timestamp=datetime.utcnow().isoformat(),
summary=summary,
issues=issues,
total_issues=len(issues),
)
with open(output_path, "w", encoding="utf-8") as f:
f.write(html_content)
def generate_sarif(
self, issues: list[dict[str, Any]], output_path: str
) -> None:
"""Generate SARIF report for GitHub Code Scanning."""
sarif = {
"$schema": "https://raw.githubusercontent.com/oasis-tcs/sarif-spec/master/Schemata/sarif-schema-2.1.0.json",
"version": "2.1.0",
"runs": [
{
"tool": {
"driver": {
"name": "VibeGuard",
"version": "0.1.0",
"informationUri": "https://github.com/vibeguard/vibeguard",
"rules": self._generate_sarif_rules(issues),
}
},
"results": self._generate_sarif_results(issues),
}
],
}
with open(output_path, "w", encoding="utf-8") as f:
json.dump(sarif, f, indent=2)
def _generate_summary(self, issues: list[dict[str, Any]]) -> dict[str, int]:
"""Generate summary statistics."""
summary: dict[str, int] = {
"critical": 0,
"error": 0,
"warning": 0,
"info": 0,
"total": len(issues),
}
for issue in issues:
severity = issue.get("severity", "info")
summary[severity] = summary.get(severity, 0) + 1
return summary
def _generate_sarif_rules(
self, issues: list[dict[str, Any]]
) -> list[dict[str, Any]]:
"""Generate SARIF rule definitions."""
rules: dict[str, dict[str, Any]] = {}
for issue in issues:
rule_id = issue.get("pattern", "UNKNOWN")
if rule_id not in rules:
rules[rule_id] = {
"id": rule_id,
"name": rule_id,
"shortDescription": {
"text": issue.get("message", "Unknown issue")
},
"fullDescription": {
"text": issue.get("suggestion", "")
},
"defaultConfiguration": {
"level": self._severity_to_sarif_level(
issue.get("severity", "warning")
)
},
}
return list(rules.values())
def _generate_sarif_results(
self, issues: list[dict[str, Any]]
) -> list[dict[str, Any]]:
"""Generate SARIF result objects."""
results: list[dict[str, Any]] = []
for issue in issues:
result = {
"ruleId": issue.get("pattern", "UNKNOWN"),
"message": {
"text": issue.get("message", "")
},
"level": self._severity_to_sarif_level(
issue.get("severity", "warning")
),
"locations": [
{
"physicalLocation": {
"artifactLocation": {
"uri": issue.get("file", "")
},
"region": {
"startLine": issue.get("line", 1),
},
}
}
],
}
results.append(result)
return results
def _severity_to_sarif_level(self, severity: str) -> str:
"""Convert VibeGuard severity to SARIF level."""
mapping = {
"critical": "error",
"error": "error",
"warning": "warning",
"info": "note",
}
return mapping.get(severity, "warning")