Merge "Add abstract job attribute"
This commit is contained in:
commit
ad82bbf09f
|
@ -546,6 +546,12 @@ Here is an example of two job definitions:
|
|||
from this job. Once this is set to ``true`` it cannot be reset to
|
||||
``false``.
|
||||
|
||||
.. attr:: abstract
|
||||
:default: false
|
||||
|
||||
To indicate a job is not intended to be run directly, but
|
||||
instead must be inherited from, set this attribute to ``true``.
|
||||
|
||||
.. attr:: success-message
|
||||
:default: SUCCESS
|
||||
|
||||
|
|
|
@ -0,0 +1,2 @@
|
|||
- hosts: all
|
||||
tasks: []
|
|
@ -0,0 +1,25 @@
|
|||
- pipeline:
|
||||
name: check
|
||||
manager: independent
|
||||
trigger:
|
||||
gerrit:
|
||||
- event: patchset-created
|
||||
success:
|
||||
gerrit:
|
||||
Verified: 1
|
||||
failure:
|
||||
gerrit:
|
||||
Verified: -1
|
||||
|
||||
- job:
|
||||
name: base
|
||||
parent: null
|
||||
run: playbooks/base.yaml
|
||||
|
||||
- job:
|
||||
name: job-abstract
|
||||
abstract: true
|
||||
|
||||
- job:
|
||||
name: job-child
|
||||
parent: job-abstract
|
|
@ -0,0 +1,4 @@
|
|||
- project:
|
||||
name: org/project
|
||||
check:
|
||||
jobs: []
|
|
@ -0,0 +1,8 @@
|
|||
- tenant:
|
||||
name: tenant-one
|
||||
source:
|
||||
gerrit:
|
||||
config-projects:
|
||||
- common-config
|
||||
untrusted-projects:
|
||||
- org/project
|
|
@ -74,44 +74,43 @@ class TestMultipleTenants(AnsibleZuulTestCase):
|
|||
|
||||
|
||||
class TestProtected(ZuulTestCase):
|
||||
|
||||
tenant_config_file = 'config/protected/main.yaml'
|
||||
|
||||
def test_protected_ok(self):
|
||||
# test clean usage of final parent job
|
||||
in_repo_conf = textwrap.dedent(
|
||||
"""
|
||||
- job:
|
||||
name: job-protected
|
||||
protected: true
|
||||
run: playbooks/job-protected.yaml
|
||||
# test clean usage of final parent job
|
||||
in_repo_conf = textwrap.dedent(
|
||||
"""
|
||||
- job:
|
||||
name: job-protected
|
||||
protected: true
|
||||
run: playbooks/job-protected.yaml
|
||||
|
||||
- project:
|
||||
name: org/project
|
||||
check:
|
||||
jobs:
|
||||
- job-child-ok
|
||||
- project:
|
||||
name: org/project
|
||||
check:
|
||||
jobs:
|
||||
- job-child-ok
|
||||
|
||||
- job:
|
||||
name: job-child-ok
|
||||
parent: job-protected
|
||||
- job:
|
||||
name: job-child-ok
|
||||
parent: job-protected
|
||||
|
||||
- project:
|
||||
name: org/project
|
||||
check:
|
||||
jobs:
|
||||
- job-child-ok
|
||||
- project:
|
||||
name: org/project
|
||||
check:
|
||||
jobs:
|
||||
- job-child-ok
|
||||
|
||||
""")
|
||||
""")
|
||||
|
||||
file_dict = {'zuul.yaml': in_repo_conf}
|
||||
A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
|
||||
files=file_dict)
|
||||
self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
|
||||
self.waitUntilSettled()
|
||||
file_dict = {'zuul.yaml': in_repo_conf}
|
||||
A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
|
||||
files=file_dict)
|
||||
self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
|
||||
self.waitUntilSettled()
|
||||
|
||||
self.assertEqual(A.reported, 1)
|
||||
self.assertEqual(A.patchsets[-1]['approvals'][0]['value'], '1')
|
||||
self.assertEqual(A.reported, 1)
|
||||
self.assertEqual(A.patchsets[-1]['approvals'][0]['value'], '1')
|
||||
|
||||
def test_protected_reset(self):
|
||||
# try to reset protected flag
|
||||
|
@ -177,6 +176,47 @@ class TestProtected(ZuulTestCase):
|
|||
"and cannot be inherited from other projects.", A.messages[0])
|
||||
|
||||
|
||||
class TestAbstract(ZuulTestCase):
|
||||
tenant_config_file = 'config/abstract/main.yaml'
|
||||
|
||||
def test_abstract_fail(self):
|
||||
in_repo_conf = textwrap.dedent(
|
||||
"""
|
||||
- project:
|
||||
check:
|
||||
jobs:
|
||||
- job-abstract
|
||||
""")
|
||||
|
||||
file_dict = {'zuul.yaml': in_repo_conf}
|
||||
A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
|
||||
files=file_dict)
|
||||
self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
|
||||
self.waitUntilSettled()
|
||||
|
||||
self.assertEqual(A.reported, 1)
|
||||
self.assertEqual(A.patchsets[-1]['approvals'][0]['value'], '-1')
|
||||
self.assertIn('may not be directly run', A.messages[0])
|
||||
|
||||
def test_child_of_abstract(self):
|
||||
in_repo_conf = textwrap.dedent(
|
||||
"""
|
||||
- project:
|
||||
check:
|
||||
jobs:
|
||||
- job-child
|
||||
""")
|
||||
|
||||
file_dict = {'zuul.yaml': in_repo_conf}
|
||||
A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
|
||||
files=file_dict)
|
||||
self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
|
||||
self.waitUntilSettled()
|
||||
|
||||
self.assertEqual(A.reported, 1)
|
||||
self.assertEqual(A.patchsets[-1]['approvals'][0]['value'], '1')
|
||||
|
||||
|
||||
class TestFinal(ZuulTestCase):
|
||||
|
||||
tenant_config_file = 'config/final/main.yaml'
|
||||
|
|
|
@ -474,6 +474,7 @@ class JobParser(object):
|
|||
# Attributes of a job that can also be used in Project and ProjectTemplate
|
||||
job_attributes = {'parent': vs.Any(str, None),
|
||||
'final': bool,
|
||||
'abstract': bool,
|
||||
'protected': bool,
|
||||
'failure-message': str,
|
||||
'success-message': str,
|
||||
|
@ -514,6 +515,7 @@ class JobParser(object):
|
|||
|
||||
simple_attributes = [
|
||||
'final',
|
||||
'abstract',
|
||||
'protected',
|
||||
'timeout',
|
||||
'workspace',
|
||||
|
|
|
@ -848,6 +848,7 @@ class Job(object):
|
|||
semaphore=None,
|
||||
attempts=3,
|
||||
final=False,
|
||||
abstract=False,
|
||||
protected=None,
|
||||
roles=(),
|
||||
required_projects={},
|
||||
|
@ -1044,7 +1045,7 @@ class Job(object):
|
|||
|
||||
for k in self.execution_attributes:
|
||||
if (other._get(k) is not None and
|
||||
k not in set(['final', 'protected'])):
|
||||
k not in set(['final', 'abstract', 'protected'])):
|
||||
if self.final:
|
||||
raise Exception("Unable to modify final job %s attribute "
|
||||
"%s=%s with variant %s" % (
|
||||
|
@ -1070,6 +1071,13 @@ class Job(object):
|
|||
if other.final != self.attributes['final']:
|
||||
self.final = other.final
|
||||
|
||||
# Abstract may not be reset by a variant, it may only be
|
||||
# cleared by inheriting.
|
||||
if other.name != self.name:
|
||||
self.abstract = other.abstract
|
||||
elif other.abstract:
|
||||
self.abstract = True
|
||||
|
||||
# Protected may only be set to true
|
||||
if other.protected is not None:
|
||||
# don't allow to reset protected flag
|
||||
|
@ -2836,6 +2844,10 @@ class Layout(object):
|
|||
item.debug("No matching pipeline variants for {jobname}".
|
||||
format(jobname=jobname), indent=2)
|
||||
continue
|
||||
if frozen_job.abstract:
|
||||
raise Exception("Job %s is abstract and may not be "
|
||||
"directly run" %
|
||||
(frozen_job.name,))
|
||||
if (frozen_job.allowed_projects is not None and
|
||||
change.project.name not in frozen_job.allowed_projects):
|
||||
raise Exception("Project %s is not allowed to run job %s" %
|
||||
|
|
Loading…
Reference in New Issue