Merge "Include tenant in pipeline log messages" into feature/zuulv3
diff --git a/.zuul.yaml b/.zuul.yaml
index a997b05..ff1a523 100644
--- a/.zuul.yaml
+++ b/.zuul.yaml
@@ -43,7 +43,7 @@
- project:
name: openstack-infra/zuul
- check:
+ infra-check:
jobs:
- build-openstack-infra-sphinx-docs:
success-url: 'html/feature/zuulv3/'
@@ -65,7 +65,7 @@
files:
- zuul/cmd/migrate.py
- playbooks/zuul-migrate/.*
- gate:
+ infra-gate:
jobs:
- build-openstack-infra-sphinx-docs:
success-url: 'html/feature/zuulv3/'
@@ -75,7 +75,7 @@
- zuul/cmd/migrate.py
- playbooks/zuul-migrate/.*
- zuul-stream-functional
- post:
+ infra-post:
jobs:
- publish-openstack-sphinx-docs-infra
- publish-openstack-python-branch-tarball
diff --git a/tests/base.py b/tests/base.py
index abec813..5841c08 100755
--- a/tests/base.py
+++ b/tests/base.py
@@ -2648,6 +2648,13 @@
return build
raise Exception("Unable to find build %s" % name)
+ def assertJobNotInHistory(self, name, project=None):
+ for job in self.history:
+ if (project is None or
+ job.parameters['zuul']['project']['name'] == project):
+ self.assertNotEqual(job.name, name,
+ 'Job %s found in history' % name)
+
def getJobFromHistory(self, name, project=None):
for job in self.history:
if (job.name == name and
diff --git a/tests/fixtures/layouts/matcher-test.yaml b/tests/fixtures/layouts/matcher-test.yaml
new file mode 100644
index 0000000..b511a2f
--- /dev/null
+++ b/tests/fixtures/layouts/matcher-test.yaml
@@ -0,0 +1,63 @@
+- pipeline:
+ name: check
+ manager: independent
+ trigger:
+ gerrit:
+ - event: patchset-created
+ success:
+ gerrit:
+ Verified: 1
+ failure:
+ gerrit:
+ Verified: -1
+
+- pipeline:
+ name: gate
+ manager: dependent
+ success-message: Build succeeded (gate).
+ 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
+
+- job:
+ name: project-test1
+ nodeset:
+ nodes:
+ - name: controller
+ label: label1
+
+- job:
+ name: ignore-branch
+ branches: ^(?!featureA).*$
+ nodeset:
+ nodes:
+ - name: controller
+ label: label2
+
+- project:
+ name: org/project
+ check:
+ jobs:
+ - project-test1
+ - ignore-branch
+ gate:
+ jobs:
+ - project-test1
+ - ignore-branch
diff --git a/tests/unit/test_change_matcher.py b/tests/unit/test_change_matcher.py
index 6b161a1..3d5345f 100644
--- a/tests/unit/test_change_matcher.py
+++ b/tests/unit/test_change_matcher.py
@@ -60,7 +60,7 @@
self.assertTrue(self.matcher.matches(self.change))
def test_matches_returns_true_on_matching_ref(self):
- self.change.branch = 'bar'
+ delattr(self.change, 'branch')
self.change.ref = 'foo'
self.assertTrue(self.matcher.matches(self.change))
@@ -69,11 +69,6 @@
self.change.ref = 'baz'
self.assertFalse(self.matcher.matches(self.change))
- def test_matches_returns_false_for_missing_attrs(self):
- delattr(self.change, 'branch')
- # ref is by default not an attribute
- self.assertFalse(self.matcher.matches(self.change))
-
class TestFileMatcher(BaseTestMatcher):
diff --git a/tests/unit/test_scheduler.py b/tests/unit/test_scheduler.py
index 267bedd..5226675 100755
--- a/tests/unit/test_scheduler.py
+++ b/tests/unit/test_scheduler.py
@@ -5642,3 +5642,30 @@
self.assertEqual(A.reported, 2)
self.assertEqual(B.reported, 2)
self.assertEqual(C.reported, 2)
+
+
+class TestSchedulerBranchMatcher(ZuulTestCase):
+
+ @simple_layout('layouts/matcher-test.yaml')
+ def test_job_branch_ignored(self):
+ '''
+ Test that branch matching logic works.
+
+ The 'ignore-branch' job has a branch matcher that is supposed to
+ match every branch except for the 'featureA' branch, so it should
+ not be run on a change to that branch.
+ '''
+ self.create_branch('org/project', 'featureA')
+ A = self.fake_gerrit.addFakeChange('org/project', 'featureA', 'A')
+ A.addApproval('Code-Review', 2)
+ self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
+ self.waitUntilSettled()
+ self.printHistory()
+ self.assertEqual(self.getJobFromHistory('project-test1').result,
+ 'SUCCESS')
+ self.assertJobNotInHistory('ignore-branch')
+ self.assertEqual(A.data['status'], 'MERGED')
+ self.assertEqual(A.reported, 2,
+ "A should report start and success")
+ self.assertIn('gate', A.messages[1],
+ "A should transit gate")
diff --git a/zuul/ansible/callback/zuul_stream.py b/zuul/ansible/callback/zuul_stream.py
index 0a266df..8ba3b86 100644
--- a/zuul/ansible/callback/zuul_stream.py
+++ b/zuul/ansible/callback/zuul_stream.py
@@ -168,32 +168,8 @@
host=host.name,
filename=included_file._filename))
- def _emit_playbook_banner(self):
- # Get the hostvars from just one host - the vars we're looking for will
- # be identical on all of them
- hostvars = next(iter(self._play._variable_manager._hostvars.values()))
- self._playbook_name = None
-
- phase = hostvars.get('zuul_execution_phase', '')
- playbook = hostvars.get('zuul_execution_canonical_name_and_path')
- trusted = hostvars.get('zuul_execution_trusted')
- trusted = 'trusted' if trusted == "True" else 'untrusted'
- branch = hostvars.get('zuul_execution_branch')
-
- if phase and phase != 'run':
- phase = '{phase}-run'.format(phase=phase)
- phase = phase.upper()
-
- self._log("{phase} [{trusted} : {playbook}@{branch}]".format(
- trusted=trusted, phase=phase, playbook=playbook, branch=branch))
-
def v2_playbook_on_play_start(self, play):
self._play = play
-
- # We can't fill in this information until the first play
- if self._playbook_name:
- self._emit_playbook_banner()
-
# Log an extra blank line to get space before each play
self._log("")
diff --git a/zuul/change_matcher.py b/zuul/change_matcher.py
index baea217..7f6673d 100644
--- a/zuul/change_matcher.py
+++ b/zuul/change_matcher.py
@@ -60,11 +60,13 @@
class BranchMatcher(AbstractChangeMatcher):
def matches(self, change):
- return (
- (hasattr(change, 'branch') and self.regex.match(change.branch)) or
- (hasattr(change, 'ref') and
- change.ref is not None and self.regex.match(change.ref))
- )
+ if hasattr(change, 'branch'):
+ if self.regex.match(change.branch):
+ return True
+ return False
+ if self.regex.match(change.ref):
+ return True
+ return False
class FileMatcher(AbstractChangeMatcher):
diff --git a/zuul/executor/server.py b/zuul/executor/server.py
index e41d6b7..82921fb 100644
--- a/zuul/executor/server.py
+++ b/zuul/executor/server.py
@@ -1740,6 +1740,37 @@
self.RESULT_MAP[result], code))
return result, code
+ def emitPlaybookBanner(self, playbook, step, phase, result=None):
+ # This is used to print a header and a footer, respectively at the
+ # beginning and the end of each playbook execution.
+ # We are doing it from the executor rather than from a callback because
+ # the parameters are not made available to the callback until it's too
+ # late.
+ phase = phase or ''
+ trusted = playbook.trusted
+ trusted = 'trusted' if trusted else 'untrusted'
+ branch = playbook.branch
+ playbook = playbook.canonical_name_and_path
+
+ if phase and phase != 'run':
+ phase = '{phase}-run'.format(phase=phase)
+ phase = phase.upper()
+
+ if result is not None:
+ result = self.RESULT_MAP[result]
+ msg = "{phase} {step} {result}: [{trusted} : {playbook}@{branch}]"
+ msg.format(phase=phase, step=step, result=result,
+ trusted=trusted, playbook=playbook, branch=branch)
+ else:
+ msg = "{phase} {step}: [{trusted} : {playbook}@{branch}]"
+ msg.format(phase=phase, step=step, trusted=trusted,
+ playbook=playbook, branch=branch)
+
+ with open(self.jobdir.job_output_file, 'a') as job_output:
+ job_output.write("{now} | {msg}".format(
+ now=datetime.datetime.now(),
+ msg=msg))
+
def runAnsiblePlaybook(self, playbook, timeout, success=None,
phase=None, index=None):
if self.executor_server.verbose:
@@ -1770,8 +1801,12 @@
if self.executor_variables_file is not None:
cmd.extend(['-e@%s' % self.executor_variables_file])
+ self.emitPlaybookBanner(playbook, 'START', phase)
+
result, code = self.runAnsible(
cmd=cmd, timeout=timeout, playbook=playbook)
self.log.debug("Ansible complete, result %s code %s" % (
self.RESULT_MAP[result], code))
+
+ self.emitPlaybookBanner(playbook, 'END', phase, result=result)
return result, code