diff --git a/github/Branch.py b/github/Branch.py index c157e12d..278dc5e9 100644 --- a/github/Branch.py +++ b/github/Branch.py @@ -116,11 +116,22 @@ class Branch(github.GithubObject.NonCompletableGithubObject): enforce_admins=github.GithubObject.NotSet, dismissal_users=github.GithubObject.NotSet, dismissal_teams=github.GithubObject.NotSet, + dismissal_apps=github.GithubObject.NotSet, dismiss_stale_reviews=github.GithubObject.NotSet, require_code_owner_reviews=github.GithubObject.NotSet, required_approving_review_count=github.GithubObject.NotSet, user_push_restrictions=github.GithubObject.NotSet, team_push_restrictions=github.GithubObject.NotSet, + app_push_restrictions=github.GithubObject.NotSet, + required_linear_history=github.GithubObject.NotSet, + allow_force_pushes=github.GithubObject.NotSet, + required_conversation_resolution=github.GithubObject.NotSet, + lock_branch=github.GithubObject.NotSet, + allow_fork_syncing=github.GithubObject.NotSet, + users_bypass_pull_request_allowances=github.GithubObject.NotSet, + teams_bypass_pull_request_allowances=github.GithubObject.NotSet, + apps_bypass_pull_request_allowances=github.GithubObject.NotSet, + block_creations=github.GithubObject.NotSet, ): """ :calls: `PUT /repos/{owner}/{repo}/branches/{branch}/protection `_ @@ -129,11 +140,22 @@ class Branch(github.GithubObject.NonCompletableGithubObject): :enforce_admins: bool :dismissal_users: list of strings :dismissal_teams: list of strings + :dismissal_apps: list of strings :dismiss_stale_reviews: bool :require_code_owner_reviews: bool :required_approving_review_count: int :user_push_restrictions: list of strings :team_push_restrictions: list of strings + :app_push_restrictions: list of strings + :required_linear_history: bool + :allow_force_pushes: bool + :required_conversation_resolution: bool + :lock_branch: bool + :allow_fork_syncing: bool + :users_bypass_pull_request_allowances: list of strings + :teams_bypass_pull_request_allowances: list of strings + :apps_bypass_pull_request_allowances: list of strings + :block_creations: bool NOTE: The GitHub API groups strict and contexts together, both must be submitted. Take care to pass both as arguments even if only one is @@ -152,6 +174,9 @@ class Branch(github.GithubObject.NonCompletableGithubObject): assert dismissal_teams is github.GithubObject.NotSet or all( isinstance(element, str) for element in dismissal_teams ), dismissal_teams + assert dismissal_apps is github.GithubObject.NotSet or all( + isinstance(element, str) for element in dismissal_apps + ), dismissal_apps assert dismiss_stale_reviews is github.GithubObject.NotSet or isinstance( dismiss_stale_reviews, bool ), dismiss_stale_reviews @@ -162,6 +187,39 @@ class Branch(github.GithubObject.NonCompletableGithubObject): required_approving_review_count is github.GithubObject.NotSet or isinstance(required_approving_review_count, int) ), (required_approving_review_count) + assert required_linear_history is github.GithubObject.NotSet or isinstance( + required_linear_history, bool + ), required_linear_history + assert allow_force_pushes is github.GithubObject.NotSet or isinstance( + allow_force_pushes, bool + ), allow_force_pushes + assert ( + required_conversation_resolution is github.GithubObject.NotSet + or isinstance(required_linear_history, bool) + ), required_conversation_resolution + assert lock_branch is github.GithubObject.NotSet or isinstance( + lock_branch, bool + ), lock_branch + assert allow_fork_syncing is github.GithubObject.NotSet or isinstance( + allow_fork_syncing, bool + ), allow_fork_syncing + assert ( + users_bypass_pull_request_allowances is github.GithubObject.NotSet + or all( + isinstance(element, str) + for element in users_bypass_pull_request_allowances + ) + ), (users_bypass_pull_request_allowances) + assert ( + teams_bypass_pull_request_allowances is github.GithubObject.NotSet + or all( + isinstance(element, str) + for element in teams_bypass_pull_request_allowances + ) + ), (teams_bypass_pull_request_allowances) + assert apps_bypass_pull_request_allowances is github.GithubObject.NotSet or all( + isinstance(element, str) for element in apps_bypass_pull_request_allowances + ), apps_bypass_pull_request_allowances post_parameters = {} if ( @@ -187,9 +245,13 @@ class Branch(github.GithubObject.NonCompletableGithubObject): if ( dismissal_users is not github.GithubObject.NotSet or dismissal_teams is not github.GithubObject.NotSet + or dismissal_apps is not github.GithubObject.NotSet or dismiss_stale_reviews is not github.GithubObject.NotSet or require_code_owner_reviews is not github.GithubObject.NotSet or required_approving_review_count is not github.GithubObject.NotSet + or users_bypass_pull_request_allowances is not github.GithubObject.NotSet + or teams_bypass_pull_request_allowances is not github.GithubObject.NotSet + or apps_bypass_pull_request_allowances is not github.GithubObject.NotSet ): post_parameters["required_pull_request_reviews"] = {} if dismiss_stale_reviews is not github.GithubObject.NotSet: @@ -204,37 +266,101 @@ class Branch(github.GithubObject.NonCompletableGithubObject): post_parameters["required_pull_request_reviews"][ "required_approving_review_count" ] = required_approving_review_count + + if ( + dismissal_users is not github.GithubObject.NotSet + or dismissal_teams is not github.GithubObject.NotSet + or dismissal_apps is not github.GithubObject.NotSet + ): + post_parameters["required_pull_request_reviews"][ + "dismissal_restrictions" + ] = {} + if dismissal_users is not github.GithubObject.NotSet: post_parameters["required_pull_request_reviews"][ "dismissal_restrictions" - ] = {"users": dismissal_users} + ]["users"] = dismissal_users if dismissal_teams is not github.GithubObject.NotSet: - if ( - "dismissal_restrictions" - not in post_parameters["required_pull_request_reviews"] - ): - post_parameters["required_pull_request_reviews"][ - "dismissal_restrictions" - ] = {} post_parameters["required_pull_request_reviews"][ "dismissal_restrictions" ]["teams"] = dismissal_teams + if dismissal_apps is not github.GithubObject.NotSet: + post_parameters["required_pull_request_reviews"][ + "dismissal_restrictions" + ]["apps"] = dismissal_apps + + if ( + users_bypass_pull_request_allowances is not github.GithubObject.NotSet + or teams_bypass_pull_request_allowances + is not github.GithubObject.NotSet + or apps_bypass_pull_request_allowances is not github.GithubObject.NotSet + ): + post_parameters["required_pull_request_reviews"][ + "bypass_pull_request_allowances" + ] = {} + if users_bypass_pull_request_allowances is github.GithubObject.NotSet: + users_bypass_pull_request_allowances = [] + if teams_bypass_pull_request_allowances is github.GithubObject.NotSet: + teams_bypass_pull_request_allowances = [] + if apps_bypass_pull_request_allowances is github.GithubObject.NotSet: + apps_bypass_pull_request_allowances = [] + post_parameters["required_pull_request_reviews"][ + "bypass_pull_request_allowances" + ] = { + "users": users_bypass_pull_request_allowances, + "teams": teams_bypass_pull_request_allowances, + "apps": apps_bypass_pull_request_allowances, + } + else: + post_parameters["required_pull_request_reviews"][ + "bypass_pull_request_allowances" + ] = None else: post_parameters["required_pull_request_reviews"] = None if ( user_push_restrictions is not github.GithubObject.NotSet or team_push_restrictions is not github.GithubObject.NotSet + or app_push_restrictions is not github.GithubObject.NotSet ): if user_push_restrictions is github.GithubObject.NotSet: user_push_restrictions = [] if team_push_restrictions is github.GithubObject.NotSet: team_push_restrictions = [] + if app_push_restrictions is github.GithubObject.NotSet: + app_push_restrictions = [] post_parameters["restrictions"] = { "users": user_push_restrictions, "teams": team_push_restrictions, + "apps": app_push_restrictions, } else: post_parameters["restrictions"] = None + if required_linear_history is not github.GithubObject.NotSet: + post_parameters["required_linear_history"] = required_linear_history + else: + post_parameters["required_linear_history"] = None + if allow_force_pushes is not github.GithubObject.NotSet: + post_parameters["allow_force_pushes"] = allow_force_pushes + else: + post_parameters["allow_force_pushes"] = None + if required_conversation_resolution is not github.GithubObject.NotSet: + post_parameters[ + "required_conversation_resolution" + ] = required_conversation_resolution + else: + post_parameters["required_conversation_resolution"] = None + if lock_branch is not github.GithubObject.NotSet: + post_parameters["lock_branch"] = lock_branch + else: + post_parameters["lock_branch"] = None + if allow_fork_syncing is not github.GithubObject.NotSet: + post_parameters["allow_fork_syncing"] = allow_fork_syncing + else: + post_parameters["allow_fork_syncing"] = None + if block_creations is not github.GithubObject.NotSet: + post_parameters["block_creations"] = block_creations + else: + post_parameters["block_creations"] = None headers, data = self._requester.requestJsonAndCheck( "PUT", @@ -315,6 +441,7 @@ class Branch(github.GithubObject.NonCompletableGithubObject): self, dismissal_users=github.GithubObject.NotSet, dismissal_teams=github.GithubObject.NotSet, + dismissal_apps=github.GithubObject.NotSet, dismiss_stale_reviews=github.GithubObject.NotSet, require_code_owner_reviews=github.GithubObject.NotSet, required_approving_review_count=github.GithubObject.NotSet, @@ -323,6 +450,7 @@ class Branch(github.GithubObject.NonCompletableGithubObject): :calls: `PATCH /repos/{owner}/{repo}/branches/{branch}/protection/required_pull_request_reviews `_ :dismissal_users: list of strings :dismissal_teams: list of strings + :dismissal_apps: list of strings :dismiss_stale_reviews: bool :require_code_owner_reviews: bool :required_approving_review_count: int @@ -345,12 +473,20 @@ class Branch(github.GithubObject.NonCompletableGithubObject): ), (required_approving_review_count) post_parameters = {} + if ( + dismissal_users is not github.GithubObject.NotSet + or dismissal_teams is not github.GithubObject.NotSet + or dismissal_apps is not github.GithubObject.NotSet + ): + post_parameters["dismissal_restrictions"] = {} + if dismissal_users is not github.GithubObject.NotSet: - post_parameters["dismissal_restrictions"] = {"users": dismissal_users} + post_parameters["dismissal_restrictions"]["users"] = dismissal_users if dismissal_teams is not github.GithubObject.NotSet: - if "dismissal_restrictions" not in post_parameters: - post_parameters["dismissal_restrictions"] = {} post_parameters["dismissal_restrictions"]["teams"] = dismissal_teams + if dismissal_apps is not github.GithubObject.NotSet: + post_parameters["dismissal_restrictions"]["apps"] = dismissal_apps + if dismiss_stale_reviews is not github.GithubObject.NotSet: post_parameters["dismiss_stale_reviews"] = dismiss_stale_reviews if require_code_owner_reviews is not github.GithubObject.NotSet: diff --git a/github/Branch.pyi b/github/Branch.pyi index 6f6def2d..71dca9b1 100644 --- a/github/Branch.pyi +++ b/github/Branch.pyi @@ -23,16 +23,27 @@ class Branch(NonCompletableGithubObject): enforce_admins: Union[bool, _NotSetType] = ..., dismissal_users: Union[_NotSetType, List[str]] = ..., dismissal_teams: Union[_NotSetType, List[str]] = ..., + dismissal_apps: Union[_NotSetType, List[str]] = ..., dismiss_stale_reviews: Union[bool, _NotSetType] = ..., require_code_owner_reviews: Union[bool, _NotSetType] = ..., required_approving_review_count: Union[int, _NotSetType] = ..., user_push_restrictions: Union[_NotSetType, List[str]] = ..., team_push_restrictions: Union[_NotSetType, List[str]] = ..., + app_push_restrictions: Union[_NotSetType, List[str]] = ..., + required_linear_history: Union[bool, _NotSetType] = ..., + allow_force_pushes: Union[bool, _NotSetType] = ..., + required_conversation_resolution: Union[bool, _NotSetType] = ..., + lock_branch: Union[bool, _NotSetType] = ..., + allow_fork_syncing: Union[bool, _NotSetType] = ..., + user_bypass_pull_request_allowances: Union[_NotSetType, List[str]] = ..., + team_bypass_pull_request_allowances: Union[_NotSetType, List[str]] = ..., + app_bypass_pull_request_allowances: Union[_NotSetType, List[str]] = ..., ) -> None: ... def edit_required_pull_request_reviews( self, dismissal_users: Union[_NotSetType, List[str]] = ..., dismissal_teams: Union[_NotSetType, List[str]] = ..., + dismissal_apps: Union[_NotSetType, List[str]] = ..., dismiss_stale_reviews: Union[bool, _NotSetType] = ..., require_code_owner_reviews: Union[_NotSetType, bool] = ..., required_approving_review_count: Union[int, _NotSetType] = ..., diff --git a/tests/ReplayData/Branch.testEditProtection.txt b/tests/ReplayData/Branch.testEditProtection.txt index f9a68736..4076466c 100644 --- a/tests/ReplayData/Branch.testEditProtection.txt +++ b/tests/ReplayData/Branch.testEditProtection.txt @@ -4,7 +4,7 @@ api.github.com None /repos/jacquev6/PyGithub/branches/integrations/protection {'Authorization': 'Basic login_and_password_removed', 'Content-Type': 'application/json', 'User-Agent': 'PyGithub/Python', 'Accept': 'application/vnd.github.luke-cage-preview+json'} -{"restrictions": null, "required_pull_request_reviews": {"require_code_owner_reviews": true, "required_approving_review_count": 2}, "required_status_checks": {"contexts": [], "strict": true}, "enforce_admins": null} +{"restrictions": null, "required_pull_request_reviews": {"bypass_pull_request_allowances": null, "require_code_owner_reviews": true, "required_approving_review_count": 2}, "required_status_checks": {"contexts": [], "strict": true}, "enforce_admins": null, "allow_force_pushes": null, "allow_fork_syncing": null, "lock_branch": null, "required_conversation_resolution": null, "required_linear_history": null, "block_creations": null } 200 [('status', '200 OK'), ('x-ratelimit-remaining', '4994'), ('content-length', '0'), ('server', 'nginx/1.0.13'), ('connection', 'keep-alive'), ('x-ratelimit-limit', '5000'), ('etag', '"e0dc2dfc56971f4a36de1216356ea98b"'), ('date', 'Sat, 05 May 2018 06:05:54 GMT'), ('content-type', 'application/json; charset=utf-8')] '' diff --git a/tests/ReplayData/Branch.testEditProtectionDismissalUsersWithUserOwnedBranch.txt b/tests/ReplayData/Branch.testEditProtectionDismissalUsersWithUserOwnedBranch.txt index 27fead7e..160e2453 100644 --- a/tests/ReplayData/Branch.testEditProtectionDismissalUsersWithUserOwnedBranch.txt +++ b/tests/ReplayData/Branch.testEditProtectionDismissalUsersWithUserOwnedBranch.txt @@ -4,7 +4,7 @@ api.github.com None /repos/jacquev6/PyGithub/branches/integrations/protection {'Authorization': 'Basic login_and_password_removed', 'Content-Type': 'application/json', 'User-Agent': 'PyGithub/Python', 'Accept': 'application/vnd.github.luke-cage-preview+json'} -{"restrictions": null, "required_pull_request_reviews": {"dismissal_restrictions": {"users": ["jacquev6"]}}, "required_status_checks": null, "enforce_admins": null} +{"restrictions": null, "required_pull_request_reviews": {"bypass_pull_request_allowances": null, "dismissal_restrictions": {"users": ["jacquev6"]}}, "required_status_checks": null, "enforce_admins": null, "allow_force_pushes": null, "allow_fork_syncing": null, "lock_branch": null, "required_conversation_resolution": null, "required_linear_history": null, "block_creations": null } 422 [('status', '422 Unprocessable Entity'), ('x-ratelimit-remaining', '4994'), ('content-length', '0'), ('server', 'nginx/1.0.13'), ('connection', 'keep-alive'), ('x-ratelimit-limit', '5000'), ('etag', '"e0dc2dfc56971f4a36de1216356ea98b"'), ('date', 'Sun, 13 May 2018 10:42:14 GMT'), ('content-type', 'application/json; charset=utf-8')] {"documentation_url":"https://developer.github.com/v3/repos/branches/#update-branch-protection","message":"Validation Failed","errors":["Only organization repositories can have users and team restrictions"]} diff --git a/tests/ReplayData/Branch.testEditProtectionPushRestrictionsAndDismissalUser.txt b/tests/ReplayData/Branch.testEditProtectionPushRestrictionsAndDismissalUser.txt index 9ed6dafc..6ed42300 100644 --- a/tests/ReplayData/Branch.testEditProtectionPushRestrictionsAndDismissalUser.txt +++ b/tests/ReplayData/Branch.testEditProtectionPushRestrictionsAndDismissalUser.txt @@ -4,7 +4,7 @@ api.github.com None /repos/PyGithub/PyGithub/branches/master/protection {'Authorization': 'Basic login_and_password_removed', 'Content-Type': 'application/json', 'User-Agent': 'PyGithub/Python', 'Accept': 'application/vnd.github.luke-cage-preview+json'} -{"restrictions": {"teams": [], "users": ["jacquev6"]}, "required_pull_request_reviews": {"dismissal_restrictions": {"users": ["jacquev6"]}}, "required_status_checks": null, "enforce_admins": null} +{"restrictions": {"apps": [], "teams": [], "users": ["jacquev6"]}, "required_pull_request_reviews": {"bypass_pull_request_allowances": null, "dismissal_restrictions": {"users": ["jacquev6"]}}, "required_status_checks": null, "enforce_admins": null, "allow_force_pushes": null, "allow_fork_syncing": null, "lock_branch": null, "required_conversation_resolution": null, "required_linear_history": null, "block_creations": null } 200 [('status', '200 OK'), ('x-ratelimit-remaining', '4994'), ('content-length', '0'), ('server', 'nginx/1.0.13'), ('connection', 'keep-alive'), ('x-ratelimit-limit', '5000'), ('etag', '"e0dc2dfc56971f4a36de1216356ea98b"'), ('date', 'Sun, 13 May 2018 13:21:24 GMT'), ('content-type', 'application/json; charset=utf-8')] '' diff --git a/tests/ReplayData/Branch.testEditProtectionPushRestrictionsWithUserOwnedBranch.txt b/tests/ReplayData/Branch.testEditProtectionPushRestrictionsWithUserOwnedBranch.txt index 154f9e3d..cbc504c4 100644 --- a/tests/ReplayData/Branch.testEditProtectionPushRestrictionsWithUserOwnedBranch.txt +++ b/tests/ReplayData/Branch.testEditProtectionPushRestrictionsWithUserOwnedBranch.txt @@ -4,7 +4,7 @@ api.github.com None /repos/jacquev6/PyGithub/branches/integrations/protection {'Authorization': 'Basic login_and_password_removed', 'Content-Type': 'application/json', 'User-Agent': 'PyGithub/Python', 'Accept': 'application/vnd.github.luke-cage-preview+json'} -{"restrictions": {"users": ["jacquev6"], "teams": []}, "required_pull_request_reviews": null, "required_status_checks": null, "enforce_admins": null} +{"restrictions": {"apps": [], "users": ["jacquev6"], "teams": []}, "required_pull_request_reviews": null, "required_status_checks": null, "enforce_admins": null, "allow_force_pushes": null, "allow_fork_syncing": null, "lock_branch": null, "required_conversation_resolution": null, "required_linear_history": null, "block_creations": null } 422 [('status', '422 Unprocessable Entity'), ('x-ratelimit-remaining', '4994'), ('content-length', '0'), ('server', 'nginx/1.0.13'), ('connection', 'keep-alive'), ('x-ratelimit-limit', '5000'), ('etag', '"e0dc2dfc56971f4a36de1216356ea98b"'), ('date', 'Sat, 05 May 2018 06:05:54 GMT'), ('content-type', 'application/json; charset=utf-8')] {"documentation_url":"https://developer.github.com/v3/repos/branches/#update-branch-protection","message":"Validation Failed","errors":["Only organization repositories can have users and team restrictions"]}