Skip to content

Commit bde0c57

Browse files
Oxygen56claude
andcommitted
feat: add Asana ticket detection to ticket compliance check
Adds support for detecting Asana task references in PR descriptions and branch names. Supports both full URLs and ASANA-123456789 shorthand format. - find_asana_tickets() extracts Asana task URLs from text - Asana tickets are included in the compliance check's related tickets - Graceful handling: Asana URLs are shown with a placeholder body since they cannot be fetched via the GitHub API Fixes #2002 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
1 parent a4fb20c commit bde0c57

1 file changed

Lines changed: 49 additions & 0 deletions

File tree

pr_agent/tools/ticket_pr_compliance_check.py

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,37 @@ def find_jira_tickets(text):
3535
return list(tickets)
3636

3737

38+
# Compiled Asana task patterns
39+
_ASANA_TASK_URL_PATTERN = re.compile(
40+
r'https://app\.asana\.com/0/(\d+)/(\d+)'
41+
)
42+
_ASANA_TASK_SHORT_PATTERN = re.compile(
43+
r'\b(?:ASANA|asana)[- ]?(\d{12,20})\b'
44+
r'|https://app\.asana\.com/0/\d+/\d+'
45+
)
46+
47+
48+
def find_asana_tickets(text: str) -> list:
49+
"""Extract Asana task references from text.
50+
51+
Supports both full Asana URLs and shorthand ``ASANA-123456789012``
52+
format. Returns a list of unique task URLs.
53+
54+
Args:
55+
text: The text to scan for Asana task references.
56+
57+
Returns:
58+
A list of Asana task URLs.
59+
"""
60+
tickets = set()
61+
for match in re.finditer(r'https://app\.asana\.com/0/(\d+)/(\d+)', text):
62+
tickets.add(match.group(0))
63+
for match in re.finditer(r'(?:^|[^A-Za-z0-9])(?:ASANA|asana)[- ]?(\d{12,20})', text):
64+
task_id = match.group(1)
65+
tickets.add(f"https://app.asana.com/0/0/{task_id}")
66+
return sorted(tickets)
67+
68+
3869
def extract_ticket_links_from_pr_description(pr_description, repo_path, base_url_html='https://github.com'):
3970
"""
4071
Extract all ticket links from PR description
@@ -123,6 +154,13 @@ async def extract_tickets(git_provider):
123154
if link not in seen:
124155
seen.add(link)
125156
merged.append(link)
157+
158+
# Also detect Asana ticket references in the PR description
159+
asana_tickets = find_asana_tickets(user_description)
160+
for link in asana_tickets:
161+
if link not in seen:
162+
seen.add(link)
163+
merged.append(link)
126164
if len(merged) > 3:
127165
get_logger().info(f"Too many tickets (description + branch): {len(merged)}")
128166
tickets = merged[:3]
@@ -133,6 +171,17 @@ async def extract_tickets(git_provider):
133171
if tickets:
134172

135173
for ticket in tickets:
174+
# Skip Asana URLs — these are external references,
175+
# included for visibility but cannot be fetched via GitHub API.
176+
if "app.asana.com" in ticket:
177+
tickets_content.append({
178+
"title": f"Asana Task: {ticket}",
179+
"url": ticket,
180+
"body": ("Asana task referenced in PR description. "
181+
"Fetch task details from Asana for full context."),
182+
})
183+
continue
184+
136185
repo_name, original_issue_number = git_provider._parse_issue_url(ticket)
137186

138187
try:

0 commit comments

Comments
 (0)