Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add support for ranking after #1160

Merged
merged 2 commits into from
Oct 17, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
81 changes: 43 additions & 38 deletions jira/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -293,7 +293,7 @@ class JIRA:
"context_path": "/",
"rest_path": "api",
"rest_api_version": "2",
"agile_rest_path": GreenHopperResource.GREENHOPPER_REST_PATH,
"agile_rest_path": GreenHopperResource.AGILE_BASE_REST_PATH,
"agile_rest_api_version": "1.0",
"verify": True,
"resilient": True,
Expand Down Expand Up @@ -4669,14 +4669,36 @@ def add_issues_to_epic(
url = self._get_url(f"epics/{epic_id}/add", base=self.AGILE_BASE_URL)
return self._session.put(url, data=json.dumps(data))

# TODO(ssbarnea): Both GreenHopper and new Jira Agile API support moving more than one issue.
def rank(self, issue: str, next_issue: str) -> Response:
"""Rank an issue before another using the default Ranking field, the one named 'Rank'.
# TODO(ssbarnea): Jira Agile API supports moving more than one issue.
def rank(
self,
issue: str,
next_issue: Optional[str] = None,
prev_issue: Optional[str] = None,
) -> Response:
"""Rank an issue before/after another using the default Ranking field, the one named 'Rank'.

Pass only ONE of `next_issue` or `prev_issue`.

Args:
issue (str): issue key of the issue to be ranked before the second one.
next_issue (str): issue key of the second issue.
issue (str): issue key of the issue to be ranked before/after the second one.
next_issue (str): issue key that the first issue is to be ranked before.
prev_issue (str): issue key that the first issue is to be ranked after.
"""

if next_issue is None and prev_issue is None:
raise ValueError("One of 'next_issue' or 'prev_issue' must be specified")
elif next_issue is not None and prev_issue is not None:
raise ValueError(
"Only one of 'next_issue' or 'prev_issue' may be specified"
)
if next_issue is not None:
before_or_after = "Before"
other_issue = next_issue
elif prev_issue is not None:
before_or_after = "After"
other_issue = prev_issue

if not self._rank:
for field in self.fields():
if field["name"] == "Rank":
Expand All @@ -4693,38 +4715,21 @@ def rank(self, issue: str, next_issue: str) -> Response:
# Obsolete since Jira v6.3.13.1
self._rank = field["schema"]["customId"]

if self._options["agile_rest_path"] == GreenHopperResource.AGILE_BASE_REST_PATH:
url = self._get_url("issue/rank", base=self.AGILE_BASE_URL)
payload = {
"issues": [issue],
"rankBeforeIssue": next_issue,
durka marked this conversation as resolved.
Show resolved Hide resolved
"rankCustomFieldId": self._rank,
}
try:
return self._session.put(url, data=json.dumps(payload))
except JIRAError as e:
if e.status_code == 404:
warnings.warn(
"Status code 404 may mean, that too old Jira Agile version is installed."
" At least version 6.7.10 is required."
)
raise
elif (
self._options["agile_rest_path"]
== GreenHopperResource.GREENHOPPER_REST_PATH
):
data = {
"issueKeys": [issue],
"rankBeforeKey": next_issue,
"customFieldId": self._rank,
}
url = self._get_url("rank", base=self.AGILE_BASE_URL)
return self._session.put(url, data=json.dumps(data))
else:
raise NotImplementedError(
'No API for ranking issues for agile_rest_path="%s"'
% self._options["agile_rest_path"]
)
url = self._get_url("issue/rank", base=self.AGILE_BASE_URL)
payload = {
"issues": [issue],
f"rank{before_or_after}Issue": other_issue,
"rankCustomFieldId": self._rank,
}
try:
return self._session.put(url, data=json.dumps(payload))
except JIRAError as e:
if e.status_code == 404:
warnings.warn(
"Status code 404 may mean, that too old Jira Agile version is installed."
" At least version 6.7.10 is required."
)
raise

def move_to_backlog(self, issue_keys: str) -> Response:
"""Move issues in ``issue_keys`` to the backlog, removing them from all sprints that have not been completed.
Expand Down
19 changes: 19 additions & 0 deletions tests/resources/test_issue.py
Original file line number Diff line number Diff line change
Expand Up @@ -446,6 +446,25 @@ def test_transitioning(self):
# self.assertEqual(issue.fields.assignee.name, self.test_manager.CI_JIRA_USER)
# self.assertEqual(issue.fields.status.id, transition_id)

def test_rank(self):
def get_issues_ordered_by_rank():
"""Search for the issues, returned in the order determined by their rank."""
return self.jira.search_issues(
f"key in ({self.issue_1},{self.issue_2}) ORDER BY Rank ASC"
)

self.jira.rank(self.issue_1, next_issue=self.issue_2)
issues = get_issues_ordered_by_rank()
assert (issues[0].key, issues[1].key) == (self.issue_1, self.issue_2)

self.jira.rank(self.issue_2, next_issue=self.issue_1)
issues = get_issues_ordered_by_rank()
assert (issues[0].key, issues[1].key) == (self.issue_2, self.issue_1)

self.jira.rank(self.issue_2, prev_issue=self.issue_1)
issues = get_issues_ordered_by_rank()
assert (issues[0].key, issues[1].key) == (self.issue_1, self.issue_2)

@broken_test(
reason="Greenhopper API doesn't work on standalone docker image with JIRA Server 8.9.0"
)
Expand Down