summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--doc/source/triggers.rst4
-rw-r--r--doc/source/zuul.rst41
-rw-r--r--etc/status/.gitignore2
-rwxr-xr-xetc/status/fetch-dependencies.sh4
-rw-r--r--etc/status/public_html/index.html3
-rw-r--r--requirements.txt4
-rw-r--r--test-requirements.txt3
-rwxr-xr-xtests/base.py48
-rw-r--r--tests/test_cloner.py177
-rw-r--r--tests/test_daemon.py63
-rwxr-xr-xtests/test_scheduler.py8
-rw-r--r--tests/test_zuultrigger.py20
-rw-r--r--tox.ini7
-rwxr-xr-xzuul/cmd/cloner.py8
-rwxr-xr-xzuul/cmd/server.py5
-rw-r--r--zuul/launcher/gearman.py19
-rw-r--r--zuul/layoutvalidator.py13
-rw-r--r--zuul/lib/cloner.py7
-rw-r--r--zuul/lib/gerrit.py3
-rw-r--r--zuul/lib/swift.py3
-rw-r--r--zuul/merger/client.py3
-rw-r--r--zuul/merger/merger.py2
-rw-r--r--zuul/model.py8
-rw-r--r--zuul/rpcclient.py2
-rw-r--r--zuul/scheduler.py50
-rw-r--r--zuul/trigger/gerrit.py14
-rw-r--r--zuul/trigger/zuultrigger.py13
27 files changed, 373 insertions, 161 deletions
diff --git a/doc/source/triggers.rst b/doc/source/triggers.rst
index dd650f2ff..5b745e643 100644
--- a/doc/source/triggers.rst
+++ b/doc/source/triggers.rst
@@ -34,6 +34,10 @@ want Zuul to gate. For instance, you may want to grant ``Verified
be added to Gerrit. Zuul is very flexible and can take advantage of
those.
+If using Gerrit 2.7 or later, make sure the user is a member of a group
+that is granted the ``Stream Events`` permission, otherwise it will not
+be able to invoke the ``gerrit stream-events`` command over SSH.
+
Timer
-----
diff --git a/doc/source/zuul.rst b/doc/source/zuul.rst
index 6cb5d5902..2883253d5 100644
--- a/doc/source/zuul.rst
+++ b/doc/source/zuul.rst
@@ -86,6 +86,8 @@ gerrit
zuul
""""
+.. _layout_config:
+
**layout_config**
Path to layout config file. Used by zuul-server only.
``layout_config=/etc/zuul/layout.yaml``
@@ -272,10 +274,12 @@ include, and currently supports one type of inclusion, a python file::
- python-file: local_functions.py
**python-file**
- The path to a python file. The file will be loaded and objects that
- it defines will be placed in a special environment which can be
- referenced in the Zuul configuration. Currently only the
- parameter-function attribute of a Job uses this feature.
+ The path to a python file (either an absolute path or relative to the
+ directory name of :ref:`layout_config <layout_config>`). The
+ file will be loaded and objects that it defines will be placed in a
+ special environment which can be referenced in the Zuul configuration.
+ Currently only the parameter-function attribute of a Job uses this
+ feature.
Pipelines
"""""""""
@@ -462,7 +466,8 @@ explanation of each of the parameters::
This may be used for any event. It requires that a certain kind
of approval be present for the current patchset of the change (the
approval could be added by the event in question). It follows the
- same syntax as the "approval" pipeline requirement below.
+ same syntax as the :ref:`"approval" pipeline requirement below
+ <pipeline-require-approval>`.
**timer**
This trigger will run based on a cron-style time specification.
@@ -497,7 +502,8 @@ explanation of each of the parameters::
This may be used for any event. It requires that a certain kind
of approval be present for the current patchset of the change (the
approval could be added by the event in question). It follows the
- same syntax as the "approval" pipeline requirement below.
+ same syntax as the :ref:`"approval" pipeline requirement below
+ <pipeline-require-approval>`.
**require**
@@ -507,6 +513,8 @@ explanation of each of the parameters::
the conditions specified here must be met or the item will not be
enqueued.
+.. _pipeline-require-approval:
+
**approval**
This requires that a certain kind of approval be present for the
current patchset of the change (the approval could be added by the
@@ -1038,10 +1046,19 @@ example, this would give you a list of Gerrit commands to reverify or
recheck changes for the gate and check pipelines respectively::
./tools/zuul-changes.py --review-host=review.openstack.org \
- http://zuul.openstack.org/ gate 'reverify no bug'
+ http://zuul.openstack.org/ gate 'reverify'
./tools/zuul-changes.py --review-host=review.openstack.org \
- http://zuul.openstack.org/ check 'recheck no bug'
-
-If you send a SIGUSR2 to the zuul-server process, Zuul will dump a stack
-trace for each running thread into its debug log. This is useful for
-tracking down deadlock or otherwise slow threads.
+ http://zuul.openstack.org/ check 'recheck'
+
+If you send a SIGUSR2 to the zuul-server process, or the forked process
+that runs the Gearman daemon, Zuul will dump a stack trace for each
+running thread into its debug log. It is written under the log bucket
+``zuul.stack_dump``. This is useful for tracking down deadlock or
+otherwise slow threads.
+
+When `yappi <https://code.google.com/p/yappi/>`_ (Yet Another Python
+Profiler) is available, additional functions' and threads' stats are
+emitted as well. The first SIGUSR2 will enable yappi, on the second
+SIGUSR2 it dumps the information collected, resets all yappi state and
+stops profiling. This is to minimize the impact of yappi on a running
+system.
diff --git a/etc/status/.gitignore b/etc/status/.gitignore
index 8b94cad18..1ecdbed42 100644
--- a/etc/status/.gitignore
+++ b/etc/status/.gitignore
@@ -1,4 +1,4 @@
public_html/jquery.min.js
-public_html/jquery-visibility.min.js
+public_html/jquery-visibility.js
public_html/bootstrap
public_html/jquery.graphite.js
diff --git a/etc/status/fetch-dependencies.sh b/etc/status/fetch-dependencies.sh
index 4868310ad..b31d0de5f 100755
--- a/etc/status/fetch-dependencies.sh
+++ b/etc/status/fetch-dependencies.sh
@@ -3,10 +3,10 @@ BASE_DIR=$(cd $(dirname $0); pwd)
echo "Destination: $BASE_DIR/public_html"
echo "Fetching jquery.min.js..."
-curl --silent http://code.jquery.com/jquery.min.js > $BASE_DIR/public_html/jquery.min.js
+curl -L --silent http://code.jquery.com/jquery.min.js > $BASE_DIR/public_html/jquery.min.js
echo "Fetching jquery-visibility.min.js..."
-curl --silent https://raw.githubusercontent.com/mathiasbynens/jquery-visibility/master/jquery-visibility.js > $BASE_DIR/public_html/jquery-visibility.min.js
+curl -L --silent https://raw.githubusercontent.com/mathiasbynens/jquery-visibility/master/jquery-visibility.js > $BASE_DIR/public_html/jquery-visibility.js
echo "Fetching jquery.graphite.js..."
curl -L --silent https://github.com/prestontimmons/graphitejs/archive/master.zip > jquery-graphite.zip
diff --git a/etc/status/public_html/index.html b/etc/status/public_html/index.html
index d77470bb7..3bd7a12fc 100644
--- a/etc/status/public_html/index.html
+++ b/etc/status/public_html/index.html
@@ -20,7 +20,6 @@ under the License.
<head>
<title>Zuul Status</title>
<link rel="stylesheet" href="bootstrap/css/bootstrap.min.css">
- <link rel="stylesheet" href="bootstrap/css/bootstrap-responsive.min.css">
<link rel="stylesheet" href="styles/zuul.css" />
</head>
<body>
@@ -28,7 +27,7 @@ under the License.
<div id="zuul_container"></div>
<script src="jquery.min.js"></script>
- <script src="jquery-visibility.min.js"></script>
+ <script src="jquery-visibility.js"></script>
<script src="jquery.graphite.js"></script>
<script src="jquery.zuul.js"></script>
<script src="zuul.app.js"></script>
diff --git a/requirements.txt b/requirements.txt
index dd947d67f..b24d1710f 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -5,10 +5,10 @@ PyYAML>=3.1.0
Paste
WebOb>=1.2.3,<1.3
paramiko>=1.8.0
-GitPython==0.3.2.RC1
+GitPython>=0.3.2.1
lockfile>=0.8
ordereddict
-python-daemon
+python-daemon>=2.0.4
extras
statsd>=1.0.0,<3.0
voluptuous>=0.7
diff --git a/test-requirements.txt b/test-requirements.txt
index 5192de701..c68b2db0a 100644
--- a/test-requirements.txt
+++ b/test-requirements.txt
@@ -1,9 +1,8 @@
hacking>=0.9.2,<0.10
coverage>=3.6
-sphinx>=1.1.2,<1.2
+sphinx>=1.1.2,!=1.2.0,!=1.3b1,<1.3
sphinxcontrib-blockdiag>=0.5.5
-docutils==0.9.1
discover
fixtures>=0.3.14
python-keystoneclient>=0.4.2
diff --git a/tests/base.py b/tests/base.py
index 46c708787..b872a8581 100755
--- a/tests/base.py
+++ b/tests/base.py
@@ -40,6 +40,7 @@ import fixtures
import six.moves.urllib.parse as urlparse
import statsd
import testtools
+from git import GitCommandError
import zuul.scheduler
import zuul.webapp
@@ -78,6 +79,16 @@ def random_sha1():
return hashlib.sha1(str(random.random())).hexdigest()
+def iterate_timeout(max_seconds, purpose):
+ start = time.time()
+ count = 0
+ while (time.time() < start + max_seconds):
+ count += 1
+ yield count
+ time.sleep(0)
+ raise Exception("Timeout waiting for %s" % purpose)
+
+
class ChangeReference(git.Reference):
_common_path_default = "refs/changes"
_points_to_commits_only = True
@@ -251,14 +262,16 @@ class FakeChange(object):
granted_on=None):
if not granted_on:
granted_on = time.time()
- approval = {'description': self.categories[category][0],
- 'type': category,
- 'value': str(value),
- 'by': {
- 'username': username,
- 'email': username + '@example.com',
- },
- 'grantedOn': int(granted_on)}
+ approval = {
+ 'description': self.categories[category][0],
+ 'type': category,
+ 'value': str(value),
+ 'by': {
+ 'username': username,
+ 'email': username + '@example.com',
+ },
+ 'grantedOn': int(granted_on)
+ }
for i, x in enumerate(self.patchsets[-1]['approvals'][:]):
if x['by']['username'] == username and x['type'] == category:
del self.patchsets[-1]['approvals'][i]
@@ -348,7 +361,7 @@ class FakeChange(object):
def setMerged(self):
if (self.depends_on_change and
- self.depends_on_change.data['status'] != 'MERGED'):
+ self.depends_on_change.data['status'] != 'MERGED'):
return
if self.fail_merge:
return
@@ -409,7 +422,7 @@ class FakeGerrit(object):
# project
self.queries.append(query)
l = [change.query() for change in self.changes.values()]
- l.append({"type":"stats","rowCount":1,"runTimeMilliseconds":3})
+ l.append({"type": "stats", "rowCount": 1, "runTimeMilliseconds": 3})
return l
def startWatching(self, *args, **kw):
@@ -824,7 +837,8 @@ class ZuulTestCase(testtools.TestCase):
'%(levelname)-8s %(message)s'))
if USE_TEMPDIR:
tmp_root = self.useFixture(fixtures.TempDir(
- rootdir=os.environ.get("ZUUL_TEST_ROOT"))).path
+ rootdir=os.environ.get("ZUUL_TEST_ROOT"))
+ ).path
else:
tmp_root = os.environ.get("ZUUL_TEST_ROOT")
self.test_root = os.path.join(tmp_root, "zuul-test")
@@ -923,7 +937,8 @@ class ZuulTestCase(testtools.TestCase):
self.sched.registerTrigger(self.gerrit)
self.timer = zuul.trigger.timer.Timer(self.config, self.sched)
self.sched.registerTrigger(self.timer)
- self.zuultrigger = zuul.trigger.zuultrigger.ZuulTrigger(self.config, self.sched)
+ self.zuultrigger = zuul.trigger.zuultrigger.ZuulTrigger(self.config,
+ self.sched)
self.sched.registerTrigger(self.zuultrigger)
self.sched.registerReporter(
@@ -1031,9 +1046,12 @@ class ZuulTestCase(testtools.TestCase):
def ref_has_change(self, ref, change):
path = os.path.join(self.git_root, change.project)
repo = git.Repo(path)
- for commit in repo.iter_commits(ref):
- if commit.message.strip() == ('%s-1' % change.subject):
- return True
+ try:
+ for commit in repo.iter_commits(ref):
+ if commit.message.strip() == ('%s-1' % change.subject):
+ return True
+ except GitCommandError:
+ pass
return False
def job_has_changes(self, *args):
diff --git a/tests/test_cloner.py b/tests/test_cloner.py
index ab2683d81..137c1570e 100644
--- a/tests/test_cloner.py
+++ b/tests/test_cloner.py
@@ -18,13 +18,13 @@
import logging
import os
import shutil
+import time
import git
import zuul.lib.cloner
from tests.base import ZuulTestCase
-from tests.base import FIXTURE_DIR
logging.basicConfig(level=logging.DEBUG,
format='%(asctime)s %(name)-32s '
@@ -80,11 +80,10 @@ class TestCloner(ZuulTestCase):
B.setMerged()
upstream = self.getUpstreamRepos(projects)
- states = [
- {'org/project1': self.builds[0].parameters['ZUUL_COMMIT'],
- 'org/project2': str(upstream['org/project2'].commit('master')),
- },
- ]
+ states = [{
+ 'org/project1': self.builds[0].parameters['ZUUL_COMMIT'],
+ 'org/project2': str(upstream['org/project2'].commit('master')),
+ }]
for number, build in enumerate(self.builds):
self.log.debug("Build parameters: %s", build.parameters)
@@ -96,7 +95,7 @@ class TestCloner(ZuulTestCase):
zuul_ref=build.parameters['ZUUL_REF'],
zuul_url=self.git_root,
cache_dir=cache_root,
- )
+ )
cloner.execute()
work = self.getWorkspaceRepos(projects)
state = states[number]
@@ -109,9 +108,11 @@ class TestCloner(ZuulTestCase):
work = self.getWorkspaceRepos(projects)
upstream_repo_path = os.path.join(self.upstream_root, 'org/project1')
- self.assertEquals(work['org/project1'].remotes.origin.url,
- upstream_repo_path,
- 'workspace repo origin should be upstream, not cache')
+ self.assertEquals(
+ work['org/project1'].remotes.origin.url,
+ upstream_repo_path,
+ 'workspace repo origin should be upstream, not cache'
+ )
self.worker.hold_jobs_in_build = False
self.worker.release()
@@ -140,7 +141,7 @@ class TestCloner(ZuulTestCase):
{'org/project1': self.builds[0].parameters['ZUUL_COMMIT'],
'org/project2': self.builds[1].parameters['ZUUL_COMMIT'],
},
- ]
+ ]
for number, build in enumerate(self.builds):
self.log.debug("Build parameters: %s", build.parameters)
@@ -151,7 +152,7 @@ class TestCloner(ZuulTestCase):
zuul_branch=build.parameters['ZUUL_BRANCH'],
zuul_ref=build.parameters['ZUUL_REF'],
zuul_url=self.git_root,
- )
+ )
cloner.execute()
work = self.getWorkspaceRepos(projects)
state = states[number]
@@ -176,7 +177,8 @@ class TestCloner(ZuulTestCase):
self.create_branch('org/project2', 'stable/havana')
self.create_branch('org/project4', 'stable/havana')
A = self.fake_gerrit.addFakeChange('org/project1', 'master', 'A')
- B = self.fake_gerrit.addFakeChange('org/project2', 'stable/havana', 'B')
+ B = self.fake_gerrit.addFakeChange('org/project2', 'stable/havana',
+ 'B')
C = self.fake_gerrit.addFakeChange('org/project3', 'master', 'C')
A.addApproval('CRVW', 2)
B.addApproval('CRVW', 2)
@@ -209,7 +211,7 @@ class TestCloner(ZuulTestCase):
'org/project4': str(upstream['org/project4'].
commit('master')),
},
- ]
+ ]
for number, build in enumerate(self.builds):
self.log.debug("Build parameters: %s", build.parameters)
@@ -220,7 +222,7 @@ class TestCloner(ZuulTestCase):
zuul_branch=build.parameters['ZUUL_BRANCH'],
zuul_ref=build.parameters['ZUUL_REF'],
zuul_url=self.git_root,
- )
+ )
cloner.execute()
work = self.getWorkspaceRepos(projects)
state = states[number]
@@ -248,9 +250,11 @@ class TestCloner(ZuulTestCase):
self.create_branch('org/project5', 'stable/havana')
A = self.fake_gerrit.addFakeChange('org/project1', 'master', 'A')
B = self.fake_gerrit.addFakeChange('org/project2', 'master', 'B')
- C = self.fake_gerrit.addFakeChange('org/project3', 'stable/havana', 'C')
+ C = self.fake_gerrit.addFakeChange('org/project3', 'stable/havana',
+ 'C')
D = self.fake_gerrit.addFakeChange('org/project3', 'master', 'D')
- E = self.fake_gerrit.addFakeChange('org/project4', 'stable/havana', 'E')
+ E = self.fake_gerrit.addFakeChange('org/project4', 'stable/havana',
+ 'E')
A.addApproval('CRVW', 2)
B.addApproval('CRVW', 2)
C.addApproval('CRVW', 2)
@@ -270,46 +274,61 @@ class TestCloner(ZuulTestCase):
upstream = self.getUpstreamRepos(projects)
states = [
{'org/project1': self.builds[0].parameters['ZUUL_COMMIT'],
- 'org/project2': str(upstream['org/project2'].commit('stable/havana')),
- 'org/project3': str(upstream['org/project3'].commit('stable/havana')),
- 'org/project4': str(upstream['org/project4'].commit('stable/havana')),
- 'org/project5': str(upstream['org/project5'].commit('stable/havana')),
+ 'org/project2': str(upstream['org/project2'].commit(
+ 'stable/havana')),
+ 'org/project3': str(upstream['org/project3'].commit(
+ 'stable/havana')),
+ 'org/project4': str(upstream['org/project4'].commit(
+ 'stable/havana')),
+ 'org/project5': str(upstream['org/project5'].commit(
+ 'stable/havana')),
'org/project6': str(upstream['org/project6'].commit('master')),
},
{'org/project1': self.builds[0].parameters['ZUUL_COMMIT'],
- 'org/project2': str(upstream['org/project2'].commit('stable/havana')),
- 'org/project3': str(upstream['org/project3'].commit('stable/havana')),
- 'org/project4': str(upstream['org/project4'].commit('stable/havana')),
- 'org/project5': str(upstream['org/project5'].commit('stable/havana')),
+ 'org/project2': str(upstream['org/project2'].commit(
+ 'stable/havana')),
+ 'org/project3': str(upstream['org/project3'].commit(
+ 'stable/havana')),
+ 'org/project4': str(upstream['org/project4'].commit(
+ 'stable/havana')),
+ 'org/project5': str(upstream['org/project5'].commit(
+ 'stable/havana')),
'org/project6': str(upstream['org/project6'].commit('master')),
},
{'org/project1': self.builds[0].parameters['ZUUL_COMMIT'],
- 'org/project2': str(upstream['org/project2'].commit('stable/havana')),
+ 'org/project2': str(upstream['org/project2'].commit(
+ 'stable/havana')),
'org/project3': self.builds[2].parameters['ZUUL_COMMIT'],
- 'org/project4': str(upstream['org/project4'].commit('stable/havana')),
+ 'org/project4': str(upstream['org/project4'].commit(
+ 'stable/havana')),
- 'org/project5': str(upstream['org/project5'].commit('stable/havana')),
+ 'org/project5': str(upstream['org/project5'].commit(
+ 'stable/havana')),
'org/project6': str(upstream['org/project6'].commit('master')),
},
{'org/project1': self.builds[0].parameters['ZUUL_COMMIT'],
- 'org/project2': str(upstream['org/project2'].commit('stable/havana')),
+ 'org/project2': str(upstream['org/project2'].commit(
+ 'stable/havana')),
'org/project3': self.builds[2].parameters['ZUUL_COMMIT'],
- 'org/project4': str(upstream['org/project4'].commit('stable/havana')),
- 'org/project5': str(upstream['org/project5'].commit('stable/havana')),
+ 'org/project4': str(upstream['org/project4'].commit(
+ 'stable/havana')),
+ 'org/project5': str(upstream['org/project5'].commit(
+ 'stable/havana')),
'org/project6': str(upstream['org/project6'].commit('master')),
},
{'org/project1': self.builds[0].parameters['ZUUL_COMMIT'],
- 'org/project2': str(upstream['org/project2'].commit('stable/havana')),
+ 'org/project2': str(upstream['org/project2'].commit(
+ 'stable/havana')),
'org/project3': self.builds[2].parameters['ZUUL_COMMIT'],
'org/project4': self.builds[4].parameters['ZUUL_COMMIT'],
- 'org/project5': str(upstream['org/project5'].commit('stable/havana')),
+ 'org/project5': str(upstream['org/project5'].commit(
+ 'stable/havana')),
'org/project6': str(upstream['org/project6'].commit('master')),
},
- ]
+ ]
for number, build in enumerate(self.builds):
self.log.debug("Build parameters: %s", build.parameters)
- change_number = int(build.parameters['ZUUL_CHANGE'])
cloner = zuul.lib.cloner.Cloner(
git_base_url=self.upstream_root,
projects=projects,
@@ -317,8 +336,8 @@ class TestCloner(ZuulTestCase):
zuul_branch=build.parameters['ZUUL_BRANCH'],
zuul_ref=build.parameters['ZUUL_REF'],
zuul_url=self.git_root,
- branch='stable/havana', # Old branch for upgrade
- )
+ branch='stable/havana', # Old branch for upgrade
+ )
cloner.execute()
work = self.getWorkspaceRepos(projects)
state = states[number]
@@ -368,11 +387,10 @@ class TestCloner(ZuulTestCase):
'org/project5': str(upstream['org/project5'].commit('master')),
'org/project6': str(upstream['org/project6'].commit('master')),
},
- ]
+ ]
for number, build in enumerate(self.builds):
self.log.debug("Build parameters: %s", build.parameters)
- change_number = int(build.parameters['ZUUL_CHANGE'])
cloner = zuul.lib.cloner.Cloner(
git_base_url=self.upstream_root,
projects=projects,
@@ -380,8 +398,8 @@ class TestCloner(ZuulTestCase):
zuul_branch=build.parameters['ZUUL_BRANCH'],
zuul_ref=build.parameters['ZUUL_REF'],
zuul_url=self.git_root,
- branch='master', # New branch for upgrade
- )
+ branch='master', # New branch for upgrade
+ )
cloner.execute()
work = self.getWorkspaceRepos(projects)
state = states[number]
@@ -409,7 +427,8 @@ class TestCloner(ZuulTestCase):
A = self.fake_gerrit.addFakeChange('org/project1', 'master', 'A')
B = self.fake_gerrit.addFakeChange('org/project1', 'master', 'B')
C = self.fake_gerrit.addFakeChange('org/project2', 'master', 'C')
- D = self.fake_gerrit.addFakeChange('org/project3', 'stable/havana', 'D')
+ D = self.fake_gerrit.addFakeChange('org/project3', 'stable/havana',
+ 'D')
A.addApproval('CRVW', 2)
B.addApproval('CRVW', 2)
C.addApproval('CRVW', 2)
@@ -451,13 +470,13 @@ class TestCloner(ZuulTestCase):
'org/project3': self.builds[3].parameters['ZUUL_COMMIT'],
'org/project4': str(upstream['org/project4'].commit('master')),
'org/project5': str(upstream['org/project5'].commit('master')),
- 'org/project6': str(upstream['org/project6'].commit('stable/havana')),
+ 'org/project6': str(upstream['org/project6'].commit(
+ 'stable/havana')),
},
- ]
+ ]
for number, build in enumerate(self.builds):
self.log.debug("Build parameters: %s", build.parameters)
- change_number = int(build.parameters['ZUUL_CHANGE'])
cloner = zuul.lib.cloner.Cloner(
git_base_url=self.upstream_root,
projects=projects,
@@ -466,7 +485,72 @@ class TestCloner(ZuulTestCase):
zuul_ref=build.parameters['ZUUL_REF'],
zuul_url=self.git_root,
project_branches={'org/project4': 'master'},
- )
+ )
+ cloner.execute()
+ work = self.getWorkspaceRepos(projects)
+ state = states[number]
+
+ for project in projects:
+ self.assertEquals(state[project],
+ str(work[project].commit('HEAD')),
+ 'Project %s commit for build %s should '
+ 'be correct' % (project, number))
+ shutil.rmtree(self.workspace_root)
+
+ self.worker.hold_jobs_in_build = False
+ self.worker.release()
+ self.waitUntilSettled()
+
+ def test_periodic(self):
+ self.worker.hold_jobs_in_build = True
+ self.create_branch('org/project', 'stable/havana')
+ self.config.set('zuul', 'layout_config',
+ 'tests/fixtures/layout-timer.yaml')
+ self.sched.reconfigure(self.config)
+ self.registerJobs()
+
+ # The pipeline triggers every second, so we should have seen
+ # several by now.
+ time.sleep(5)
+ self.waitUntilSettled()
+
+ builds = self.builds[:]
+
+ self.worker.hold_jobs_in_build = False
+ # Stop queuing timer triggered jobs so that the assertions
+ # below don't race against more jobs being queued.
+ self.config.set('zuul', 'layout_config',
+ 'tests/fixtures/layout-no-timer.yaml')
+ self.sched.reconfigure(self.config)
+ self.registerJobs()
+ self.worker.release()
+ self.waitUntilSettled()
+
+ projects = ['org/project']
+
+ self.assertEquals(2, len(builds), "Two builds are running")
+
+ upstream = self.getUpstreamRepos(projects)
+ states = [
+ {'org/project':
+ str(upstream['org/project'].commit('stable/havana')),
+ },
+ {'org/project':
+ str(upstream['org/project'].commit('stable/havana')),
+ },
+ ]
+
+ for number, build in enumerate(builds):
+ self.log.debug("Build parameters: %s", build.parameters)
+ cloner = zuul.lib.cloner.Cloner(
+ git_base_url=self.upstream_root,
+ projects=projects,
+ workspace=self.workspace_root,
+ zuul_branch=build.parameters.get('ZUUL_BRANCH', None),
+ zuul_ref=build.parameters.get('ZUUL_REF', None),
+ zuul_url=self.git_root,
+ branch='stable/havana',
+ )
cloner.execute()
work = self.getWorkspaceRepos(projects)
state = states[number]
@@ -476,6 +560,7 @@ class TestCloner(ZuulTestCase):
str(work[project].commit('HEAD')),
'Project %s commit for build %s should '
'be correct' % (project, number))
+
shutil.rmtree(self.workspace_root)
self.worker.hold_jobs_in_build = False
diff --git a/tests/test_daemon.py b/tests/test_daemon.py
new file mode 100644
index 000000000..689d4f709
--- /dev/null
+++ b/tests/test_daemon.py
@@ -0,0 +1,63 @@
+#!/usr/bin/env python
+
+# Copyright 2014 Hewlett-Packard Development Company, L.P.
+#
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+import daemon
+import logging
+import os
+import sys
+
+import extras
+import fixtures
+import testtools
+
+from tests.base import iterate_timeout
+
+# as of python-daemon 1.6 it doesn't bundle pidlockfile anymore
+# instead it depends on lockfile-0.9.1 which uses pidfile.
+pid_file_module = extras.try_imports(['daemon.pidlockfile', 'daemon.pidfile'])
+
+
+def daemon_test(pidfile, flagfile):
+ pid = pid_file_module.TimeoutPIDLockFile(pidfile, 10)
+ with daemon.DaemonContext(pidfile=pid):
+ for x in iterate_timeout(30, "flagfile to be removed"):
+ if not os.path.exists(flagfile):
+ break
+ sys.exit(0)
+
+
+class TestDaemon(testtools.TestCase):
+ log = logging.getLogger("zuul.test.daemon")
+
+ def setUp(self):
+ super(TestDaemon, self).setUp()
+ self.test_root = self.useFixture(fixtures.TempDir(
+ rootdir=os.environ.get("ZUUL_TEST_ROOT"))).path
+
+ def test_daemon(self):
+ pidfile = os.path.join(self.test_root, "daemon.pid")
+ flagfile = os.path.join(self.test_root, "daemon.flag")
+ open(flagfile, 'w').close()
+ if not os.fork():
+ self._cleanups = []
+ daemon_test(pidfile, flagfile)
+ for x in iterate_timeout(30, "daemon to start"):
+ if os.path.exists(pidfile):
+ break
+ os.unlink(flagfile)
+ for x in iterate_timeout(30, "daemon to stop"):
+ if not os.path.exists(pidfile):
+ break
diff --git a/tests/test_scheduler.py b/tests/test_scheduler.py
index a7548c132..89056f4cd 100755
--- a/tests/test_scheduler.py
+++ b/tests/test_scheduler.py
@@ -1427,10 +1427,10 @@ class TestScheduler(ZuulTestCase):
self.waitUntilSettled()
# For debugging purposes...
- #for pipeline in self.sched.layout.pipelines.values():
- # for queue in pipeline.queues:
- # self.log.info("pipepline %s queue %s contents %s" % (
- # pipeline.name, queue.name, queue.queue))
+ # for pipeline in self.sched.layout.pipelines.values():
+ # for queue in pipeline.queues:
+ # self.log.info("pipepline %s queue %s contents %s" % (
+ # pipeline.name, queue.name, queue.queue))
self.worker.release('.*-merge')
self.waitUntilSettled()
diff --git a/tests/test_zuultrigger.py b/tests/test_zuultrigger.py
index 9a90a982e..3f339beff 100644
--- a/tests/test_zuultrigger.py
+++ b/tests/test_zuultrigger.py
@@ -15,7 +15,6 @@
# under the License.
import logging
-import time
from tests.base import ZuulTestCase
@@ -46,9 +45,9 @@ class TestZuulTrigger(ZuulTestCase):
A.addApproval('CRVW', 2)
B1.addApproval('CRVW', 2)
B2.addApproval('CRVW', 2)
- A.addApproval('VRFY', 1) # required by gate
- B1.addApproval('VRFY', -1) # should go to check
- B2.addApproval('VRFY', 1) # should go to gate
+ A.addApproval('VRFY', 1) # required by gate
+ B1.addApproval('VRFY', -1) # should go to check
+ B2.addApproval('VRFY', 1) # should go to gate
B1.addApproval('APRV', 1)
B2.addApproval('APRV', 1)
B1.setDependsOn(A, 1)
@@ -106,11 +105,14 @@ class TestZuulTrigger(ZuulTestCase):
self.assertEqual(C.reported, 0)
self.assertEqual(D.reported, 0)
self.assertEqual(E.reported, 0)
- self.assertEqual(B.messages[0],
+ self.assertEqual(
+ B.messages[0],
"Merge Failed.\n\nThis change was unable to be automatically "
"merged with the current state of the repository. Please rebase "
"your change and upload a new patchset.")
- self.assertEqual(self.fake_gerrit.queries[0], "project:org/project status:open")
+
+ self.assertEqual(self.fake_gerrit.queries[0],
+ "project:org/project status:open")
# Reconfigure and run the test again. This is a regression
# check to make sure that we don't end up with a stale trigger
@@ -129,8 +131,10 @@ class TestZuulTrigger(ZuulTestCase):
self.assertEqual(C.reported, 0)
self.assertEqual(D.reported, 2)
self.assertEqual(E.reported, 1)
- self.assertEqual(E.messages[0],
+ self.assertEqual(
+ E.messages[0],
"Merge Failed.\n\nThis change was unable to be automatically "
"merged with the current state of the repository. Please rebase "
"your change and upload a new patchset.")
- self.assertEqual(self.fake_gerrit.queries[1], "project:org/project status:open")
+ self.assertEqual(self.fake_gerrit.queries[1],
+ "project:org/project status:open")
diff --git a/tox.ini b/tox.ini
index 6e459699d..d716bb715 100644
--- a/tox.ini
+++ b/tox.ini
@@ -20,7 +20,7 @@ commands =
downloadcache = ~/cache/pip
[testenv:pep8]
-commands = flake8
+commands = flake8 {posargs}
[testenv:cover]
commands =
@@ -36,7 +36,8 @@ commands = {posargs}
commands = zuul-server -c etc/zuul.conf-sample -t -l {posargs}
[flake8]
-ignore = E125,H
-select = H231
+# These are ignored intentionally in openstack-infra projects;
+# please don't submit patches that solely correct them or enable them.
+ignore = E125,E129,H
show-source = True
exclude = .venv,.tox,dist,doc,build,*.egg
diff --git a/zuul/cmd/cloner.py b/zuul/cmd/cloner.py
index a895f2433..d0bb96694 100755
--- a/zuul/cmd/cloner.py
+++ b/zuul/cmd/cloner.py
@@ -65,20 +65,20 @@ class Cloner(zuul.cmd.ZuulApp):
project_env = parser.add_argument_group(
'project tuning'
- )
+ )
project_env.add_argument(
'--branch',
help=('branch to checkout instead of Zuul selected branch, '
'for example to specify an alternate branch to test '
'client library compatibility.')
- )
+ )
project_env.add_argument(
'--project-branch', nargs=1, action='append',
metavar='PROJECT=BRANCH',
help=('project-specific branch to checkout which takes precedence '
'over --branch if it is provided; may be specified multiple '
'times.')
- )
+ )
zuul_env = parser.add_argument_group(
'zuul environnement',
@@ -97,7 +97,7 @@ class Cloner(zuul.cmd.ZuulApp):
zuul_missing = [zuul_opt for zuul_opt, val in vars(args).items()
if zuul_opt.startswith('zuul') and val is None]
if zuul_missing:
- parser.error(("Some Zuul parameters are not properly set:\n\t%s\n"
+ parser.error(("Some Zuul parameters are not set:\n\t%s\n"
"Define them either via environment variables or "
"using options above." %
"\n\t".join(sorted(zuul_missing))))
diff --git a/zuul/cmd/server.py b/zuul/cmd/server.py
index 25dab6f42..832eae412 100755
--- a/zuul/cmd/server.py
+++ b/zuul/cmd/server.py
@@ -150,6 +150,7 @@ class Server(zuul.cmd.ZuulApp):
import zuul.webapp
import zuul.rpclistener
+ signal.signal(signal.SIGUSR2, zuul.cmd.stack_dump_handler)
if (self.config.has_option('gearman_server', 'start') and
self.config.getboolean('gearman_server', 'start')):
self.start_gear_server()
@@ -165,7 +166,8 @@ class Server(zuul.cmd.ZuulApp):
merger = zuul.merger.client.MergeClient(self.config, self.sched)
gerrit = zuul.trigger.gerrit.Gerrit(self.config, self.sched)
timer = zuul.trigger.timer.Timer(self.config, self.sched)
- zuultrigger = zuul.trigger.zuultrigger.ZuulTrigger(self.config, self.sched)
+ zuultrigger = zuul.trigger.zuultrigger.ZuulTrigger(self.config,
+ self.sched)
if self.config.has_option('zuul', 'status_expiry'):
cache_expiry = self.config.getint('zuul', 'status_expiry')
else:
@@ -203,7 +205,6 @@ class Server(zuul.cmd.ZuulApp):
signal.signal(signal.SIGHUP, self.reconfigure_handler)
signal.signal(signal.SIGUSR1, self.exit_handler)
- signal.signal(signal.SIGUSR2, zuul.cmd.stack_dump_handler)
signal.signal(signal.SIGTERM, self.term_handler)
while True:
try:
diff --git a/zuul/launcher/gearman.py b/zuul/launcher/gearman.py
index 57db7dc28..564a554ba 100644
--- a/zuul/launcher/gearman.py
+++ b/zuul/launcher/gearman.py
@@ -128,7 +128,7 @@ class ZuulGearmanClient(gear.Client):
for connection in self.active_connections:
try:
req = gear.StatusAdminRequest()
- connection.sendAdminRequest(req)
+ connection.sendAdminRequest(req, timeout=300)
except Exception:
self.log.exception("Exception while checking functions")
continue
@@ -203,7 +203,7 @@ class Gearman(object):
for connection in self.gearman.active_connections:
try:
req = gear.StatusAdminRequest()
- connection.sendAdminRequest(req)
+ connection.sendAdminRequest(req, timeout=300)
except Exception:
self.log.exception("Exception while checking functions")
continue
@@ -361,15 +361,16 @@ class Gearman(object):
precedence = gear.PRECEDENCE_LOW
try:
- self.gearman.submitJob(gearman_job, precedence=precedence)
+ self.gearman.submitJob(gearman_job, precedence=precedence,
+ timeout=300)
except Exception:
self.log.exception("Unable to submit job to Gearman")
self.onBuildCompleted(gearman_job, 'EXCEPTION')
return build
if not gearman_job.handle:
- self.log.error("No job handle was received for %s after 30 seconds"
- " marking as lost." %
+ self.log.error("No job handle was received for %s after"
+ " 300 seconds; marking as lost." %
gearman_job)
self.onBuildCompleted(gearman_job, 'NO_HANDLE')
@@ -467,7 +468,7 @@ class Gearman(object):
job = build.__gearman_job
req = gear.CancelJobAdminRequest(job.handle)
- job.connection.sendAdminRequest(req)
+ job.connection.sendAdminRequest(req, timeout=300)
self.log.debug("Response to cancel build %s request: %s" %
(build, req.response.strip()))
if req.response.startswith("OK"):
@@ -486,7 +487,8 @@ class Gearman(object):
json.dumps(data), unique=stop_uuid)
self.meta_jobs[stop_uuid] = stop_job
self.log.debug("Submitting stop job: %s", stop_job)
- self.gearman.submitJob(stop_job, precedence=gear.PRECEDENCE_HIGH)
+ self.gearman.submitJob(stop_job, precedence=gear.PRECEDENCE_HIGH,
+ timeout=300)
return True
def setBuildDescription(self, build, desc):
@@ -507,7 +509,8 @@ class Gearman(object):
desc_job = gear.Job(name, json.dumps(data), unique=desc_uuid)
self.meta_jobs[desc_uuid] = desc_job
self.log.debug("Submitting describe job: %s", desc_job)
- self.gearman.submitJob(desc_job, precedence=gear.PRECEDENCE_LOW)
+ self.gearman.submitJob(desc_job, precedence=gear.PRECEDENCE_LOW,
+ timeout=300)
return True
def lookForLostBuilds(self):
diff --git a/zuul/layoutvalidator.py b/zuul/layoutvalidator.py
index 696965399..f71c853f4 100644
--- a/zuul/layoutvalidator.py
+++ b/zuul/layoutvalidator.py
@@ -20,6 +20,7 @@ import string
from zuul.trigger import gerrit
+
# Several forms accept either a single item or a list, this makes
# specifying that in the schema easy (and explicit).
def toList(x):
@@ -152,11 +153,11 @@ class LayoutSchema(object):
def validateJob(self, value, path=[]):
if isinstance(value, list):
- for (i, v) in enumerate(value):
- self.validateJob(v, path + [i])
+ for (i, val) in enumerate(value):
+ self.validateJob(val, path + [i])
elif isinstance(value, dict):
- for k, v in value.items():
- self.validateJob(v, path + [k])
+ for k, val in value.items():
+ self.validateJob(val, path + [k])
else:
self.job_name.schema(value)
@@ -193,6 +194,9 @@ class LayoutSchema(object):
return parameters
def getSchema(self, data):
+ if not isinstance(data, dict):
+ raise Exception("Malformed layout configuration: top-level type "
+ "should be a dictionary")
pipelines = data.get('pipelines')
if not pipelines:
pipelines = []
@@ -275,4 +279,3 @@ class LayoutValidator(object):
for pipeline in data['pipelines']:
if 'gerrit' in pipeline['trigger']:
gerrit.validate_trigger(pipeline['trigger'])
-
diff --git a/zuul/lib/cloner.py b/zuul/lib/cloner.py
index 89ebada0e..2b35e41a3 100644
--- a/zuul/lib/cloner.py
+++ b/zuul/lib/cloner.py
@@ -39,8 +39,8 @@ class Cloner(object):
self.cache_dir = cache_dir
self.projects = projects
self.workspace = workspace
- self.zuul_branch = zuul_branch
- self.zuul_ref = zuul_ref
+ self.zuul_branch = zuul_branch or ''
+ self.zuul_ref = zuul_ref or ''
self.zuul_url = zuul_url
self.project_branches = project_branches or {}
@@ -80,8 +80,7 @@ class Cloner(object):
new_repo = git.Repo.clone_from(git_cache, dest)
self.log.info("Updating origin remote in repo %s to %s",
project, git_upstream)
- origin = new_repo.remotes.origin.config_writer.set(
- 'url', git_upstream)
+ new_repo.remotes.origin.config_writer.set('url', git_upstream)
else:
self.log.info("Creating repo %s from upstream %s",
project, git_upstream)
diff --git a/zuul/lib/gerrit.py b/zuul/lib/gerrit.py
index 67400216a..9aeff3df8 100644
--- a/zuul/lib/gerrit.py
+++ b/zuul/lib/gerrit.py
@@ -156,7 +156,8 @@ class Gerrit(object):
lines = out.split('\n')
if not lines:
return False
- data = [json.loads(line) for line in lines[:-1]]
+ data = [json.loads(line) for line in lines
+ if "sortKey" in line]
if not data:
return False
self.log.debug("Received data from Gerrit query: \n%s" %
diff --git a/zuul/lib/swift.py b/zuul/lib/swift.py
index 5781a4d82..9b9bea375 100644
--- a/zuul/lib/swift.py
+++ b/zuul/lib/swift.py
@@ -45,7 +45,8 @@ class Swift(object):
try:
if self.config.has_section('swift'):
if (not self.config.has_option('swift', 'Send-Temp-Url-Key')
- or self.config.getboolean('swift', 'Send-Temp-Url-Key')):
+ or self.config.getboolean('swift',
+ 'Send-Temp-Url-Key')):
self.connect()
# Tell swift of our key
diff --git a/zuul/merger/client.py b/zuul/merger/client.py
index 8c4156351..8d8f7eebd 100644
--- a/zuul/merger/client.py
+++ b/zuul/merger/client.py
@@ -89,7 +89,8 @@ class MergeClient(object):
json.dumps(data),
unique=uuid)
self.build_sets[uuid] = build_set
- self.gearman.submitJob(job, precedence=precedence)
+ self.gearman.submitJob(job, precedence=precedence,
+ timeout=300)
def mergeChanges(self, items, build_set,
precedence=zuul.model.PRECEDENCE_NORMAL):
diff --git a/zuul/merger/merger.py b/zuul/merger/merger.py
index 922c67ef3..8774f109e 100644
--- a/zuul/merger/merger.py
+++ b/zuul/merger/merger.py
@@ -105,7 +105,7 @@ class Repo(object):
def getCommitFromRef(self, refname):
repo = self.createRepoObject()
- if not refname in repo.refs:
+ if refname not in repo.refs:
return None
ref = repo.refs[refname]
return ref.commit
diff --git a/zuul/model.py b/zuul/model.py
index 67ce8be96..b705982bf 100644
--- a/zuul/model.py
+++ b/zuul/model.py
@@ -266,8 +266,8 @@ class Pipeline(object):
j_changes = []
j_changes.append(e.formatJSON())
if (len(j_changes) > 1 and
- (j_changes[-2]['remaining_time'] is not None) and
- (j_changes[-1]['remaining_time'] is not None)):
+ (j_changes[-2]['remaining_time'] is not None) and
+ (j_changes[-1]['remaining_time'] is not None)):
j_changes[-1]['remaining_time'] = max(
j_changes[-2]['remaining_time'],
j_changes[-1]['remaining_time'])
@@ -340,7 +340,7 @@ class ChangeQueue(object):
for job in self._jobs:
if job.queue_name:
if (self.assigned_name and
- job.queue_name != self.assigned_name):
+ job.queue_name != self.assigned_name):
raise Exception("More than one name assigned to "
"change queue: %s != %s" %
(self.assigned_name, job.queue_name))
@@ -1150,7 +1150,7 @@ class EventFilter(BaseFilter):
matches_email_re = False
for email_re in self.emails:
if (account_email is not None and
- email_re.search(account_email)):
+ email_re.search(account_email)):
matches_email_re = True
if self.emails and not matches_email_re:
return False
diff --git a/zuul/rpcclient.py b/zuul/rpcclient.py
index 7f572be76..f43c3b905 100644
--- a/zuul/rpcclient.py
+++ b/zuul/rpcclient.py
@@ -38,7 +38,7 @@ class RPCClient(object):
job = gear.Job(name,
json.dumps(data),
unique=str(time.time()))
- self.gearman.submitJob(job)
+ self.gearman.submitJob(job, timeout=300)
self.log.debug("Waiting for job completion")
while not job.complete:
diff --git a/zuul/scheduler.py b/zuul/scheduler.py
index 9effcb896..7d41fb182 100644
--- a/zuul/scheduler.py
+++ b/zuul/scheduler.py
@@ -226,7 +226,7 @@ class Scheduler(threading.Thread):
if 'python-file' in include:
fn = include['python-file']
if not os.path.isabs(fn):
- base = os.path.dirname(config_path)
+ base = os.path.dirname(os.path.realpath(config_path))
fn = os.path.join(base, fn)
fn = os.path.expanduser(fn)
execfile(fn, config_env)
@@ -235,7 +235,8 @@ class Scheduler(threading.Thread):
pipeline = Pipeline(conf_pipeline['name'])
pipeline.description = conf_pipeline.get('description')
# TODO(jeblair): remove backwards compatibility:
- pipeline.source = self.triggers[conf_pipeline.get('source', 'gerrit')]
+ pipeline.source = self.triggers[conf_pipeline.get('source',
+ 'gerrit')]
precedence = model.PRECEDENCE_MAP[conf_pipeline.get('precedence')]
pipeline.precedence = precedence
pipeline.failure_message = conf_pipeline.get('failure-message',
@@ -314,16 +315,19 @@ class Scheduler(threading.Thread):
usernames = toList(trigger.get('username'))
if not usernames:
usernames = toList(trigger.get('username_filter'))
- f = EventFilter(trigger=self.triggers['gerrit'],
- types=toList(trigger['event']),
- branches=toList(trigger.get('branch')),
- refs=toList(trigger.get('ref')),
- event_approvals=approvals,
- comments=comments,
- emails=emails,
- usernames=usernames,
- required_approvals=
- toList(trigger.get('require-approval')))
+ f = EventFilter(
+ trigger=self.triggers['gerrit'],
+ types=toList(trigger['event']),
+ branches=toList(trigger.get('branch')),
+ refs=toList(trigger.get('ref')),
+ event_approvals=approvals,
+ comments=comments,
+ emails=emails,
+ usernames=usernames,
+ required_approvals=toList(
+ trigger.get('require-approval')
+ )
+ )
manager.event_filters.append(f)
if 'timer' in conf_pipeline['trigger']:
for trigger in toList(conf_pipeline['trigger']['timer']):
@@ -333,11 +337,14 @@ class Scheduler(threading.Thread):
manager.event_filters.append(f)
if 'zuul' in conf_pipeline['trigger']:
for trigger in toList(conf_pipeline['trigger']['zuul']):
- f = EventFilter(trigger=self.triggers['zuul'],
- types=toList(trigger['event']),
- pipelines=toList(trigger.get('pipeline')),
- required_approvals=
- toList(trigger.get('require-approval')))
+ f = EventFilter(
+ trigger=self.triggers['zuul'],
+ types=toList(trigger['event']),
+ pipelines=toList(trigger.get('pipeline')),
+ required_approvals=toList(
+ trigger.get('require-approval')
+ )
+ )
manager.event_filters.append(f)
for project_template in data.get('project-templates', []):
@@ -692,7 +699,7 @@ class Scheduler(threading.Thread):
break
for item in shared_queue.queue:
if (item.change.number == change_ids[0][0] and
- item.change.patchset == change_ids[0][1]):
+ item.change.patchset == change_ids[0][1]):
change_queue = shared_queue
break
if not change_queue:
@@ -702,7 +709,7 @@ class Scheduler(threading.Thread):
found = False
for item in change_queue.queue:
if (item.change.number == number and
- item.change.patchset == patchset):
+ item.change.patchset == patchset):
found = True
items_to_enqueue.append(item)
break
@@ -810,7 +817,7 @@ class Scheduler(threading.Thread):
try:
project = self.layout.projects.get(event.project_name)
if not project:
- self.log.warning("Project %s not found" % event.project_name)
+ self.log.debug("Project %s not found" % event.project_name)
return
for pipeline in self.layout.pipelines.values():
@@ -1157,7 +1164,8 @@ class BasePipelineManager(object):
item.enqueue_time = enqueue_time
self.reportStats(item)
self.enqueueChangesBehind(change, quiet, ignore_requirements)
- self.sched.triggers['zuul'].onChangeEnqueued(item.change, self.pipeline)
+ self.sched.triggers['zuul'].onChangeEnqueued(item.change,
+ self.pipeline)
else:
self.log.error("Unable to find change queue for project %s" %
change.project)
diff --git a/zuul/trigger/gerrit.py b/zuul/trigger/gerrit.py
index 0c0a37654..6782534c2 100644
--- a/zuul/trigger/gerrit.py
+++ b/zuul/trigger/gerrit.py
@@ -250,7 +250,7 @@ class Gerrit(object):
data = change._data
if not data:
return False
- if not 'submitRecords' in data:
+ if 'submitRecords' not in data:
return False
try:
for sr in data['submitRecords']:
@@ -328,15 +328,18 @@ class Gerrit(object):
# This is a best-effort function in case Gerrit is unable to return
# a particular change. It happens.
query = "project:%s status:open" % (project.name,)
- self.log.debug("Running query %s to get project open changes" % (query,))
+ self.log.debug("Running query %s to get project open changes" %
+ (query,))
data = self.gerrit.simpleQuery(query)
changes = []
for record in data:
try:
- changes.append(self._getChange(record['number'],
- record['currentPatchSet']['number']))
+ changes.append(
+ self._getChange(record['number'],
+ record['currentPatchSet']['number']))
except Exception:
- self.log.exception("Unable to query change %s" % (record.get('number'),))
+ self.log.exception("Unable to query change %s" %
+ (record.get('number'),))
return changes
def updateChange(self, change):
@@ -423,4 +426,3 @@ def validate_trigger(trigger_data):
raise voluptuous.Invalid(
"The event %s does not include ref information, Zuul cannot "
"use ref filter 'ref: %s'" % (event['event'], event['ref']))
-
diff --git a/zuul/trigger/zuultrigger.py b/zuul/trigger/zuultrigger.py
index 27098ab81..4418d6f8e 100644
--- a/zuul/trigger/zuultrigger.py
+++ b/zuul/trigger/zuultrigger.py
@@ -47,8 +47,9 @@ class ZuulTrigger(object):
try:
self._createProjectChangeMergedEvents(change)
except Exception:
- self.log.exception("Unable to create project-change-merged events for %s" %
- (change,))
+ self.log.exception(
+ "Unable to create project-change-merged events for "
+ "%s" % (change,))
def onChangeEnqueued(self, change, pipeline):
# Called each time a change is enqueued in a pipeline
@@ -56,11 +57,13 @@ class ZuulTrigger(object):
try:
self._createParentChangeEnqueuedEvents(change, pipeline)
except Exception:
- self.log.exception("Unable to create parent-change-enqueued events for %s in %s" %
- (change, pipeline))
+ self.log.exception(
+ "Unable to create parent-change-enqueued events for "
+ "%s in %s" % (change, pipeline))
def _createProjectChangeMergedEvents(self, change):
- changes = self.sched.triggers['gerrit'].getProjectOpenChanges(change.project)
+ changes = self.sched.triggers['gerrit'].getProjectOpenChanges(
+ change.project)
for open_change in changes:
self._createProjectChangeMergedEvent(open_change)