jira-ai-fixer/docs/DEVELOPER_GUIDE.md

8.5 KiB

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:

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

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:
def normalize_newsystem(payload: dict) -> Optional[NormalizedIssue]:
    # Extract fields from payload
    return NormalizedIssue(
        external_id=...,
        external_key=...,
        source="newsystem",
        title=...,
        description=...,
        callback_url=...
    )
  1. Add webhook endpoint:
@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)
  1. Add callback format in post_analysis_to_source():
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

# 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

# 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