Apply metajobs in order

Metajobs were being applied in dict key order, which meant that
if more that one metajob matched a job, the actual attributes
applied were non-deterministic.  This was compounded by the fact
that attributes of each metajob were being strictly copied to
the real job, so the attributes of the second metajob would always
completely replace the first.

Instead, keep metajobs in config file order, and only copy attributes
that are non-null.  Boolean attributes are still last-wins, and
so must be set explicitly by each matching metajob.

Change-Id: Ie255658719d5ded1663c3513dae1fc297ce357c4
This commit is contained in:
James E. Blair 2013-07-19 11:37:06 -07:00
parent bd6bc1da9d
commit c28d1b0d19
2 changed files with 20 additions and 13 deletions

View File

@ -437,17 +437,24 @@ class Job(object):
return '<Job %s>' % (self.name)
def copy(self, other):
self.failure_message = other.failure_message
self.success_message = other.success_message
self.failure_pattern = other.failure_pattern
self.success_pattern = other.success_pattern
self.parameter_function = other.parameter_function
if other.failure_message:
self.failure_message = other.failure_message
if other.success_message:
self.success_message = other.success_message
if other.failure_pattern:
self.failure_pattern = other.failure_pattern
if other.success_pattern:
self.success_pattern = other.success_pattern
if other.parameter_function:
self.parameter_function = other.parameter_function
if other.branches:
self.branches = other.branches[:]
self._branches = other._branches[:]
if other.files:
self.files = other.files[:]
self._files = other._files[:]
self.hold_following_changes = other.hold_following_changes
self.voting = other.voting
self.branches = other.branches[:]
self._branches = other._branches[:]
self.files = other.files[:]
self._files = other._files[:]
def changeMatches(self, change):
matches_branch = False
@ -848,7 +855,7 @@ class Layout(object):
self.projects = {}
self.pipelines = {}
self.jobs = {}
self.metajobs = {}
self.metajobs = []
def getJob(self, name):
if name in self.jobs:
@ -857,10 +864,10 @@ class Layout(object):
if name.startswith('^'):
# This is a meta-job
regex = re.compile(name)
self.metajobs[regex] = job
self.metajobs.append((regex, job))
else:
# Apply attributes from matching meta-jobs
for regex, metajob in self.metajobs.items():
for regex, metajob in self.metajobs:
if regex.match(name):
job.copy(metajob)
self.jobs[name] = job

View File

@ -239,7 +239,7 @@ class Scheduler(threading.Thread):
# All jobs should be defined at this point, get rid of
# metajobs so that getJob isn't doing anything weird.
layout.metajobs = {}
layout.metajobs = []
for pipeline in layout.pipelines.values():
pipeline.manager._postConfig(layout)