diff --git a/tests/fixtures/config/tenant-parser/git/org_project3/.zuul.yaml b/tests/fixtures/config/tenant-parser/git/org_project3/.zuul.yaml new file mode 100644 index 0000000000..6de845c21f --- /dev/null +++ b/tests/fixtures/config/tenant-parser/git/org_project3/.zuul.yaml @@ -0,0 +1,10 @@ +- job: + name: project3-job + required-projects: + - doesnot/exist + +- project: + name: org/project3 + check: + jobs: + - project3-job diff --git a/tests/fixtures/config/tenant-parser/groups2.yaml b/tests/fixtures/config/tenant-parser/groups2.yaml index dc8d339568..2da980b534 100644 --- a/tests/fixtures/config/tenant-parser/groups2.yaml +++ b/tests/fixtures/config/tenant-parser/groups2.yaml @@ -10,3 +10,5 @@ - org/project1 - org/project2: exclude: job + - org/project3: + exclude: job diff --git a/tests/unit/test_configloader.py b/tests/unit/test_configloader.py index 35c9b5dd4d..0e963d064a 100644 --- a/tests/unit/test_configloader.py +++ b/tests/unit/test_configloader.py @@ -153,7 +153,7 @@ class TestTenantGroups2(TenantParserTestCase): tenant = self.sched.abide.tenants.get('tenant-one') self.assertEqual(['common-config'], [x.name for x in tenant.config_projects]) - self.assertEqual(['org/project1', 'org/project2'], + self.assertEqual(['org/project1', 'org/project2', 'org/project3'], [x.name for x in tenant.untrusted_projects]) project = tenant.config_projects[0] tpc = tenant.project_configs[project.canonical_name] diff --git a/tests/unit/test_v3.py b/tests/unit/test_v3.py index 91715026f5..ed7610ccba 100755 --- a/tests/unit/test_v3.py +++ b/tests/unit/test_v3.py @@ -1582,6 +1582,30 @@ class TestInRepoConfig(ZuulTestCase): self.assertIn('nodeset "does-not-exist" was not found', A.messages[0], "A should have a syntax error reported") + def test_required_project_not_found_error(self): + in_repo_conf = textwrap.dedent( + """ + - job: + name: project-test1 + - job: + name: test + required-projects: + - does-not-exist + """) + + 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('Unknown project does-not-exist', A.messages[0], + "A should have a syntax error reported") + def test_template_not_found_error(self): in_repo_conf = textwrap.dedent( """ diff --git a/zuul/configloader.py b/zuul/configloader.py index 0d1a535de2..bf6dbe4bf1 100644 --- a/zuul/configloader.py +++ b/zuul/configloader.py @@ -1563,7 +1563,7 @@ class TenantParser(object): return data.copy(trusted=False) def _getLoadClasses(self, tenant, conf_object): - project = conf_object.source_context.project + project = conf_object.get('_source_context').project tpc = tenant.project_configs[project.canonical_name] return tpc.load_classes @@ -1577,36 +1577,57 @@ class TenantParser(object): pcontext.pragma_parser.fromYaml(config_pragma) for config_pipeline in unparsed_config.pipelines: + classes = self._getLoadClasses(tenant, config_pipeline) + if 'pipeline' not in classes: + continue with configuration_exceptions('pipeline', config_pipeline): parsed_config.pipelines.append( pcontext.pipeline_parser.fromYaml(config_pipeline)) for config_nodeset in unparsed_config.nodesets: + classes = self._getLoadClasses(tenant, config_nodeset) + if 'nodeset' not in classes: + continue with configuration_exceptions('nodeset', config_nodeset): parsed_config.nodesets.append( pcontext.nodeset_parser.fromYaml(config_nodeset)) for config_secret in unparsed_config.secrets: + classes = self._getLoadClasses(tenant, config_secret) + if 'secret' not in classes: + continue with configuration_exceptions('secret', config_secret): parsed_config.secrets.append( pcontext.secret_parser.fromYaml(config_secret)) for config_job in unparsed_config.jobs: + classes = self._getLoadClasses(tenant, config_job) + if 'job' not in classes: + continue with configuration_exceptions('job', config_job): parsed_config.jobs.append( pcontext.job_parser.fromYaml(config_job)) for config_semaphore in unparsed_config.semaphores: + classes = self._getLoadClasses(tenant, config_semaphore) + if 'semaphore' not in classes: + continue with configuration_exceptions('semaphore', config_semaphore): parsed_config.semaphores.append( pcontext.semaphore_parser.fromYaml(config_semaphore)) for config_template in unparsed_config.project_templates: + classes = self._getLoadClasses(tenant, config_template) + if 'project-template' not in classes: + continue with configuration_exceptions('project-template', config_template): parsed_config.project_templates.append( pcontext.project_template_parser.fromYaml(config_template)) for config_project in unparsed_config.projects: + classes = self._getLoadClasses(tenant, config_project) + if 'project' not in classes: + continue with configuration_exceptions('project', config_project): # we need to separate the regex projects as they are processed # differently later @@ -1665,29 +1686,17 @@ class TenantParser(object): # reference_exceptions has it; add tests if needed. if not skip_pipelines: for pipeline in parsed_config.pipelines: - classes = self._getLoadClasses(tenant, pipeline) - if 'pipeline' not in classes: - continue layout.addPipeline(pipeline) for nodeset in parsed_config.nodesets: - classes = self._getLoadClasses(tenant, nodeset) - if 'nodeset' not in classes: - continue with reference_exceptions('nodeset', nodeset): layout.addNodeSet(nodeset) for secret in parsed_config.secrets: - classes = self._getLoadClasses(tenant, secret) - if 'secret' not in classes: - continue with reference_exceptions('secret', secret): layout.addSecret(secret) for job in parsed_config.jobs: - classes = self._getLoadClasses(tenant, job) - if 'job' not in classes: - continue with reference_exceptions('job', job): added = layout.addJob(job) if not added: @@ -1711,16 +1720,10 @@ class TenantParser(object): else: semaphore_layout = layout for semaphore in parsed_config.semaphores: - classes = self._getLoadClasses(tenant, semaphore) - if 'semaphore' not in classes: - continue with reference_exceptions('semaphore', semaphore): semaphore_layout.addSemaphore(semaphore) for template in parsed_config.project_templates: - classes = self._getLoadClasses(tenant, template) - if 'project-template' not in classes: - continue with reference_exceptions('project-template', template): layout.addProjectTemplate(template) @@ -1741,9 +1744,6 @@ class TenantParser(object): parsed_config.projects.append(conf) for project in parsed_config.projects: - classes = self._getLoadClasses(tenant, project) - if 'project' not in classes: - continue layout.addProjectConfig(project) # Now that all the project pipelines are loaded, fixup and