Merge "Add implied-branch-matchers to tenant config"
This commit is contained in:
commit
640d65a647
|
@ -1036,7 +1036,9 @@ Here is an example of two job definitions:
|
||||||
only affect it.
|
only affect it.
|
||||||
|
|
||||||
See :attr:`pragma.implied-branch-matchers` for how to override
|
See :attr:`pragma.implied-branch-matchers` for how to override
|
||||||
this behavior on a per-file basis.
|
this behavior on a per-file basis. The behavior may also be
|
||||||
|
configured by a Zuul administrator using
|
||||||
|
:attr:`tenant.untrusted-projects.<project>.implied-branch-matchers`.
|
||||||
|
|
||||||
.. attr:: files
|
.. attr:: files
|
||||||
|
|
||||||
|
|
|
@ -25,7 +25,7 @@ pragma directives may not be set and then unset within the same file.
|
||||||
.. attr:: implied-branch-matchers
|
.. attr:: implied-branch-matchers
|
||||||
|
|
||||||
This is a boolean, which, if set, may be used to enable
|
This is a boolean, which, if set, may be used to enable
|
||||||
(``True``) or disable (``False``) the addition of implied branch
|
(``true``) or disable (``false``) the addition of implied branch
|
||||||
matchers to job and project-template definitions. Normally Zuul
|
matchers to job and project-template definitions. Normally Zuul
|
||||||
decides whether to add these based on heuristics described in
|
decides whether to add these based on heuristics described in
|
||||||
:attr:`job.branches`. This attribute overrides that behavior.
|
:attr:`job.branches`. This attribute overrides that behavior.
|
||||||
|
@ -33,6 +33,11 @@ pragma directives may not be set and then unset within the same file.
|
||||||
This can be useful if a project has multiple branches, yet the
|
This can be useful if a project has multiple branches, yet the
|
||||||
jobs defined in the master branch should apply to all branches.
|
jobs defined in the master branch should apply to all branches.
|
||||||
|
|
||||||
|
The behavior may also be configured by a Zuul administrator
|
||||||
|
using
|
||||||
|
:attr:`tenant.untrusted-projects.<project>.implied-branch-matchers`.
|
||||||
|
This pragma overrides that setting if both are present.
|
||||||
|
|
||||||
Note that if a job contains an explicit branch matcher, it will
|
Note that if a job contains an explicit branch matcher, it will
|
||||||
be used regardless of the value supplied here.
|
be used regardless of the value supplied here.
|
||||||
|
|
||||||
|
|
|
@ -270,6 +270,27 @@ configuration. Some examples of tenant definitions are:
|
||||||
circumstances and only calculate the configuration of a
|
circumstances and only calculate the configuration of a
|
||||||
single additional branch when it is used.
|
single additional branch when it is used.
|
||||||
|
|
||||||
|
.. attr:: implied-branch-matchers
|
||||||
|
|
||||||
|
This is a boolean, which, if set, may be used to enable
|
||||||
|
(``true``) or disable (``false``) the addition of implied
|
||||||
|
branch matchers to job and project-template definitions.
|
||||||
|
Normally Zuul decides whether to add these based on
|
||||||
|
heuristics described in :attr:`job.branches`. This
|
||||||
|
attribute overrides that behavior.
|
||||||
|
|
||||||
|
This can be useful if branch settings for this project may
|
||||||
|
produce an unpredictable number of branches to load from.
|
||||||
|
Setting this value explicitly here can avoid unexpected
|
||||||
|
behavior changes as branches are added or removed from the
|
||||||
|
load set.
|
||||||
|
|
||||||
|
The :attr:`pragma.implied-branch-matchers` pragma will
|
||||||
|
override the setting here if present.
|
||||||
|
|
||||||
|
Note that if a job contains an explicit branch matcher, it
|
||||||
|
will be used regardless of the value supplied here.
|
||||||
|
|
||||||
.. attr:: extra-config-paths
|
.. attr:: extra-config-paths
|
||||||
|
|
||||||
Normally Zuul loads in-repo configuration from the first
|
Normally Zuul loads in-repo configuration from the first
|
||||||
|
|
|
@ -0,0 +1,10 @@
|
||||||
|
---
|
||||||
|
features:
|
||||||
|
- |
|
||||||
|
A new tenant project configuration option,
|
||||||
|
`implied-branch-matchers` has been added. This is useful in
|
||||||
|
conjunction with the branch exclusion options which may cause Zuul
|
||||||
|
to change behavior as the set of load branches switches between
|
||||||
|
one and more than one. The operator can fix the appropriate
|
||||||
|
behavior in the tenant config file rather than relying on the
|
||||||
|
heuristic in these cases.
|
53
tests/fixtures/config/tenant-implied-branch-matchers/git/common-config/zuul.yaml
vendored
Normal file
53
tests/fixtures/config/tenant-implied-branch-matchers/git/common-config/zuul.yaml
vendored
Normal file
|
@ -0,0 +1,53 @@
|
||||||
|
- pipeline:
|
||||||
|
name: check
|
||||||
|
manager: independent
|
||||||
|
trigger:
|
||||||
|
gerrit:
|
||||||
|
- event: patchset-created
|
||||||
|
success:
|
||||||
|
gerrit:
|
||||||
|
Verified: 1
|
||||||
|
failure:
|
||||||
|
gerrit:
|
||||||
|
Verified: -1
|
||||||
|
|
||||||
|
- pipeline:
|
||||||
|
name: gate
|
||||||
|
manager: dependent
|
||||||
|
post-review: True
|
||||||
|
trigger:
|
||||||
|
gerrit:
|
||||||
|
- event: comment-added
|
||||||
|
approval:
|
||||||
|
- Approved: 1
|
||||||
|
success:
|
||||||
|
gerrit:
|
||||||
|
Verified: 2
|
||||||
|
submit: true
|
||||||
|
failure:
|
||||||
|
gerrit:
|
||||||
|
Verified: -2
|
||||||
|
start:
|
||||||
|
gerrit:
|
||||||
|
Verified: 0
|
||||||
|
precedence: high
|
||||||
|
|
||||||
|
- job:
|
||||||
|
name: base
|
||||||
|
parent: null
|
||||||
|
|
||||||
|
- project:
|
||||||
|
name: common-config
|
||||||
|
check:
|
||||||
|
jobs: []
|
||||||
|
gate:
|
||||||
|
jobs:
|
||||||
|
- noop
|
||||||
|
|
||||||
|
- project:
|
||||||
|
name: org/project
|
||||||
|
check:
|
||||||
|
jobs: []
|
||||||
|
gate:
|
||||||
|
jobs:
|
||||||
|
- noop
|
|
@ -0,0 +1 @@
|
||||||
|
test
|
2
tests/fixtures/config/tenant-implied-branch-matchers/git/org_project/playbooks/test-job.yaml
vendored
Normal file
2
tests/fixtures/config/tenant-implied-branch-matchers/git/org_project/playbooks/test-job.yaml
vendored
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
- hosts: all
|
||||||
|
tasks: []
|
2
tests/fixtures/config/tenant-implied-branch-matchers/git/org_project/zuul.yaml
vendored
Normal file
2
tests/fixtures/config/tenant-implied-branch-matchers/git/org_project/zuul.yaml
vendored
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
- job:
|
||||||
|
name: test-job
|
|
@ -0,0 +1,9 @@
|
||||||
|
- tenant:
|
||||||
|
name: tenant-one
|
||||||
|
source:
|
||||||
|
gerrit:
|
||||||
|
config-projects:
|
||||||
|
- common-config
|
||||||
|
untrusted-projects:
|
||||||
|
- org/project:
|
||||||
|
implied-branch-matchers: true
|
|
@ -6105,6 +6105,48 @@ class TestPragmaMultibranch(ZuulTestCase):
|
||||||
], ordered=False)
|
], ordered=False)
|
||||||
|
|
||||||
|
|
||||||
|
class TestTenantImpliedBranchMatchers(ZuulTestCase):
|
||||||
|
tenant_config_file = 'config/tenant-implied-branch-matchers/main.yaml'
|
||||||
|
|
||||||
|
def test_tenant_implied_branch_matchers(self):
|
||||||
|
# Test that we can force implied branch matchers in the tenant
|
||||||
|
# config even in the case where a project only has one branch.
|
||||||
|
tenant = self.scheds.first.sched.abide.tenants.get('tenant-one')
|
||||||
|
jobs = tenant.layout.getJobs('test-job')
|
||||||
|
self.assertEqual(len(jobs), 1)
|
||||||
|
for job in tenant.layout.getJobs('test-job'):
|
||||||
|
self.assertIsNotNone(job.branch_matcher)
|
||||||
|
|
||||||
|
def test_pragma_overrides_tenant_implied_branch_matchers(self):
|
||||||
|
# Test that we can force implied branch matchers off with a pragma
|
||||||
|
# even if the tenant config has it set on.
|
||||||
|
config = textwrap.dedent(
|
||||||
|
"""
|
||||||
|
- job:
|
||||||
|
name: test-job
|
||||||
|
- pragma:
|
||||||
|
implied-branch-matchers: False
|
||||||
|
""")
|
||||||
|
file_dict = {'zuul.yaml': config}
|
||||||
|
A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
|
||||||
|
files=file_dict)
|
||||||
|
A.setMerged()
|
||||||
|
self.fake_gerrit.addEvent(A.getChangeMergedEvent())
|
||||||
|
self.waitUntilSettled()
|
||||||
|
|
||||||
|
self.create_branch('org/project', 'stable/pike')
|
||||||
|
self.fake_gerrit.addEvent(
|
||||||
|
self.fake_gerrit.getFakeBranchCreatedEvent(
|
||||||
|
'org/project', 'stable/pike'))
|
||||||
|
self.waitUntilSettled()
|
||||||
|
|
||||||
|
tenant = self.scheds.first.sched.abide.tenants.get('tenant-one')
|
||||||
|
jobs = tenant.layout.getJobs('test-job')
|
||||||
|
self.assertEqual(len(jobs), 2)
|
||||||
|
for job in tenant.layout.getJobs('test-job'):
|
||||||
|
self.assertIsNone(job.branch_matcher)
|
||||||
|
|
||||||
|
|
||||||
class TestBaseJobs(ZuulTestCase):
|
class TestBaseJobs(ZuulTestCase):
|
||||||
tenant_config_file = 'config/base-jobs/main.yaml'
|
tenant_config_file = 'config/base-jobs/main.yaml'
|
||||||
|
|
||||||
|
|
|
@ -1690,7 +1690,7 @@ class ParseContext(object):
|
||||||
|
|
||||||
def getImpliedBranches(self, source_context):
|
def getImpliedBranches(self, source_context):
|
||||||
# If the user has set a pragma directive for this, use the
|
# If the user has set a pragma directive for this, use the
|
||||||
# value (if unset, the value is None).
|
# value (ixf unset, the value is None).
|
||||||
if source_context.implied_branch_matchers is True:
|
if source_context.implied_branch_matchers is True:
|
||||||
if source_context.implied_branches is not None:
|
if source_context.implied_branches is not None:
|
||||||
return source_context.implied_branches
|
return source_context.implied_branches
|
||||||
|
@ -1742,6 +1742,7 @@ class TenantParser(object):
|
||||||
'exclude-branches': to_list(str),
|
'exclude-branches': to_list(str),
|
||||||
'always-dynamic-branches': to_list(str),
|
'always-dynamic-branches': to_list(str),
|
||||||
'allow-circular-dependencies': bool,
|
'allow-circular-dependencies': bool,
|
||||||
|
'implied-branch-matchers': bool,
|
||||||
}}
|
}}
|
||||||
|
|
||||||
project = vs.Any(str, project_dict)
|
project = vs.Any(str, project_dict)
|
||||||
|
@ -1985,6 +1986,7 @@ class TenantParser(object):
|
||||||
project_exclude_branches = None
|
project_exclude_branches = None
|
||||||
project_always_dynamic_branches = None
|
project_always_dynamic_branches = None
|
||||||
project_load_branch = None
|
project_load_branch = None
|
||||||
|
project_implied_branch_matchers = None
|
||||||
else:
|
else:
|
||||||
project_name = list(conf.keys())[0]
|
project_name = list(conf.keys())[0]
|
||||||
project = source.getProject(project_name)
|
project = source.getProject(project_name)
|
||||||
|
@ -2039,6 +2041,8 @@ class TenantParser(object):
|
||||||
if x.endswith('/')])
|
if x.endswith('/')])
|
||||||
project_load_branch = conf[project_name].get(
|
project_load_branch = conf[project_name].get(
|
||||||
'load-branch', None)
|
'load-branch', None)
|
||||||
|
project_implied_branch_matchers = conf[project_name].get(
|
||||||
|
'implied-branch-matchers', None)
|
||||||
|
|
||||||
tenant_project_config = model.TenantProjectConfig(project)
|
tenant_project_config = model.TenantProjectConfig(project)
|
||||||
tenant_project_config.load_classes = frozenset(project_include)
|
tenant_project_config.load_classes = frozenset(project_include)
|
||||||
|
@ -2052,6 +2056,8 @@ class TenantParser(object):
|
||||||
tenant_project_config.extra_config_files = extra_config_files
|
tenant_project_config.extra_config_files = extra_config_files
|
||||||
tenant_project_config.extra_config_dirs = extra_config_dirs
|
tenant_project_config.extra_config_dirs = extra_config_dirs
|
||||||
tenant_project_config.load_branch = project_load_branch
|
tenant_project_config.load_branch = project_load_branch
|
||||||
|
tenant_project_config.implied_branch_matchers = \
|
||||||
|
project_implied_branch_matchers
|
||||||
|
|
||||||
return tenant_project_config
|
return tenant_project_config
|
||||||
|
|
||||||
|
@ -2231,7 +2237,8 @@ class TenantParser(object):
|
||||||
# accumulates a list of all merger jobs submitted.
|
# accumulates a list of all merger jobs submitted.
|
||||||
source_context = model.SourceContext(
|
source_context = model.SourceContext(
|
||||||
project.canonical_name, project.name,
|
project.canonical_name, project.name,
|
||||||
project.connection_name, branch, '', False)
|
project.connection_name, branch, '', False,
|
||||||
|
tpc.implied_branch_matchers)
|
||||||
if min_ltimes is not None:
|
if min_ltimes is not None:
|
||||||
files_cache = self.unparsed_config_cache.getFilesCache(
|
files_cache = self.unparsed_config_cache.getFilesCache(
|
||||||
project.canonical_name, branch)
|
project.canonical_name, branch)
|
||||||
|
@ -2966,7 +2973,8 @@ class ConfigLoader(object):
|
||||||
if data:
|
if data:
|
||||||
source_context = model.SourceContext(
|
source_context = model.SourceContext(
|
||||||
project.canonical_name, project.name,
|
project.canonical_name, project.name,
|
||||||
project.connection_name, branch, fn, trusted)
|
project.connection_name, branch, fn, trusted,
|
||||||
|
tpc.implied_branch_matchers)
|
||||||
# Prevent mixing configuration source
|
# Prevent mixing configuration source
|
||||||
conf_root = fn.split('/')[0]
|
conf_root = fn.split('/')[0]
|
||||||
|
|
||||||
|
|
|
@ -1914,7 +1914,8 @@ class SourceContext(ConfigObject):
|
||||||
originate."""
|
originate."""
|
||||||
|
|
||||||
def __init__(self, project_canonical_name, project_name,
|
def __init__(self, project_canonical_name, project_name,
|
||||||
project_connection_name, branch, path, trusted):
|
project_connection_name, branch, path, trusted,
|
||||||
|
implied_branch_matchers=None):
|
||||||
super(SourceContext, self).__init__()
|
super(SourceContext, self).__init__()
|
||||||
self.project_canonical_name = project_canonical_name
|
self.project_canonical_name = project_canonical_name
|
||||||
self.project_name = project_name
|
self.project_name = project_name
|
||||||
|
@ -1922,7 +1923,7 @@ class SourceContext(ConfigObject):
|
||||||
self.branch = branch
|
self.branch = branch
|
||||||
self.path = path
|
self.path = path
|
||||||
self.trusted = trusted
|
self.trusted = trusted
|
||||||
self.implied_branch_matchers = None
|
self.implied_branch_matchers = implied_branch_matchers
|
||||||
self.implied_branches = None
|
self.implied_branches = None
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
|
@ -1939,7 +1940,8 @@ class SourceContext(ConfigObject):
|
||||||
def copy(self):
|
def copy(self):
|
||||||
return self.__class__(
|
return self.__class__(
|
||||||
self.project_canonical_name, self.project_name,
|
self.project_canonical_name, self.project_name,
|
||||||
self.project_connection_name, self.branch, self.path, self.trusted)
|
self.project_connection_name, self.branch, self.path, self.trusted,
|
||||||
|
self.implied_branch_matchers)
|
||||||
|
|
||||||
def isSameProject(self, other):
|
def isSameProject(self, other):
|
||||||
if not isinstance(other, SourceContext):
|
if not isinstance(other, SourceContext):
|
||||||
|
@ -7263,6 +7265,7 @@ class TenantProjectConfig(object):
|
||||||
# Load config from a different branch if this is a config project
|
# Load config from a different branch if this is a config project
|
||||||
self.load_branch = None
|
self.load_branch = None
|
||||||
self.merge_modes = None
|
self.merge_modes = None
|
||||||
|
self.implied_branch_matchers = None
|
||||||
|
|
||||||
def isAlwaysDynamicBranch(self, branch):
|
def isAlwaysDynamicBranch(self, branch):
|
||||||
if self.always_dynamic_branches is None:
|
if self.always_dynamic_branches is None:
|
||||||
|
|
Loading…
Reference in New Issue