mirror of
https://github.com/openSUSE/osc.git
synced 2026-01-07 15:37:37 +01:00
Add command git-obs pr review cancel-request
This commit is contained in:
73
behave/features/git-pr-review-request.feature
Normal file
73
behave/features/git-pr-review-request.feature
Normal file
@@ -0,0 +1,73 @@
|
||||
Feature: `git-obs pr` command
|
||||
|
||||
Background:
|
||||
Given I set working directory to "{context.osc.temp}"
|
||||
And I execute git-obs with args "repo fork pool/test-GitPkgA"
|
||||
And I execute git-obs with args "repo clone Admin/test-GitPkgA --no-ssh-strict-host-key-checking"
|
||||
And I set working directory to "{context.osc.temp}/test-GitPkgA"
|
||||
And I execute "sed -i 's@^\(Version: *\) .*@\1 v1.1@' *.spec"
|
||||
And I execute "git commit -m 'v1.1' -a"
|
||||
And I execute "sed -i 's@^\(Version: *\) .*@\1 v1.2@' *.spec"
|
||||
And I execute "git commit -m 'v1.2' -a"
|
||||
And I execute "git push"
|
||||
And I execute git-obs with args "pr create --title 'Change version' --description='some text'"
|
||||
And I execute git-obs with args "api -X POST /repos/pool/test-GitPkgA/pulls/1/requested_reviewers --data='{{"reviewers": ["bob", "alice"]}}'"
|
||||
|
||||
@destructive
|
||||
Scenario: Check setup is correct
|
||||
When I execute git-obs with args "api /repos/pool/test-GitPkgA/pulls/1/reviews"
|
||||
Then the exit code is 0
|
||||
And stdout contains "bob"
|
||||
And stdout contains "alice"
|
||||
|
||||
@destructive
|
||||
Scenario: Cancel reviews for single user
|
||||
When I execute git-obs with args "pr review cancel-request pool/test-GitPkgA#1 bob --dry-run"
|
||||
Then the exit code is 0
|
||||
When I execute git-obs with args "api /repos/pool/test-GitPkgA/pulls/1/reviews"
|
||||
Then the exit code is 0
|
||||
And stdout contains "bob"
|
||||
And stdout contains "alice"
|
||||
# When I execute git-obs with args "api -X DELETE /repos/pool/test-GitPkgA/pulls/1/requested_reviewers --data='{{"reviewers": ["bob"]}}'"
|
||||
When I execute git-obs with args "pr review cancel-request pool/test-GitPkgA#1 bob"
|
||||
Then the exit code is 0
|
||||
When I execute git-obs with args "api /repos/pool/test-GitPkgA/pulls/1/reviews"
|
||||
Then the exit code is 0
|
||||
And stdout doesn't contain "bob"
|
||||
And stdout contains "alice"
|
||||
When I execute git-obs with args "pr review cancel-request pool/test-GitPkgA#1 bob"
|
||||
Then the exit code is 1
|
||||
|
||||
@destructive
|
||||
Scenario: Cancel review requests for all
|
||||
When I execute git-obs with args "pr review cancel-request pool/test-GitPkgA#1 --all --dry-run"
|
||||
Then the exit code is 0
|
||||
When I execute git-obs with args "api /repos/pool/test-GitPkgA/pulls/1/reviews"
|
||||
Then the exit code is 0
|
||||
And stdout contains "bob"
|
||||
And stdout contains "alice"
|
||||
# When I execute git-obs with args "api -X DELETE /repos/pool/test-GitPkgA/pulls/1/requested_reviewers --data='{{"reviewers": ["bob","alice"]}}'"
|
||||
When I execute git-obs with args "pr review cancel-request pool/test-GitPkgA#1 --all"
|
||||
Then the exit code is 0
|
||||
When I execute git-obs with args "api /repos/pool/test-GitPkgA/pulls/1/reviews"
|
||||
Then the exit code is 0
|
||||
And stdout doesn't contain "bob"
|
||||
And stdout doesn't contain "alice"
|
||||
|
||||
@destructive
|
||||
Scenario: Cancel review requests for all with exclude lowercase
|
||||
When I execute git-obs with args "pr review cancel-request pool/test-GitPkgA#1 --all --exclude bob"
|
||||
Then the exit code is 0
|
||||
When I execute git-obs with args "api /repos/pool/test-GitPkgA/pulls/1/reviews"
|
||||
Then the exit code is 0
|
||||
And stdout contains "bob"
|
||||
And stdout doesn't contain "alice"
|
||||
|
||||
@destructive
|
||||
Scenario: Cancel review request for all with exclude mixed case
|
||||
When I execute git-obs with args "pr review cancel-request pool/test-GitPkgA#1 --all --exclude BoB --exclude unknown"
|
||||
Then the exit code is 0
|
||||
When I execute git-obs with args "api /repos/pool/test-GitPkgA/pulls/1/reviews"
|
||||
Then the exit code is 0
|
||||
And stdout contains "bob"
|
||||
And stdout doesn't contain "alice"
|
||||
63
osc/commands_git/pr_review_cancel_request.py
Normal file
63
osc/commands_git/pr_review_cancel_request.py
Normal file
@@ -0,0 +1,63 @@
|
||||
import osc.commandline_git
|
||||
|
||||
|
||||
class PullRequestReviewCancelRequestCommand(osc.commandline_git.GitObsCommand):
|
||||
"""
|
||||
Cancel a request for review of pull request
|
||||
"""
|
||||
|
||||
name = "cancel-request"
|
||||
parent = "PullRequestReviewCommand"
|
||||
|
||||
def init_arguments(self):
|
||||
self.add_argument(
|
||||
"id",
|
||||
help="Pull request ID in <owner>/<repo>#<number> format",
|
||||
)
|
||||
self.add_argument(
|
||||
"user",
|
||||
nargs="*",
|
||||
help="User with pending review request",
|
||||
)
|
||||
self.add_argument(
|
||||
"-n",
|
||||
"--dry-run",
|
||||
action="store_true",
|
||||
help="Don't do any action, only report what should be done",
|
||||
)
|
||||
self.add_argument(
|
||||
"-a",
|
||||
"--all",
|
||||
action="store_true",
|
||||
help="Cancel all pending review requests",
|
||||
)
|
||||
self.add_argument(
|
||||
"-x",
|
||||
"--exclude",
|
||||
action="append",
|
||||
help="Users to ignore when cancelling review requests.",
|
||||
)
|
||||
|
||||
def run(self, args):
|
||||
from osc import gitea_api
|
||||
|
||||
if len(args.user) < 1 and not args.all:
|
||||
self.parser.error("Must specify a user or --all for all users")
|
||||
|
||||
self.print_gitea_settings()
|
||||
|
||||
owner, repo, number = gitea_api.PullRequest.split_id(args.id)
|
||||
if args.all:
|
||||
gitea_api.PullRequest.cancel_review_requests_all(
|
||||
self.gitea_conn, owner, repo, number, args.exclude, args.dry_run
|
||||
)
|
||||
else:
|
||||
gitea_api.PullRequest.cancel_review_requests(
|
||||
self.gitea_conn,
|
||||
owner,
|
||||
repo,
|
||||
number,
|
||||
args.user,
|
||||
args.exclude,
|
||||
args.dry_run,
|
||||
)
|
||||
@@ -802,3 +802,107 @@ class PullRequest(GiteaModel):
|
||||
for label_id in label_id_list:
|
||||
url = conn.makeurl("repos", owner, repo, "issues", str(number), "labels", str(label_id))
|
||||
conn.request("DELETE", url)
|
||||
|
||||
@classmethod
|
||||
def _cancel_review_requests(
|
||||
cls,
|
||||
conn: Connection,
|
||||
owner: str,
|
||||
repo: str,
|
||||
number: int,
|
||||
users: Optional[list],
|
||||
exclude: Optional[list],
|
||||
dry_run: Optional[bool],
|
||||
) -> GiteaHTTPResponse:
|
||||
"""
|
||||
Internal method to cancel all pending review requests. Empty user list means for all users.
|
||||
"""
|
||||
from .exceptions import GitObsRuntimeError
|
||||
|
||||
pr_obj = cls.get(conn, owner, repo, number)
|
||||
|
||||
review_states = ["REQUEST_REVIEW"]
|
||||
all_reviews = pr_obj.get_reviews(conn)
|
||||
user_reviews = {i.user.lower() for i in all_reviews if i.user and i.state in review_states}
|
||||
team_reviews = {i.team.lower() for i in all_reviews if i.team and i.state in review_states}
|
||||
|
||||
users_to_remove = []
|
||||
teams_to_remove = []
|
||||
|
||||
if exclude:
|
||||
exclude[:] = [i.lower() for i in exclude]
|
||||
|
||||
# empty list means we remove all users
|
||||
if not users:
|
||||
for user in user_reviews:
|
||||
if exclude and user in exclude:
|
||||
continue
|
||||
users_to_remove.append(user)
|
||||
else:
|
||||
# remove eventual empty strings
|
||||
users[:] = [i for i in users if i]
|
||||
|
||||
for user in users:
|
||||
if exclude and user in exclude:
|
||||
continue
|
||||
if user[0] == "@":
|
||||
team = user[1:]
|
||||
if team.lower() not in team_reviews:
|
||||
msg = f"Team {team} has no pending review requests in {owner}/{repo}#{number}"
|
||||
raise GitObsRuntimeError(msg)
|
||||
teams_to_remove.append(team)
|
||||
else:
|
||||
if user.lower() not in user_reviews:
|
||||
msg = f"User {user} has no pending review requests in {owner}/{repo}#{number}"
|
||||
raise GitObsRuntimeError(msg)
|
||||
users_to_remove.append(user)
|
||||
|
||||
data = {
|
||||
"reviewers": users_to_remove,
|
||||
"teams": teams_to_remove,
|
||||
}
|
||||
|
||||
if not users_to_remove and not teams_to_remove:
|
||||
return None
|
||||
|
||||
url = conn.makeurl("repos", owner, repo, "pulls", str(number), "/requested_reviewers")
|
||||
if dry_run:
|
||||
import sys
|
||||
|
||||
print(f"DELETE {url} {data}", file=sys.stderr)
|
||||
else:
|
||||
conn.request("DELETE", url, data)
|
||||
|
||||
@classmethod
|
||||
def cancel_review_requests_all(
|
||||
cls,
|
||||
conn: Connection,
|
||||
owner: str,
|
||||
repo: str,
|
||||
number: int,
|
||||
exclude: Optional[list],
|
||||
dry_run: Optional[bool] = False,
|
||||
) -> GiteaHTTPResponse:
|
||||
"""
|
||||
Cancel all pending review requests.
|
||||
"""
|
||||
return cls._cancel_review_requests(conn, owner, repo, number, [], exclude, dry_run)
|
||||
|
||||
@classmethod
|
||||
def cancel_review_requests(
|
||||
cls,
|
||||
conn: Connection,
|
||||
owner: str,
|
||||
repo: str,
|
||||
number: int,
|
||||
users: List[str],
|
||||
exclude: Optional[list],
|
||||
dry_run: Optional[bool] = False,
|
||||
) -> GiteaHTTPResponse:
|
||||
"""
|
||||
Cancel pending review requests for particular users.
|
||||
"""
|
||||
if not users:
|
||||
return None
|
||||
|
||||
return cls._cancel_review_requests(conn, owner, repo, number, users, exclude, dry_run)
|
||||
|
||||
Reference in New Issue
Block a user