Merge "Report layout config errors for config repos" into feature/zuulv3

This commit is contained in:
Jenkins 2017-03-06 18:49:46 +00:00 committed by Gerrit Code Review
commit df1f701cb7
5 changed files with 104 additions and 35 deletions

View File

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

View File

@ -35,3 +35,12 @@
gerrit:
verified: 0
precedence: high
- job:
name: common-config-test
- project:
name: common-config
tenant-one-gate:
jobs:
- common-config-test

View File

@ -185,7 +185,7 @@ class TestInRepoConfig(ZuulTestCase):
dict(name='project-test1', result='SUCCESS', changes='2,1'),
dict(name='project-test2', result='SUCCESS', changes='3,1')])
def test_dynamic_syntax_error(self):
def test_untrusted_syntax_error(self):
in_repo_conf = textwrap.dedent(
"""
- job:
@ -206,6 +206,27 @@ class TestInRepoConfig(ZuulTestCase):
self.assertIn('syntax error', A.messages[1],
"A should have a syntax error reported")
def test_trusted_syntax_error(self):
in_repo_conf = textwrap.dedent(
"""
- job:
name: project-test2
foo: error
""")
file_dict = {'zuul.yaml': in_repo_conf}
A = self.fake_gerrit.addFakeChange('common-config', 'master', 'A',
files=file_dict)
A.addApproval('code-review', 2)
self.fake_gerrit.addEvent(A.addApproval('approved', 1))
self.waitUntilSettled()
self.assertEqual(A.data['status'], 'NEW')
self.assertEqual(A.reported, 2,
"A should report start and failure")
self.assertIn('syntax error', A.messages[1],
"A should have a syntax error reported")
class TestAnsible(AnsibleZuulTestCase):
# A temporary class to hold new tests while others are disabled

View File

@ -841,21 +841,41 @@ class ConfigLoader(object):
new_abide.tenants[tenant.name] = new_tenant
return new_abide
def createDynamicLayout(self, tenant, files):
config = tenant.config_repos_config.copy()
for source, project in tenant.project_repos:
for branch in source.getProjectBranches(project):
def _loadDynamicProjectData(self, config, source, project, files,
config_repo):
for branch in source.getProjectBranches(project):
data = None
if config_repo:
data = files.getFile(project.name, branch, 'zuul.yaml')
if not data:
data = files.getFile(project.name, branch, '.zuul.yaml')
if data:
source_context = model.SourceContext(project,
branch, False)
incdata = TenantParser._parseProjectRepoLayout(
if data:
source_context = model.SourceContext(project, branch,
config_repo)
if config_repo:
incdata = TenantParser._parseConfigRepoLayout(
data, source_context)
else:
incdata = project.unparsed_branch_config[branch]
if not incdata:
continue
config.extend(incdata)
incdata = TenantParser._parseProjectRepoLayout(
data, source_context)
else:
incdata = project.unparsed_branch_config.get(branch)
if not incdata:
continue
config.extend(incdata)
def createDynamicLayout(self, tenant, files, include_config_repos=False):
if include_config_repos:
config = model.UnparsedTenantConfig()
for source, project in tenant.config_repos:
self._loadDynamicProjectData(config, source, project,
files, True)
else:
config = tenant.config_repos_config.copy()
for source, project in tenant.project_repos:
self._loadDynamicProjectData(config, source, project,
files, False)
layout = model.Layout()
# TODOv3(jeblair): copying the pipelines could be dangerous/confusing.
layout.pipelines = tenant.layout.pipelines

View File

@ -466,6 +466,43 @@ class PipelineManager(object):
newrev=newrev,
)
def _loadDynamicLayout(self, item):
# Load layout
# Late import to break an import loop
import zuul.configloader
loader = zuul.configloader.ConfigLoader()
build_set = item.current_build_set
self.log.debug("Load dynamic layout with %s" % build_set.files)
try:
# First parse the config with as it will land with the
# full set of config and project repos. This lets us
# catch syntax errors in config repos even though we won't
# actually run with that config.
loader.createDynamicLayout(
item.pipeline.layout.tenant,
build_set.files,
include_config_repos=True)
# Then create the config a second time but without changes
# to config repos so that we actually use this config.
layout = loader.createDynamicLayout(
item.pipeline.layout.tenant,
build_set.files,
include_config_repos=False)
except zuul.configloader.ConfigurationSyntaxError as e:
self.log.info("Configuration syntax error "
"in dynamic layout %s" %
build_set.files)
item.setConfigError(str(e))
return None
except Exception:
self.log.exception("Error in dynamic layout %s" %
build_set.files)
item.setConfigError("Unknown configuration error")
return None
return layout
def getLayout(self, item):
if not item.change.updatesConfig():
if item.item_ahead:
@ -479,27 +516,7 @@ class PipelineManager(object):
if build_set.merge_state == build_set.COMPLETE:
if build_set.unable_to_merge:
return None
# Load layout
# Late import to break an import loop
import zuul.configloader
loader = zuul.configloader.ConfigLoader()
self.log.debug("Load dynamic layout with %s" % build_set.files)
try:
layout = loader.createDynamicLayout(
item.pipeline.layout.tenant,
build_set.files)
except zuul.configloader.ConfigurationSyntaxError as e:
self.log.info("Configuration syntax error "
"in dynamic layout %s" %
build_set.files)
item.setConfigError(str(e))
return None
except Exception:
self.log.exception("Error in dynamic layout %s" %
build_set.files)
item.setConfigError("Unknown configuration error")
return None
return layout
return self._loadDynamicLayout(item)
build_set.merge_state = build_set.PENDING
self.log.debug("Preparing dynamic layout for: %s" % item.change)
dependent_items = self.getDependentItems(item)
@ -508,7 +525,7 @@ class PipelineManager(object):
merger_items = map(self._makeMergerItem, all_items)
self.sched.merger.mergeChanges(merger_items,
item.current_build_set,
['.zuul.yaml'],
['zuul.yaml', '.zuul.yaml'],
self.pipeline.precedence)
def prepareLayout(self, item):