Pipeline/backend/app/services/issue_template.py

110 lines
2.5 KiB
Python
Raw Permalink Normal View History

2026-05-22 01:44:39 -05:00
"""Standard issue body template for Forgejo issues created via Pipeline."""
from __future__ import annotations
ISSUE_TEMPLATE = """\
## Summary
Briefly describe the issue in 1 to 3 sentences.
## Problem
Explain what is wrong, missing, confusing, or broken.
## Affected area
Example:
- UI page:
- Backend service:
- API:
- Database:
- Auth:
- CI/CD:
- Docs:
## Affected files
Known or suspected files:
- `path/to/file`
- `path/to/other-file`
## Affected routes or endpoints
Known or suspected routes:
- `GET /example`
- `POST /api/example`
## Steps to reproduce
1.
2.
3.
## Expected behavior
Describe what should happen.
## Actual behavior
Describe what actually happens.
## Error output, logs, or screenshots
Paste relevant logs only. Redact secrets.
```text
Paste logs here
```\
"""
def _section(heading: str, body: str) -> str:
return f"## {heading}\n{body.strip()}"
def _code_block(content: str, lang: str = "text") -> str:
return f"```{lang}\n{content.strip()}\n```"
def render_error_report(
*,
summary: str,
problem: str,
affected_area: str | None = None,
affected_files: list[str] | None = None,
affected_routes: list[str] | None = None,
actual_behavior: str | None = None,
stack_trace: str | None = None,
reporter: str | None = None,
) -> str:
"""Render the standard template from structured error data."""
parts: list[str] = []
if reporter:
parts.append(f"_Reported by: {reporter}_\n")
parts.append(_section("Summary", summary))
parts.append(_section("Problem", problem))
area_body = affected_area.strip() if affected_area else "_Not identified._"
parts.append(_section("Affected area", area_body))
if affected_files:
files_body = "\n".join(f"- `{f}`" for f in affected_files)
else:
files_body = "_Not identified._"
parts.append(_section("Affected files", files_body))
if affected_routes:
routes_body = "\n".join(f"- `{r}`" for r in affected_routes)
else:
routes_body = "_Not identified._"
parts.append(_section("Affected routes or endpoints", routes_body))
parts.append(_section("Steps to reproduce", "_Not provided._"))
parts.append(_section("Expected behavior", "_Not provided._"))
actual = actual_behavior or problem
parts.append(_section("Actual behavior", actual))
if stack_trace:
log_body = _code_block(stack_trace)
else:
log_body = "_No output provided._"
parts.append(_section("Error output, logs, or screenshots", log_body))
return "\n\n".join(parts)