Skip to content

Commit 2865eb7

Browse files
Merge pull request #441 from Bala-Sakabattula/GDAP-issue
gdap issue fix
2 parents 6a790b4 + f9cacbf commit 2865eb7

4 files changed

Lines changed: 53 additions & 33 deletions

File tree

sync2jira/downstream_issue.py

Lines changed: 33 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323
import operator
2424
import os
2525
import re
26-
from typing import Any, Optional, Union
26+
from typing import Any, Dict, Optional, Union
2727
import unicodedata
2828

2929
from dotenv import load_dotenv
@@ -568,38 +568,46 @@ def _upgrade_jira_issue(client, downstream, issue, config):
568568
attach_link(client, downstream, remote_link)
569569

570570

571-
def match_user(emails: list[str], client: jira.client.JIRA) -> Optional[str]:
572-
"""Match an upstream user to an assignable downstream user and return the
573-
downstream username; return None on failure.
571+
def match_user(emails: list[str], client: jira.client.JIRA) -> Optional[Dict[str, str]]:
572+
"""Match an upstream user to an assignable downstream Jira user.
573+
574+
Returns a dict with ``name`` (display name) and ``accountId`` for Jira Cloud,
575+
or None on failure.
574576
"""
575577

576578
for email in emails:
577579
# Get a list from Jira of users that match the supplied email address.
578-
users = client.search_users(user=email)
580+
# Use query= for Jira Cloud (GDPR strict mode rejects the username param).
581+
users = client.search_users(query=email)
579582

580583
if not users:
581584
continue
582585

583586
if len(users) == 1:
584-
# TODO: We should probably return the ID here, instead.
585-
return users[0].name
587+
u = users[0]
588+
return {
589+
"name": getattr(u, "displayName", None) or "<name-not-available>",
590+
"accountId": getattr(u, "accountId", None),
591+
}
586592

587593
limit = 5
588594
log.warning(
589595
"Found %d Jira users for %r: %s%s",
590596
len(users),
591597
email,
592-
", ".join(u.name for u in users[0:limit]),
598+
", ".join(
599+
getattr(u, "displayName", "<name-not-available>")
600+
for u in users[0:limit]
601+
),
593602
"..." if len(users) > limit else "",
594603
)
595604
for user in users:
596-
# This condition _should_ be true for *all* entries returned, in
597-
# which case we'll just return the first entry; however it appears
598-
# that sometimes Jira returns _all_ assignable users, so do our own
599-
# filtering.
600-
if user.emailAddress == email:
601-
log.info("Found matching user: %r", user.name)
602-
return user.name
605+
# Filter by email when present (can be omitted in Cloud when hidden).
606+
if getattr(user, "emailAddress", None) == email:
607+
name = getattr(user, "displayName", None) or "<no-name-available>"
608+
aid = getattr(user, "accountId", None)
609+
log.info("Found matching user: %r", name)
610+
return {"name": name, "accountId": aid}
603611
else:
604612
log.warning("Found no Jira user which matches %r", email)
605613

@@ -637,11 +645,16 @@ def assign_user(
637645
continue
638646

639647
# Try to match the upstream assignee's emails to a Jira user
640-
match_name = match_user(emails, client)
641-
if match_name:
642-
# Assign the downstream issue to the matched user
643-
downstream.update({"assignee": {"name": match_name}})
644-
log.info("Assigned %s to %r", downstream.key, match_name)
648+
matched = match_user(emails, client)
649+
if matched and matched["accountId"]:
650+
# Jira Cloud assigns by accountId
651+
downstream.update({"assignee": {"accountId": matched["accountId"]}})
652+
log.info(
653+
"Assigned %s to %r,%r",
654+
downstream.key,
655+
matched["name"],
656+
matched["accountId"],
657+
)
645658
return
646659

647660
if issue.assignee:

sync2jira/downstream_pr.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -41,12 +41,12 @@ def format_comment(pr, pr_suffix, client):
4141
:return: Formatted comment
4242
:rtype: String
4343
"""
44-
# Find the pr.reporters JIRA username
45-
ret = client.search_users(pr.reporter)
44+
# Find the pr.reporter's Jira user (use query= for Jira Cloud GDPR strict mode).
45+
ret = client.search_users(query=pr.reporter)
4646
# Loop through ret till we find a match
4747
for user in ret:
48-
if user.displayName == pr.reporter:
49-
reporter = f"[~{user.key}]"
48+
if getattr(user, "displayName", "") == pr.reporter:
49+
reporter = f"[~accountId:{user.accountId}]"
5050
break
5151
else:
5252
reporter = pr.reporter

tests/test_downstream_issue.py

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -516,6 +516,7 @@ def test_assign_user(self, mock_client, mock_rover_lookup):
516516
mock_user = MagicMock()
517517
mock_user.displayName = "mock_assignee"
518518
mock_user.key = "mock_user_key"
519+
mock_user.accountId = "mock-account-id-assign"
519520
mock_client.search_users.return_value = [mock_user]
520521
mock_client.assign_issue.return_value = True
521522
mock_rover_lookup.return_value = ["mock_user@redhat.com"]
@@ -525,11 +526,11 @@ def test_assign_user(self, mock_client, mock_rover_lookup):
525526
issue=self.mock_issue, downstream=self.mock_downstream, client=mock_client
526527
)
527528

