Skip to content

Commit 3b70f20

Browse files
committed
EX-329: added remove comment from jira
1 parent 62c36fb commit 3b70f20

File tree

2 files changed

+91
-8
lines changed

2 files changed

+91
-8
lines changed

src/code_review_agent/cli.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -466,8 +466,8 @@ def assess(
466466
return
467467

468468
comment_body = (
469-
f"🤖 **AI Assessment Complete**\n\n"
470-
f"Relevance: **{relevance.score}%**\n\n"
469+
f"🤖 *AI Assessment Complete*\n\n"
470+
f"Relevance: *{relevance.score}%*\n\n"
471471
f"Justification: {relevance.justification}"
472472
)
473473
jira_client.add_comment(task_id, comment_body)

src/code_review_agent/jira_client.py

Lines changed: 89 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -78,18 +78,101 @@ def get_task_details(task_id: str) -> dict | None:
7878
logger.error(f"Failed to connect to Jira: {e}")
7979
return None
8080

81+
def _extract_text_from_adf(body):
82+
"""
83+
Extract plain text from Atlassian Document Format (very simplified).
84+
"""
85+
if isinstance(body, str):
86+
return body
87+
if isinstance(body, dict):
88+
parts = []
89+
for block in body.get("content", []):
90+
for item in block.get("content", []):
91+
txt = item.get("text")
92+
if txt:
93+
parts.append(txt)
94+
return "\n".join(parts)
95+
return ""
96+
97+
def _current_account_id() -> str | None:
98+
try:
99+
jira_url = os.environ["JIRA_URL"].rstrip("/")
100+
auth, headers = _auth_headers()
101+
r = requests.get(f"{jira_url}/rest/api/3/myself", headers=headers, auth=auth, timeout=10)
102+
if r.status_code == 200:
103+
return r.json().get("accountId")
104+
except Exception:
105+
pass
106+
return None
107+
108+
def _remove_previous_ai_comments(jira_url: str, task_id: str, marker: str, account_id: str | None):
109+
auth, headers = _auth_headers()
110+
try:
111+
resp = requests.get(
112+
f"{jira_url}/rest/api/3/issue/{task_id}/comment?maxResults=100",
113+
headers=headers, auth=auth, timeout=20
114+
)
115+
if resp.status_code != 200:
116+
logger.debug(f"[AI Comment] List comments status={resp.status_code}")
117+
return
118+
data = resp.json()
119+
removed = 0
120+
for c in data.get("comments", []):
121+
cid = c.get("id")
122+
author_id = c.get("author", {}).get("accountId")
123+
body_text = _extract_text_from_adf(c.get("body"))
124+
if marker in body_text and (account_id is None or author_id == account_id):
125+
try:
126+
d = requests.delete(
127+
f"{jira_url}/rest/api/3/issue/{task_id}/comment/{cid}",
128+
headers=headers, auth=auth, timeout=15
129+
)
130+
if d.status_code in (204, 200):
131+
removed += 1
132+
else:
133+
logger.debug(f"[AI Comment] Delete {cid} status={d.status_code}")
134+
except Exception as e:
135+
logger.debug(f"[AI Comment] Delete {cid} exception: {e}")
136+
if removed:
137+
logger.info(f"Removed {removed} previous AI comment(s).")
138+
except Exception as e:
139+
logger.debug(f"[AI Comment] Cleanup failed: {e}")
140+
141+
81142
def add_comment(task_id: str, comment: str):
143+
"""
144+
Adds (replaces) AI assessment comment:
145+
- Deletes previous comments containing marker (and authored by this user if detectable)
146+
- Posts a fresh one.
147+
"""
82148
logger.info(f"Adding comment to Jira task {task_id}...")
83149
try:
84150
jira_url = os.environ["JIRA_URL"].rstrip("/")
85151
auth, headers = _auth_headers()
86-
api_url = f"{jira_url}/rest/api/2/issue/{task_id}/comment"
152+
153+
marker = os.getenv("JIRA_AI_COMMENT_TAG", "🤖 AI Assessment")
154+
if marker not in comment:
155+
comment = f"{marker}\n\n{comment}"
156+
157+
account_id = _current_account_id()
158+
_remove_previous_ai_comments(jira_url, task_id, marker, account_id)
159+
160+
# Use v3 first, fallback v2
87161
payload = {"body": comment}
88-
resp = requests.post(api_url, json=payload, headers=headers, auth=auth, timeout=15)
89-
if resp.status_code == 404:
90-
logger.warning(f"Cannot add comment: issue {task_id} not found or no permission (404). Skipping.")
162+
for ver in ("3", "2"):
163+
api_url = f"{jira_url}/rest/api/{ver}/issue/{task_id}/comment"
164+
resp = requests.post(api_url, json=payload, headers=headers, auth=auth, timeout=20)
165+
if resp.status_code == 404:
166+
logger.warning(f"[Jira] 404 on comment POST v{ver} (issue not visible).")
167+
continue
168+
if resp.status_code == 403:
169+
logger.warning(f"[Jira] 403 on comment POST v{ver} (no Add Comments permission).")
170+
continue
171+
if resp.status_code not in (201, 200):
172+
logger.error(f"[Jira] comment POST v{ver} status={resp.status_code} body={resp.text[:160]}")
173+
continue
174+
logger.info("✅ Comment added (replaced previous).")
91175
return
92-
resp.raise_for_status()
93-
logger.info("✅ Successfully added comment to Jira.")
176+
logger.warning("Failed to add comment after trying v3 and v2.")
94177
except Exception as e:
95178
logger.error(f"Failed to add comment to Jira task {task_id}. Error: {e}")

0 commit comments

Comments
 (0)