Skip to content

Commit 238ea90

Browse files
committed
EX-329: added jira comment integration v1
1 parent 246219e commit 238ea90

File tree

4 files changed

+122
-1
lines changed

4 files changed

+122
-1
lines changed

src/code_review_agent/cli.py

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
from . import bitbucket_client, github_client
1212
from . import git_utils, context_builder, reviewer
1313
from . import jira_client
14+
from . import relevance_assessor
1415
from .models import IssueType, CodeIssue
1516

1617
def prioritize_changed_files(changed_files_map: Dict[str, str]) -> List[List[str]]:
@@ -328,6 +329,27 @@ def review(
328329
if issue.suggestion:
329330
logging.info(f" 💡 Suggestion: {issue.suggestion}")
330331
logging.info(f" ```\n {issue.suggestion}\n ```")
332+
333+
if task_id:
334+
logging.info("\n--- Assessing Task Relevance ---")
335+
336+
review_summary = f"Found {len(all_issues)} issue(s)."
337+
338+
relevance = relevance_assessor.assess_relevance(
339+
jira_details=jira_details_text,
340+
commit_messages=commit_messages,
341+
diff_text="\n".join(changed_files_map.values()),
342+
review_summary=review_summary,
343+
llm_config=llm_config
344+
)
345+
346+
if relevance:
347+
comment_body = (
348+
f"🤖 **AI Assessment Complete for this PR**\n\n"
349+
f"/!\\ The code changes have a **{relevance.score}%** relevance score to this task.\n\n"
350+
f"**Justification:** {relevance.justification}"
351+
)
352+
jira_client.add_comment(task_id, comment_body)
331353

332354

333355
if not all_issues:

src/code_review_agent/jira_client.py

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,4 +45,17 @@ def get_task_details(task_id: str) -> dict | None:
4545
}
4646
except Exception as e:
4747
logger.warning(f"Could not fetch details for Jira task {task_id}. Error: {e}")
48-
return None
48+
return None
49+
50+
def add_comment(task_id: str, comment: str):
51+
"""Adds a comment to a Jira issue."""
52+
client = _get_jira_client()
53+
if not client or not task_id:
54+
return
55+
56+
logger.info(f"Adding comment to Jira task {task_id}...")
57+
try:
58+
client.add_comment(task_id, comment)
59+
logger.info("✅ Successfully added comment to Jira.")
60+
except Exception as e:
61+
logger.error(f"Failed to add comment to Jira task {task_id}. Error: {e}")

src/code_review_agent/models.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,3 +33,16 @@ class ReviewResult(BaseModel):
3333

3434
def is_ok(self) -> bool:
3535
return not self.issues
36+
37+
38+
class TaskRelevance(BaseModel):
39+
score: int = Field(
40+
...,
41+
description="A score from 0 to 100 representing how related the code change is to the Jira task.",
42+
ge=0,
43+
le=100
44+
)
45+
justification: str = Field(
46+
...,
47+
description="A brief, one-sentence justification for the score."
48+
)
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
import json
2+
import logging
3+
from pydantic import ValidationError
4+
from .models import TaskRelevance
5+
from .llm_client import get_client
6+
7+
logger = logging.getLogger(__name__)
8+
9+
def assess_relevance(
10+
jira_details: str,
11+
commit_messages: str,
12+
diff_text: str,
13+
review_summary: str,
14+
llm_config: dict,
15+
) -> TaskRelevance | None:
16+
17+
client = get_client(llm_config)
18+
19+
model = llm_config.get('models', {}).get('assessor', 'google/gemini-flash-1.5')
20+
21+
system_prompt = """
22+
You are an expert project manager AI. Your task is to assess how relevant a code change is to its associated Jira task.
23+
You MUST provide a score from 0 to 100 and a brief justification.
24+
25+
CRITICAL OUTPUT FORMATTING RULE:
26+
Your entire response MUST be a single, valid JSON object with two keys: "score" (integer, 0-100) and "justification" (string).
27+
Do not add any other text or explanations.
28+
"""
29+
30+
user_prompt = f"""
31+
Please assess the relevance of the following code changes to the Jira task.
32+
33+
{jira_details}
34+
35+
**Commit Messages:**
36+
```
37+
{commit_messages}
38+
```
39+
40+
**Summary of Code Changes (Git Diff):**
41+
```diff
42+
{diff_text}
43+
```
44+
45+
**AI Code Review Summary:**
46+
```
47+
{review_summary}
48+
```
49+
50+
Based on all this information, rate from 0 to 100% how related the code change is to the Jira task.
51+
Return your assessment as a raw JSON object string.
52+
"""
53+
54+
try:
55+
response = client.chat.completions.create(
56+
model=model,
57+
messages=[
58+
{"role": "system", "content": system_prompt},
59+
{"role": "user", "content": user_prompt},
60+
]
61+
)
62+
raw_response_text = response.choices.message.content.strip()
63+
64+
try:
65+
parsed_json = json.loads(raw_response_text, strict=False)
66+
return TaskRelevance(**parsed_json)
67+
except (json.JSONDecodeError, ValidationError) as e:
68+
logger.warning(f"Failed to parse relevance assessment response. Error: {e}")
69+
return None
70+
71+
except Exception as e:
72+
logger.error(f"Critical error during relevance assessment LLM call: {e}", exc_info=True)
73+
return None

0 commit comments

Comments
 (0)