Merge "Don't match branch protection rule patterns locally"

This commit is contained in:
Zuul 2020-09-15 07:38:19 +00:00 committed by Gerrit Code Review
commit fd519765e6
6 changed files with 51 additions and 12 deletions

View File

@ -32,7 +32,6 @@ paho-mqtt
cherrypy
ws4py
routes
pathspec
jsonpath-rw
urllib3!=1.25.4,!=1.25.5 # https://github.com/urllib3/urllib3/pull/1684
cheroot!=8.1.*,!=8.2.*,!=8.3.0 # https://github.com/cherrypy/cheroot/issues/263

View File

@ -26,11 +26,28 @@ class FakePageInfo(ObjectType):
return False
class FakeMatchingRef(ObjectType):
name = String()
def resolve_name(parent, info):
return parent
class FakeMatchingRefs(ObjectType):
nodes = List(FakeMatchingRef)
def resolve_nodes(parent, info):
# To simplify tests just return the pattern and a bogus ref that should
# not disturb zuul.
return [parent.pattern, 'bogus-ref']
class FakeBranchProtectionRule(ObjectType):
pattern = String()
requiredStatusCheckContexts = List(String)
requiresApprovingReviews = Boolean()
requiresCodeOwnerReviews = Boolean()
matchingRefs = Field(FakeMatchingRefs, first=Int())
def resolve_pattern(parent, info):
return parent.pattern
@ -44,6 +61,9 @@ class FakeBranchProtectionRule(ObjectType):
def resolve_requiresCodeOwnerReviews(parent, info):
return parent.require_codeowners_review
def resolve_matchingRefs(parent, info, first=None):
return parent
class FakeBranchProtectionRules(ObjectType):
nodes = List(FakeBranchProtectionRule)

View File

@ -1633,7 +1633,8 @@ class GithubConnection(BaseConnection):
# For performance reasons fetch all needed data for canMerge upfront
# using a single graphql call.
canmerge_data = self.graphql_client.fetch_canmerge(github, change)
canmerge_data = self.graphql_client.fetch_canmerge(
github, change, zuul_event_id=event)
# If the PR is a draft it cannot be merged.
if canmerge_data.get('isDraft', False):

View File

@ -13,9 +13,10 @@
# under the License.
import logging
import pathspec
from pkg_resources import resource_string
from zuul.lib.logutil import get_annotated_logger
def nested_get(d, *keys, default=None):
temp = d
@ -70,7 +71,8 @@ class GraphQLClient:
response = github.session.post(self.url, json=query)
return response.json()
def fetch_canmerge(self, github, change):
def fetch_canmerge(self, github, change, zuul_event_id=None):
log = get_annotated_logger(self.log, zuul_event_id)
owner, repo = change.project.name.split('/')
data = self._fetch_canmerge(github, owner, repo, change.number,
@ -81,14 +83,21 @@ class GraphQLClient:
# Find corresponding rule to our branch
rules = nested_get(repository, 'branchProtectionRules', 'nodes',
default=[])
matching_rule = None
for rule in rules:
pattern = pathspec.patterns.GitWildMatchPattern(
rule.get('pattern'))
match = pathspec.match_files([pattern], [change.branch])
if match:
matching_rule = rule
break
# Filter branch protection rules for the one matching the change.
matching_rules = [
rule for rule in rules
for ref in nested_get(rule, 'matchingRefs', 'nodes', default=[])
if ref.get('name') == change.branch
]
if len(matching_rules) > 1:
log.warn('More than one branch protection rules match change %s',
change)
return result
elif len(matching_rules) == 1:
matching_rule = matching_rules[0]
else:
matching_rule = None
# If there is a matching rule, get required status checks
if matching_rule:

View File

@ -11,6 +11,11 @@ query canMergeData(
requiredStatusCheckContexts
requiresApprovingReviews
requiresCodeOwnerReviews
matchingRefs(first: 100) {
nodes {
name
}
}
}
}
pullRequest(number: $pull) {

View File

@ -11,6 +11,11 @@ query canMergeData(
requiredStatusCheckContexts
requiresApprovingReviews
requiresCodeOwnerReviews
matchingRefs(first: 100) {
nodes {
name
}
}
}
}
pullRequest(number: $pull) {