Merge "Fix broken jobs overriding checkout to an unprotected branch"

This commit is contained in:
Zuul 2021-04-30 23:20:53 +00:00 committed by Gerrit Code Review
commit 014574925b
7 changed files with 82 additions and 4 deletions

View File

@ -26,16 +26,28 @@
- event: comment-added
approval:
- Code-Review: 2
github:
- event: pull_request
action: opened
success:
gerrit:
Verified: 1
submit: true
github:
check: success
comment: false
failure:
gerrit:
Verified: -1
github:
check: failure
comment: false
start:
gerrit:
Verified: 0
github:
check: in_progress
comment: false
precedence: high
- job:

View File

@ -0,0 +1 @@
test

View File

@ -0,0 +1,13 @@
- job:
name: require-test1-github
parent: null
run: playbooks/require-test.yaml
required-projects:
- name: org/requiredproject-github
# Checkout unprotected branch
override-checkout: feat-x
- project:
check:
jobs:
- require-test1-github

View File

@ -0,0 +1,2 @@
- hosts: localhost
tasks: []

View File

@ -1,5 +1,6 @@
- tenant:
name: tenant-one
exclude-unprotected-branches: true
source:
gerrit:
config-projects:
@ -10,3 +11,8 @@
- org/requiredproject
- org/requiringproject
- org/roles
github:
config-projects:
- org/requiringproject-github
untrusted-projects:
- org/requiredproject-github

View File

@ -2436,6 +2436,7 @@ class TestInRepoConfig(ZuulTestCase):
class TestGlobalRepoState(AnsibleZuulTestCase):
config_file = 'zuul-connections-gerrit-and-github.conf'
tenant_config_file = 'config/global-repo-state/main.yaml'
def test_inherited_playbooks(self):
@ -2484,6 +2485,34 @@ class TestGlobalRepoState(AnsibleZuulTestCase):
dict(name='test2', result='SUCCESS', changes='1,1'),
])
def test_required_projects_unprotected_override_checkout(self):
# Setup branch protection for master on org/requiringproject-github
github = self.fake_github.getGithubClient()
github.repo_from_project(
'org/requiringproject-github')._set_branch_protection(
'master', True)
# Create unprotected branch feat-x. This branch will be the target
# of override-checkout
repo = github.repo_from_project('org/requiredproject-github')
repo._set_branch_protection('master', True)
repo._create_branch('feat-x')
self.create_branch('org/requiredproject-github', 'feat-x')
# Reconfigure to ensure zuul knows about the branch protection
self.scheds.execute(lambda app: app.sched.reconfigure(app.config))
self.waitUntilSettled()
A = self.fake_github.openFakePullRequest(
'org/requiringproject-github', 'master', 'A')
self.fake_github.emitEvent(A.getPullRequestOpenedEvent())
self.waitUntilSettled()
# Job must be successful
self.assertHistory([
dict(name='require-test1-github', result='SUCCESS'),
])
def test_required_projects(self):
# Test that the repo state is restored globally for the whole buildset
# including required projects not in the dependency chain.

View File

@ -864,6 +864,7 @@ class PipelineManager(metaclass=ABCMeta):
return self._loadDynamicLayout(item)
def _branchesForRepoState(self, projects, tenant, items=None):
items = items or []
if all(tenant.getExcludeUnprotectedBranches(project)
for project in projects):
branches = set()
@ -873,9 +874,22 @@ class PipelineManager(metaclass=ABCMeta):
branches.update(tenant.getProjectBranches(project))
# Additionally add all target branches of all involved items.
if items is not None:
branches.update(item.change.branch for item in items
if hasattr(item.change, 'branch'))
branches.update(item.change.branch for item in items
if hasattr(item.change, 'branch'))
# Make sure override-checkout targets are part of the repo state
for item in items:
if not item.job_graph:
continue
for job in item.job_graph.jobs.values():
if job.override_checkout:
branches.add(job.override_checkout)
for p in job.required_projects.values():
if p.override_checkout:
branches.add(p.override_checkout)
branches = list(branches)
else:
branches = None
@ -959,7 +973,8 @@ class PipelineManager(metaclass=ABCMeta):
item.current_build_set.COMPLETE
return True
branches = self._branchesForRepoState(projects=projects, tenant=tenant)
branches = self._branchesForRepoState(
projects=projects, tenant=tenant, items=[item])
new_items = list()
for project in projects: