jira-ai-fixer/docs/DEVELOPER_GUIDE.md

230 lines
8.5 KiB
Markdown

# JIRA AI Fixer - Developer Guide
## Overview
JIRA AI Fixer is a universal AI-powered issue analysis engine that integrates with multiple issue tracking systems to automatically analyze support cases and suggest code fixes.
## Architecture
```
┌─────────────────────────────────────────────────────────────────┐
│ JIRA AI Fixer │
├─────────────────────────────────────────────────────────────────┤
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
│ │TicketHub │ │ JIRA │ │ServiceNow│ │ Zendesk │ ... │
│ │ Webhook │ │ Webhook │ │ Webhook │ │ Webhook │ │
│ └────┬─────┘ └────┬─────┘ └────┬─────┘ └────┬─────┘ │
│ │ │ │ │ │
│ └─────────────┴──────┬──────┴─────────────┘ │
│ │ │
│ ┌───────▼───────┐ │
│ │ Normalizer │ (Adapter Pattern) │
│ └───────┬───────┘ │
│ │ │
│ ┌───────▼───────┐ │
│ │ Analyzer │ (LLM + Code Analysis) │
│ └───────┬───────┘ │
│ │ │
│ ┌─────────────┼─────────────┐ │
│ │ │ │ │
│ ┌──────▼─────┐ ┌─────▼─────┐ ┌────▼────┐ │
│ │ Database │ │ PR Gen │ │Callback │ │
│ │ PostgreSQL │ │ Gitea │ │ to Src │ │
│ └────────────┘ └───────────┘ └─────────┘ │
└─────────────────────────────────────────────────────────────────┘
```
## Tech Stack
- **Language**: Python 3.11
- **Framework**: FastAPI (async)
- **Database**: PostgreSQL 15
- **LLM**: OpenRouter API (Llama 3.3 70B free tier)
- **Code Hosting**: Gitea (self-hosted)
## Project Structure
```
jira-ai-fixer/
├── api/
│ └── main_v3.py # Main application (monolith)
├── docs/
│ ├── DEVELOPER_GUIDE.md
│ ├── USER_GUIDE.md
│ └── ARCHITECTURE.md
└── README.md
```
## Key Components
### 1. Webhook Adapters
Each supported system has a dedicated adapter that normalizes payloads:
```python
def normalize_jira(payload: dict) -> Optional[NormalizedIssue]:
"""Normalize JIRA webhook payload"""
issue = payload.get("issue", {})
fields = issue.get("fields", {})
return NormalizedIssue(
external_id=str(issue.get("id")),
external_key=issue.get("key"),
source="jira",
title=fields.get("summary"),
description=fields.get("description"),
callback_url=f"{base_url}/rest/api/2/issue/{issue.get('key')}/comment"
)
```
### 2. Analysis Pipeline
```python
async def analyze_issue(issue_id: int, issue: NormalizedIssue):
# 1. Fetch source code from repositories
cobol_files = await fetch_cobol_files()
# 2. Build LLM prompt
prompt = build_analysis_prompt(issue, cobol_files)
# 3. Call LLM API
analysis = await call_llm(prompt)
# 4. Parse response
result = parse_analysis(analysis)
# 5. Create fix branch and PR
pr_info = await create_fix_branch_and_pr(issue, result)
# 6. Post back to source system
await post_analysis_to_source(issue, result, pr_info)
```
### 3. Callback System
Results are posted back to the source system in their native format:
| System | Method | Format |
|--------|--------|--------|
| TicketHub | POST /tickets/{id}/comments | `{"author": "...", "content": "..."}` |
| JIRA | POST /rest/api/2/issue/{key}/comment | `{"body": "..."}` |
| ServiceNow | PATCH /api/now/table/incident/{sys_id} | `{"work_notes": "..."}` |
| Zendesk | PUT /api/v2/tickets/{id}.json | `{"ticket": {"comment": {...}}}` |
| Azure DevOps | POST /workitems/{id}/comments | `{"text": "..."}` |
| GitHub | POST /repos/.../issues/{n}/comments | `{"body": "..."}` |
## Adding a New Integration
1. Create normalizer function:
```python
def normalize_newsystem(payload: dict) -> Optional[NormalizedIssue]:
# Extract fields from payload
return NormalizedIssue(
external_id=...,
external_key=...,
source="newsystem",
title=...,
description=...,
callback_url=...
)
```
2. Add webhook endpoint:
```python
@app.post("/api/webhook/newsystem")
async def webhook_newsystem(payload: dict, background_tasks: BackgroundTasks):
issue = normalize_newsystem(payload)
if not issue:
return WebhookResponse(status="ignored", message="Event not handled")
issue_id = await save_and_queue_issue(issue, background_tasks)
return WebhookResponse(status="accepted", issue_id=issue_id)
```
3. Add callback format in `post_analysis_to_source()`:
```python
elif issue.source == "newsystem":
await client.post(issue.callback_url, json={...})
```
## Environment Variables
| Variable | Description | Default |
|----------|-------------|---------|
| `DATABASE_URL` | PostgreSQL connection string | `postgresql://jira:jira_secret_2026@postgres:5432/jira_fixer` |
| `OPENROUTER_API_KEY` | OpenRouter API key for LLM | (empty = mock mode) |
| `GITEA_URL` | Gitea instance URL | `https://gitea.startdata.com.br` |
| `GITEA_TOKEN` | Gitea API token | (empty) |
| `COBOL_REPO` | Default repository to analyze | `startdata/cobol-sample-app` |
## API Endpoints
### Webhooks
| Endpoint | Description |
|----------|-------------|
| `POST /api/webhook/tickethub` | TicketHub webhooks |
| `POST /api/webhook/jira` | JIRA webhooks |
| `POST /api/webhook/servicenow` | ServiceNow webhooks |
| `POST /api/webhook/zendesk` | Zendesk webhooks |
| `POST /api/webhook/azure-devops` | Azure DevOps webhooks |
| `POST /api/webhook/github` | GitHub Issues webhooks |
| `POST /api/webhook/gitlab` | GitLab Issues webhooks |
| `POST /api/webhook/generic` | Generic webhook format |
### Management
| Endpoint | Description |
|----------|-------------|
| `GET /api/health` | Health check |
| `GET /api/issues` | List issues |
| `GET /api/issues/{id}` | Get issue details |
| `GET /api/integrations` | List integrations |
| `GET /api/stats` | Dashboard statistics |
## Running Locally
```bash
# Install dependencies
pip install fastapi uvicorn httpx asyncpg pydantic
# Run with PostgreSQL
export DATABASE_URL="postgresql://user:pass@localhost:5432/jira_fixer"
uvicorn main:app --reload --port 8000
```
## Testing Webhooks
```bash
# Test TicketHub webhook
curl -X POST http://localhost:8000/api/webhook/tickethub \
-H "Content-Type: application/json" \
-d '{
"event": "ticket.created",
"timestamp": "2026-02-18T18:00:00Z",
"data": {
"id": 1,
"key": "SUPP-1",
"title": "Test issue",
"description": "Test description"
}
}'
# Test generic webhook
curl -X POST http://localhost:8000/api/webhook/generic \
-H "Content-Type: application/json" \
-d '{
"id": "123",
"key": "CUSTOM-1",
"title": "Custom issue",
"description": "From custom system",
"source": "my-system",
"callback_url": "https://my-system.com/api/issues/123/comments"
}'
```
## License
MIT License - StartData 2026