Merge "Provide error message on malformed job list" into feature/zuulv3
This commit is contained in:
commit
7099e5873d
|
@ -67,7 +67,7 @@
|
||||||
dependencies: project-merge
|
dependencies: project-merge
|
||||||
gate:
|
gate:
|
||||||
jobs:
|
jobs:
|
||||||
- project-merge:
|
- project-merge
|
||||||
- project-test1:
|
- project-test1:
|
||||||
dependencies: project-merge
|
dependencies: project-merge
|
||||||
- project-test2:
|
- project-test2:
|
||||||
|
|
|
@ -851,6 +851,60 @@ class TestInRepoConfig(ZuulTestCase):
|
||||||
A.messages[0],
|
A.messages[0],
|
||||||
"A should have a syntax error reported")
|
"A should have a syntax error reported")
|
||||||
|
|
||||||
|
def test_job_list_in_project_template_not_dict_error(self):
|
||||||
|
in_repo_conf = textwrap.dedent(
|
||||||
|
"""
|
||||||
|
- job:
|
||||||
|
name: project-test1
|
||||||
|
- project-template:
|
||||||
|
name: some-jobs
|
||||||
|
check:
|
||||||
|
jobs:
|
||||||
|
- project-test1:
|
||||||
|
- required-projects:
|
||||||
|
org/project2
|
||||||
|
""")
|
||||||
|
|
||||||
|
file_dict = {'.zuul.yaml': in_repo_conf}
|
||||||
|
A = self.fake_gerrit.addFakeChange('org/project', '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, 1,
|
||||||
|
"A should report failure")
|
||||||
|
self.assertIn('expected str for dictionary value',
|
||||||
|
A.messages[0], "A should have a syntax error reported")
|
||||||
|
|
||||||
|
def test_job_list_in_project_not_dict_error(self):
|
||||||
|
in_repo_conf = textwrap.dedent(
|
||||||
|
"""
|
||||||
|
- job:
|
||||||
|
name: project-test1
|
||||||
|
- project:
|
||||||
|
name: org/project1
|
||||||
|
check:
|
||||||
|
jobs:
|
||||||
|
- project-test1:
|
||||||
|
- required-projects:
|
||||||
|
org/project2
|
||||||
|
""")
|
||||||
|
|
||||||
|
file_dict = {'.zuul.yaml': in_repo_conf}
|
||||||
|
A = self.fake_gerrit.addFakeChange('org/project', '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, 1,
|
||||||
|
"A should report failure")
|
||||||
|
self.assertIn('expected str for dictionary value',
|
||||||
|
A.messages[0], "A should have a syntax error reported")
|
||||||
|
|
||||||
def test_multi_repo(self):
|
def test_multi_repo(self):
|
||||||
downstream_repo_conf = textwrap.dedent(
|
downstream_repo_conf = textwrap.dedent(
|
||||||
"""
|
"""
|
||||||
|
|
|
@ -11,6 +11,7 @@
|
||||||
# under the License.
|
# under the License.
|
||||||
|
|
||||||
import base64
|
import base64
|
||||||
|
import collections
|
||||||
from contextlib import contextmanager
|
from contextlib import contextmanager
|
||||||
import copy
|
import copy
|
||||||
import os
|
import os
|
||||||
|
@ -397,39 +398,42 @@ class JobParser(object):
|
||||||
secret = {vs.Required('name'): str,
|
secret = {vs.Required('name'): str,
|
||||||
vs.Required('secret'): str}
|
vs.Required('secret'): str}
|
||||||
|
|
||||||
job = {vs.Required('name'): str,
|
# Attributes of a job that can also be used in Project and ProjectTemplate
|
||||||
'parent': vs.Any(str, None),
|
job_attributes = {'parent': vs.Any(str, None),
|
||||||
'final': bool,
|
'final': bool,
|
||||||
'failure-message': str,
|
'failure-message': str,
|
||||||
'success-message': str,
|
'success-message': str,
|
||||||
'failure-url': str,
|
'failure-url': str,
|
||||||
'success-url': str,
|
'success-url': str,
|
||||||
'hold-following-changes': bool,
|
'hold-following-changes': bool,
|
||||||
'voting': bool,
|
'voting': bool,
|
||||||
'semaphore': str,
|
'semaphore': str,
|
||||||
'tags': to_list(str),
|
'tags': to_list(str),
|
||||||
'branches': to_list(str),
|
'branches': to_list(str),
|
||||||
'files': to_list(str),
|
'files': to_list(str),
|
||||||
'secrets': to_list(vs.Any(secret, str)),
|
'secrets': to_list(vs.Any(secret, str)),
|
||||||
'irrelevant-files': to_list(str),
|
'irrelevant-files': to_list(str),
|
||||||
# validation happens in NodeSetParser
|
# validation happens in NodeSetParser
|
||||||
'nodeset': vs.Any(dict, str),
|
'nodeset': vs.Any(dict, str),
|
||||||
'timeout': int,
|
'timeout': int,
|
||||||
'attempts': int,
|
'attempts': int,
|
||||||
'pre-run': to_list(str),
|
'pre-run': to_list(str),
|
||||||
'post-run': to_list(str),
|
'post-run': to_list(str),
|
||||||
'run': str,
|
'run': str,
|
||||||
'_source_context': model.SourceContext,
|
'_source_context': model.SourceContext,
|
||||||
'_start_mark': ZuulMark,
|
'_start_mark': ZuulMark,
|
||||||
'roles': to_list(role),
|
'roles': to_list(role),
|
||||||
'required-projects': to_list(vs.Any(job_project, str)),
|
'required-projects': to_list(vs.Any(job_project, str)),
|
||||||
'vars': dict,
|
'vars': dict,
|
||||||
'dependencies': to_list(str),
|
'dependencies': to_list(str),
|
||||||
'allowed-projects': to_list(str),
|
'allowed-projects': to_list(str),
|
||||||
'override-branch': str,
|
'override-branch': str,
|
||||||
'description': str,
|
'description': str,
|
||||||
'post-review': bool
|
'post-review': bool}
|
||||||
}
|
|
||||||
|
job_name = {vs.Required('name'): str}
|
||||||
|
|
||||||
|
job = dict(collections.ChainMap(job_name, job_attributes))
|
||||||
|
|
||||||
schema = vs.Schema(job)
|
schema = vs.Schema(job)
|
||||||
|
|
||||||
|
@ -725,9 +729,12 @@ class ProjectTemplateParser(object):
|
||||||
'_start_mark': ZuulMark,
|
'_start_mark': ZuulMark,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
job = {str: vs.Any(str, JobParser.job_attributes)}
|
||||||
|
job_list = [vs.Any(str, job)]
|
||||||
|
pipeline_contents = {'queue': str, 'jobs': job_list}
|
||||||
|
|
||||||
for p in self.layout.pipelines.values():
|
for p in self.layout.pipelines.values():
|
||||||
project_template[p.name] = {'queue': str,
|
project_template[p.name] = pipeline_contents
|
||||||
'jobs': [vs.Any(str, dict)]}
|
|
||||||
return vs.Schema(project_template)
|
return vs.Schema(project_template)
|
||||||
|
|
||||||
def fromYaml(self, conf, validate=True):
|
def fromYaml(self, conf, validate=True):
|
||||||
|
@ -796,9 +803,12 @@ class ProjectParser(object):
|
||||||
'_start_mark': ZuulMark,
|
'_start_mark': ZuulMark,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
job = {str: vs.Any(str, JobParser.job_attributes)}
|
||||||
|
job_list = [vs.Any(str, job)]
|
||||||
|
pipeline_contents = {'queue': str, 'jobs': job_list}
|
||||||
|
|
||||||
for p in self.layout.pipelines.values():
|
for p in self.layout.pipelines.values():
|
||||||
project[p.name] = {'queue': str,
|
project[p.name] = pipeline_contents
|
||||||
'jobs': [vs.Any(str, dict)]}
|
|
||||||
return vs.Schema(project)
|
return vs.Schema(project)
|
||||||
|
|
||||||
def fromYaml(self, conf_list):
|
def fromYaml(self, conf_list):
|
||||||
|
|
Loading…
Reference in New Issue