528-
# Assert that all calls mocked were called properly
529+
# Assert that all calls mocked were called properly (Jira Cloud: accountId)
529530
self.mock_downstream.update.assert_called_with(
530-
{"assignee": {"name": mock_user.name}}
531+
{"assignee": {"accountId": mock_user.accountId}}
531532
)
532-
mock_client.search_users.assert_called_with(user="mock_user@redhat.com")
533+
mock_client.search_users.assert_called_with(query="mock_user@redhat.com")
533534

534535
@mock.patch("Rover_Lookup.github_username_to_emails")
535536
@mock.patch("jira.client.JIRA")
@@ -542,6 +543,7 @@ def test_assign_user_diacritics(self, mock_client, mock_rover_lookup):
542543
mock_user = MagicMock()
543544
mock_user.displayName = "mock_assignee"
544545
mock_user.key = "mock_user_key"
546+
mock_user.accountId = "mock-account-id-diacritics"
545547
mock_client.search_users.return_value = [mock_user]
546548
mock_client.assign_issue.return_value = True
547549
mock_rover_lookup.return_value = ["mock_user@redhat.com"]
@@ -555,9 +557,9 @@ def test_assign_user_diacritics(self, mock_client, mock_rover_lookup):
555557

556558
# Assert that all calls mocked were called properly
557559
self.mock_downstream.update.assert_called_with(
558-
{"assignee": {"name": mock_user.name}}
560+
{"assignee": {"accountId": mock_user.accountId}}
559561
)
560-
mock_client.search_users.assert_called_with(user="mock_user@redhat.com")
562+
mock_client.search_users.assert_called_with(query="mock_user@redhat.com")
561563

562564
@mock.patch("Rover_Lookup.github_username_to_emails")
563565
@mock.patch("jira.client.JIRA")
@@ -572,11 +574,13 @@ def test_assign_user_multiple(self, mock_client, mock_rover_lookup):
572574
mock_user.name = "mock_assignee_name"
573575
mock_user.emailAddress = "mock_user@redhat.com"
574576
mock_user.key = "mock_user_key"
577+
mock_user.accountId = "mock-account-id-multi"
575578
mock_user2 = MagicMock()
576579
mock_user2.displayName = "mock_assignee2"
577580
mock_user2.name = "mock_assignee2_name"
578581
mock_user2.emailAddress = "wrong_mock_user@redhat.com"
579582
mock_user2.key = "mock_user2_key"
583+
mock_user2.accountId = "mock-account-id-2"
580584
mock_client.search_users.return_value = [
581585
mock_user,
582586
mock_user2,
@@ -608,9 +612,9 @@ def test_assign_user_multiple(self, mock_client, mock_rover_lookup):
608612

609613
# Assert that all calls mocked were called properly
610614
self.mock_downstream.update.assert_called_with(
611-
{"assignee": {"name": mock_user.name}}
615+
{"assignee": {"accountId": mock_user.accountId}}
612616
)
613-
mock_client.search_users.assert_called_with(user="mock_user@redhat.com")
617+
mock_client.search_users.assert_called_with(query="mock_user@redhat.com")
614618

615619
@mock.patch("Rover_Lookup.github_username_to_emails")
616620
@mock.patch("jira.client.JIRA")
@@ -658,7 +662,7 @@ def test_assign_user_with_owner_no_match(self, mock_client, mock_rover_lookup):
658662

659663
# Assert that all calls mocked were called properly
660664
mock_client.assign_issue.assert_called_with(1234, "mock_owner")
661-
mock_client.search_users.assert_called_with(user="no_match@redhat.com")
665+
mock_client.search_users.assert_called_with(query="no_match@redhat.com")
662666

663667
@mock.patch("Rover_Lookup.github_username_to_emails")
664668
@mock.patch("jira.client.JIRA")

tests/test_downstream_pr.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ def setUp(self):
5050
mock_user = MagicMock()
5151
mock_user.displayName = "mock_reporter"
5252
mock_user.key = "mock_key"
53+
mock_user.accountId = "mock-atlassian-account-id"
5354
self.mock_client.search_users.return_value = [mock_user]
5455
self.mock_client.search_issues.return_value = ["mock_existing"]
5556

@@ -331,9 +332,10 @@ def test_format_comment_open(self):
331332
response = d.format_comment(self.mock_pr, "open", self.mock_client)
332333

333334
# Assert Everything was called correctly
335+
self.mock_client.search_users.assert_called_with(query="mock_reporter")
334336
self.assertEqual(
335337
response,
336-
"[~mock_key] mentioned this issue in merge request [mock_title| mock_url].",
338+
"[~accountId:mock-atlassian-account-id] mentioned this issue in merge request [mock_title| mock_url].",
337339
)
338340

339341
def test_format_comment_open_no_user_found(self):
@@ -347,6 +349,7 @@ def test_format_comment_open_no_user_found(self):
347349
response = d.format_comment(self.mock_pr, "open", self.mock_client)
348350

349351
# Assert Everything was called correctly
352+
self.mock_client.search_users.assert_called_with(query="mock_reporter")
350353
self.assertEqual(
351354
response,
352355
"mock_reporter mentioned this issue in merge request [mock_title| mock_url].",

0 commit comments

Comments
 (0)