mirror of
https://github.com/qodo-ai/pr-agent.git
synced 2025-12-12 02:45:18 +00:00
- Implement provider-agnostic push_outputs function supporting stdout, file, and webhook channels - Add FastAPI-based Slack webhook relay server for external integrations - Integrate push_outputs into PR reviewer tool to emit review data - Add configuration section for push_outputs with default disabled state
95 lines
3 KiB
Python
95 lines
3 KiB
Python
"""
|
|
Provider-agnostic push outputs relay for Slack
|
|
|
|
This FastAPI service receives generic PR-Agent push outputs (from [push_outputs]) and relays them
|
|
as Slack Incoming Webhook messages.
|
|
|
|
Usage
|
|
-----
|
|
1) Run the relay (choose one):
|
|
- uvicorn pr_agent.servers.push_outputs_relay:app --host 0.0.0.0 --port 8000
|
|
- python -m pr_agent.servers.push_outputs_relay
|
|
|
|
2) Configure the destination Slack webhook:
|
|
- Set environment variable SLACK_WEBHOOK_URL to your Slack Incoming Webhook URL.
|
|
|
|
3) Point PR-Agent to the relay:
|
|
In your configuration (e.g., .pr_agent.toml or central config), enable generic push outputs:
|
|
|
|
[push_outputs]
|
|
enable = true
|
|
channels = ["webhook"]
|
|
webhook_url = "http://localhost:8000/relay" # adjust host/port if needed
|
|
presentation = "markdown"
|
|
|
|
Security
|
|
--------
|
|
- Keep the relay private or place it behind an auth gateway if exposed externally.
|
|
- You can also wrap this service with a reverse proxy that enforces authentication and rate limits.
|
|
|
|
Notes
|
|
-----
|
|
- The relay is intentionally Slack-specific while living outside the provider-agnostic core.
|
|
- If record['markdown'] is present, it will be used as Slack message text. Otherwise, a JSON fallback
|
|
is generated from record['payload'].
|
|
- Slack supports basic Markdown (mrkdwn). Complex HTML/GitGFM sections may not render perfectly.
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
import json
|
|
import os
|
|
from typing import Any, Dict
|
|
|
|
import requests
|
|
from fastapi import FastAPI, HTTPException
|
|
|
|
app = FastAPI(title="PR-Agent Push Outputs Relay (Slack)")
|
|
|
|
|
|
def _to_slack_text(record: Dict[str, Any]) -> str:
|
|
"""
|
|
Prefer full review markdown; otherwise fallback to a compact JSON of the payload.
|
|
"""
|
|
markdown = record.get("markdown")
|
|
if isinstance(markdown, str) and markdown.strip():
|
|
return markdown
|
|
|
|
payload = record.get("payload") or {}
|
|
try:
|
|
return "```\n" + json.dumps(payload, ensure_ascii=False, indent=2) + "\n```"
|
|
except Exception:
|
|
return str(payload)
|
|
|
|
|
|
@app.post("/relay")
|
|
async def relay(record: Dict[str, Any]):
|
|
slack_url = os.environ.get("SLACK_WEBHOOK_URL", "").strip()
|
|
if not slack_url:
|
|
raise HTTPException(status_code=500, detail="SLACK_WEBHOOK_URL environment variable is not set")
|
|
|
|
text = _to_slack_text(record)
|
|
|
|
body = {
|
|
"text": text,
|
|
"mrkdwn": True,
|
|
}
|
|
|
|
try:
|
|
resp = requests.post(slack_url, json=body, timeout=8)
|
|
if resp.status_code >= 300:
|
|
raise HTTPException(status_code=resp.status_code, detail=f"Slack webhook error: {resp.text}")
|
|
except HTTPException:
|
|
raise
|
|
except Exception as e:
|
|
raise HTTPException(status_code=502, detail=f"Failed to post to Slack: {e}")
|
|
|
|
return {"status": "ok"}
|
|
|
|
|
|
if __name__ == "__main__":
|
|
# Allow running directly: python -m pr_agent.servers.push_outputs_relay
|
|
import uvicorn
|
|
|
|
port = int(os.environ.get("PORT", "8000"))
|
|
uvicorn.run("pr_agent.servers.push_outputs_relay:app", host="0.0.0.0", port=port, reload=False)
|