Merge "Fix broken project config in dynamic config test" into feature/zuulv3
diff --git a/.gitignore b/.gitignore
index a2dd0a3..d7e2fac 100644
--- a/.gitignore
+++ b/.gitignore
@@ -3,6 +3,7 @@
 *.egg-info
 *.pyc
 .idea
+.mypy_cache
 .test
 .testrepository
 .tox
diff --git a/.zuul.yaml b/.zuul.yaml
index 8095733..3922dd3 100644
--- a/.zuul.yaml
+++ b/.zuul.yaml
@@ -3,7 +3,8 @@
     check:
       jobs:
         - tox-docs
-        - tox-cover
+        - tox-cover:
+            voting: false
         - tox-pep8
         - tox-py35
         - tox-tarball
diff --git a/doc/source/admin/components.rst b/doc/source/admin/components.rst
index cc9d181..08671c9 100644
--- a/doc/source/admin/components.rst
+++ b/doc/source/admin/components.rst
@@ -296,10 +296,29 @@
      finger_port=79
 
 **git_dir**
-  Directory that Zuul should clone local git repositories to::
+  Directory that Zuul should clone local git repositories to.  The
+  executor keeps a local copy of every git repository it works with to
+  speed operations and perform speculative merging.
+
+  This should be on the same filesystem as **job_dir** so that when
+  git repos are cloned into the job workspaces, they can be
+  hard-linked to the local git cache.  Example::
 
      git_dir=/var/lib/zuul/git
 
+**job_dir**
+  Directory that Zuul should use to hold temporary job directories.
+  When each job is run, a new entry will be created under this
+  directory to hold the configuration and scratch workspace for that
+  job.  It will be deleted at the end of the job (unless the
+  `--keep-jobdir` command line option is specified).
+
+  This should be on the same filesystem as **git_dir** so that when
+  git repos are cloned into the job workspaces, they can be
+  hard-linked to the local git cache.  Example::
+
+     job_dir=/var/lib/zuul/jobs
+
 **log_config**
   Path to log config file for the executor process::
 
@@ -317,6 +336,31 @@
 
      user=zuul
 
+.. _admin_sitewide_variables:
+
+**variables**
+  Path to an Ansible variables file to supply site-wide variables.
+  This should be a YAML-formatted file consisting of a single
+  dictionary.  The contents will be made available to all jobs as
+  Ansible variables.  These variables take precedence over all other
+  forms (job variables and secrets).  Care should be taken when naming
+  these variables to avoid potential collisions with those used by
+  jobs.  Prefixing variable names with a site-specific identifier is
+  recommended.  The default is not to add any site-wide variables.
+  See the :ref:`User's Guide <user_sitewide_variables>` for more
+  information.
+
+  Example::
+
+     variables=/etc/zuul/variables.yaml
+
+**disk_limit_per_job**
+  This integer is the maximum number of megabytes that any one job is
+  allowed to consume on disk while it is running. If a job's scratch
+  space has more than this much space consumed, it will be aborted::
+
+      disk_limit_per_job=100
+
 merger
 """"""
 
diff --git a/doc/source/admin/drivers/gerrit.rst b/doc/source/admin/drivers/gerrit.rst
index 29e136b..296e47f 100644
--- a/doc/source/admin/drivers/gerrit.rst
+++ b/doc/source/admin/drivers/gerrit.rst
@@ -105,7 +105,7 @@
 **approval**
   This is only used for ``comment-added`` events.  It only matches if
   the event has a matching approval associated with it.  Example:
-  ``code-review: 2`` matches a ``+2`` vote on the code review
+  ``Code-Review: 2`` matches a ``+2`` vote on the code review
   category.  Multiple approvals may be listed.
 
 **email**
@@ -146,8 +146,8 @@
   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 :ref:`"approval" pipeline requirement
-  <pipeline-require-approval>`. For each specified criteria there must
-  exist a matching approval.
+  <gerrit-pipeline-require-approval>`. For each specified criteria
+  there must exist a matching approval.
 
 **reject-approval**
   This takes a list of approvals in the same format as
@@ -170,3 +170,102 @@
 
 A :ref:`connection<connections>` that uses the gerrit driver must be
 supplied to the trigger.
+
+Requirements Configuration
+--------------------------
+
+As described in :ref:`pipeline.require <pipeline-require>` and
+:ref:`pipeline.reject <pipeline-reject>`, pipelines may specify that
+items meet certain conditions in order to be enqueued into the
+pipeline.  These conditions vary according to the source of the
+project in question.  To supply requirements for changes from a Gerrit
+source named *my-gerrit*, create a configuration such as the
+following::
+
+  pipeline:
+    require:
+      my-gerrit:
+        approval:
+          - Code-Review: 2
+
+This indicates that changes originating from the Gerrit connection
+named *my-gerrit* must have a Code Review vote of +2 in order to be
+enqueued into the pipeline.
+
+.. zuul:configobject:: pipeline.require.<source>
+
+   The dictionary passed to the Gerrit pipeline `require` attribute
+   supports the following attributes:
+
+   .. _gerrit-pipeline-require-approval:
+
+   .. zuul:attr:: 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 event in question).  It takes several sub-parameters, all of
+      which are optional and are combined together so that there must
+      be an approval matching all specified requirements.
+
+      .. zuul:attr:: username
+
+         If present, an approval from this username is required.  It is
+         treated as a regular expression.
+
+      .. zuul:attr:: email
+
+         If present, an approval with this email address is required.  It is
+         treated as a regular expression.
+
+      .. zuul:attr:: older-than
+
+         If present, the approval must be older than this amount of time
+         to match.  Provide a time interval as a number with a suffix of
+         "w" (weeks), "d" (days), "h" (hours), "m" (minutes), "s"
+         (seconds).  Example ``48h`` or ``2d``.
+
+      .. zuul:attr:: newer-than
+
+         If present, the approval must be newer than this amount
+         of time to match.  Same format as "older-than".
+
+      Any other field is interpreted as a review category and value
+      pair.  For example ``Verified: 1`` would require that the
+      approval be for a +1 vote in the "Verified" column.  The value
+      may either be a single value or a list: ``Verified: [1, 2]``
+      would match either a +1 or +2 vote.
+
+   .. zuul:attr:: open
+
+      A boolean value (``true`` or ``false``) that indicates whether
+      the change must be open or closed in order to be enqueued.
+
+   .. zuul:attr:: current-patchset
+
+      A boolean value (``true`` or ``false``) that indicates whether the
+      change must be the current patchset in order to be enqueued.
+
+   .. zuul:attr:: status
+
+      A string value that corresponds with the status of the change
+      reported by the trigger.
+
+.. zuul:configobject:: pipeline.reject.<source>
+
+   The `reject` attribute is the mirror of the `require` attribute.  It
+   also accepts a dictionary under the connection name.  This
+   dictionary supports the following attributes:
+
+   .. zuul:attr:: approval
+
+      This takes a list of approvals. If an approval matches the
+      provided criteria the change can not be entered into the
+      pipeline. It follows the same syntax as the :ref:`approval
+      pipeline requirement above <gerrit-pipeline-require-approval>`.
+
+      Example to reject a change with any negative vote::
+
+        reject:
+          my-gerrit:
+            approval:
+              - Code-Review: [-1, -2]
diff --git a/doc/source/admin/drivers/github.rst b/doc/source/admin/drivers/github.rst
index 9740292..6619322 100644
--- a/doc/source/admin/drivers/github.rst
+++ b/doc/source/admin/drivers/github.rst
@@ -22,18 +22,36 @@
 Connection Configuration
 ------------------------
 
+There are two forms of operation. Either the Zuul installation can be
+configured as a `Github App`_ or it can be configured as a Webhook.
+
+If the `Github App`_ approach is taken, the config settings ``app_id`` and
+``app_key`` are required. If the Webhook approach is taken, the ``api_token``
+setting is required.
+
 The supported options in zuul.conf connections are:
 
 **driver=github**
 
+**app_id**
+  App ID if you are using a GitHub App. Can be found under the "Public Link"
+  on the right hand side labeled "ID".
+  ``app_id=1234``
+
+**app_key**
+  Path to a file containing the Secret Key Zuul will use to create tokens for
+  the API interactions. In Github this is known as "Private key" and must be
+  collected when generated.
+  ``app_key=/etc/zuul/github.key``
+
 **api_token**
-  API token for accessing GitHub.
+  API token for accessing GitHub if Zuul is configured with Webhooks.
   See `Creating an access token for command-line use
   <https://help.github.com/articles/creating-an-access-token-for-command-line-use/>`_.
 
 **webhook_token**
-  Optional: Token for validating the webhook event payloads.
-  If not specified, payloads are not validated.
+  Required token for validating the webhook event payloads.  In the
+  GitHub App Configuration page, this is called "Webhook secret".
   See `Securing your webhooks
   <https://developer.github.com/webhooks/securing/>`_.
 
@@ -174,3 +192,113 @@
   List of strings each representing an exact label name which should
   be removed from the pull request by reporter. Only used for Pull
   Request based events.  ``unlabel: 'test failed'``
+
+.. _Github App: https://developer.github.com/apps/
+
+Requirements Configuration
+--------------------------
+
+As described in :ref:`pipeline.require <pipeline-require>` and
+:ref:`pipeline.reject <pipeline-reject>`, pipelines may specify that
+items meet certain conditions in order to be enqueued into the
+pipeline.  These conditions vary according to the source of the
+project in question.  To supply requirements for changes from a GitHub
+source named *my-github*, create a congfiguration such as the
+following::
+
+  pipeline:
+    require:
+      my-github:
+        review:
+          - type: approval
+
+This indicates that changes originating from the GitHub connection
+named *my-github* must have an approved code review in order to be
+enqueued into the pipeline.
+
+.. zuul:configobject:: pipeline.require.<source>
+
+   The dictionary passed to the GitHub pipeline `require` attribute
+   supports the following attributes:
+
+   .. _github-pipeline-require-review:
+
+   .. zuul:attr:: review
+
+      This requires that a certain kind of code review be present for
+      the pull request (it could be added by the event in question).
+      It takes several sub-parameters, all of which are optional and
+      are combined together so that there must be a code review
+      matching all specified requirements.
+
+      .. zuul:attr:: username
+
+         If present, a code review from this username is required.  It
+         is treated as a regular expression.
+
+      .. zuul:attr:: email
+
+         If present, a code review with this email address is
+         required.  It is treated as a regular expression.
+
+      .. zuul:attr:: older-than
+
+         If present, the code review must be older than this amount of
+         time to match.  Provide a time interval as a number with a
+         suffix of "w" (weeks), "d" (days), "h" (hours), "m"
+         (minutes), "s" (seconds).  Example ``48h`` or ``2d``.
+
+      .. zuul:attr:: newer-than
+
+         If present, the code review must be newer than this amount of
+         time to match.  Same format as "older-than".
+
+      .. zuul:attr:: type
+
+         If present, the code review must match this type (or types).
+
+         .. TODO: what types are valid?
+
+      .. zuul:attr:: permission
+
+         If present, the author of the code review must have this
+         permission (or permissions).  The available values are
+         ``read``, ``write``, and ``admin``.
+
+   .. zuul:attr:: open
+
+      A boolean value (``true`` or ``false``) that indicates whether
+      the change must be open or closed in order to be enqueued.
+
+   .. zuul:attr:: current-patchset
+
+      A boolean value (``true`` or ``false``) that indicates whether
+      the item must be associated with the latest commit in the pull
+      request in order to be enqueued.
+
+      .. TODO: this could probably be expanded upon -- under what
+         circumstances might this happen with github
+
+   .. zuul:attr:: status
+
+      A string value that corresponds with the status of the pull
+      request.  The syntax is ``user:status:value``.
+
+   .. zuul:attr:: label
+
+      A string value indicating that the pull request must have the
+      indicated label (or labels).
+
+
+.. zuul:configobject:: pipeline.reject.<source>
+
+   The `reject` attribute is the mirror of the `require` attribute.  It
+   also accepts a dictionary under the connection name.  This
+   dictionary supports the following attributes:
+
+   .. zuul:attr:: review
+
+      This takes a list of code reviews.  If a code review matches the
+      provided criteria the pull request can not be entered into the
+      pipeline.  It follows the same syntax as the :ref:`review
+      pipeline requirement above <github-pipeline-require-review>`.
diff --git a/doc/source/admin/drivers/zuul.rst b/doc/source/admin/drivers/zuul.rst
index a23c875..b531754 100644
--- a/doc/source/admin/drivers/zuul.rst
+++ b/doc/source/admin/drivers/zuul.rst
@@ -25,16 +25,3 @@
 **pipeline**
   Only available for ``parent-change-enqueued`` events.  This is the
   name of the pipeline in which the parent change was enqueued.
-
-**require-approval**
-  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 :ref:`"approval" pipeline requirement
-  <pipeline-require-approval>`. For each specified criteria there must
-  exist a matching approval.
-
-**reject-approval**
-  This takes a list of approvals in the same format as
-  *require-approval* but will fail to enter the pipeline if there is a
-  matching approval.
diff --git a/doc/source/admin/tenants.rst b/doc/source/admin/tenants.rst
index 60873a9..18ec381 100644
--- a/doc/source/admin/tenants.rst
+++ b/doc/source/admin/tenants.rst
@@ -33,7 +33,7 @@
           config-projects:
             - common-config
             - shared-jobs:
-                include: jobs
+                include: job
           untrusted-projects:
             - zuul-jobs:
                 shadow: common-config
diff --git a/doc/source/conf.py b/doc/source/conf.py
index 71c7697..80cde65 100644
--- a/doc/source/conf.py
+++ b/doc/source/conf.py
@@ -29,7 +29,7 @@
     'sphinx.ext.autodoc',
     'sphinxcontrib.blockdiag',
     'sphinxcontrib.programoutput',
-    'oslosphinx'
+    'zuul.sphinx.zuul',
 ]
 #extensions = ['sphinx.ext.intersphinx']
 #intersphinx_mapping = {'python': ('http://docs.python.org/2.7', None)}
@@ -89,7 +89,7 @@
 
 # The theme to use for HTML and HTML Help pages.  See the documentation for
 # a list of builtin themes.
-html_theme = 'default'
+#html_theme = 'alabaster'
 
 # Theme options are theme-specific and customize the look and feel of a theme
 # further.  For a list of options available for each theme, see the
diff --git a/doc/source/index.rst b/doc/source/index.rst
index 24ab31b..0aefa84 100644
--- a/doc/source/index.rst
+++ b/doc/source/index.rst
@@ -25,6 +25,5 @@
 ==================
 
 * :ref:`genindex`
-* :ref:`modindex`
 * :ref:`search`
 
diff --git a/doc/source/user/config.rst b/doc/source/user/config.rst
index c137918..2ef581a 100644
--- a/doc/source/user/config.rst
+++ b/doc/source/user/config.rst
@@ -115,292 +115,282 @@
           - event: patchset-created
       success:
         my_gerrit:
-          verified: 1
+          Verified: 1
       failure:
         my_gerrit
-          verified: -1
+          Verified: -1
 
 .. TODO: See TODO for more annotated examples of common pipeline configurations.
 
-The attributes available on a pipeline are as follows (all are
-optional unless otherwise specified):
+.. zuul:configobject:: pipeline
 
-**name** (required)
-  This is used later in the project definition to indicate what jobs
-  should be run for events in the pipeline.
+   The attributes available on a pipeline are as follows (all are
+   optional unless otherwise specified):
 
-**manager** (required)
-  There are currently two schemes for managing pipelines:
+   .. zuul:attr:: name
+      :required:
 
-  .. _independent_pipeline_manager:
+      This is used later in the project definition to indicate what jobs
+      should be run for events in the pipeline.
 
-  *independent*
-    Every event in this pipeline should be treated as independent of
-    other events in the pipeline.  This is appropriate when the order of
-    events in the pipeline doesn't matter because the results of the
-    actions this pipeline performs can not affect other events in the
-    pipeline.  For example, when a change is first uploaded for review,
-    you may want to run tests on that change to provide early feedback
-    to reviewers.  At the end of the tests, the change is not going to
-    be merged, so it is safe to run these tests in parallel without
-    regard to any other changes in the pipeline.  They are independent.
+   .. zuul:attr:: manager
+      :required:
 
-    Another type of pipeline that is independent is a post-merge
-    pipeline. In that case, the changes have already merged, so the
-    results can not affect any other events in the pipeline.
+      There are currently two schemes for managing pipelines:
 
-  .. _dependent_pipeline_manager:
+      .. _independent_pipeline_manager:
 
-  *dependent*
-    The dependent pipeline manager is designed for gating.  It ensures
-    that every change is tested exactly as it is going to be merged
-    into the repository.  An ideal gating system would test one change
-    at a time, applied to the tip of the repository, and only if that
-    change passed tests would it be merged.  Then the next change in
-    line would be tested the same way.  In order to achieve parallel
-    testing of changes, the dependent pipeline manager performs
-    speculative execution on changes.  It orders changes based on
-    their entry into the pipeline.  It begins testing all changes in
-    parallel, assuming that each change ahead in the pipeline will pass
-    its tests.  If they all succeed, all the changes can be tested and
-    merged in parallel.  If a change near the front of the pipeline
-    fails its tests, each change behind it ignores whatever tests have
-    been completed and are tested again without the change in front.
-    This way gate tests may run in parallel but still be tested
-    correctly, exactly as they will appear in the repository when
-    merged.
+      .. zuul:value:: independent
 
-    For more detail on the theory and operation of Zuul's dependent
-    pipeline manager, see: :doc:`gating`.
+         Every event in this pipeline should be treated as independent
+         of other events in the pipeline.  This is appropriate when
+         the order of events in the pipeline doesn't matter because
+         the results of the actions this pipeline performs can not
+         affect other events in the pipeline.  For example, when a
+         change is first uploaded for review, you may want to run
+         tests on that change to provide early feedback to reviewers.
+         At the end of the tests, the change is not going to be
+         merged, so it is safe to run these tests in parallel without
+         regard to any other changes in the pipeline.  They are
+         independent.
 
-**allow-secrets**
-  This is a boolean which can be used to prevent jobs which require
-  secrets from running in this pipeline.  Some pipelines run on
-  proposed changes and therefore execute code which has not yet been
-  reviewed.  In such a case, allowing a job to use a secret could
-  result in that secret being exposed.  The default is False, meaning
-  that in order to run jobs with secrets, this must be explicitly
-  enabled on each Pipeline where that is safe.
+         Another type of pipeline that is independent is a post-merge
+         pipeline. In that case, the changes have already merged, so
+         the results can not affect any other events in the pipeline.
 
-  For more information, see :ref:`secret`.
+      .. _dependent_pipeline_manager:
 
-**description**
-  This field may be used to provide a textual description of the
-  pipeline.  It may appear in the status page or in documentation.
+      .. zuul:value:: dependent
 
-**success-message**
-  The introductory text in reports when all the voting jobs are
-  successful.  Defaults to "Build successful."
+         The dependent pipeline manager is designed for gating.  It
+         ensures that every change is tested exactly as it is going to
+         be merged into the repository.  An ideal gating system would
+         test one change at a time, applied to the tip of the
+         repository, and only if that change passed tests would it be
+         merged.  Then the next change in line would be tested the
+         same way.  In order to achieve parallel testing of changes,
+         the dependent pipeline manager performs speculative execution
+         on changes.  It orders changes based on their entry into the
+         pipeline.  It begins testing all changes in parallel,
+         assuming that each change ahead in the pipeline will pass its
+         tests.  If they all succeed, all the changes can be tested
+         and merged in parallel.  If a change near the front of the
+         pipeline fails its tests, each change behind it ignores
+         whatever tests have been completed and are tested again
+         without the change in front.  This way gate tests may run in
+         parallel but still be tested correctly, exactly as they will
+         appear in the repository when merged.
 
-**failure-message**
-  The introductory text in reports when at least one voting job fails.
-  Defaults to "Build failed."
+         For more detail on the theory and operation of Zuul's
+         dependent pipeline manager, see: :doc:`gating`.
 
-**merge-failure-message**
-  The introductory text in the message reported when a change fails to
-  merge with the current state of the repository.  Defaults to "Merge
-  failed."
+   .. zuul:attr:: allow-secrets
 
-**footer-message**
-  Supplies additional information after test results.  Useful for
-  adding information about the CI system such as debugging and contact
-  details.
+      This is a boolean which can be used to prevent jobs which
+      require secrets from running in this pipeline.  Some pipelines
+      run on proposed changes and therefore execute code which has not
+      yet been reviewed.  In such a case, allowing a job to use a
+      secret could result in that secret being exposed.  The default
+      is False, meaning that in order to run jobs with secrets, this
+      must be explicitly enabled on each Pipeline where that is safe.
 
-**trigger**
-  At least one trigger source must be supplied for each pipeline.
-  Triggers are not exclusive -- matching events may be placed in
-  multiple pipelines, and they will behave independently in each of
-  the pipelines they match.
+      For more information, see :ref:`secret`.
 
-  Triggers are loaded from their connection name. The driver type of
-  the connection will dictate which options are available.
-  See :ref:`drivers`.
+   .. zuul:attr:: description
 
-**require**
-  If this section is present, it established pre-requisites for any
-  kind of item entering the Pipeline.  Regardless of how the item is
-  to be enqueued (via any trigger or automatic dependency resolution),
-  the conditions specified here must be met or the item will not be
-  enqueued.
+      This field may be used to provide a textual description of the
+      pipeline.  It may appear in the status page or in documentation.
 
-.. _pipeline-require-approval:
+   .. zuul:attr:: success-message
 
-  **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
-  event in question).  It takes several sub-parameters, all of which
-  are optional and are combined together so that there must be an
-  approval matching all specified requirements.
+      The introductory text in reports when all the voting jobs are
+      successful.  Defaults to "Build successful."
 
-    *username*
-    If present, an approval from this username is required.  It is
-    treated as a regular expression.
+   .. zuul:attr:: failure-message
 
-    *email*
-    If present, an approval with this email address is required.  It
-    is treated as a regular expression.
+      The introductory text in reports when at least one voting job
+      fails.  Defaults to "Build failed."
 
-    *email-filter* (deprecated)
-    A deprecated alternate spelling of *email*.  Only one of *email* or
-    *email_filter* should be used.
+   .. zuul:attr:: merge-failure-message
 
-    *older-than*
-    If present, the approval must be older than this amount of time
-    to match.  Provide a time interval as a number with a suffix of
-    "w" (weeks), "d" (days), "h" (hours), "m" (minutes), "s"
-    (seconds).  Example ``48h`` or ``2d``.
+      The introductory text in the message reported when a change
+      fails to merge with the current state of the repository.
+      Defaults to "Merge failed."
 
-    *newer-than*
-    If present, the approval must be newer than this amount of time
-    to match.  Same format as "older-than".
+   .. zuul:attr:: footer-message
 
-    Any other field is interpreted as a review category and value
-    pair.  For example ``verified: 1`` would require that the approval
-    be for a +1 vote in the "Verified" column.  The value may either
-    be a single value or a list: ``verified: [1, 2]`` would match
-    either a +1 or +2 vote.
+      Supplies additional information after test results.  Useful for
+      adding information about the CI system such as debugging and
+      contact details.
 
-  **open**
-  A boolean value (``true`` or ``false``) that indicates whether the change
-  must be open or closed in order to be enqueued.
+   .. zuul:attr:: trigger
 
-  **current-patchset**
-  A boolean value (``true`` or ``false``) that indicates whether the change
-  must be the current patchset in order to be enqueued.
+      At least one trigger source must be supplied for each pipeline.
+      Triggers are not exclusive -- matching events may be placed in
+      multiple pipelines, and they will behave independently in each
+      of the pipelines they match.
 
-  **status**
-  A string value that corresponds with the status of the change
-  reported by the trigger.
+      Triggers are loaded from their connection name. The driver type
+      of the connection will dictate which options are available.  See
+      :ref:`drivers`.
 
-**reject**
-  If this section is present, it establishes pre-requisites that can
-  block an item from being enqueued. It can be considered a negative
-  version of **require**.
+   .. _pipeline-require:
 
-  **approval**
-  This takes a list of approvals. If an approval matches the provided
-  criteria the change can not be entered into the pipeline. It follows
-  the same syntax as the :ref:`"require approval" pipeline above
-  <pipeline-require-approval>`.
+   .. zuul:attr:: require
 
-  Example to reject a change with any negative vote::
+      If this section is present, it establishes pre-requisites for
+      any kind of item entering the Pipeline.  Regardless of how the
+      item is to be enqueued (via any trigger or automatic dependency
+      resolution), the conditions specified here must be met or the
+      item will not be enqueued.  These requirements may vary
+      depending on the source of the item being enqueued.
 
-    reject:
-      approval:
-        - code-review: [-1, -2]
+      Requirements are loaded from their connection name. The driver
+      type of the connection will dictate which options are available.
+      See :ref:`drivers`.
 
-**dequeue-on-new-patchset**
-  Normally, if a new patchset is uploaded to a change that is in a
-  pipeline, the existing entry in the pipeline will be removed (with
-  jobs canceled and any dependent changes that can no longer merge as
-  well.  To suppress this behavior (and allow jobs to continue
-  running), set this to ``false``.  Default: ``true``.
+   .. _pipeline-reject:
 
-**ignore-dependencies**
-  In any kind of pipeline (dependent or independent), Zuul will
-  attempt to enqueue all dependencies ahead of the current change so
-  that they are tested together (independent pipelines report the
-  results of each change regardless of the results of changes ahead).
-  To ignore dependencies completely in an independent pipeline, set
-  this to ``true``.  This option is ignored by dependent pipelines.
-  The default is: ``false``.
+   .. zuul:attr:: reject
 
-**precedence**
-  Indicates how the build scheduler should prioritize jobs for
-  different pipelines.  Each pipeline may have one precedence, jobs
-  for pipelines with a higher precedence will be run before ones with
-  lower.  The value should be one of ``high``, ``normal``, or ``low``.
-  Default: ``normal``.
+      If this section is present, it establishes pre-requisites that
+      can block an item from being enqueued. It can be considered a
+      negative version of **require**.
 
-The following options configure *reporters*.  Reporters are
-complementary to triggers; where a trigger is an event on a connection
-which causes Zuul to enqueue an item, a reporter is the action
-performed on a connection when an item is dequeued after its jobs
-complete.  The actual syntax for a reporter is defined by the driver
-which implements it.  See :ref:`drivers` for more information.
+      Requirements are loaded from their connection name. The driver
+      type of the connection will dictate which options are available.
+      See :ref:`drivers`.
 
-**success**
-  Describes where Zuul should report to if all the jobs complete
-  successfully.  This section is optional; if it is omitted, Zuul will
-  run jobs and do nothing on success -- it will not report at all.  If
-  the section is present, the listed reporters will be asked to report
-  on the jobs.  The reporters are listed by their connection name. The
-  options available depend on the driver for the supplied connection.
+   .. zuul:attr:: dequeue-on-new-patchset
 
-**failure**
-  These reporters describe what Zuul should do if at least one job
-  fails.
+      Normally, if a new patchset is uploaded to a change that is in a
+      pipeline, the existing entry in the pipeline will be removed
+      (with jobs canceled and any dependent changes that can no longer
+      merge as well.  To suppress this behavior (and allow jobs to
+      continue running), set this to ``false``.  Default: ``true``.
 
-**merge-failure**
-  These reporters describe what Zuul should do if it is unable to
-  merge in the patchset. If no merge-failure reporters are listed then
-  the ``failure`` reporters will be used to notify of unsuccessful
-  merges.
+   .. zuul:attr:: ignore-dependencies
 
-**start**
-  These reporters describe what Zuul should do when a change is added
-  to the pipeline.  This can be used, for example, to reset a
-  previously reported result.
+      In any kind of pipeline (dependent or independent), Zuul will
+      attempt to enqueue all dependencies ahead of the current change
+      so that they are tested together (independent pipelines report
+      the results of each change regardless of the results of changes
+      ahead).  To ignore dependencies completely in an independent
+      pipeline, set this to ``true``.  This option is ignored by
+      dependent pipelines.  The default is: ``false``.
 
-**disabled**
-  These reporters describe what Zuul should do when a pipeline is
-  disabled.  See ``disable-after-consecutive-failures``.
+   .. zuul:attr:: precedence
 
-The following options can be used to alter Zuul's behavior to mitigate
-situations in which jobs are failing frequently (perhaps due to a
-problem with an external dependency, or unusually high
-non-deterministic test failures).
+      Indicates how the build scheduler should prioritize jobs for
+      different pipelines.  Each pipeline may have one precedence,
+      jobs for pipelines with a higher precedence will be run before
+      ones with lower.  The value should be one of ``high``,
+      ``normal``, or ``low``.  Default: ``normal``.
 
-**disable-after-consecutive-failures**
-  If set, a pipeline can enter a ''disabled'' state if too many changes
-  in a row fail. When this value is exceeded the pipeline will stop
-  reporting to any of the ``success``, ``failure`` or ``merge-failure``
-  reporters and instead only report to the ``disabled`` reporters.
-  (No ``start`` reports are made when a pipeline is disabled).
+   The following options configure *reporters*.  Reporters are
+   complementary to triggers; where a trigger is an event on a
+   connection which causes Zuul to enqueue an item, a reporter is the
+   action performed on a connection when an item is dequeued after its
+   jobs complete.  The actual syntax for a reporter is defined by the
+   driver which implements it.  See :ref:`drivers` for more
+   information.
 
-**window**
-  Dependent pipeline managers only. Zuul can rate limit dependent
-  pipelines in a manner similar to TCP flow control.  Jobs are only
-  started for items in the queue if they are within the actionable
-  window for the pipeline. The initial length of this window is
-  configurable with this value. The value given should be a positive
-  integer value. A value of ``0`` disables rate limiting on the
-  DependentPipelineManager.  Default: ``20``.
+   .. zuul:attr:: success
 
-**window-floor**
-  Dependent pipeline managers only. This is the minimum value for the
-  window described above. Should be a positive non zero integer value.
-  Default: ``3``.
+      Describes where Zuul should report to if all the jobs complete
+      successfully.  This section is optional; if it is omitted, Zuul
+      will run jobs and do nothing on success -- it will not report at
+      all.  If the section is present, the listed reporters will be
+      asked to report on the jobs.  The reporters are listed by their
+      connection name. The options available depend on the driver for
+      the supplied connection.
 
-**window-increase-type**
-  Dependent pipeline managers only. This value describes how the window
-  should grow when changes are successfully merged by zuul. A value of
-  ``linear`` indicates that ``window-increase-factor`` should be added
-  to the previous window value. A value of ``exponential`` indicates
-  that ``window-increase-factor`` should be multiplied against the
-  previous window value and the result will become the window size.
-  Default: ``linear``.
+   .. zuul:attr:: failure
 
-**window-increase-factor**
-  Dependent pipeline managers only. The value to be added or multiplied
-  against the previous window value to determine the new window after
-  successful change merges.
-  Default: ``1``.
+      These reporters describe what Zuul should do if at least one job
+      fails.
 
-**window-decrease-type**
-  Dependent pipeline managers only. This value describes how the window
-  should shrink when changes are not able to be merged by Zuul. A value
-  of ``linear`` indicates that ``window-decrease-factor`` should be
-  subtracted from the previous window value. A value of ``exponential``
-  indicates that ``window-decrease-factor`` should be divided against
-  the previous window value and the result will become the window size.
-  Default: ``exponential``.
+   .. zuul:attr:: merge-failure
 
-**window-decrease-factor**
-  Dependent pipline managers only. The value to be subtracted or divided
-  against the previous window value to determine the new window after
-  unsuccessful change merges.
-  Default: ``2``.
+      These reporters describe what Zuul should do if it is unable to
+      merge in the patchset. If no merge-failure reporters are listed
+      then the ``failure`` reporters will be used to notify of
+      unsuccessful merges.
+
+   .. zuul:attr:: start
+
+      These reporters describe what Zuul should do when a change is
+      added to the pipeline.  This can be used, for example, to reset
+      a previously reported result.
+
+   .. zuul:attr:: disabled
+
+      These reporters describe what Zuul should do when a pipeline is
+      disabled.  See ``disable-after-consecutive-failures``.
+
+   The following options can be used to alter Zuul's behavior to
+   mitigate situations in which jobs are failing frequently (perhaps
+   due to a problem with an external dependency, or unusually high
+   non-deterministic test failures).
+
+   .. zuul:attr:: disable-after-consecutive-failures
+
+      If set, a pipeline can enter a ''disabled'' state if too many
+      changes in a row fail. When this value is exceeded the pipeline
+      will stop reporting to any of the ``success``, ``failure`` or
+      ``merge-failure`` reporters and instead only report to the
+      ``disabled`` reporters.  (No ``start`` reports are made when a
+      pipeline is disabled).
+
+   .. zuul:attr:: window
+
+      Dependent pipeline managers only. Zuul can rate limit dependent
+      pipelines in a manner similar to TCP flow control.  Jobs are
+      only started for items in the queue if they are within the
+      actionable window for the pipeline. The initial length of this
+      window is configurable with this value. The value given should
+      be a positive integer value. A value of ``0`` disables rate
+      limiting on the DependentPipelineManager.  Default: ``20``.
+
+   .. zuul:attr:: window-floor
+
+      Dependent pipeline managers only. This is the minimum value for
+      the window described above. Should be a positive non zero
+      integer value.  Default: ``3``.
+
+   .. zuul:attr:: window-increase-type
+
+      Dependent pipeline managers only. This value describes how the
+      window should grow when changes are successfully merged by
+      zuul. A value of ``linear`` indicates that
+      ``window-increase-factor`` should be added to the previous
+      window value. A value of ``exponential`` indicates that
+      ``window-increase-factor`` should be multiplied against the
+      previous window value and the result will become the window
+      size.  Default: ``linear``.
+
+   .. zuul:attr:: window-increase-factor
+
+      Dependent pipeline managers only. The value to be added or
+      multiplied against the previous window value to determine the
+      new window after successful change merges.  Default: ``1``.
+
+   .. zuul:attr:: window-decrease-type
+
+      Dependent pipeline managers only. This value describes how the
+      window should shrink when changes are not able to be merged by
+      Zuul. A value of ``linear`` indicates that
+      ``window-decrease-factor`` should be subtracted from the
+      previous window value. A value of ``exponential`` indicates that
+      ``window-decrease-factor`` should be divided against the
+      previous window value and the result will become the window
+      size.  Default: ``exponential``.
+
+   .. zuul:attr:: window-decrease-factor
+
+      Dependent pipline managers only. The value to be subtracted or
+      divided against the previous window value to determine the new
+      window after unsuccessful change merges.  Default: ``2``.
 
 
 .. _job:
@@ -473,7 +463,7 @@
       parent: base
       nodes:
         - name: test-node
-	  image: fedora
+          image: fedora
 
 The following attributes are available on a job; all are optional
 unless otherwise specified:
diff --git a/doc/source/user/jobs.rst b/doc/source/user/jobs.rst
index a367aa0..80ce3f9 100644
--- a/doc/source/user/jobs.rst
+++ b/doc/source/user/jobs.rst
@@ -73,6 +73,24 @@
 Variables
 ---------
 
+There are several sources of variables which are available to Ansible:
+variables defined in jobs, secrets, and site-wide variables.  The
+order of precedence is:
+
+* Site-wide variables
+
+* Secrets
+
+* Job variables
+
+Meaning that a site-wide variable with the same name as any other will
+override its value, and similarly, secrets override job variables of
+the same name.  Each of the three sources is described below.
+
+
+Job Variables
+~~~~~~~~~~~~~
+
 Any variables specified in the job definition are available as Ansible
 host variables.  They are added to the `vars` section of the inventory
 file under the `all` hosts group, so they are available to all hosts.
@@ -147,6 +165,9 @@
 **zuul.job**
   The name of the job being run.
 
+**zuul.voting**
+  A boolean indicating whether the job is voting.
+
 **zuul.project**
   The item's project.  This is a data structure with the following
   fields:
@@ -293,6 +314,19 @@
 **zuul.executor.log_root**
   The path to the logs directory.
 
+
+.. _user_sitewide_variables:
+
+Site-wide Variables
+~~~~~~~~~~~~~~~~~~~
+
+The Zuul administrator may define variables which will be available to
+all jobs running in the system.  These are statically defined and may
+not be altered by jobs.  See the :ref:`Administrator's Guide
+<admin_sitewide_variables>` for information on how a site
+administrator may define these variables.
+
+
 SSH Keys
 --------
 
diff --git a/etc/layout.yaml-sample b/etc/layout.yaml-sample
index 53f6ba1..b84be11 100644
--- a/etc/layout.yaml-sample
+++ b/etc/layout.yaml-sample
@@ -6,10 +6,10 @@
         - event: patchset-created
     success:
       gerrit:
-        verified: 1
+        Verified: 1
     failure:
      gerrit:
-        verified: -1
+        Verified: -1
 
   - name: tests
     manager: IndependentPipelineManager
@@ -19,10 +19,10 @@
           email_filter: ^.*@example.org$
     success:
       gerrit:
-        verified: 1
+        Verified: 1
     failure:
       gerrit:
-        verified: -1
+        Verified: -1
 
   - name: post
     manager: IndependentPipelineManager
@@ -38,16 +38,16 @@
       gerrit:
         - event: comment-added
           approval:
-            - approved: 1
+            - Approved: 1
     start:
       gerrit:
-        verified: 0
+        Verified: 0
     success:
       gerrit:
-        verified: 1
+        Verified: 1
     failure:
       gerrit:
-        verified: -1
+        Verified: -1
 
 jobs:
   - name: ^.*-merge$
diff --git a/test-requirements.txt b/test-requirements.txt
index eea1d69..dcc67e2 100644
--- a/test-requirements.txt
+++ b/test-requirements.txt
@@ -11,6 +11,6 @@
 testrepository>=0.0.17
 testtools>=0.9.32
 sphinxcontrib-programoutput
-oslosphinx
 mock
 PyMySQL
+mypy
diff --git a/tests/base.py b/tests/base.py
index 2c478ad..568e15f 100755
--- a/tests/base.py
+++ b/tests/base.py
@@ -16,6 +16,7 @@
 # under the License.
 
 import configparser
+from contextlib import contextmanager
 import datetime
 import gc
 import hashlib
@@ -133,9 +134,9 @@
 
 
 class FakeGerritChange(object):
-    categories = {'approved': ('Approved', -1, 1),
-                  'code-review': ('Code-Review', -2, 2),
-                  'verified': ('Verified', -2, 2)}
+    categories = {'Approved': ('Approved', -1, 1),
+                  'Code-Review': ('Code-Review', -2, 2),
+                  'Verified': ('Verified', -2, 2)}
 
     def __init__(self, gerrit, number, project, branch, subject,
                  status='NEW', upstream_root=None, files={}):
@@ -291,7 +292,7 @@
                             "url": "https://hostname/3"},
                  "patchSet": self.patchsets[patchset - 1],
                  "author": {"name": "User Name"},
-                 "approvals": [{"type": "code-review",
+                 "approvals": [{"type": "Code-Review",
                                 "description": "Code-Review",
                                 "value": "0"}],
                  "comment": "This is a comment"}
@@ -917,7 +918,9 @@
         port = self.webapp.server.socket.getsockname()[1]
         name, data = event
         payload = json.dumps(data).encode('utf8')
-        headers = {'X-Github-Event': name}
+        secret = self.connection_config['webhook_token']
+        signature = githubconnection._sign_request(payload, secret)
+        headers = {'X-Github-Event': name, 'X-Hub-Signature': signature}
         req = urllib.request.Request(
             'http://localhost:%s/connection/%s/payload'
             % (port, self.connection_name),
@@ -1121,9 +1124,9 @@
         self.node = None
         if len(self.parameters.get('nodes')) == 1:
             self.node = self.parameters['nodes'][0]['label']
-        self.unique = self.parameters['ZUUL_UUID']
-        self.pipeline = self.parameters['ZUUL_PIPELINE']
-        self.project = self.parameters['ZUUL_PROJECT']
+        self.unique = self.parameters['zuul']['build']
+        self.pipeline = self.parameters['zuul']['pipeline']
+        self.project = self.parameters['zuul']['project']['name']
         self.name = self.parameters['job']
         self.wait_condition = threading.Condition()
         self.waiting = False
@@ -1131,8 +1134,9 @@
         self.requeue = False
         self.created = time.time()
         self.changes = None
-        if 'ZUUL_CHANGE_IDS' in self.parameters:
-            self.changes = self.parameters['ZUUL_CHANGE_IDS']
+        items = self.parameters['zuul']['items']
+        self.changes = ' '.join(['%s,%s' % (x['change'], x['patchset'])
+                                for x in items if 'change' in x])
 
     def __repr__(self):
         waiting = ''
@@ -1180,7 +1184,7 @@
         self.log.debug("Build %s continuing" % self.unique)
 
         result = (RecordingAnsibleJob.RESULT_NORMAL, 0)  # Success
-        if (('ZUUL_REF' in self.parameters) and self.shouldFail()):
+        if self.shouldFail():
             result = (RecordingAnsibleJob.RESULT_NORMAL, 1)  # Failure
         if self.aborted:
             result = (RecordingAnsibleJob.RESULT_ABORTED, None)
@@ -1215,8 +1219,7 @@
             except NoSuchPathError as e:
                 self.log.debug('%s' % e)
                 return False
-            ref = self.parameters['ZUUL_REF']
-            repo_messages = [c.message.strip() for c in repo.iter_commits(ref)]
+            repo_messages = [c.message.strip() for c in repo.iter_commits()]
             commit_message = '%s-1' % change.subject
             self.log.debug("Checking if build %s has changes; commit_message "
                            "%s; repo_messages %s" % (self, commit_message,
@@ -1296,11 +1299,11 @@
         for build in builds:
             if not regex or re.match(regex, build.name):
                 self.log.debug("Releasing build %s" %
-                               (build.parameters['ZUUL_UUID']))
+                               (build.parameters['zuul']['build']))
                 build.release()
             else:
                 self.log.debug("Not releasing build %s" %
-                               (build.parameters['ZUUL_UUID']))
+                               (build.parameters['zuul']['build']))
         self.log.debug("Done releasing builds %s (%s)" %
                        (regex, len(self.running_builds)))
 
@@ -1348,7 +1351,7 @@
                          node=build.node, uuid=build.unique,
                          ref=build.parameters['zuul']['ref'],
                          parameters=build.parameters, jobdir=build.jobdir,
-                         pipeline=build.parameters['ZUUL_PIPELINE'])
+                         pipeline=build.parameters['zuul']['pipeline'])
         )
         self.executor_server.running_builds.remove(build)
         del self.executor_server.job_builds[self.job.unique]
@@ -2222,19 +2225,12 @@
         # Make sure no jobs are running
         self.assertEqual({}, self.executor_server.job_workers)
         # Make sure that git.Repo objects have been garbage collected.
-        repos = []
         gc.disable()
         gc.collect()
         for obj in gc.get_objects():
             if isinstance(obj, git.Repo):
                 self.log.debug("Leaked git repo object: 0x%x %s" %
                                (id(obj), repr(obj)))
-                for ref in gc.get_referrers(obj):
-                    self.log.debug("  Referrer %s" % (repr(ref)))
-                repos.append(obj)
-        if repos:
-            for obj in gc.garbage:
-                self.log.debug("  Garbage %s" % (repr(obj)))
         gc.enable()
         self.assertEmptyQueues()
         self.assertNodepoolState()
@@ -2511,7 +2507,7 @@
         for job in self.history:
             if (job.name == name and
                 (project is None or
-                 job.parameters['ZUUL_PROJECT'] == project)):
+                 job.parameters['zuul']['project']['name'] == project)):
                 return job
         raise Exception("Unable to find job %s in history" % name)
 
@@ -2769,6 +2765,24 @@
     """ZuulTestCase but with an actual ansible executor running"""
     run_ansible = True
 
+    @contextmanager
+    def jobLog(self, build):
+        """Print job logs on assertion errors
+
+        This method is a context manager which, if it encounters an
+        ecxeption, adds the build log to the debug output.
+
+        :arg Build build: The build that's being asserted.
+        """
+        try:
+            yield
+        except Exception:
+            path = os.path.join(self.test_root, build.uuid,
+                                'work', 'logs', 'job-output.txt')
+            with open(path) as f:
+                self.log.debug(f.read())
+            raise
+
 
 class SSLZuulTestCase(ZuulTestCase):
     """ZuulTestCase but using SSL when possible"""
diff --git a/tests/fixtures/config/ansible/git/common-config/playbooks/check-vars.yaml b/tests/fixtures/config/ansible/git/common-config/playbooks/check-vars.yaml
index ce392a4..3f62c4c 100644
--- a/tests/fixtures/config/ansible/git/common-config/playbooks/check-vars.yaml
+++ b/tests/fixtures/config/ansible/git/common-config/playbooks/check-vars.yaml
@@ -20,3 +20,13 @@
           - zuul.project.name == 'org/project'
           - zuul.project.canonical_hostname == 'review.example.com'
           - zuul.project.canonical_name == 'review.example.com/org/project'
+
+    - debug:
+        msg: "vartest secret {{ vartest_secret }}"
+
+    - name: Assert variable precedence.
+      assert:
+        that:
+          - vartest_job == 'vartest_job'
+          - vartest_secret.value == 'vartest_secret'
+          - vartest_site == 'vartest_site'
\ No newline at end of file
diff --git a/tests/fixtures/config/ansible/git/common-config/zuul.yaml b/tests/fixtures/config/ansible/git/common-config/zuul.yaml
index 1a1b22f..7a144fb 100644
--- a/tests/fixtures/config/ansible/git/common-config/zuul.yaml
+++ b/tests/fixtures/config/ansible/git/common-config/zuul.yaml
@@ -7,10 +7,10 @@
         - event: patchset-created
     success:
       gerrit:
-        verified: 1
+        Verified: 1
     failure:
       gerrit:
-        verified: -1
+        Verified: -1
 
 - pipeline:
     name: gate
@@ -20,17 +20,17 @@
       gerrit:
         - event: comment-added
           approval:
-            - approved: 1
+            - Approved: 1
     success:
       gerrit:
-        verified: 2
+        Verified: 2
         submit: true
     failure:
       gerrit:
-        verified: -2
+        Verified: -2
     start:
       gerrit:
-        verified: 0
+        Verified: 0
     precedence: high
 
 - secret:
@@ -48,6 +48,27 @@
         Z3QSO1NjbBxWnaHKZYT7nkrJm8AMCgZU0ZArFLpaufKCeiK5ECSsDxic4FIsY1OkWT42qEUfL0Wd
         +150AKGNZpPJnnP3QYY4W/MWcKH/zdO400+zWN52WevbSqZy90tqKDJrBkMl1ydqbuw1E4ZHvIs=
 
+# This is used by the check-vars job to evaluate variable precedence.
+# The name of this secret conflicts with a site variable.
+- secret:
+    name: vartest_site
+    data:
+      value: vartest_secret
+
+# This is used by the check-vars job to evaluate variable precedence.
+# The name of this secret conflicts with a job variable.
+- secret:
+    name: vartest_job
+    data:
+      value: vartest_secret
+
+# This is used by the check-vars job to evaluate variable precedence.
+# The name of this secret should not conflict.
+- secret:
+    name: vartest_secret
+    data:
+      value: vartest_secret
+
 - job:
     name: base-urls
     success-url: https://success.example.com/zuul-logs/{build.uuid}/
@@ -77,6 +98,14 @@
     nodes:
       - name: ubuntu-xenial
         label: ubuntu-xenial
+    vars:
+      vartest_job: vartest_job
+      vartest_secret: vartest_job
+      vartest_site: vartest_job
+    auth:
+      secrets:
+        - vartest_site
+        - vartest_secret
 
 - job:
     parent: base-urls
diff --git a/tests/fixtures/config/ansible/variables.yaml b/tests/fixtures/config/ansible/variables.yaml
new file mode 100644
index 0000000..692eb7f
--- /dev/null
+++ b/tests/fixtures/config/ansible/variables.yaml
@@ -0,0 +1 @@
+vartest_site: vartest_site
diff --git a/tests/fixtures/config/broken/git/common-config/zuul.yaml b/tests/fixtures/config/broken/git/common-config/zuul.yaml
index 162a982..91b1b2d 100644
--- a/tests/fixtures/config/broken/git/common-config/zuul.yaml
+++ b/tests/fixtures/config/broken/git/common-config/zuul.yaml
@@ -6,10 +6,10 @@
         - event: patchset-created
     success:
       gerrit:
-        verified: 1
+        Verified: 1
     failure:
       gerrit:
-        verified: -1
+        Verified: -1
 
 - project:
 error: true
diff --git a/tests/fixtures/config/data-return/git/common-config/zuul.yaml b/tests/fixtures/config/data-return/git/common-config/zuul.yaml
index 8d602f1..38107e5 100644
--- a/tests/fixtures/config/data-return/git/common-config/zuul.yaml
+++ b/tests/fixtures/config/data-return/git/common-config/zuul.yaml
@@ -7,10 +7,10 @@
         - event: patchset-created
     success:
       gerrit:
-        verified: 1
+        Verified: 1
     failure:
       gerrit:
-        verified: -1
+        Verified: -1
 
 - job:
     name: data-return
diff --git a/tests/fixtures/config/dependency-graph/git/common-config/zuul.yaml b/tests/fixtures/config/dependency-graph/git/common-config/zuul.yaml
index cdf989e..975d04e 100644
--- a/tests/fixtures/config/dependency-graph/git/common-config/zuul.yaml
+++ b/tests/fixtures/config/dependency-graph/git/common-config/zuul.yaml
@@ -6,17 +6,17 @@
       gerrit:
         - event: comment-added
           approval:
-            - approved: 1
+            - Approved: 1
     success:
       gerrit:
-        verified: 2
+        Verified: 2
         submit: true
     failure:
       gerrit:
-        verified: -2
+        Verified: -2
     start:
       gerrit:
-        verified: 0
+        Verified: 0
     precedence: high
 
 - job:
diff --git a/tests/fixtures/config/disk-accountant/git/common-config/playbooks/dd-big-empty-file.yaml b/tests/fixtures/config/disk-accountant/git/common-config/playbooks/dd-big-empty-file.yaml
new file mode 100644
index 0000000..95ab870
--- /dev/null
+++ b/tests/fixtures/config/disk-accountant/git/common-config/playbooks/dd-big-empty-file.yaml
@@ -0,0 +1,6 @@
+- hosts: localhost
+  tasks:
+    - command: dd if=/dev/zero of=toobig bs=1M count=2
+    - wait_for:
+        delay: 10
+        path: /
diff --git a/tests/fixtures/config/disk-accountant/git/common-config/zuul.yaml b/tests/fixtures/config/disk-accountant/git/common-config/zuul.yaml
new file mode 100644
index 0000000..83a5158
--- /dev/null
+++ b/tests/fixtures/config/disk-accountant/git/common-config/zuul.yaml
@@ -0,0 +1,22 @@
+- pipeline:
+    name: check
+    manager: independent
+    allow-secrets: true
+    trigger:
+      gerrit:
+        - event: patchset-created
+    success:
+      gerrit:
+        verified: 1
+    failure:
+      gerrit:
+        verified: -1
+
+- job:
+    name: dd-big-empty-file
+
+- project:
+    name: org/project
+    check:
+      jobs:
+        - dd-big-empty-file
diff --git a/tests/fixtures/config/disk-accountant/git/org_project/README b/tests/fixtures/config/disk-accountant/git/org_project/README
new file mode 100644
index 0000000..9daeafb
--- /dev/null
+++ b/tests/fixtures/config/disk-accountant/git/org_project/README
@@ -0,0 +1 @@
+test
diff --git a/tests/fixtures/config/disk-accountant/main.yaml b/tests/fixtures/config/disk-accountant/main.yaml
new file mode 100644
index 0000000..208e274
--- /dev/null
+++ b/tests/fixtures/config/disk-accountant/main.yaml
@@ -0,0 +1,8 @@
+- tenant:
+    name: tenant-one
+    source:
+      gerrit:
+        config-projects:
+          - common-config
+        untrusted-projects:
+          - org/project
diff --git a/tests/fixtures/config/duplicate-pipeline/git/common-config/zuul.yaml b/tests/fixtures/config/duplicate-pipeline/git/common-config/zuul.yaml
index 60d7363..dabe58c 100755
--- a/tests/fixtures/config/duplicate-pipeline/git/common-config/zuul.yaml
+++ b/tests/fixtures/config/duplicate-pipeline/git/common-config/zuul.yaml
@@ -7,10 +7,10 @@
         - event: change-restored
     success:
       gerrit:
-        verified: 1
+        Verified: 1
     failure:
       gerrit:
-        verified: -1
+        Verified: -1
 
 - pipeline:
     name: dup2
@@ -21,10 +21,10 @@
         - event: change-restored
     success:
       gerrit:
-        verified: 1
+        Verified: 1
     failure:
       gerrit:
-        verified: -1
+        Verified: -1
 
 - job:
     name: project-test1
diff --git a/tests/fixtures/config/git-driver/git/common-config/zuul.yaml b/tests/fixtures/config/git-driver/git/common-config/zuul.yaml
index 8fe8749..128bbb5 100644
--- a/tests/fixtures/config/git-driver/git/common-config/zuul.yaml
+++ b/tests/fixtures/config/git-driver/git/common-config/zuul.yaml
@@ -6,10 +6,10 @@
         - event: patchset-created
     success:
       gerrit:
-        verified: 1
+        Verified: 1
     failure:
       gerrit:
-        verified: -1
+        Verified: -1
 
 - job:
     name: project-test1
diff --git a/tests/fixtures/config/implicit-roles/git/common-config/zuul.yaml b/tests/fixtures/config/implicit-roles/git/common-config/zuul.yaml
index ba91fb5..5b2636f 100644
--- a/tests/fixtures/config/implicit-roles/git/common-config/zuul.yaml
+++ b/tests/fixtures/config/implicit-roles/git/common-config/zuul.yaml
@@ -6,7 +6,7 @@
         - event: patchset-created
     success:
       gerrit:
-        verified: 1
+        Verified: 1
     failure:
       gerrit:
-        verified: -1
+        Verified: -1
diff --git a/tests/fixtures/config/in-repo/git/common-config/zuul.yaml b/tests/fixtures/config/in-repo/git/common-config/zuul.yaml
index fce086e..bfd6199 100644
--- a/tests/fixtures/config/in-repo/git/common-config/zuul.yaml
+++ b/tests/fixtures/config/in-repo/git/common-config/zuul.yaml
@@ -6,10 +6,10 @@
         - event: patchset-created
     success:
       gerrit:
-        verified: 1
+        Verified: 1
     failure:
       gerrit:
-        verified: -1
+        Verified: -1
 
 - pipeline:
     name: tenant-one-gate
@@ -19,17 +19,17 @@
       gerrit:
         - event: comment-added
           approval:
-            - approved: 1
+            - Approved: 1
     success:
       gerrit:
-        verified: 2
+        Verified: 2
         submit: true
     failure:
       gerrit:
-        verified: -2
+        Verified: -2
     start:
       gerrit:
-        verified: 0
+        Verified: 0
     precedence: high
 
 - pipeline:
@@ -39,19 +39,36 @@
       gerrit:
         - event: comment-added
           approval:
-            - code-review: 2
+            - Code-Review: 2
     success:
       gerrit:
-        verified: 2
+        Verified: 2
         submit: true
     failure:
       gerrit:
-        verified: -2
+        Verified: -2
     start:
       gerrit:
-        verified: 0
+        Verified: 0
     precedence: high
 
+# This pipeline is there to ensure that dynamic pipeline copy operations also
+# work with regex approval filters.
+- pipeline:
+    name: pipeline-with-regex
+    manager: independent
+    require:
+      gerrit:
+        approval:
+          - Code-Review: 2
+            username: maintainer
+    require:
+      github:
+        review:
+          - username: '^(herp|derp)$'
+            type: approved
+    trigger: {}
+
 - job:
     name: common-config-test
 
diff --git a/tests/fixtures/config/inventory/git/common-config/zuul.yaml b/tests/fixtures/config/inventory/git/common-config/zuul.yaml
index e147b98..177633d 100644
--- a/tests/fixtures/config/inventory/git/common-config/zuul.yaml
+++ b/tests/fixtures/config/inventory/git/common-config/zuul.yaml
@@ -7,10 +7,10 @@
         - event: patchset-created
     success:
       gerrit:
-        verified: 1
+        Verified: 1
     failure:
       gerrit:
-        verified: -1
+        Verified: -1
 
 - nodeset:
     name: nodeset1
diff --git a/tests/fixtures/config/merges/git/common-config/zuul.yaml b/tests/fixtures/config/merges/git/common-config/zuul.yaml
index 1309b3f..7ae2ef0 100644
--- a/tests/fixtures/config/merges/git/common-config/zuul.yaml
+++ b/tests/fixtures/config/merges/git/common-config/zuul.yaml
@@ -6,10 +6,10 @@
         - event: patchset-created
     success:
       gerrit:
-        verified: 1
+        Verified: 1
     failure:
       gerrit:
-        verified: -1
+        Verified: -1
 
 - pipeline:
     name: gate
@@ -19,17 +19,17 @@
       gerrit:
         - event: comment-added
           approval:
-            - approved: 1
+            - Approved: 1
     success:
       gerrit:
-        verified: 2
+        Verified: 2
         submit: true
     failure:
       gerrit:
-        verified: -2
+        Verified: -2
     start:
       gerrit:
-        verified: 0
+        Verified: 0
     precedence: high
 
 - job:
diff --git a/tests/fixtures/config/multi-tenant-semaphore/git/common-config/zuul.yaml b/tests/fixtures/config/multi-tenant-semaphore/git/common-config/zuul.yaml
index ba91fb5..5b2636f 100644
--- a/tests/fixtures/config/multi-tenant-semaphore/git/common-config/zuul.yaml
+++ b/tests/fixtures/config/multi-tenant-semaphore/git/common-config/zuul.yaml
@@ -6,7 +6,7 @@
         - event: patchset-created
     success:
       gerrit:
-        verified: 1
+        Verified: 1
     failure:
       gerrit:
-        verified: -1
+        Verified: -1
diff --git a/tests/fixtures/config/multi-tenant/git/common-config/zuul.yaml b/tests/fixtures/config/multi-tenant/git/common-config/zuul.yaml
index 362434e..8e29d3b 100644
--- a/tests/fixtures/config/multi-tenant/git/common-config/zuul.yaml
+++ b/tests/fixtures/config/multi-tenant/git/common-config/zuul.yaml
@@ -6,10 +6,10 @@
         - event: patchset-created
     success:
       gerrit:
-        verified: 1
+        Verified: 1
     failure:
       gerrit:
-        verified: -1
+        Verified: -1
 
 - job:
     name: python27
diff --git a/tests/fixtures/config/multi-tenant/git/tenant-one-config/zuul.yaml b/tests/fixtures/config/multi-tenant/git/tenant-one-config/zuul.yaml
index 347bc53..9a1b928 100644
--- a/tests/fixtures/config/multi-tenant/git/tenant-one-config/zuul.yaml
+++ b/tests/fixtures/config/multi-tenant/git/tenant-one-config/zuul.yaml
@@ -6,17 +6,17 @@
       gerrit:
         - event: comment-added
           approval:
-            - approved: 1
+            - Approved: 1
     success:
       gerrit:
-        verified: 2
+        Verified: 2
         submit: true
     failure:
       gerrit:
-        verified: -2
+        Verified: -2
     start:
       gerrit:
-        verified: 0
+        Verified: 0
     precedence: high
 
 - nodeset:
diff --git a/tests/fixtures/config/multi-tenant/git/tenant-two-config/zuul.yaml b/tests/fixtures/config/multi-tenant/git/tenant-two-config/zuul.yaml
index 5ea803e..9496a49 100644
--- a/tests/fixtures/config/multi-tenant/git/tenant-two-config/zuul.yaml
+++ b/tests/fixtures/config/multi-tenant/git/tenant-two-config/zuul.yaml
@@ -6,17 +6,17 @@
       gerrit:
         - event: comment-added
           approval:
-            - approved: 1
+            - Approved: 1
     success:
       gerrit:
-        verified: 2
+        Verified: 2
         submit: true
     failure:
       gerrit:
-        verified: -2
+        Verified: -2
     start:
       gerrit:
-        verified: 0
+        Verified: 0
     precedence: high
 
 - nodeset:
diff --git a/tests/fixtures/config/openstack/git/project-config/zuul.yaml b/tests/fixtures/config/openstack/git/project-config/zuul.yaml
index 2ad600c..b3a8b0c 100644
--- a/tests/fixtures/config/openstack/git/project-config/zuul.yaml
+++ b/tests/fixtures/config/openstack/git/project-config/zuul.yaml
@@ -7,10 +7,10 @@
         - event: patchset-created
     success:
       gerrit:
-        verified: 1
+        Verified: 1
     failure:
       gerrit:
-        verified: -1
+        Verified: -1
 
 - pipeline:
     name: gate
@@ -20,17 +20,17 @@
       gerrit:
         - event: comment-added
           approval:
-            - approved: 1
+            - Approved: 1
     success:
       gerrit:
-        verified: 2
+        Verified: 2
         submit: true
     failure:
       gerrit:
-        verified: -2
+        Verified: -2
     start:
       gerrit:
-        verified: 0
+        Verified: 0
     precedence: high
 
 - job:
diff --git a/tests/fixtures/config/pre-playbook/git/common-config/zuul.yaml b/tests/fixtures/config/pre-playbook/git/common-config/zuul.yaml
index 3de0d6d..cfece30 100644
--- a/tests/fixtures/config/pre-playbook/git/common-config/zuul.yaml
+++ b/tests/fixtures/config/pre-playbook/git/common-config/zuul.yaml
@@ -7,10 +7,10 @@
         - event: patchset-created
     success:
       gerrit:
-        verified: 1
+        Verified: 1
     failure:
       gerrit:
-        verified: -1
+        Verified: -1
 
 - job:
     name: python27
diff --git a/tests/fixtures/config/requirements/email/git/common-config/zuul.yaml b/tests/fixtures/config/requirements/email/git/common-config/zuul.yaml
index efc3b32..1626168 100644
--- a/tests/fixtures/config/requirements/email/git/common-config/zuul.yaml
+++ b/tests/fixtures/config/requirements/email/git/common-config/zuul.yaml
@@ -6,10 +6,10 @@
         - event: comment-added
     success:
       gerrit:
-        verified: 1
+        Verified: 1
     failure:
       gerrit:
-        verified: -1
+        Verified: -1
     require:
       gerrit:
         approval:
@@ -25,10 +25,10 @@
             - email: jenkins@example.com
     success:
       gerrit:
-        verified: 1
+        Verified: 1
     failure:
       gerrit:
-        verified: -1
+        Verified: -1
 
 - job:
     name: project1-job
diff --git a/tests/fixtures/config/requirements/newer-than/git/common-config/zuul.yaml b/tests/fixtures/config/requirements/newer-than/git/common-config/zuul.yaml
index 6f0601d..2980ef1 100644
--- a/tests/fixtures/config/requirements/newer-than/git/common-config/zuul.yaml
+++ b/tests/fixtures/config/requirements/newer-than/git/common-config/zuul.yaml
@@ -6,10 +6,10 @@
         - event: comment-added
     success:
       gerrit:
-        verified: 1
+        Verified: 1
     failure:
       gerrit:
-        verified: -1
+        Verified: -1
     require:
       gerrit:
         approval:
@@ -27,10 +27,10 @@
               newer-than: 48h
     success:
       gerrit:
-        verified: 1
+        Verified: 1
     failure:
       gerrit:
-        verified: -1
+        Verified: -1
 
 - job:
     name: project1-job
diff --git a/tests/fixtures/config/requirements/older-than/git/common-config/zuul.yaml b/tests/fixtures/config/requirements/older-than/git/common-config/zuul.yaml
index 77ee388..9e2f5d7 100644
--- a/tests/fixtures/config/requirements/older-than/git/common-config/zuul.yaml
+++ b/tests/fixtures/config/requirements/older-than/git/common-config/zuul.yaml
@@ -6,10 +6,10 @@
         - event: comment-added
     success:
       gerrit:
-        verified: 1
+        Verified: 1
     failure:
       gerrit:
-        verified: -1
+        Verified: -1
     require:
       gerrit:
         approval:
@@ -27,10 +27,10 @@
               older-than: 48h
     success:
       gerrit:
-        verified: 1
+        Verified: 1
     failure:
       gerrit:
-        verified: -1
+        Verified: -1
 
 - job:
     name: project1-job
diff --git a/tests/fixtures/config/requirements/reject-username/git/common-config/zuul.yaml b/tests/fixtures/config/requirements/reject-username/git/common-config/zuul.yaml
index 9e9d000..333a4c7 100644
--- a/tests/fixtures/config/requirements/reject-username/git/common-config/zuul.yaml
+++ b/tests/fixtures/config/requirements/reject-username/git/common-config/zuul.yaml
@@ -10,10 +10,10 @@
         - event: comment-added
     success:
       gerrit:
-        verified: 1
+        Verified: 1
     failure:
       gerrit:
-        verified: -1
+        Verified: -1
 
 - pipeline:
     name: trigger
@@ -25,10 +25,10 @@
             - username: jenkins
     success:
       gerrit:
-        verified: 1
+        Verified: 1
     failure:
       gerrit:
-        verified: -1
+        Verified: -1
 
 - job:
     name: project1-job
diff --git a/tests/fixtures/config/requirements/reject/git/common-config/zuul.yaml b/tests/fixtures/config/requirements/reject/git/common-config/zuul.yaml
index b08a105..9aef0c5 100644
--- a/tests/fixtures/config/requirements/reject/git/common-config/zuul.yaml
+++ b/tests/fixtures/config/requirements/reject/git/common-config/zuul.yaml
@@ -5,13 +5,13 @@
       gerrit:
         approval:
           - username: jenkins
-            verified:
+            Verified:
               - 1
               - 2
     reject:
       gerrit:
         approval:
-          - verified:
+          - Verified:
               - -1
               - -2
     trigger:
@@ -19,10 +19,10 @@
         - event: comment-added
     success:
       gerrit:
-        verified: 1
+        Verified: 1
     failure:
       gerrit:
-        verified: -1
+        Verified: -1
 
 - pipeline:
     name: trigger
@@ -32,19 +32,19 @@
         - event: comment-added
           require-approval:
             - username: jenkins
-              verified:
+              Verified:
                 - 1
                 - 2
           reject-approval:
-            - verified:
+            - Verified:
                 - -1
                 - -2
     success:
       gerrit:
-        verified: 1
+        Verified: 1
     failure:
       gerrit:
-        verified: -1
+        Verified: -1
 
 - job:
     name: project1-job
diff --git a/tests/fixtures/config/requirements/state/git/common-config/zuul.yaml b/tests/fixtures/config/requirements/state/git/common-config/zuul.yaml
index bd9dc8f..081b655 100644
--- a/tests/fixtures/config/requirements/state/git/common-config/zuul.yaml
+++ b/tests/fixtures/config/requirements/state/git/common-config/zuul.yaml
@@ -10,10 +10,10 @@
         - event: comment-added
     success:
       gerrit:
-        verified: 1
+        Verified: 1
     failure:
       gerrit:
-        verified: -1
+        Verified: -1
 
 - pipeline:
     name: open-check
@@ -27,10 +27,10 @@
         - event: comment-added
     success:
       gerrit:
-        verified: 1
+        Verified: 1
     failure:
       gerrit:
-        verified: -1
+        Verified: -1
 
 - pipeline:
     name: status-check
@@ -44,10 +44,10 @@
         - event: comment-added
     success:
       gerrit:
-        verified: 1
+        Verified: 1
     failure:
       gerrit:
-        verified: -1
+        Verified: -1
 
 - job:
     name: project-job
diff --git a/tests/fixtures/config/requirements/username/git/common-config/zuul.yaml b/tests/fixtures/config/requirements/username/git/common-config/zuul.yaml
index 455d9de..d5f3553 100644
--- a/tests/fixtures/config/requirements/username/git/common-config/zuul.yaml
+++ b/tests/fixtures/config/requirements/username/git/common-config/zuul.yaml
@@ -6,10 +6,10 @@
         - event: comment-added
     success:
       gerrit:
-        verified: 1
+        Verified: 1
     failure:
       gerrit:
-        verified: -1
+        Verified: -1
     require:
       gerrit:
         approval:
@@ -25,10 +25,10 @@
             - username: jenkins
     success:
       gerrit:
-        verified: 1
+        Verified: 1
     failure:
       gerrit:
-        verified: -1
+        Verified: -1
 
 - job:
     name: project1-job
diff --git a/tests/fixtures/config/requirements/vote1/git/common-config/zuul.yaml b/tests/fixtures/config/requirements/vote1/git/common-config/zuul.yaml
index 799282d..787cf0d 100644
--- a/tests/fixtures/config/requirements/vote1/git/common-config/zuul.yaml
+++ b/tests/fixtures/config/requirements/vote1/git/common-config/zuul.yaml
@@ -5,16 +5,16 @@
       gerrit:
         approval:
           - username: jenkins
-            verified: 1
+            Verified: 1
     trigger:
       gerrit:
         - event: comment-added
     success:
       gerrit:
-        verified: 1
+        Verified: 1
     failure:
       gerrit:
-        verified: -1
+        Verified: -1
 
 - pipeline:
     name: trigger
@@ -24,13 +24,13 @@
         - event: comment-added
           require-approval:
             - username: jenkins
-              verified: 1
+              Verified: 1
     success:
       gerrit:
-        verified: 1
+        Verified: 1
     failure:
       gerrit:
-        verified: -1
+        Verified: -1
 
 - job:
     name: project1-job
diff --git a/tests/fixtures/config/requirements/vote2/git/common-config/zuul.yaml b/tests/fixtures/config/requirements/vote2/git/common-config/zuul.yaml
index f337371..b91a216 100644
--- a/tests/fixtures/config/requirements/vote2/git/common-config/zuul.yaml
+++ b/tests/fixtures/config/requirements/vote2/git/common-config/zuul.yaml
@@ -5,7 +5,7 @@
       gerrit:
         approval:
           - username: jenkins
-            verified:
+            Verified:
               - 1
               - 2
     trigger:
@@ -13,10 +13,10 @@
         - event: comment-added
     success:
       gerrit:
-        verified: 1
+        Verified: 1
     failure:
       gerrit:
-        verified: -1
+        Verified: -1
 
 - pipeline:
     name: trigger
@@ -26,15 +26,15 @@
         - event: comment-added
           require-approval:
             - username: jenkins
-              verified:
+              Verified:
                 - 1
                 - 2
     success:
       gerrit:
-        verified: 1
+        Verified: 1
     failure:
       gerrit:
-        verified: -1
+        Verified: -1
 
 - job:
     name: project1-job
diff --git a/tests/fixtures/config/roles/git/common-config/zuul.yaml b/tests/fixtures/config/roles/git/common-config/zuul.yaml
index 1fdaf2e..a1b6e42 100644
--- a/tests/fixtures/config/roles/git/common-config/zuul.yaml
+++ b/tests/fixtures/config/roles/git/common-config/zuul.yaml
@@ -6,10 +6,10 @@
         - event: patchset-created
     success:
       gerrit:
-        verified: 1
+        Verified: 1
     failure:
       gerrit:
-        verified: -1
+        Verified: -1
 
 - pipeline:
     name: tenant-one-gate
@@ -19,17 +19,17 @@
       gerrit:
         - event: comment-added
           approval:
-            - approved: 1
+            - Approved: 1
     success:
       gerrit:
-        verified: 2
+        Verified: 2
         submit: true
     failure:
       gerrit:
-        verified: -2
+        Verified: -2
     start:
       gerrit:
-        verified: 0
+        Verified: 0
     precedence: high
 
 - job:
diff --git a/tests/fixtures/config/semaphore/git/common-config/zuul.yaml b/tests/fixtures/config/semaphore/git/common-config/zuul.yaml
index 9d1cacf..5eeee21 100644
--- a/tests/fixtures/config/semaphore/git/common-config/zuul.yaml
+++ b/tests/fixtures/config/semaphore/git/common-config/zuul.yaml
@@ -6,10 +6,10 @@
         - event: patchset-created
     success:
       gerrit:
-        verified: 1
+        Verified: 1
     failure:
       gerrit:
-        verified: -1
+        Verified: -1
 
 # TODOv3(jeblair, tobiash): make semaphore definitions required, which
 # will cause these tests to fail until we define test-semaphore
diff --git a/tests/fixtures/config/semaphore/zuul-reconfiguration.yaml b/tests/fixtures/config/semaphore/zuul-reconfiguration.yaml
index 8fe8749..128bbb5 100644
--- a/tests/fixtures/config/semaphore/zuul-reconfiguration.yaml
+++ b/tests/fixtures/config/semaphore/zuul-reconfiguration.yaml
@@ -6,10 +6,10 @@
         - event: patchset-created
     success:
       gerrit:
-        verified: 1
+        Verified: 1
     failure:
       gerrit:
-        verified: -1
+        Verified: -1
 
 - job:
     name: project-test1
diff --git a/tests/fixtures/config/shadow/git/local-config/zuul.yaml b/tests/fixtures/config/shadow/git/local-config/zuul.yaml
index 756e843..dc2133f 100644
--- a/tests/fixtures/config/shadow/git/local-config/zuul.yaml
+++ b/tests/fixtures/config/shadow/git/local-config/zuul.yaml
@@ -6,10 +6,10 @@
         - event: patchset-created
     success:
       gerrit:
-        verified: 1
+        Verified: 1
     failure:
       gerrit:
-        verified: -1
+        Verified: -1
 
 - job:
     name: base
diff --git a/tests/fixtures/config/single-tenant/git/common-config/zuul.yaml b/tests/fixtures/config/single-tenant/git/common-config/zuul.yaml
index 27454d3..b768a83 100644
--- a/tests/fixtures/config/single-tenant/git/common-config/zuul.yaml
+++ b/tests/fixtures/config/single-tenant/git/common-config/zuul.yaml
@@ -6,10 +6,10 @@
         - event: patchset-created
     success:
       gerrit:
-        verified: 1
+        Verified: 1
     failure:
       gerrit:
-        verified: -1
+        Verified: -1
 
 - pipeline:
     name: gate
@@ -19,17 +19,17 @@
       gerrit:
         - event: comment-added
           approval:
-            - approved: 1
+            - Approved: 1
     success:
       gerrit:
-        verified: 2
+        Verified: 2
         submit: true
     failure:
       gerrit:
-        verified: -2
+        Verified: -2
     start:
       gerrit:
-        verified: 0
+        Verified: 0
     precedence: high
 
 - pipeline:
diff --git a/tests/fixtures/config/split-config/git/common-config/zuul.d/pipelines.yaml b/tests/fixtures/config/split-config/git/common-config/zuul.d/pipelines.yaml
index ba91fb5..5b2636f 100644
--- a/tests/fixtures/config/split-config/git/common-config/zuul.d/pipelines.yaml
+++ b/tests/fixtures/config/split-config/git/common-config/zuul.d/pipelines.yaml
@@ -6,7 +6,7 @@
         - event: patchset-created
     success:
       gerrit:
-        verified: 1
+        Verified: 1
     failure:
       gerrit:
-        verified: -1
+        Verified: -1
diff --git a/tests/fixtures/config/sql-driver/git/common-config/zuul.yaml b/tests/fixtures/config/sql-driver/git/common-config/zuul.yaml
index dd80d08..0cb1d04 100644
--- a/tests/fixtures/config/sql-driver/git/common-config/zuul.yaml
+++ b/tests/fixtures/config/sql-driver/git/common-config/zuul.yaml
@@ -6,12 +6,12 @@
         - event: patchset-created
     success:
       gerrit:
-        verified: 1
+        Verified: 1
       resultsdb:
         score: 1
     failure:
       gerrit:
-        verified: -1
+        Verified: -1
       resultsdb:
         score: -1
       resultsdb_failures:
diff --git a/tests/fixtures/config/streamer/git/common-config/zuul.yaml b/tests/fixtures/config/streamer/git/common-config/zuul.yaml
index 6f4fa7e..5a653b4 100644
--- a/tests/fixtures/config/streamer/git/common-config/zuul.yaml
+++ b/tests/fixtures/config/streamer/git/common-config/zuul.yaml
@@ -6,10 +6,10 @@
         - event: patchset-created
     success:
       gerrit:
-        verified: 1
+        Verified: 1
     failure:
       gerrit:
-        verified: -1
+        Verified: -1
 
 - job:
     name: python27
diff --git a/tests/fixtures/config/success-url/git/common-config/zuul.yaml b/tests/fixtures/config/success-url/git/common-config/zuul.yaml
index 7082b8c..6fbad0d 100644
--- a/tests/fixtures/config/success-url/git/common-config/zuul.yaml
+++ b/tests/fixtures/config/success-url/git/common-config/zuul.yaml
@@ -9,12 +9,12 @@
         to: alternative_me@example.com
     success:
       gerrit:
-        verified: 1
+        Verified: 1
       smtp:
         to: alternative_me@example.com
     failure:
       gerrit:
-        verified: -1
+        Verified: -1
 
 - job:
     name: docs-draft-test
diff --git a/tests/fixtures/config/templated-project/git/common-config/zuul.d/pipelines.yaml b/tests/fixtures/config/templated-project/git/common-config/zuul.d/pipelines.yaml
index 4a19796..3f01e8a 100644
--- a/tests/fixtures/config/templated-project/git/common-config/zuul.d/pipelines.yaml
+++ b/tests/fixtures/config/templated-project/git/common-config/zuul.d/pipelines.yaml
@@ -6,10 +6,10 @@
         - event: patchset-created
     success:
       gerrit:
-        verified: 1
+        Verified: 1
     failure:
       gerrit:
-        verified: -1
+        Verified: -1
 
 - pipeline:
     name: gate
@@ -19,17 +19,17 @@
       gerrit:
         - event: comment-added
           approval:
-            - approved: 1
+            - Approved: 1
     success:
       gerrit:
-        verified: 2
+        Verified: 2
         submit: true
     failure:
       gerrit:
-        verified: -2
+        Verified: -2
     start:
       gerrit:
-        verified: 0
+        Verified: 0
     precedence: high
 
 - pipeline:
diff --git a/tests/fixtures/config/tenant-parser/git/common-config/zuul.yaml b/tests/fixtures/config/tenant-parser/git/common-config/zuul.yaml
index 9e52187..ec371e8 100644
--- a/tests/fixtures/config/tenant-parser/git/common-config/zuul.yaml
+++ b/tests/fixtures/config/tenant-parser/git/common-config/zuul.yaml
@@ -6,10 +6,10 @@
         - event: patchset-created
     success:
       gerrit:
-        verified: 1
+        Verified: 1
     failure:
       gerrit:
-        verified: -1
+        Verified: -1
 
 - job:
     name: common-config-job
diff --git a/tests/fixtures/config/zuul-connections-multiple-gerrits/git/common-config/zuul.yaml b/tests/fixtures/config/zuul-connections-multiple-gerrits/git/common-config/zuul.yaml
index 8f858cd..87182b0 100644
--- a/tests/fixtures/config/zuul-connections-multiple-gerrits/git/common-config/zuul.yaml
+++ b/tests/fixtures/config/zuul-connections-multiple-gerrits/git/common-config/zuul.yaml
@@ -6,10 +6,10 @@
         - event: patchset-created
     success:
       review_gerrit:
-        verified: 1
+        Verified: 1
     failure:
       review_gerrit:
-        verified: -1
+        Verified: -1
 
 - pipeline:
     name: another_check
@@ -19,10 +19,10 @@
         - event: patchset-created
     success:
       another_gerrit:
-        verified: 1
+        Verified: 1
     failure:
       another_gerrit:
-        verified: -1
+        Verified: -1
 
 - pipeline:
     name: common_check
@@ -34,14 +34,14 @@
         - event: patchset-created
     success:
       review_gerrit:
-        verified: 1
+        Verified: 1
       another_gerrit:
-        verified: 1
+        Verified: 1
     failure:
       review_gerrit:
-        verified: -1
+        Verified: -1
       another_gerrit:
-        verified: -1
+        Verified: -1
 
 - job:
     name: project-test1
diff --git a/tests/fixtures/config/zuul-connections-same-gerrit/git/common-config/zuul.yaml b/tests/fixtures/config/zuul-connections-same-gerrit/git/common-config/zuul.yaml
index adc61a3..e16bb80 100644
--- a/tests/fixtures/config/zuul-connections-same-gerrit/git/common-config/zuul.yaml
+++ b/tests/fixtures/config/zuul-connections-same-gerrit/git/common-config/zuul.yaml
@@ -6,10 +6,10 @@
         - event: patchset-created
     success:
       review_gerrit:
-        verified: 1
+        Verified: 1
     failure:
       alt_voting_gerrit:
-        verified: -1
+        Verified: -1
 
 - job:
     name: project-test1
diff --git a/tests/fixtures/config/zuultrigger/parent-change-enqueued/git/common-config/zuul.yaml b/tests/fixtures/config/zuultrigger/parent-change-enqueued/git/common-config/zuul.yaml
index 351092c..aae8b8d 100644
--- a/tests/fixtures/config/zuultrigger/parent-change-enqueued/git/common-config/zuul.yaml
+++ b/tests/fixtures/config/zuultrigger/parent-change-enqueued/git/common-config/zuul.yaml
@@ -4,7 +4,7 @@
     require:
       gerrit:
         approval:
-          - verified: -1
+          - Verified: -1
     trigger:
       gerrit:
         - event: patchset-created
@@ -13,10 +13,10 @@
           pipeline: gate
     success:
       gerrit:
-        verified: 1
+        Verified: 1
     failure:
       gerrit:
-        verified: -1
+        Verified: -1
 
 - pipeline:
     name: gate
@@ -24,25 +24,25 @@
     require:
       gerrit:
         approval:
-          - verified: 1
+          - Verified: 1
     trigger:
       gerrit:
         - event: comment-added
           approval:
-            - approved: 1
+            - Approved: 1
       zuul:
         - event: parent-change-enqueued
           pipeline: gate
     success:
       gerrit:
-        verified: 2
+        Verified: 2
         submit: true
     failure:
       gerrit:
-        verified: -2
+        Verified: -2
     start:
       gerrit:
-        verified: 0
+        Verified: 0
     precedence: high
 
 - job:
diff --git a/tests/fixtures/config/zuultrigger/project-change-merged/git/common-config/zuul.yaml b/tests/fixtures/config/zuultrigger/project-change-merged/git/common-config/zuul.yaml
index 48fdffe..f0f3584 100644
--- a/tests/fixtures/config/zuultrigger/project-change-merged/git/common-config/zuul.yaml
+++ b/tests/fixtures/config/zuultrigger/project-change-merged/git/common-config/zuul.yaml
@@ -6,10 +6,10 @@
         - event: patchset-created
     success:
       gerrit:
-        verified: 1
+        Verified: 1
     failure:
       gerrit:
-        verified: -1
+        Verified: -1
 
 - pipeline:
     name: gate
@@ -19,17 +19,17 @@
       gerrit:
         - event: comment-added
           approval:
-            - approved: 1
+            - Approved: 1
     success:
       gerrit:
-        verified: 2
+        Verified: 2
         submit: true
     failure:
       gerrit:
-        verified: -2
+        Verified: -2
     start:
       gerrit:
-        verified: 0
+        Verified: 0
     precedence: high
 
 - pipeline:
@@ -41,7 +41,7 @@
         - event: project-change-merged
     merge-failure:
       gerrit:
-        verified: -1
+        Verified: -1
 
 - job:
     name: project-check
diff --git a/tests/fixtures/layout-cloner.yaml b/tests/fixtures/layout-cloner.yaml
index e8b5dde..0d51129 100644
--- a/tests/fixtures/layout-cloner.yaml
+++ b/tests/fixtures/layout-cloner.yaml
@@ -6,10 +6,10 @@
         - event: patchset-created
     success:
       gerrit:
-        verified: 1
+        Verified: 1
     failure:
       gerrit:
-        verified: -1
+        Verified: -1
 
   - name: gate
     manager: DependentPipelineManager
@@ -18,17 +18,17 @@
       gerrit:
         - event: comment-added
           approval:
-            - approved: 1
+            - Approved: 1
     start:
       gerrit:
-        verified: 0
+        Verified: 0
     success:
       gerrit:
-        verified: 2
+        Verified: 2
         submit: true
     failure:
       gerrit:
-        verified: -2
+        Verified: -2
 
   - name: post
     manager: IndependentPipelineManager
diff --git a/tests/fixtures/layout-delayed-repo-init.yaml b/tests/fixtures/layout-delayed-repo-init.yaml
index 6caf622..04dc010 100644
--- a/tests/fixtures/layout-delayed-repo-init.yaml
+++ b/tests/fixtures/layout-delayed-repo-init.yaml
@@ -6,10 +6,10 @@
         - event: patchset-created
     success:
       gerrit:
-        verified: 1
+        Verified: 1
     failure:
       gerrit:
-        verified: -1
+        Verified: -1
 
   - name: post
     manager: IndependentPipelineManager
@@ -25,17 +25,17 @@
       gerrit:
         - event: comment-added
           approval:
-            - approved: 1
+            - Approved: 1
     success:
       gerrit:
-        verified: 2
+        Verified: 2
         submit: true
     failure:
       gerrit:
-        verified: -2
+        Verified: -2
     start:
       gerrit:
-        verified: 0
+        Verified: 0
     precedence: high
 
 projects:
diff --git a/tests/fixtures/layout-disable-at.yaml b/tests/fixtures/layout-disable-at.yaml
index a2b2526..0ec8257 100644
--- a/tests/fixtures/layout-disable-at.yaml
+++ b/tests/fixtures/layout-disable-at.yaml
@@ -6,10 +6,10 @@
         - event: patchset-created
     success:
       gerrit:
-        verified: 1
+        Verified: 1
     failure:
       gerrit:
-        verified: -1
+        Verified: -1
     disabled:
       smtp:
         to: you@example.com
diff --git a/tests/fixtures/layout-live-reconfiguration-functions.yaml b/tests/fixtures/layout-live-reconfiguration-functions.yaml
index b22b3ab..ef2186e 100644
--- a/tests/fixtures/layout-live-reconfiguration-functions.yaml
+++ b/tests/fixtures/layout-live-reconfiguration-functions.yaml
@@ -9,17 +9,17 @@
       gerrit:
         - event: comment-added
           approval:
-            - approved: 1
+            - Approved: 1
     success:
       gerrit:
-        verified: 2
+        Verified: 2
         submit: true
     failure:
       gerrit:
-        verified: -2
+        Verified: -2
     start:
       gerrit:
-        verified: 0
+        Verified: 0
     precedence: high
 
 jobs:
diff --git a/tests/fixtures/layout-merge-queues.yaml b/tests/fixtures/layout-merge-queues.yaml
index be39a1c..b328341 100644
--- a/tests/fixtures/layout-merge-queues.yaml
+++ b/tests/fixtures/layout-merge-queues.yaml
@@ -6,7 +6,7 @@
       gerrit:
         - event: comment-added
           approval:
-            - approved: 1
+            - Approved: 1
 
 projects:
   - name: projectA
diff --git a/tests/fixtures/layout-requirement-vote.yaml b/tests/fixtures/layout-requirement-vote.yaml
index 7ccadff..01aa97d 100644
--- a/tests/fixtures/layout-requirement-vote.yaml
+++ b/tests/fixtures/layout-requirement-vote.yaml
@@ -4,16 +4,16 @@
     require:
       approval:
         - username: jenkins
-          verified: 1
+          Verified: 1
     trigger:
       gerrit:
         - event: comment-added
     success:
       gerrit:
-        verified: 1
+        Verified: 1
     failure:
       gerrit:
-        verified: -1
+        Verified: -1
 
   - name: trigger
     manager: IndependentPipelineManager
@@ -22,13 +22,13 @@
         - event: comment-added
           require-approval:
             - username: jenkins
-              verified: 1
+              Verified: 1
     success:
       gerrit:
-        verified: 1
+        Verified: 1
     failure:
       gerrit:
-        verified: -1
+        Verified: -1
 
 projects:
   - name: org/project1
diff --git a/tests/fixtures/layout-smtp.yaml b/tests/fixtures/layout-smtp.yaml
index 813857b..4306443 100644
--- a/tests/fixtures/layout-smtp.yaml
+++ b/tests/fixtures/layout-smtp.yaml
@@ -9,13 +9,13 @@
         to: you@example.com
     success:
       gerrit:
-        verified: 1
+        Verified: 1
       smtp:
         to: alternative_me@example.com
         from: zuul_from@example.com
     failure:
       gerrit:
-        verified: -1
+        Verified: -1
 
 projects:
   - name: org/project
diff --git a/tests/fixtures/layout.yaml b/tests/fixtures/layout.yaml
index 6131de0..cd8ce19 100644
--- a/tests/fixtures/layout.yaml
+++ b/tests/fixtures/layout.yaml
@@ -11,10 +11,10 @@
         - event: patchset-created
     success:
       gerrit:
-        verified: 1
+        Verified: 1
     failure:
       gerrit:
-        verified: -1
+        Verified: -1
 
   - name: post
     manager: independent
@@ -34,17 +34,17 @@
       gerrit:
         - event: comment-added
           approval:
-            - approved: 1
+            - Approved: 1
     success:
       gerrit:
-        verified: 2
+        Verified: 2
         submit: true
     failure:
       gerrit:
-        verified: -2
+        Verified: -2
     start:
       gerrit:
-        verified: 0
+        Verified: 0
     precedence: high
 
   - name: unused
@@ -56,7 +56,7 @@
       gerrit:
         - event: comment-added
           approval:
-            - approved: 1
+            - Approved: 1
 
   - name: dup1
     manager: independent
@@ -67,10 +67,10 @@
         - event: change-restored
     success:
       gerrit:
-        verified: 1
+        Verified: 1
     failure:
       gerrit:
-        verified: -1
+        Verified: -1
 
   - name: dup2
     manager: independent
@@ -81,10 +81,10 @@
         - event: change-restored
     success:
       gerrit:
-        verified: 1
+        Verified: 1
     failure:
       gerrit:
-        verified: -1
+        Verified: -1
 
   - name: conflict
     manager: dependent
@@ -95,17 +95,17 @@
       gerrit:
         - event: comment-added
           approval:
-            - approved: 1
+            - Approved: 1
     success:
       gerrit:
-        verified: 2
+        Verified: 2
         submit: true
     failure:
       gerrit:
-        verified: -2
+        Verified: -2
     start:
       gerrit:
-        verified: 0
+        Verified: 0
 
   - name: experimental
     manager: independent
diff --git a/tests/fixtures/layouts/disable_at.yaml b/tests/fixtures/layouts/disable_at.yaml
index 8e352d8..09082a4 100644
--- a/tests/fixtures/layouts/disable_at.yaml
+++ b/tests/fixtures/layouts/disable_at.yaml
@@ -6,10 +6,10 @@
         - event: patchset-created
     success:
       gerrit:
-        verified: 1
+        Verified: 1
     failure:
       gerrit:
-        verified: -1
+        Verified: -1
     disabled:
       smtp:
         to: you@example.com
diff --git a/tests/fixtures/layouts/footer-message.yaml b/tests/fixtures/layouts/footer-message.yaml
index 1261902..e500371 100644
--- a/tests/fixtures/layouts/footer-message.yaml
+++ b/tests/fixtures/layouts/footer-message.yaml
@@ -8,21 +8,21 @@
       gerrit:
         - event: comment-added
           approval:
-            - approved: 1
+            - Approved: 1
     success:
       smtp:
         to: you@example.com
       gerrit:
-        verified: 2
+        Verified: 2
         submit: true
     failure:
       gerrit:
-        verified: -2
+        Verified: -2
       smtp:
         to: you@example.com
     start:
       gerrit:
-        verified: 0
+        Verified: 0
     precedence: high
 
 - job:
diff --git a/tests/fixtures/layouts/ignore-dependencies.yaml b/tests/fixtures/layouts/ignore-dependencies.yaml
index 86fe674..9eab9f4 100644
--- a/tests/fixtures/layouts/ignore-dependencies.yaml
+++ b/tests/fixtures/layouts/ignore-dependencies.yaml
@@ -7,10 +7,10 @@
         - event: patchset-created
     success:
       gerrit:
-        verified: 1
+        Verified: 1
     failure:
       gerrit:
-        verified: -1
+        Verified: -1
 
 - job:
     name: project1-merge
diff --git a/tests/fixtures/layouts/inheritance.yaml b/tests/fixtures/layouts/inheritance.yaml
index 65dddab..146ca4d 100644
--- a/tests/fixtures/layouts/inheritance.yaml
+++ b/tests/fixtures/layouts/inheritance.yaml
@@ -6,10 +6,10 @@
         - event: patchset-created
     success:
       gerrit:
-        verified: 1
+        Verified: 1
     failure:
       gerrit:
-        verified: -1
+        Verified: -1
 
 - job:
     name: project-test-irrelevant-starts-empty
diff --git a/tests/fixtures/layouts/irrelevant-files.yaml b/tests/fixtures/layouts/irrelevant-files.yaml
index 3d086dc..fbcca8f 100644
--- a/tests/fixtures/layouts/irrelevant-files.yaml
+++ b/tests/fixtures/layouts/irrelevant-files.yaml
@@ -6,10 +6,10 @@
         - event: patchset-created
     success:
       gerrit:
-        verified: 1
+        Verified: 1
     failure:
       gerrit:
-        verified: -1
+        Verified: -1
 
 - job:
     name: project-test-irrelevant-files
diff --git a/tests/fixtures/layouts/live-reconfiguration-add-job.yaml b/tests/fixtures/layouts/live-reconfiguration-add-job.yaml
index 5916282..1616dcb 100644
--- a/tests/fixtures/layouts/live-reconfiguration-add-job.yaml
+++ b/tests/fixtures/layouts/live-reconfiguration-add-job.yaml
@@ -6,17 +6,17 @@
       gerrit:
         - event: comment-added
           approval:
-            - approved: 1
+            - Approved: 1
     success:
       gerrit:
-        verified: 2
+        Verified: 2
         submit: true
     failure:
       gerrit:
-        verified: -2
+        Verified: -2
     start:
       gerrit:
-        verified: 0
+        Verified: 0
     precedence: high
 
 - job:
diff --git a/tests/fixtures/layouts/live-reconfiguration-del-project.yaml b/tests/fixtures/layouts/live-reconfiguration-del-project.yaml
index 299c612..1eada5c 100644
--- a/tests/fixtures/layouts/live-reconfiguration-del-project.yaml
+++ b/tests/fixtures/layouts/live-reconfiguration-del-project.yaml
@@ -6,10 +6,10 @@
         - event: patchset-created
     success:
       gerrit:
-        verified: 1
+        Verified: 1
     failure:
       gerrit:
-        verified: -1
+        Verified: -1
 
 - job:
     name: project-merge
diff --git a/tests/fixtures/layouts/live-reconfiguration-failed-job.yaml b/tests/fixtures/layouts/live-reconfiguration-failed-job.yaml
index 0907880..2b97419 100644
--- a/tests/fixtures/layouts/live-reconfiguration-failed-job.yaml
+++ b/tests/fixtures/layouts/live-reconfiguration-failed-job.yaml
@@ -6,10 +6,10 @@
         - event: patchset-created
     success:
       gerrit:
-        verified: 1
+        Verified: 1
     failure:
       gerrit:
-        verified: -1
+        Verified: -1
 
 - job:
     name: project-merge
diff --git a/tests/fixtures/layouts/live-reconfiguration-shared-queue.yaml b/tests/fixtures/layouts/live-reconfiguration-shared-queue.yaml
index bf4416a..3cbed68 100644
--- a/tests/fixtures/layouts/live-reconfiguration-shared-queue.yaml
+++ b/tests/fixtures/layouts/live-reconfiguration-shared-queue.yaml
@@ -6,10 +6,10 @@
         - event: patchset-created
     success:
       gerrit:
-        verified: 1
+        Verified: 1
     failure:
       gerrit:
-        verified: -1
+        Verified: -1
 
 - pipeline:
     name: gate
@@ -19,17 +19,17 @@
       gerrit:
         - event: comment-added
           approval:
-            - approved: 1
+            - Approved: 1
     success:
       gerrit:
-        verified: 2
+        Verified: 2
         submit: true
     failure:
       gerrit:
-        verified: -2
+        Verified: -2
     start:
       gerrit:
-        verified: 0
+        Verified: 0
     precedence: high
 
 - job:
diff --git a/tests/fixtures/layouts/merge-failure.yaml b/tests/fixtures/layouts/merge-failure.yaml
index 228963f..cc683a9 100644
--- a/tests/fixtures/layouts/merge-failure.yaml
+++ b/tests/fixtures/layouts/merge-failure.yaml
@@ -6,10 +6,10 @@
         - event: patchset-created
     success:
       gerrit:
-        verified: 1
+        Verified: 1
     failure:
       gerrit:
-        verified: -1
+        Verified: -1
 
 - pipeline:
     name: post
@@ -28,22 +28,22 @@
       gerrit:
         - event: comment-added
           approval:
-            - approved: 1
+            - Approved: 1
     success:
       gerrit:
-        verified: 2
+        Verified: 2
         submit: true
     failure:
       gerrit:
-        verified: -2
+        Verified: -2
     merge-failure:
       gerrit:
-        verified: -1
+        Verified: -1
       smtp:
         to: you@example.com
     start:
       gerrit:
-        verified: 0
+        Verified: 0
     precedence: high
 
 - job:
diff --git a/tests/fixtures/layouts/no-jobs-project.yaml b/tests/fixtures/layouts/no-jobs-project.yaml
index 803e5a0..593a8d7 100644
--- a/tests/fixtures/layouts/no-jobs-project.yaml
+++ b/tests/fixtures/layouts/no-jobs-project.yaml
@@ -6,10 +6,10 @@
         - event: patchset-created
     success:
       gerrit:
-        verified: 1
+        Verified: 1
     failure:
       gerrit:
-        verified: -1
+        Verified: -1
 
 - job:
     name: project-testfile
diff --git a/tests/fixtures/layouts/no-jobs.yaml b/tests/fixtures/layouts/no-jobs.yaml
index 66193b0..facae0a 100644
--- a/tests/fixtures/layouts/no-jobs.yaml
+++ b/tests/fixtures/layouts/no-jobs.yaml
@@ -6,10 +6,10 @@
         - event: patchset-created
     success:
       gerrit:
-        verified: 1
+        Verified: 1
     failure:
       gerrit:
-        verified: -1
+        Verified: -1
 
 - pipeline:
     name: gate
@@ -19,17 +19,17 @@
       gerrit:
         - event: comment-added
           approval:
-            - approved: 1
+            - Approved: 1
     success:
       gerrit:
-        verified: 2
+        Verified: 2
         submit: true
     failure:
       gerrit:
-        verified: -2
+        Verified: -2
     start:
       gerrit:
-        verified: 0
+        Verified: 0
     precedence: high
 
 - job:
diff --git a/tests/fixtures/layouts/no-timer.yaml b/tests/fixtures/layouts/no-timer.yaml
index 05f17d2..fda7b8b 100644
--- a/tests/fixtures/layouts/no-timer.yaml
+++ b/tests/fixtures/layouts/no-timer.yaml
@@ -6,10 +6,10 @@
         - event: patchset-created
     success:
       gerrit:
-        verified: 1
+        Verified: 1
     failure:
       gerrit:
-        verified: -1
+        Verified: -1
 
 - pipeline:
     name: periodic
diff --git a/tests/fixtures/layouts/nonvoting-job.yaml b/tests/fixtures/layouts/nonvoting-job.yaml
index fee5043..c536e11 100644
--- a/tests/fixtures/layouts/nonvoting-job.yaml
+++ b/tests/fixtures/layouts/nonvoting-job.yaml
@@ -6,17 +6,17 @@
       gerrit:
         - event: comment-added
           approval:
-            - approved: 1
+            - Approved: 1
     success:
       gerrit:
-        verified: 2
+        Verified: 2
         submit: true
     failure:
       gerrit:
-        verified: -2
+        Verified: -2
     start:
       gerrit:
-        verified: 0
+        Verified: 0
     precedence: high
 
 - job:
diff --git a/tests/fixtures/layouts/noop-job.yaml b/tests/fixtures/layouts/noop-job.yaml
index 8081216..3d1b20f 100644
--- a/tests/fixtures/layouts/noop-job.yaml
+++ b/tests/fixtures/layouts/noop-job.yaml
@@ -6,17 +6,17 @@
       gerrit:
         - event: comment-added
           approval:
-            - approved: 1
+            - Approved: 1
     success:
       gerrit:
-        verified: 2
+        Verified: 2
         submit: true
     failure:
       gerrit:
-        verified: -2
+        Verified: -2
     start:
       gerrit:
-        verified: 0
+        Verified: 0
     precedence: high
 
 - project:
diff --git a/tests/fixtures/layouts/one-job-project.yaml b/tests/fixtures/layouts/one-job-project.yaml
index b293269..db117b1 100644
--- a/tests/fixtures/layouts/one-job-project.yaml
+++ b/tests/fixtures/layouts/one-job-project.yaml
@@ -6,10 +6,10 @@
         - event: patchset-created
     success:
       gerrit:
-        verified: 1
+        Verified: 1
     failure:
       gerrit:
-        verified: -1
+        Verified: -1
 
 - pipeline:
     name: gate
@@ -19,17 +19,17 @@
       gerrit:
         - event: comment-added
           approval:
-            - approved: 1
+            - Approved: 1
     success:
       gerrit:
-        verified: 2
+        Verified: 2
         submit: true
     failure:
       gerrit:
-        verified: -2
+        Verified: -2
     start:
       gerrit:
-        verified: 0
+        Verified: 0
     precedence: high
 
 - pipeline:
diff --git a/tests/fixtures/layouts/rate-limit.yaml b/tests/fixtures/layouts/rate-limit.yaml
index 283354e..9392f5e 100644
--- a/tests/fixtures/layouts/rate-limit.yaml
+++ b/tests/fixtures/layouts/rate-limit.yaml
@@ -6,17 +6,17 @@
       gerrit:
         - event: comment-added
           approval:
-            - approved: 1
+            - Approved: 1
     start:
       gerrit:
-        verified: 0
+        Verified: 0
     success:
       gerrit:
-        verified: 2
+        Verified: 2
         submit: true
     failure:
       gerrit:
-        verified: -2
+        Verified: -2
     window: 2
     window-floor: 1
     window-increase-type: linear
diff --git a/tests/fixtures/layouts/repo-checkout-four-project.yaml b/tests/fixtures/layouts/repo-checkout-four-project.yaml
index 392931a..36937e9 100644
--- a/tests/fixtures/layouts/repo-checkout-four-project.yaml
+++ b/tests/fixtures/layouts/repo-checkout-four-project.yaml
@@ -6,10 +6,10 @@
         - event: patchset-created
     success:
       gerrit:
-        verified: 1
+        Verified: 1
     failure:
       gerrit:
-        verified: -1
+        Verified: -1
 
 - pipeline:
     name: gate
@@ -19,17 +19,17 @@
       gerrit:
         - event: comment-added
           approval:
-            - approved: 1
+            - Approved: 1
     success:
       gerrit:
-        verified: 2
+        Verified: 2
         submit: true
     failure:
       gerrit:
-        verified: -2
+        Verified: -2
     start:
       gerrit:
-        verified: 0
+        Verified: 0
     precedence: high
 
 - job:
diff --git a/tests/fixtures/layouts/repo-checkout-no-timer-override.yaml b/tests/fixtures/layouts/repo-checkout-no-timer-override.yaml
new file mode 100644
index 0000000..de3bfe0
--- /dev/null
+++ b/tests/fixtures/layouts/repo-checkout-no-timer-override.yaml
@@ -0,0 +1,21 @@
+- pipeline:
+    name: periodic
+    manager: independent
+    # Trigger is required, set it to one that is a noop
+    # during tests that check the timer trigger.
+    trigger:
+      gerrit:
+        - event: ref-updated
+
+- job:
+    name: integration
+    branches: master
+    override-branch: stable/havana
+    required-projects:
+      - org/project1
+
+- project:
+    name: org/project1
+    periodic:
+      jobs:
+        - integration
diff --git a/tests/fixtures/layouts/repo-checkout-six-project.yaml b/tests/fixtures/layouts/repo-checkout-six-project.yaml
index 93a64ea..c0de47d 100644
--- a/tests/fixtures/layouts/repo-checkout-six-project.yaml
+++ b/tests/fixtures/layouts/repo-checkout-six-project.yaml
@@ -6,10 +6,10 @@
         - event: patchset-created
     success:
       gerrit:
-        verified: 1
+        Verified: 1
     failure:
       gerrit:
-        verified: -1
+        Verified: -1
 
 - pipeline:
     name: gate
@@ -19,17 +19,17 @@
       gerrit:
         - event: comment-added
           approval:
-            - approved: 1
+            - Approved: 1
     success:
       gerrit:
-        verified: 2
+        Verified: 2
         submit: true
     failure:
       gerrit:
-        verified: -2
+        Verified: -2
     start:
       gerrit:
-        verified: 0
+        Verified: 0
     precedence: high
 
 - job:
diff --git a/tests/fixtures/layouts/repo-checkout-two-project.yaml b/tests/fixtures/layouts/repo-checkout-two-project.yaml
index 239d80c..e25554b 100644
--- a/tests/fixtures/layouts/repo-checkout-two-project.yaml
+++ b/tests/fixtures/layouts/repo-checkout-two-project.yaml
@@ -6,10 +6,10 @@
         - event: patchset-created
     success:
       gerrit:
-        verified: 1
+        Verified: 1
     failure:
       gerrit:
-        verified: -1
+        Verified: -1
 
 - pipeline:
     name: gate
@@ -19,17 +19,17 @@
       gerrit:
         - event: comment-added
           approval:
-            - approved: 1
+            - Approved: 1
     success:
       gerrit:
-        verified: 2
+        Verified: 2
         submit: true
     failure:
       gerrit:
-        verified: -2
+        Verified: -2
     start:
       gerrit:
-        verified: 0
+        Verified: 0
     precedence: high
 
 - job:
diff --git a/tests/fixtures/layouts/repo-deleted.yaml b/tests/fixtures/layouts/repo-deleted.yaml
index 95d11bb..cea3dda 100644
--- a/tests/fixtures/layouts/repo-deleted.yaml
+++ b/tests/fixtures/layouts/repo-deleted.yaml
@@ -6,10 +6,10 @@
         - event: patchset-created
     success:
       gerrit:
-        verified: 1
+        Verified: 1
     failure:
       gerrit:
-        verified: -1
+        Verified: -1
 
 - pipeline:
     name: gate
@@ -19,17 +19,17 @@
       gerrit:
         - event: comment-added
           approval:
-            - approved: 1
+            - Approved: 1
     success:
       gerrit:
-        verified: 2
+        Verified: 2
         submit: true
     failure:
       gerrit:
-        verified: -2
+        Verified: -2
     start:
       gerrit:
-        verified: 0
+        Verified: 0
     precedence: high
 
 - job:
diff --git a/tests/fixtures/layouts/smtp.yaml b/tests/fixtures/layouts/smtp.yaml
index fd91d36..bf1d273 100644
--- a/tests/fixtures/layouts/smtp.yaml
+++ b/tests/fixtures/layouts/smtp.yaml
@@ -9,13 +9,13 @@
         to: you@example.com
     success:
       gerrit:
-        verified: 1
+        Verified: 1
       smtp:
         to: alternative_me@example.com
         from: zuul_from@example.com
     failure:
       gerrit:
-        verified: -1
+        Verified: -1
 
 - pipeline:
     name: gate
@@ -25,17 +25,17 @@
       gerrit:
         - event: comment-added
           approval:
-            - approved: 1
+            - Approved: 1
     success:
       gerrit:
-        verified: 2
+        Verified: 2
         submit: true
     failure:
       gerrit:
-        verified: -2
+        Verified: -2
     start:
       gerrit:
-        verified: 0
+        Verified: 0
     precedence: high
 
 - job:
diff --git a/tests/fixtures/layouts/tags.yaml b/tests/fixtures/layouts/tags.yaml
index 422eca2..646160e 100644
--- a/tests/fixtures/layouts/tags.yaml
+++ b/tests/fixtures/layouts/tags.yaml
@@ -6,10 +6,10 @@
         - event: patchset-created
     success:
       gerrit:
-        verified: 1
+        Verified: 1
     failure:
       gerrit:
-        verified: -1
+        Verified: -1
 
 - job:
     name: merge
diff --git a/tests/fixtures/layouts/three-projects.yaml b/tests/fixtures/layouts/three-projects.yaml
index 5d10276..6481fb9 100644
--- a/tests/fixtures/layouts/three-projects.yaml
+++ b/tests/fixtures/layouts/three-projects.yaml
@@ -6,10 +6,10 @@
         - event: patchset-created
     success:
       gerrit:
-        verified: 1
+        Verified: 1
     failure:
       gerrit:
-        verified: -1
+        Verified: -1
 
 - pipeline:
     name: gate
@@ -19,17 +19,17 @@
       gerrit:
         - event: comment-added
           approval:
-            - approved: 1
+            - Approved: 1
     success:
       gerrit:
-        verified: 2
+        Verified: 2
         submit: true
     failure:
       gerrit:
-        verified: -2
+        Verified: -2
     start:
       gerrit:
-        verified: 0
+        Verified: 0
     precedence: high
 
 - job:
diff --git a/tests/fixtures/layouts/timer.yaml b/tests/fixtures/layouts/timer.yaml
index dbce516..45f137c 100644
--- a/tests/fixtures/layouts/timer.yaml
+++ b/tests/fixtures/layouts/timer.yaml
@@ -6,10 +6,10 @@
         - event: patchset-created
     success:
       gerrit:
-        verified: 1
+        Verified: 1
     failure:
       gerrit:
-        verified: -1
+        Verified: -1
 
 - pipeline:
     name: periodic
diff --git a/tests/fixtures/layouts/unmanaged-project.yaml b/tests/fixtures/layouts/unmanaged-project.yaml
index d72c26e..4c4305e 100644
--- a/tests/fixtures/layouts/unmanaged-project.yaml
+++ b/tests/fixtures/layouts/unmanaged-project.yaml
@@ -10,13 +10,13 @@
         - event: patchset-created
     success:
       gerrit:
-        verified: 1
+        Verified: 1
     failure:
       gerrit:
-        verified: -1
+        Verified: -1
     start:
       gerrit:
-        verified: 0
+        Verified: 0
 
 - project:
     name: org/project1
diff --git a/tests/fixtures/zuul-connections-gerrit-and-github.conf b/tests/fixtures/zuul-connections-gerrit-and-github.conf
index 64757d8..04f2cc2 100644
--- a/tests/fixtures/zuul-connections-gerrit-and-github.conf
+++ b/tests/fixtures/zuul-connections-gerrit-and-github.conf
@@ -21,6 +21,7 @@
 
 [connection github]
 driver=github
+webhook_token=00000000000000000000000000000000000000000
 
 [connection outgoing_smtp]
 driver=smtp
diff --git a/tests/fixtures/zuul-disk-accounting.conf b/tests/fixtures/zuul-disk-accounting.conf
new file mode 100644
index 0000000..b0ae48e
--- /dev/null
+++ b/tests/fixtures/zuul-disk-accounting.conf
@@ -0,0 +1,28 @@
+[gearman]
+server=127.0.0.1
+
+[scheduler]
+tenant_config=main.yaml
+
+[merger]
+git_dir=/tmp/zuul-test/merger-git
+git_user_email=zuul@example.com
+git_user_name=zuul
+zuul_url=http://zuul.example.com/p
+
+[executor]
+git_dir=/tmp/zuul-test/executor-git
+disk_limit_per_job=1
+
+[connection gerrit]
+driver=gerrit
+server=review.example.com
+user=jenkins
+sshkey=fake_id_rsa_path
+
+[connection smtp]
+driver=smtp
+server=localhost
+port=25
+default_from=zuul@example.com
+default_to=you@example.com
diff --git a/tests/fixtures/zuul-github-driver.conf b/tests/fixtures/zuul-github-driver.conf
index 3d61ab6..732c30a 100644
--- a/tests/fixtures/zuul-github-driver.conf
+++ b/tests/fixtures/zuul-github-driver.conf
@@ -15,6 +15,7 @@
 
 [connection github]
 driver=github
+webhook_token=0000000000000000000000000000000000000000
 
 [connection github_ssh]
 driver=github
diff --git a/tests/fixtures/zuul-push-reqs.conf b/tests/fixtures/zuul-push-reqs.conf
index 4faac13..cb699e0 100644
--- a/tests/fixtures/zuul-push-reqs.conf
+++ b/tests/fixtures/zuul-push-reqs.conf
@@ -15,6 +15,7 @@
 
 [connection github]
 driver=github
+webhook_token=00000000000000000000000000000000000000000
 
 [connection gerrit]
 driver=gerrit
diff --git a/tests/unit/test_connection.py b/tests/unit/test_connection.py
index c9e2e91..77b13a5 100644
--- a/tests/unit/test_connection.py
+++ b/tests/unit/test_connection.py
@@ -39,7 +39,7 @@
         self.waitUntilSettled()
 
         self.assertEqual(len(A.patchsets[-1]['approvals']), 1)
-        self.assertEqual(A.patchsets[-1]['approvals'][0]['type'], 'verified')
+        self.assertEqual(A.patchsets[-1]['approvals'][0]['type'], 'Verified')
         self.assertEqual(A.patchsets[-1]['approvals'][0]['value'], '1')
         self.assertEqual(A.patchsets[-1]['approvals'][0]['by']['username'],
                          'jenkins')
@@ -51,7 +51,7 @@
         self.waitUntilSettled()
 
         self.assertEqual(len(B.patchsets[-1]['approvals']), 1)
-        self.assertEqual(B.patchsets[-1]['approvals'][0]['type'], 'verified')
+        self.assertEqual(B.patchsets[-1]['approvals'][0]['type'], 'Verified')
         self.assertEqual(B.patchsets[-1]['approvals'][0]['value'], '-1')
         self.assertEqual(B.patchsets[-1]['approvals'][0]['by']['username'],
                          'civoter')
diff --git a/tests/unit/test_disk_accountant.py b/tests/unit/test_disk_accountant.py
new file mode 100644
index 0000000..22c8f34
--- /dev/null
+++ b/tests/unit/test_disk_accountant.py
@@ -0,0 +1,89 @@
+# 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 os
+import tempfile
+import time
+
+from tests.base import BaseTestCase
+
+from zuul.executor.server import DiskAccountant
+
+
+class FakeExecutor(object):
+    def __init__(self):
+        self.stopped_jobs = set()
+        self.used = {}
+
+    def stopJobByJobDir(self, jobdir):
+        self.stopped_jobs.add(jobdir)
+
+    def usage(self, dirname, used):
+        self.used[dirname] = used
+
+
+class TestDiskAccountant(BaseTestCase):
+    def test_disk_accountant(self):
+        jobs_dir = tempfile.mkdtemp()
+        cache_dir = tempfile.mkdtemp()
+        executor_server = FakeExecutor()
+        da = DiskAccountant(jobs_dir, 1, executor_server.stopJobByJobDir,
+                            cache_dir)
+        da.start()
+
+        jobdir = os.path.join(jobs_dir, '012345')
+        os.mkdir(jobdir)
+        testfile = os.path.join(jobdir, 'tfile')
+        with open(testfile, 'w') as tf:
+            tf.write(2 * 1024 * 1024 * '.')
+
+        # da should catch over-limit dir within 5 seconds
+        for i in range(0, 50):
+            if jobdir in executor_server.stopped_jobs:
+                break
+            time.sleep(0.1)
+        self.assertEqual(set([jobdir]), executor_server.stopped_jobs)
+        da.stop()
+        self.assertFalse(da.thread.is_alive())
+
+    def test_cache_hard_links(self):
+        root_dir = tempfile.mkdtemp()
+        jobs_dir = os.path.join(root_dir, 'jobs')
+        os.mkdir(jobs_dir)
+        cache_dir = os.path.join(root_dir, 'cache')
+        os.mkdir(cache_dir)
+
+        executor_server = FakeExecutor()
+        da = DiskAccountant(jobs_dir, 1, executor_server.stopJobByJobDir,
+                            cache_dir, executor_server.usage)
+        da.start()
+
+        jobdir = os.path.join(jobs_dir, '012345')
+        os.mkdir(jobdir)
+
+        repo_dir = os.path.join(cache_dir, 'a.repo')
+        os.mkdir(repo_dir)
+        source_file = os.path.join(repo_dir, 'big_file')
+        with open(source_file, 'w') as tf:
+            tf.write(2 * 1024 * 1024 * '.')
+        dest_link = os.path.join(jobdir, 'big_file')
+        os.link(source_file, dest_link)
+
+        # da should _not_ count this file. Wait for 5s to get noticed
+        for i in range(0, 50):
+            if jobdir in executor_server.used:
+                break
+            time.sleep(0.1)
+        self.assertEqual(set(), executor_server.stopped_jobs)
+        self.assertIn(jobdir, executor_server.used)
+        self.assertEqual(1, executor_server.used[jobdir])
+        da.stop()
diff --git a/tests/unit/test_executor.py b/tests/unit/test_executor.py
index 4700bd1..46f3b26 100755
--- a/tests/unit/test_executor.py
+++ b/tests/unit/test_executor.py
@@ -86,10 +86,10 @@
         projects = [p1, p2]
         A = self.fake_gerrit.addFakeChange('org/project1', 'master', 'A')
         B = self.fake_gerrit.addFakeChange('org/project2', 'master', 'B')
-        A.addApproval('code-review', 2)
-        B.addApproval('code-review', 2)
-        self.fake_gerrit.addEvent(A.addApproval('approved', 1))
-        self.fake_gerrit.addEvent(B.addApproval('approved', 1))
+        A.addApproval('Code-Review', 2)
+        B.addApproval('Code-Review', 2)
+        self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
+        self.fake_gerrit.addEvent(B.addApproval('Approved', 1))
 
         self.waitUntilSettled()
 
@@ -124,12 +124,12 @@
         B = self.fake_gerrit.addFakeChange('org/project2', 'stable/havana',
                                            'B')
         C = self.fake_gerrit.addFakeChange('org/project3', 'master', 'C')
-        A.addApproval('code-review', 2)
-        B.addApproval('code-review', 2)
-        C.addApproval('code-review', 2)
-        self.fake_gerrit.addEvent(A.addApproval('approved', 1))
-        self.fake_gerrit.addEvent(B.addApproval('approved', 1))
-        self.fake_gerrit.addEvent(C.addApproval('approved', 1))
+        A.addApproval('Code-Review', 2)
+        B.addApproval('Code-Review', 2)
+        C.addApproval('Code-Review', 2)
+        self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
+        self.fake_gerrit.addEvent(B.addApproval('Approved', 1))
+        self.fake_gerrit.addEvent(C.addApproval('Approved', 1))
 
         self.waitUntilSettled()
 
@@ -183,14 +183,14 @@
         C = self.fake_gerrit.addFakeChange('org/project2', 'master', 'C')
         D = self.fake_gerrit.addFakeChange('org/project3', 'stable/havana',
                                            'D')
-        A.addApproval('code-review', 2)
-        B.addApproval('code-review', 2)
-        C.addApproval('code-review', 2)
-        D.addApproval('code-review', 2)
-        self.fake_gerrit.addEvent(A.addApproval('approved', 1))
-        self.fake_gerrit.addEvent(B.addApproval('approved', 1))
-        self.fake_gerrit.addEvent(C.addApproval('approved', 1))
-        self.fake_gerrit.addEvent(D.addApproval('approved', 1))
+        A.addApproval('Code-Review', 2)
+        B.addApproval('Code-Review', 2)
+        C.addApproval('Code-Review', 2)
+        D.addApproval('Code-Review', 2)
+        self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
+        self.fake_gerrit.addEvent(B.addApproval('Approved', 1))
+        self.fake_gerrit.addEvent(C.addApproval('Approved', 1))
+        self.fake_gerrit.addEvent(D.addApproval('Approved', 1))
 
         self.waitUntilSettled()
 
@@ -274,8 +274,9 @@
         # Stop queuing timer triggered jobs so that the assertions
         # below don't race against more jobs being queued.
         self.commitConfigUpdate('common-config',
-                                'layouts/repo-checkout-no-timer.yaml')
+                                'layouts/repo-checkout-no-timer-override.yaml')
         self.sched.reconfigure(self.config)
+        self.waitUntilSettled()
 
         self.assertEquals(1, len(self.builds), "One build is running")
 
@@ -313,6 +314,7 @@
         self.commitConfigUpdate('common-config',
                                 'layouts/repo-checkout-no-timer.yaml')
         self.sched.reconfigure(self.config)
+        self.waitUntilSettled()
 
         self.assertEquals(2, len(self.builds), "Two builds are running")
 
diff --git a/tests/unit/test_github_driver.py b/tests/unit/test_github_driver.py
index 8493570..e8dff51 100644
--- a/tests/unit/test_github_driver.py
+++ b/tests/unit/test_github_driver.py
@@ -34,11 +34,6 @@
         self.fake_github.emitEvent(A.getPullRequestOpenedEvent())
         self.waitUntilSettled()
 
-        build_params = self.builds[0].parameters
-        self.assertEqual('master', build_params['ZUUL_BRANCH'])
-        self.assertEqual(str(A.number), build_params['ZUUL_CHANGE'])
-        self.assertEqual(A.head_sha, build_params['ZUUL_PATCHSET'])
-
         self.executor_server.hold_jobs_in_build = False
         self.executor_server.release()
         self.waitUntilSettled()
@@ -50,8 +45,9 @@
 
         job = self.getJobFromHistory('project-test2')
         zuulvars = job.parameters['zuul']
-        self.assertEqual(A.number, zuulvars['change'])
-        self.assertEqual(A.head_sha, zuulvars['patchset'])
+        self.assertEqual(str(A.number), zuulvars['change'])
+        self.assertEqual(str(A.head_sha), zuulvars['patchset'])
+        self.assertEqual('master', zuulvars['branch'])
         self.assertEqual(1, len(A.comments))
         self.assertEqual(2, len(self.history))
 
@@ -113,10 +109,10 @@
         self.waitUntilSettled()
 
         build_params = self.builds[0].parameters
-        self.assertEqual('refs/tags/newtag', build_params['ZUUL_REF'])
+        self.assertEqual('refs/tags/newtag', build_params['zuul']['ref'])
         self.assertEqual('00000000000000000000000000000000',
-                         build_params['ZUUL_OLDREV'])
-        self.assertEqual(sha, build_params['ZUUL_NEWREV'])
+                         build_params['zuul']['oldrev'])
+        self.assertEqual(sha, build_params['zuul']['newrev'])
 
         self.executor_server.hold_jobs_in_build = False
         self.executor_server.release()
@@ -137,9 +133,9 @@
         self.waitUntilSettled()
 
         build_params = self.builds[0].parameters
-        self.assertEqual('refs/heads/master', build_params['ZUUL_REF'])
-        self.assertEqual(old_sha, build_params['ZUUL_OLDREV'])
-        self.assertEqual(new_sha, build_params['ZUUL_NEWREV'])
+        self.assertEqual('refs/heads/master', build_params['zuul']['ref'])
+        self.assertEqual(old_sha, build_params['zuul']['oldrev'])
+        self.assertEqual(new_sha, build_params['zuul']['newrev'])
 
         self.executor_server.hold_jobs_in_build = False
         self.executor_server.release()
diff --git a/tests/unit/test_openstack.py b/tests/unit/test_openstack.py
index 4fceba0..980797f 100644
--- a/tests/unit/test_openstack.py
+++ b/tests/unit/test_openstack.py
@@ -27,8 +27,8 @@
 
     def test_nova_master(self):
         A = self.fake_gerrit.addFakeChange('openstack/nova', 'master', 'A')
-        A.addApproval('code-review', 2)
-        self.fake_gerrit.addEvent(A.addApproval('approved', 1))
+        A.addApproval('Code-Review', 2)
+        self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
         self.waitUntilSettled()
         self.assertEqual(self.getJobFromHistory('python27').result,
                          'SUCCESS')
@@ -44,8 +44,8 @@
         self.create_branch('openstack/nova', 'stable/mitaka')
         A = self.fake_gerrit.addFakeChange('openstack/nova',
                                            'stable/mitaka', 'A')
-        A.addApproval('code-review', 2)
-        self.fake_gerrit.addEvent(A.addApproval('approved', 1))
+        A.addApproval('Code-Review', 2)
+        self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
         self.waitUntilSettled()
         self.assertEqual(self.getJobFromHistory('python27').result,
                          'SUCCESS')
diff --git a/tests/unit/test_requirements.py b/tests/unit/test_requirements.py
index 7e578cf..ff39fd7 100644
--- a/tests/unit/test_requirements.py
+++ b/tests/unit/test_requirements.py
@@ -37,21 +37,21 @@
     def _test_require_approval_newer_than(self, project, job):
         A = self.fake_gerrit.addFakeChange(project, 'master', 'A')
         # A comment event that we will keep submitting to trigger
-        comment = A.addApproval('code-review', 2, username='nobody')
+        comment = A.addApproval('Code-Review', 2, username='nobody')
         self.fake_gerrit.addEvent(comment)
         self.waitUntilSettled()
         # No +1 from Jenkins so should not be enqueued
         self.assertEqual(len(self.history), 0)
 
         # Add a too-old +1, should not be enqueued
-        A.addApproval('verified', 1, username='jenkins',
+        A.addApproval('Verified', 1, username='jenkins',
                       granted_on=time.time() - 72 * 60 * 60)
         self.fake_gerrit.addEvent(comment)
         self.waitUntilSettled()
         self.assertEqual(len(self.history), 0)
 
         # Add a recent +1
-        self.fake_gerrit.addEvent(A.addApproval('verified', 1,
+        self.fake_gerrit.addEvent(A.addApproval('Verified', 1,
                                                 username='jenkins'))
         self.fake_gerrit.addEvent(comment)
         self.waitUntilSettled()
@@ -77,20 +77,20 @@
     def _test_require_approval_older_than(self, project, job):
         A = self.fake_gerrit.addFakeChange(project, 'master', 'A')
         # A comment event that we will keep submitting to trigger
-        comment = A.addApproval('code-review', 2, username='nobody')
+        comment = A.addApproval('Code-Review', 2, username='nobody')
         self.fake_gerrit.addEvent(comment)
         self.waitUntilSettled()
         # No +1 from Jenkins so should not be enqueued
         self.assertEqual(len(self.history), 0)
 
         # Add a recent +1 which should not be enqueued
-        A.addApproval('verified', 1)
+        A.addApproval('Verified', 1)
         self.fake_gerrit.addEvent(comment)
         self.waitUntilSettled()
         self.assertEqual(len(self.history), 0)
 
         # Add an old +1 which should be enqueued
-        A.addApproval('verified', 1, username='jenkins',
+        A.addApproval('Verified', 1, username='jenkins',
                       granted_on=time.time() - 72 * 60 * 60)
         self.fake_gerrit.addEvent(comment)
         self.waitUntilSettled()
@@ -116,14 +116,14 @@
     def _test_require_approval_username(self, project, job):
         A = self.fake_gerrit.addFakeChange(project, 'master', 'A')
         # A comment event that we will keep submitting to trigger
-        comment = A.addApproval('code-review', 2, username='nobody')
+        comment = A.addApproval('Code-Review', 2, username='nobody')
         self.fake_gerrit.addEvent(comment)
         self.waitUntilSettled()
         # No approval from Jenkins so should not be enqueued
         self.assertEqual(len(self.history), 0)
 
         # Add an approval from Jenkins
-        A.addApproval('verified', 1, username='jenkins')
+        A.addApproval('Verified', 1, username='jenkins')
         self.fake_gerrit.addEvent(comment)
         self.waitUntilSettled()
         self.assertEqual(len(self.history), 1)
@@ -148,14 +148,14 @@
     def _test_require_approval_email(self, project, job):
         A = self.fake_gerrit.addFakeChange(project, 'master', 'A')
         # A comment event that we will keep submitting to trigger
-        comment = A.addApproval('code-review', 2, username='nobody')
+        comment = A.addApproval('Code-Review', 2, username='nobody')
         self.fake_gerrit.addEvent(comment)
         self.waitUntilSettled()
         # No approval from Jenkins so should not be enqueued
         self.assertEqual(len(self.history), 0)
 
         # Add an approval from Jenkins
-        A.addApproval('verified', 1, username='jenkins')
+        A.addApproval('Verified', 1, username='jenkins')
         self.fake_gerrit.addEvent(comment)
         self.waitUntilSettled()
         self.assertEqual(len(self.history), 1)
@@ -180,20 +180,20 @@
     def _test_require_approval_vote1(self, project, job):
         A = self.fake_gerrit.addFakeChange(project, 'master', 'A')
         # A comment event that we will keep submitting to trigger
-        comment = A.addApproval('code-review', 2, username='nobody')
+        comment = A.addApproval('Code-Review', 2, username='nobody')
         self.fake_gerrit.addEvent(comment)
         self.waitUntilSettled()
         # No approval from Jenkins so should not be enqueued
         self.assertEqual(len(self.history), 0)
 
         # A -1 from jenkins should not cause it to be enqueued
-        A.addApproval('verified', -1, username='jenkins')
+        A.addApproval('Verified', -1, username='jenkins')
         self.fake_gerrit.addEvent(comment)
         self.waitUntilSettled()
         self.assertEqual(len(self.history), 0)
 
         # A +1 should allow it to be enqueued
-        A.addApproval('verified', 1, username='jenkins')
+        A.addApproval('Verified', 1, username='jenkins')
         self.fake_gerrit.addEvent(comment)
         self.waitUntilSettled()
         self.assertEqual(len(self.history), 1)
@@ -218,26 +218,26 @@
     def _test_require_approval_vote2(self, project, job):
         A = self.fake_gerrit.addFakeChange(project, 'master', 'A')
         # A comment event that we will keep submitting to trigger
-        comment = A.addApproval('code-review', 2, username='nobody')
+        comment = A.addApproval('Code-Review', 2, username='nobody')
         self.fake_gerrit.addEvent(comment)
         self.waitUntilSettled()
         # No approval from Jenkins so should not be enqueued
         self.assertEqual(len(self.history), 0)
 
         # A -1 from jenkins should not cause it to be enqueued
-        A.addApproval('verified', -1, username='jenkins')
+        A.addApproval('Verified', -1, username='jenkins')
         self.fake_gerrit.addEvent(comment)
         self.waitUntilSettled()
         self.assertEqual(len(self.history), 0)
 
         # A -2 from jenkins should not cause it to be enqueued
-        A.addApproval('verified', -2, username='jenkins')
+        A.addApproval('Verified', -2, username='jenkins')
         self.fake_gerrit.addEvent(comment)
         self.waitUntilSettled()
         self.assertEqual(len(self.history), 0)
 
         # A +1 from jenkins should allow it to be enqueued
-        A.addApproval('verified', 1, username='jenkins')
+        A.addApproval('Verified', 1, username='jenkins')
         self.fake_gerrit.addEvent(comment)
         self.waitUntilSettled()
         self.assertEqual(len(self.history), 1)
@@ -246,13 +246,13 @@
         # A +2 from nobody should not cause it to be enqueued
         B = self.fake_gerrit.addFakeChange(project, 'master', 'B')
         # A comment event that we will keep submitting to trigger
-        comment = B.addApproval('code-review', 2, username='nobody')
+        comment = B.addApproval('Code-Review', 2, username='nobody')
         self.fake_gerrit.addEvent(comment)
         self.waitUntilSettled()
         self.assertEqual(len(self.history), 1)
 
         # A +2 from jenkins should allow it to be enqueued
-        B.addApproval('verified', 2, username='jenkins')
+        B.addApproval('Verified', 2, username='jenkins')
         self.fake_gerrit.addEvent(comment)
         self.waitUntilSettled()
         self.assertEqual(len(self.history), 2)
@@ -269,10 +269,10 @@
         # comment on first patchset and check that no additional
         # jobs are run.
         A = self.fake_gerrit.addFakeChange('current-project', 'master', 'A')
-        self.fake_gerrit.addEvent(A.addApproval('code-review', 1))
+        self.fake_gerrit.addEvent(A.addApproval('Code-Review', 1))
         self.waitUntilSettled()
         A.addPatchset()
-        self.fake_gerrit.addEvent(A.addApproval('code-review', 1))
+        self.fake_gerrit.addEvent(A.addApproval('Code-Review', 1))
         self.waitUntilSettled()
 
         self.assertEqual(len(self.history), 2)  # one job for each ps
@@ -290,24 +290,24 @@
     def test_pipeline_require_open(self):
         A = self.fake_gerrit.addFakeChange('open-project', 'master', 'A',
                                            status='MERGED')
-        self.fake_gerrit.addEvent(A.addApproval('code-review', 2))
+        self.fake_gerrit.addEvent(A.addApproval('Code-Review', 2))
         self.waitUntilSettled()
         self.assertEqual(len(self.history), 0)
 
         B = self.fake_gerrit.addFakeChange('open-project', 'master', 'B')
-        self.fake_gerrit.addEvent(B.addApproval('code-review', 2))
+        self.fake_gerrit.addEvent(B.addApproval('Code-Review', 2))
         self.waitUntilSettled()
         self.assertEqual(len(self.history), 1)
 
     def test_pipeline_require_status(self):
         A = self.fake_gerrit.addFakeChange('status-project', 'master', 'A',
                                            status='MERGED')
-        self.fake_gerrit.addEvent(A.addApproval('code-review', 2))
+        self.fake_gerrit.addEvent(A.addApproval('Code-Review', 2))
         self.waitUntilSettled()
         self.assertEqual(len(self.history), 0)
 
         B = self.fake_gerrit.addFakeChange('status-project', 'master', 'B')
-        self.fake_gerrit.addEvent(B.addApproval('code-review', 2))
+        self.fake_gerrit.addEvent(B.addApproval('Code-Review', 2))
         self.waitUntilSettled()
         self.assertEqual(len(self.history), 1)
 
@@ -326,21 +326,21 @@
         self.assertEqual(len(self.history), 0)
 
         # add in a comment that will trigger
-        self.fake_gerrit.addEvent(A.addApproval('code-review', 1,
+        self.fake_gerrit.addEvent(A.addApproval('Code-Review', 1,
                                                 username='reviewer'))
         self.waitUntilSettled()
         self.assertEqual(len(self.history), 1)
         self.assertEqual(self.history[0].name, job)
 
         # add in a comment from jenkins user which shouldn't trigger
-        self.fake_gerrit.addEvent(A.addApproval('verified', 1,
+        self.fake_gerrit.addEvent(A.addApproval('Verified', 1,
                                                 username='jenkins'))
         self.waitUntilSettled()
         self.assertEqual(len(self.history), 1)
 
         # Check future reviews also won't trigger as a 'jenkins' user has
         # commented previously
-        self.fake_gerrit.addEvent(A.addApproval('code-review', 1,
+        self.fake_gerrit.addEvent(A.addApproval('Code-Review', 1,
                                                 username='reviewer'))
         self.waitUntilSettled()
         self.assertEqual(len(self.history), 1)
@@ -368,39 +368,39 @@
         self.assertEqual(len(self.history), 0)
 
         # First positive vote should not queue until jenkins has +1'd
-        comment = A.addApproval('verified', 1, username='reviewer_a')
+        comment = A.addApproval('Verified', 1, username='reviewer_a')
         self.fake_gerrit.addEvent(comment)
         self.waitUntilSettled()
         self.assertEqual(len(self.history), 0)
 
         # Jenkins should put in a +1 which will also queue
-        comment = A.addApproval('verified', 1, username='jenkins')
+        comment = A.addApproval('Verified', 1, username='jenkins')
         self.fake_gerrit.addEvent(comment)
         self.waitUntilSettled()
         self.assertEqual(len(self.history), 1)
         self.assertEqual(self.history[0].name, job)
 
         # Negative vote should not queue
-        comment = A.addApproval('verified', -1, username='reviewer_b')
+        comment = A.addApproval('Verified', -1, username='reviewer_b')
         self.fake_gerrit.addEvent(comment)
         self.waitUntilSettled()
         self.assertEqual(len(self.history), 1)
 
         # Future approvals should do nothing
-        comment = A.addApproval('verified', 1, username='reviewer_c')
+        comment = A.addApproval('Verified', 1, username='reviewer_c')
         self.fake_gerrit.addEvent(comment)
         self.waitUntilSettled()
         self.assertEqual(len(self.history), 1)
 
         # Change/update negative vote should queue
-        comment = A.addApproval('verified', 1, username='reviewer_b')
+        comment = A.addApproval('Verified', 1, username='reviewer_b')
         self.fake_gerrit.addEvent(comment)
         self.waitUntilSettled()
         self.assertEqual(len(self.history), 2)
         self.assertEqual(self.history[1].name, job)
 
         # Future approvals should also queue
-        comment = A.addApproval('verified', 1, username='reviewer_d')
+        comment = A.addApproval('Verified', 1, username='reviewer_d')
         self.fake_gerrit.addEvent(comment)
         self.waitUntilSettled()
         self.assertEqual(len(self.history), 3)
diff --git a/tests/unit/test_scheduler.py b/tests/unit/test_scheduler.py
index d4290a9..5dd3f4e 100755
--- a/tests/unit/test_scheduler.py
+++ b/tests/unit/test_scheduler.py
@@ -49,8 +49,8 @@
         "Test that jobs are executed and a change is merged"
 
         A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
-        A.addApproval('code-review', 2)
-        self.fake_gerrit.addEvent(A.addApproval('approved', 1))
+        A.addApproval('Code-Review', 2)
+        self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
         self.waitUntilSettled()
         self.assertEqual(self.getJobFromHistory('project-merge').result,
                          'SUCCESS')
@@ -72,8 +72,8 @@
         "Test that jobs are executed and a change is merged"
 
         A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
-        A.addApproval('code-review', 2)
-        self.fake_gerrit.addEvent(A.addApproval('approved', 1))
+        A.addApproval('Code-Review', 2)
+        self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
         self.waitUntilSettled()
         self.assertEqual(self.getJobFromHistory('project-merge').result,
                          'SUCCESS')
@@ -107,8 +107,8 @@
         self.assertReportedStat(
             'zuul.pipeline.gate.org.project.total_changes', value='1|c')
 
-        for build in self.builds:
-            self.assertEqual(build.parameters['ZUUL_VOTING'], '1')
+        for build in self.history:
+            self.assertTrue(build.parameters['zuul']['voting'])
 
     def test_initial_pipeline_gauges(self):
         "Test that each pipeline reported its length on start"
@@ -121,8 +121,8 @@
         "Test the correct variant of a job runs on a branch"
         self.create_branch('org/project', 'stable')
         A = self.fake_gerrit.addFakeChange('org/project', 'stable', 'A')
-        A.addApproval('code-review', 2)
-        self.fake_gerrit.addEvent(A.addApproval('approved', 1))
+        A.addApproval('Code-Review', 2)
+        self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
         self.waitUntilSettled()
         self.assertEqual(self.getJobFromHistory('project-test1').result,
                          'SUCCESS')
@@ -143,13 +143,13 @@
         A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
         B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
         C = self.fake_gerrit.addFakeChange('org/project', 'master', 'C')
-        A.addApproval('code-review', 2)
-        B.addApproval('code-review', 2)
-        C.addApproval('code-review', 2)
+        A.addApproval('Code-Review', 2)
+        B.addApproval('Code-Review', 2)
+        C.addApproval('Code-Review', 2)
 
-        self.fake_gerrit.addEvent(A.addApproval('approved', 1))
-        self.fake_gerrit.addEvent(B.addApproval('approved', 1))
-        self.fake_gerrit.addEvent(C.addApproval('approved', 1))
+        self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
+        self.fake_gerrit.addEvent(B.addApproval('Approved', 1))
+        self.fake_gerrit.addEvent(C.addApproval('Approved', 1))
 
         self.waitUntilSettled()
         self.assertEqual(len(self.builds), 1)
@@ -219,13 +219,13 @@
 
         A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
         B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
-        A.addApproval('code-review', 2)
-        B.addApproval('code-review', 2)
+        A.addApproval('Code-Review', 2)
+        B.addApproval('Code-Review', 2)
 
         self.executor_server.failJob('project-test1', A)
 
-        self.fake_gerrit.addEvent(A.addApproval('approved', 1))
-        self.fake_gerrit.addEvent(B.addApproval('approved', 1))
+        self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
+        self.fake_gerrit.addEvent(B.addApproval('Approved', 1))
         self.waitUntilSettled()
         self.assertBuilds([dict(name='project-merge', changes='1,1')])
 
@@ -279,17 +279,17 @@
         A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
         B = self.fake_gerrit.addFakeChange('org/project1', 'master', 'B')
         C = self.fake_gerrit.addFakeChange('org/project2', 'master', 'C')
-        A.addApproval('code-review', 2)
-        B.addApproval('code-review', 2)
-        C.addApproval('code-review', 2)
+        A.addApproval('Code-Review', 2)
+        B.addApproval('Code-Review', 2)
+        C.addApproval('Code-Review', 2)
 
-        self.fake_gerrit.addEvent(A.addApproval('approved', 1))
+        self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
         self.waitUntilSettled()
 
-        self.fake_gerrit.addEvent(B.addApproval('approved', 1))
+        self.fake_gerrit.addEvent(B.addApproval('Approved', 1))
         self.waitUntilSettled()
 
-        self.fake_gerrit.addEvent(C.addApproval('approved', 1))
+        self.fake_gerrit.addEvent(C.addApproval('Approved', 1))
         self.waitUntilSettled()
 
         # There should be one merge job at the head of each queue running
@@ -353,15 +353,15 @@
         A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
         B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
         C = self.fake_gerrit.addFakeChange('org/project', 'master', 'C')
-        A.addApproval('code-review', 2)
-        B.addApproval('code-review', 2)
-        C.addApproval('code-review', 2)
+        A.addApproval('Code-Review', 2)
+        B.addApproval('Code-Review', 2)
+        C.addApproval('Code-Review', 2)
 
         self.executor_server.failJob('project-test1', A)
 
-        self.fake_gerrit.addEvent(A.addApproval('approved', 1))
-        self.fake_gerrit.addEvent(B.addApproval('approved', 1))
-        self.fake_gerrit.addEvent(C.addApproval('approved', 1))
+        self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
+        self.fake_gerrit.addEvent(B.addApproval('Approved', 1))
+        self.fake_gerrit.addEvent(C.addApproval('Approved', 1))
 
         self.waitUntilSettled()
 
@@ -468,15 +468,15 @@
         A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
         B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
         C = self.fake_gerrit.addFakeChange('org/project', 'master', 'C')
-        A.addApproval('code-review', 2)
-        B.addApproval('code-review', 2)
-        C.addApproval('code-review', 2)
+        A.addApproval('Code-Review', 2)
+        B.addApproval('Code-Review', 2)
+        C.addApproval('Code-Review', 2)
 
         self.executor_server.failJob('project-test1', B)
 
-        self.fake_gerrit.addEvent(A.addApproval('approved', 1))
-        self.fake_gerrit.addEvent(B.addApproval('approved', 1))
-        self.fake_gerrit.addEvent(C.addApproval('approved', 1))
+        self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
+        self.fake_gerrit.addEvent(B.addApproval('Approved', 1))
+        self.fake_gerrit.addEvent(C.addApproval('Approved', 1))
 
         self.waitUntilSettled()
 
@@ -545,15 +545,15 @@
         A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
         B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
         C = self.fake_gerrit.addFakeChange('org/project', 'master', 'C')
-        A.addApproval('code-review', 2)
-        B.addApproval('code-review', 2)
-        C.addApproval('code-review', 2)
+        A.addApproval('Code-Review', 2)
+        B.addApproval('Code-Review', 2)
+        C.addApproval('Code-Review', 2)
 
         self.executor_server.failJob('project-test1', A)
 
-        self.fake_gerrit.addEvent(A.addApproval('approved', 1))
-        self.fake_gerrit.addEvent(B.addApproval('approved', 1))
-        self.fake_gerrit.addEvent(C.addApproval('approved', 1))
+        self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
+        self.fake_gerrit.addEvent(B.addApproval('Approved', 1))
+        self.fake_gerrit.addEvent(C.addApproval('Approved', 1))
 
         self.waitUntilSettled()
         queue = self.gearman_server.getQueue()
@@ -619,8 +619,8 @@
     def _test_time_database(self, iteration):
         self.executor_server.hold_jobs_in_build = True
         A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
-        A.addApproval('code-review', 2)
-        self.fake_gerrit.addEvent(A.addApproval('approved', 1))
+        A.addApproval('Code-Review', 2)
+        self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
         self.waitUntilSettled()
         time.sleep(2)
 
@@ -664,16 +664,16 @@
         A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
         B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
         C = self.fake_gerrit.addFakeChange('org/project', 'master', 'C')
-        A.addApproval('code-review', 2)
-        B.addApproval('code-review', 2)
-        C.addApproval('code-review', 2)
+        A.addApproval('Code-Review', 2)
+        B.addApproval('Code-Review', 2)
+        C.addApproval('Code-Review', 2)
 
         self.executor_server.failJob('project-test1', A)
         self.executor_server.failJob('project-test1', B)
 
-        self.fake_gerrit.addEvent(A.addApproval('approved', 1))
-        self.fake_gerrit.addEvent(B.addApproval('approved', 1))
-        self.fake_gerrit.addEvent(C.addApproval('approved', 1))
+        self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
+        self.fake_gerrit.addEvent(B.addApproval('Approved', 1))
+        self.fake_gerrit.addEvent(C.addApproval('Approved', 1))
         self.waitUntilSettled()
 
         self.executor_server.release('.*-merge')
@@ -767,9 +767,9 @@
         A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
         B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
         C = self.fake_gerrit.addFakeChange('org/project', 'master', 'C')
-        A.addApproval('code-review', 2)
-        B.addApproval('code-review', 2)
-        C.addApproval('code-review', 2)
+        A.addApproval('Code-Review', 2)
+        B.addApproval('Code-Review', 2)
+        C.addApproval('Code-Review', 2)
 
         M2 = self.fake_gerrit.addFakeChange('org/project', 'master', 'M2')
         M1 = self.fake_gerrit.addFakeChange('org/project', 'master', 'M1')
@@ -786,7 +786,7 @@
         A.setDependsOn(M1, 1)
         M1.setDependsOn(M2, 1)
 
-        self.fake_gerrit.addEvent(C.addApproval('approved', 1))
+        self.fake_gerrit.addEvent(C.addApproval('Approved', 1))
 
         self.waitUntilSettled()
 
@@ -794,8 +794,8 @@
         self.assertEqual(B.data['status'], 'NEW')
         self.assertEqual(C.data['status'], 'NEW')
 
-        self.fake_gerrit.addEvent(B.addApproval('approved', 1))
-        self.fake_gerrit.addEvent(A.addApproval('approved', 1))
+        self.fake_gerrit.addEvent(B.addApproval('Approved', 1))
+        self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
 
         self.waitUntilSettled()
         self.assertEqual(M2.queried, 0)
@@ -830,14 +830,14 @@
         F.setDependsOn(B, 1)
         G.setDependsOn(A, 1)
 
-        A.addApproval('code-review', 2)
-        B.addApproval('code-review', 2)
-        C.addApproval('code-review', 2)
-        D.addApproval('code-review', 2)
-        E.addApproval('code-review', 2)
-        F.addApproval('code-review', 2)
-        G.addApproval('code-review', 2)
-        self.fake_gerrit.addEvent(C.addApproval('approved', 1))
+        A.addApproval('Code-Review', 2)
+        B.addApproval('Code-Review', 2)
+        C.addApproval('Code-Review', 2)
+        D.addApproval('Code-Review', 2)
+        E.addApproval('Code-Review', 2)
+        F.addApproval('Code-Review', 2)
+        G.addApproval('Code-Review', 2)
+        self.fake_gerrit.addEvent(C.addApproval('Approved', 1))
 
         self.waitUntilSettled()
 
@@ -859,13 +859,13 @@
             connection.maintainCache([])
 
         self.executor_server.hold_jobs_in_build = True
-        A.addApproval('approved', 1)
-        B.addApproval('approved', 1)
-        D.addApproval('approved', 1)
-        E.addApproval('approved', 1)
-        F.addApproval('approved', 1)
-        G.addApproval('approved', 1)
-        self.fake_gerrit.addEvent(C.addApproval('approved', 1))
+        A.addApproval('Approved', 1)
+        B.addApproval('Approved', 1)
+        D.addApproval('Approved', 1)
+        E.addApproval('Approved', 1)
+        F.addApproval('Approved', 1)
+        G.addApproval('Approved', 1)
+        self.fake_gerrit.addEvent(C.addApproval('Approved', 1))
 
         for x in range(8):
             self.executor_server.release('.*-merge')
@@ -898,8 +898,8 @@
         A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
         B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
         X = self.fake_gerrit.addFakeChange('org/project', 'master', 'X')
-        A.addApproval('code-review', 2)
-        B.addApproval('code-review', 2)
+        A.addApproval('Code-Review', 2)
+        B.addApproval('Code-Review', 2)
 
         M1 = self.fake_gerrit.addFakeChange('org/project', 'master', 'M1')
         M1.setMerged()
@@ -907,21 +907,21 @@
         B.setDependsOn(A, 1)
         A.setDependsOn(M1, 1)
 
-        self.fake_gerrit.addEvent(A.addApproval('approved', 1))
+        self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
         self.fake_gerrit.addEvent(X.getPatchsetCreatedEvent(1))
 
         self.waitUntilSettled()
 
         for build in self.builds:
-            if build.parameters['ZUUL_PIPELINE'] == 'check':
+            if build.pipeline == 'check':
                 build.release()
         self.waitUntilSettled()
         for build in self.builds:
-            if build.parameters['ZUUL_PIPELINE'] == 'check':
+            if build.pipeline == 'check':
                 build.release()
         self.waitUntilSettled()
 
-        self.fake_gerrit.addEvent(B.addApproval('approved', 1))
+        self.fake_gerrit.addEvent(B.addApproval('Approved', 1))
         self.waitUntilSettled()
 
         self.log.debug("len %s" % self.fake_gerrit._change_cache.keys())
@@ -956,11 +956,11 @@
         mgr = tenant.layout.pipelines['gate'].manager
         self.assertFalse(source.canMerge(a, mgr.getSubmitAllowNeeds()))
 
-        A.addApproval('code-review', 2)
+        A.addApproval('Code-Review', 2)
         a = source.getChange(event, refresh=True)
         self.assertFalse(source.canMerge(a, mgr.getSubmitAllowNeeds()))
 
-        A.addApproval('approved', 1)
+        A.addApproval('Approved', 1)
         a = source.getChange(event, refresh=True)
         self.assertTrue(source.canMerge(a, mgr.getSubmitAllowNeeds()))
 
@@ -976,12 +976,12 @@
                                            files={'conflict': 'bar'})
         C = self.fake_gerrit.addFakeChange('org/project',
                                            'master', 'C')
-        A.addApproval('code-review', 2)
-        B.addApproval('code-review', 2)
-        C.addApproval('code-review', 2)
-        self.fake_gerrit.addEvent(A.addApproval('approved', 1))
-        self.fake_gerrit.addEvent(B.addApproval('approved', 1))
-        self.fake_gerrit.addEvent(C.addApproval('approved', 1))
+        A.addApproval('Code-Review', 2)
+        B.addApproval('Code-Review', 2)
+        C.addApproval('Code-Review', 2)
+        self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
+        self.fake_gerrit.addEvent(B.addApproval('Approved', 1))
+        self.fake_gerrit.addEvent(C.addApproval('Approved', 1))
         self.waitUntilSettled()
 
         self.assertEqual(A.reported, 1)
@@ -1033,8 +1033,8 @@
         C.setDependsOn(B, 1)
 
         # A enters the gate queue; B and C enter the check queue
-        A.addApproval('code-review', 2)
-        self.fake_gerrit.addEvent(A.addApproval('approved', 1))
+        A.addApproval('Code-Review', 2)
+        self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
         self.waitUntilSettled()
         self.fake_gerrit.addEvent(B.getPatchsetCreatedEvent(1))
         self.waitUntilSettled()
@@ -1212,9 +1212,9 @@
         A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
         B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
         C = self.fake_gerrit.addFakeChange('org/project', 'master', 'C')
-        A.addApproval('code-review', 2)
-        B.addApproval('code-review', 2)
-        C.addApproval('code-review', 2)
+        A.addApproval('Code-Review', 2)
+        B.addApproval('Code-Review', 2)
+        C.addApproval('Code-Review', 2)
 
         M1 = self.fake_gerrit.addFakeChange('org/project', 'master', 'M1')
         M1.setMerged()
@@ -1227,9 +1227,9 @@
 
         self.executor_server.failJob('project-merge', A)
 
-        self.fake_gerrit.addEvent(C.addApproval('approved', 1))
-        self.fake_gerrit.addEvent(B.addApproval('approved', 1))
-        self.fake_gerrit.addEvent(A.addApproval('approved', 1))
+        self.fake_gerrit.addEvent(C.addApproval('Approved', 1))
+        self.fake_gerrit.addEvent(B.addApproval('Approved', 1))
+        self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
 
         self.waitUntilSettled()
 
@@ -1250,11 +1250,11 @@
         C = self.fake_gerrit.addFakeChange('org/project', 'master', 'C')
         D = self.fake_gerrit.addFakeChange('org/project', 'master', 'D')
         E = self.fake_gerrit.addFakeChange('org/project', 'master', 'E')
-        A.addApproval('code-review', 2)
-        B.addApproval('code-review', 2)
-        C.addApproval('code-review', 2)
-        D.addApproval('code-review', 2)
-        E.addApproval('code-review', 2)
+        A.addApproval('Code-Review', 2)
+        B.addApproval('Code-Review', 2)
+        C.addApproval('Code-Review', 2)
+        D.addApproval('Code-Review', 2)
+        E.addApproval('Code-Review', 2)
 
         # E, D -> C -> B, A
 
@@ -1263,11 +1263,11 @@
 
         self.executor_server.failJob('project-test1', B)
 
-        self.fake_gerrit.addEvent(A.addApproval('approved', 1))
-        self.fake_gerrit.addEvent(D.addApproval('approved', 1))
-        self.fake_gerrit.addEvent(C.addApproval('approved', 1))
-        self.fake_gerrit.addEvent(B.addApproval('approved', 1))
-        self.fake_gerrit.addEvent(E.addApproval('approved', 1))
+        self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
+        self.fake_gerrit.addEvent(D.addApproval('Approved', 1))
+        self.fake_gerrit.addEvent(C.addApproval('Approved', 1))
+        self.fake_gerrit.addEvent(B.addApproval('Approved', 1))
+        self.fake_gerrit.addEvent(E.addApproval('Approved', 1))
 
         self.waitUntilSettled()
         self.executor_server.release('.*-merge')
@@ -1283,7 +1283,7 @@
 
         self.executor_server.hold_jobs_in_build = False
         for build in self.builds:
-            if build.parameters['ZUUL_CHANGE'] != '1':
+            if build.parameters['zuul']['change'] != '1':
                 build.release()
                 self.waitUntilSettled()
 
@@ -1316,16 +1316,16 @@
         A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
         B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
         C = self.fake_gerrit.addFakeChange('org/project', 'master', 'C')
-        A.addApproval('code-review', 2)
-        B.addApproval('code-review', 2)
-        C.addApproval('code-review', 2)
+        A.addApproval('Code-Review', 2)
+        B.addApproval('Code-Review', 2)
+        C.addApproval('Code-Review', 2)
 
         self.executor_server.failJob('project-test1', A)
         self.executor_server.failJob('project-test2', A)
 
-        self.fake_gerrit.addEvent(A.addApproval('approved', 1))
-        self.fake_gerrit.addEvent(B.addApproval('approved', 1))
-        self.fake_gerrit.addEvent(C.addApproval('approved', 1))
+        self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
+        self.fake_gerrit.addEvent(B.addApproval('Approved', 1))
+        self.fake_gerrit.addEvent(C.addApproval('Approved', 1))
 
         self.waitUntilSettled()
 
@@ -1374,9 +1374,9 @@
 
         A = self.fake_gerrit.addFakeChange('org/nonvoting-project',
                                            'master', 'A')
-        A.addApproval('code-review', 2)
+        A.addApproval('Code-Review', 2)
         self.executor_server.failJob('nonvoting-project-test2', A)
-        self.fake_gerrit.addEvent(A.addApproval('approved', 1))
+        self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
 
         self.waitUntilSettled()
 
@@ -1392,8 +1392,12 @@
             self.getJobFromHistory('nonvoting-project-test2').result,
             'FAILURE')
 
-        for build in self.builds:
-            self.assertEqual(build.parameters['ZUUL_VOTING'], '0')
+        self.assertTrue(self.getJobFromHistory('nonvoting-project-merge').
+                        parameters['zuul']['voting'])
+        self.assertTrue(self.getJobFromHistory('nonvoting-project-test1').
+                        parameters['zuul']['voting'])
+        self.assertFalse(self.getJobFromHistory('nonvoting-project-test2').
+                         parameters['zuul']['voting'])
 
     def test_check_queue_success(self):
         "Test successful check queue jobs."
@@ -1448,21 +1452,21 @@
         F = self.fake_gerrit.addFakeChange('org/project3', 'master', 'F')
         D.setDependsOn(C, 1)
         E.setDependsOn(D, 1)
-        A.addApproval('code-review', 2)
-        B.addApproval('code-review', 2)
-        C.addApproval('code-review', 2)
-        D.addApproval('code-review', 2)
-        E.addApproval('code-review', 2)
-        F.addApproval('code-review', 2)
+        A.addApproval('Code-Review', 2)
+        B.addApproval('Code-Review', 2)
+        C.addApproval('Code-Review', 2)
+        D.addApproval('Code-Review', 2)
+        E.addApproval('Code-Review', 2)
+        F.addApproval('Code-Review', 2)
 
         A.fail_merge = True
 
         # Change object re-use in the gerrit trigger is hidden if
         # changes are added in quick succession; waiting makes it more
         # like real life.
-        self.fake_gerrit.addEvent(A.addApproval('approved', 1))
+        self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
         self.waitUntilSettled()
-        self.fake_gerrit.addEvent(B.addApproval('approved', 1))
+        self.fake_gerrit.addEvent(B.addApproval('Approved', 1))
         self.waitUntilSettled()
 
         self.executor_server.release('.*-merge')
@@ -1470,13 +1474,13 @@
         self.executor_server.release('.*-merge')
         self.waitUntilSettled()
 
-        self.fake_gerrit.addEvent(C.addApproval('approved', 1))
+        self.fake_gerrit.addEvent(C.addApproval('Approved', 1))
         self.waitUntilSettled()
-        self.fake_gerrit.addEvent(D.addApproval('approved', 1))
+        self.fake_gerrit.addEvent(D.addApproval('Approved', 1))
         self.waitUntilSettled()
-        self.fake_gerrit.addEvent(E.addApproval('approved', 1))
+        self.fake_gerrit.addEvent(E.addApproval('Approved', 1))
         self.waitUntilSettled()
-        self.fake_gerrit.addEvent(F.addApproval('approved', 1))
+        self.fake_gerrit.addEvent(F.addApproval('Approved', 1))
         self.waitUntilSettled()
 
         self.executor_server.release('.*-merge')
@@ -1524,8 +1528,8 @@
         "Test that the merger works after a repack"
 
         A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
-        A.addApproval('code-review', 2)
-        self.fake_gerrit.addEvent(A.addApproval('approved', 1))
+        A.addApproval('Code-Review', 2)
+        self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
         self.waitUntilSettled()
         self.assertEqual(self.getJobFromHistory('project-merge').result,
                          'SUCCESS')
@@ -1548,8 +1552,8 @@
             repack_repo(path)
 
         A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
-        A.addApproval('code-review', 2)
-        self.fake_gerrit.addEvent(A.addApproval('approved', 1))
+        A.addApproval('Code-Review', 2)
+        self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
         self.waitUntilSettled()
         self.assertEqual(self.getJobFromHistory('project-merge').result,
                          'SUCCESS')
@@ -1583,8 +1587,8 @@
         if os.path.exists(path):
             repack_repo(path)
 
-        A.addApproval('code-review', 2)
-        self.fake_gerrit.addEvent(A.addApproval('approved', 1))
+        A.addApproval('Code-Review', 2)
+        self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
         self.waitUntilSettled()
         self.assertEqual(self.getJobFromHistory('project-merge').result,
                          'SUCCESS')
@@ -1606,19 +1610,19 @@
         B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
         C = self.fake_gerrit.addFakeChange('org/project', 'master', 'C')
         D = self.fake_gerrit.addFakeChange('org/project', 'master', 'D')
-        A.addApproval('code-review', 2)
-        B.addApproval('code-review', 2)
-        C.addApproval('code-review', 2)
-        D.addApproval('code-review', 2)
+        A.addApproval('Code-Review', 2)
+        B.addApproval('Code-Review', 2)
+        C.addApproval('Code-Review', 2)
+        D.addApproval('Code-Review', 2)
 
         C.setDependsOn(B, 1)
         B.setDependsOn(A, 1)
         A.setDependsOn(M, 1)
 
-        self.fake_gerrit.addEvent(A.addApproval('approved', 1))
-        self.fake_gerrit.addEvent(B.addApproval('approved', 1))
-        self.fake_gerrit.addEvent(C.addApproval('approved', 1))
-        self.fake_gerrit.addEvent(D.addApproval('approved', 1))
+        self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
+        self.fake_gerrit.addEvent(B.addApproval('Approved', 1))
+        self.fake_gerrit.addEvent(C.addApproval('Approved', 1))
+        self.fake_gerrit.addEvent(D.addApproval('Approved', 1))
         self.waitUntilSettled()
 
         B.addPatchset()
@@ -1741,8 +1745,8 @@
         self.executor_server.hold_jobs_in_build = True
 
         A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
-        A.addApproval('code-review', 2)
-        self.fake_gerrit.addEvent(A.addApproval('approved', 1))
+        A.addApproval('Code-Review', 2)
+        self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
         self.waitUntilSettled()
         self.assertEqual(len(self.builds), 1, "One job being built (on hold)")
         self.assertEqual(self.builds[0].name, 'project-merge')
@@ -1833,6 +1837,7 @@
         # Must be in same repo, so overwrite config with another one
         self.commitConfigUpdate('common-config', 'layouts/no-timer.yaml')
         self.sched.reconfigure(self.config)
+        self.waitUntilSettled()
 
         self.assertEqual(len(self.builds), 1, "One timer job")
 
@@ -1849,24 +1854,6 @@
         self.executor_server.release()
         self.waitUntilSettled()
 
-    def test_zuul_url_return(self):
-        "Test if ZUUL_URL is returning when zuul_url is set in zuul.conf"
-        self.assertTrue(self.sched.config.has_option('merger', 'zuul_url'))
-        self.executor_server.hold_jobs_in_build = True
-
-        A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
-        A.addApproval('code-review', 2)
-        self.fake_gerrit.addEvent(A.addApproval('approved', 1))
-        self.waitUntilSettled()
-
-        self.assertEqual(len(self.builds), 1)
-        for build in self.builds:
-            self.assertTrue('ZUUL_URL' in build.parameters)
-
-        self.executor_server.hold_jobs_in_build = False
-        self.executor_server.release()
-        self.waitUntilSettled()
-
     def test_new_patchset_dequeues_old_on_head(self):
         "Test that a new patchset causes the old to be dequeued (at head)"
         # D -> C (depends on B) -> B (depends on A) -> A -> M
@@ -1877,19 +1864,19 @@
         B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
         C = self.fake_gerrit.addFakeChange('org/project', 'master', 'C')
         D = self.fake_gerrit.addFakeChange('org/project', 'master', 'D')
-        A.addApproval('code-review', 2)
-        B.addApproval('code-review', 2)
-        C.addApproval('code-review', 2)
-        D.addApproval('code-review', 2)
+        A.addApproval('Code-Review', 2)
+        B.addApproval('Code-Review', 2)
+        C.addApproval('Code-Review', 2)
+        D.addApproval('Code-Review', 2)
 
         C.setDependsOn(B, 1)
         B.setDependsOn(A, 1)
         A.setDependsOn(M, 1)
 
-        self.fake_gerrit.addEvent(A.addApproval('approved', 1))
-        self.fake_gerrit.addEvent(B.addApproval('approved', 1))
-        self.fake_gerrit.addEvent(C.addApproval('approved', 1))
-        self.fake_gerrit.addEvent(D.addApproval('approved', 1))
+        self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
+        self.fake_gerrit.addEvent(B.addApproval('Approved', 1))
+        self.fake_gerrit.addEvent(C.addApproval('Approved', 1))
+        self.fake_gerrit.addEvent(D.addApproval('Approved', 1))
         self.waitUntilSettled()
 
         A.addPatchset()
@@ -1916,13 +1903,13 @@
         A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
         B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
         C = self.fake_gerrit.addFakeChange('org/project', 'master', 'C')
-        A.addApproval('code-review', 2)
-        B.addApproval('code-review', 2)
-        C.addApproval('code-review', 2)
+        A.addApproval('Code-Review', 2)
+        B.addApproval('Code-Review', 2)
+        C.addApproval('Code-Review', 2)
 
-        self.fake_gerrit.addEvent(C.addApproval('approved', 1))
-        self.fake_gerrit.addEvent(B.addApproval('approved', 1))
-        self.fake_gerrit.addEvent(A.addApproval('approved', 1))
+        self.fake_gerrit.addEvent(C.addApproval('Approved', 1))
+        self.fake_gerrit.addEvent(B.addApproval('Approved', 1))
+        self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
         self.waitUntilSettled()
 
         B.addPatchset()
@@ -1973,8 +1960,8 @@
     def test_noop_job(self):
         "Test that the internal noop job works"
         A = self.fake_gerrit.addFakeChange('org/noop-project', 'master', 'A')
-        A.addApproval('code-review', 2)
-        self.fake_gerrit.addEvent(A.addApproval('approved', 1))
+        A.addApproval('Code-Review', 2)
+        self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
         self.waitUntilSettled()
 
         self.assertEqual(len(self.gearman_server.getQueue()), 0)
@@ -2014,14 +2001,14 @@
         B = self.fake_gerrit.addFakeChange('org/project1', 'master', 'B')
         C = self.fake_gerrit.addFakeChange('org/project2', 'master', 'C')
         D = self.fake_gerrit.addFakeChange('org/project2', 'master', 'D')
-        A.addApproval('code-review', 2)
-        B.addApproval('code-review', 2)
-        C.addApproval('code-review', 2)
-        D.addApproval('code-review', 2)
-        self.fake_gerrit.addEvent(A.addApproval('approved', 1))
-        self.fake_gerrit.addEvent(B.addApproval('approved', 1))
-        self.fake_gerrit.addEvent(C.addApproval('approved', 1))
-        self.fake_gerrit.addEvent(D.addApproval('approved', 1))
+        A.addApproval('Code-Review', 2)
+        B.addApproval('Code-Review', 2)
+        C.addApproval('Code-Review', 2)
+        D.addApproval('Code-Review', 2)
+        self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
+        self.fake_gerrit.addEvent(B.addApproval('Approved', 1))
+        self.fake_gerrit.addEvent(C.addApproval('Approved', 1))
+        self.fake_gerrit.addEvent(D.addApproval('Approved', 1))
 
         self.waitUntilSettled()
         self.executor_server.release('.*-merge')
@@ -2033,34 +2020,19 @@
         self.executor_server.release('.*-merge')
         self.waitUntilSettled()
 
-        a_zref = b_zref = c_zref = d_zref = None
         a_build = b_build = c_build = d_build = None
         for x in self.builds:
-            if x.parameters['ZUUL_CHANGE'] == '3':
-                a_zref = x.parameters['ZUUL_REF']
+            if x.parameters['zuul']['change'] == '3':
                 a_build = x
-            elif x.parameters['ZUUL_CHANGE'] == '4':
-                b_zref = x.parameters['ZUUL_REF']
+            elif x.parameters['zuul']['change'] == '4':
                 b_build = x
-            elif x.parameters['ZUUL_CHANGE'] == '5':
-                c_zref = x.parameters['ZUUL_REF']
+            elif x.parameters['zuul']['change'] == '5':
                 c_build = x
-            elif x.parameters['ZUUL_CHANGE'] == '6':
-                d_zref = x.parameters['ZUUL_REF']
+            elif x.parameters['zuul']['change'] == '6':
                 d_build = x
             if a_build and b_build and c_build and d_build:
                 break
 
-        # There are... four... refs.
-        self.assertIsNotNone(a_zref)
-        self.assertIsNotNone(b_zref)
-        self.assertIsNotNone(c_zref)
-        self.assertIsNotNone(d_zref)
-
-        # And they should all be different
-        refs = set([a_zref, b_zref, c_zref, d_zref])
-        self.assertEqual(len(refs), 4)
-
         # should have a, not b, and should not be in project2
         self.assertTrue(a_build.hasChanges(A))
         self.assertFalse(a_build.hasChanges(B, M2))
@@ -2093,8 +2065,8 @@
         "Test that if a worker fails to run a job, it is run again"
         self.executor_server.hold_jobs_in_build = True
         A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
-        A.addApproval('code-review', 2)
-        self.fake_gerrit.addEvent(A.addApproval('approved', 1))
+        A.addApproval('Code-Review', 2)
+        self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
         self.waitUntilSettled()
 
         self.builds[0].requeue = True
@@ -2121,8 +2093,8 @@
         # We want to hold the project-merge job that the fake change enqueues
         self.gearman_server.hold_jobs_in_queue = True
         A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
-        A.addApproval('code-review', 2)
-        self.fake_gerrit.addEvent(A.addApproval('approved', 1))
+        A.addApproval('Code-Review', 2)
+        self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
         self.waitUntilSettled()
         # The assertion is that we have one job in the queue, project-merge
         self.assertEqual(len(self.gearman_server.getQueue()), 1)
@@ -2170,10 +2142,10 @@
         A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
         A.addPatchset({'pip-requires': 'foo'})
         B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
-        A.addApproval('code-review', 2)
-        B.addApproval('code-review', 2)
-        self.fake_gerrit.addEvent(A.addApproval('approved', 1))
-        self.fake_gerrit.addEvent(B.addApproval('approved', 1))
+        A.addApproval('Code-Review', 2)
+        B.addApproval('Code-Review', 2)
+        self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
+        self.fake_gerrit.addEvent(B.addApproval('Approved', 1))
         self.waitUntilSettled()
 
         testfile_jobs = [x for x in self.history
@@ -2249,8 +2221,8 @@
         self.executor_server.hold_jobs_in_build = True
         A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
         self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
-        A.addApproval('code-review', 2)
-        self.fake_gerrit.addEvent(A.addApproval('approved', 1))
+        A.addApproval('Code-Review', 2)
+        self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
 
         self.waitUntilSettled()
         self.gearman_server.hold_jobs_in_queue = False
@@ -2274,8 +2246,8 @@
         "Test that we can retrieve JSON status info"
         self.executor_server.hold_jobs_in_build = True
         A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
-        A.addApproval('code-review', 2)
-        self.fake_gerrit.addEvent(A.addApproval('approved', 1))
+        A.addApproval('Code-Review', 2)
+        self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
         self.waitUntilSettled()
 
         self.executor_server.release('project-merge')
@@ -2378,8 +2350,8 @@
         "Test that live reconfiguration works"
         self.executor_server.hold_jobs_in_build = True
         A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
-        A.addApproval('code-review', 2)
-        self.fake_gerrit.addEvent(A.addApproval('approved', 1))
+        A.addApproval('Code-Review', 2)
+        self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
         self.waitUntilSettled()
 
         self.sched.reconfigure(self.config)
@@ -2410,17 +2382,17 @@
         # next change.  This change will succeed and merge.
         A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
         A.addPatchset({'conflict': 'A'})
-        A.addApproval('code-review', 2)
+        A.addApproval('Code-Review', 2)
 
         # This change will be in merge conflict.  During the
         # reconfiguration, we will add a job.  We want to make sure
         # that doesn't cause it to get stuck.
         B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
         B.addPatchset({'conflict': 'B'})
-        B.addApproval('code-review', 2)
+        B.addApproval('Code-Review', 2)
 
-        self.fake_gerrit.addEvent(A.addApproval('approved', 1))
-        self.fake_gerrit.addEvent(B.addApproval('approved', 1))
+        self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
+        self.fake_gerrit.addEvent(B.addApproval('Approved', 1))
 
         self.waitUntilSettled()
 
@@ -2465,16 +2437,16 @@
         # reconfiguration.  This change will succeed and merge.
         A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
         A.addPatchset({'conflict': 'A'})
-        A.addApproval('code-review', 2)
-        self.fake_gerrit.addEvent(A.addApproval('approved', 1))
+        A.addApproval('Code-Review', 2)
+        self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
         self.waitUntilSettled()
         self.executor_server.release('.*-merge')
         self.waitUntilSettled()
 
         B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
         self.executor_server.failJob('project-merge', B)
-        B.addApproval('code-review', 2)
-        self.fake_gerrit.addEvent(B.addApproval('approved', 1))
+        B.addApproval('Code-Review', 2)
+        self.fake_gerrit.addEvent(B.addApproval('Approved', 1))
         self.waitUntilSettled()
 
         self.executor_server.release('.*-merge')
@@ -2633,11 +2605,11 @@
         A = self.fake_gerrit.addFakeChange('org/project1', 'master', 'A')
         B = self.fake_gerrit.addFakeChange('org/project1', 'master', 'B')
         B.setDependsOn(A, 1)
-        A.addApproval('code-review', 2)
-        B.addApproval('code-review', 2)
+        A.addApproval('Code-Review', 2)
+        B.addApproval('Code-Review', 2)
 
         # Add the parent change.
-        self.fake_gerrit.addEvent(A.addApproval('approved', 1))
+        self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
         self.waitUntilSettled()
         self.executor_server.release('.*-merge')
         self.waitUntilSettled()
@@ -2647,7 +2619,7 @@
         self.waitUntilSettled()
 
         # Add the child change.
-        self.fake_gerrit.addEvent(B.addApproval('approved', 1))
+        self.fake_gerrit.addEvent(B.addApproval('Approved', 1))
         self.waitUntilSettled()
         self.executor_server.release('.*-merge')
         self.waitUntilSettled()
@@ -2679,7 +2651,7 @@
         # A Depends-On: B
         A.data['commitMessage'] = '%s\n\nDepends-On: %s\n' % (
             A.subject, B.data['id'])
-        self.fake_gerrit.addEvent(B.addApproval('approved', 1))
+        self.fake_gerrit.addEvent(B.addApproval('Approved', 1))
 
         self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
         self.fake_gerrit.addEvent(C.getPatchsetCreatedEvent(1))
@@ -2729,8 +2701,8 @@
         self.init_repo("org/new-project")
         A = self.fake_gerrit.addFakeChange('org/new-project', 'master', 'A')
 
-        A.addApproval('code-review', 2)
-        self.fake_gerrit.addEvent(A.addApproval('approved', 1))
+        A.addApproval('Code-Review', 2)
+        self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
         self.waitUntilSettled()
         self.assertEqual(self.getJobFromHistory('project-merge').result,
                          'SUCCESS')
@@ -2746,8 +2718,8 @@
         self.init_repo("org/delete-project")
         A = self.fake_gerrit.addFakeChange('org/delete-project', 'master', 'A')
 
-        A.addApproval('code-review', 2)
-        self.fake_gerrit.addEvent(A.addApproval('approved', 1))
+        A.addApproval('Code-Review', 2)
+        self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
         self.waitUntilSettled()
         self.assertEqual(self.getJobFromHistory('project-merge').result,
                          'SUCCESS')
@@ -2767,8 +2739,8 @@
 
         B = self.fake_gerrit.addFakeChange('org/delete-project', 'master', 'B')
 
-        B.addApproval('code-review', 2)
-        self.fake_gerrit.addEvent(B.addApproval('approved', 1))
+        B.addApproval('Code-Review', 2)
+        self.fake_gerrit.addEvent(B.addApproval('Approved', 1))
         self.waitUntilSettled()
         self.assertEqual(self.getJobFromHistory('project-merge').result,
                          'SUCCESS')
@@ -3004,8 +2976,8 @@
     def test_client_enqueue_change(self):
         "Test that the RPC client can enqueue a change"
         A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
-        A.addApproval('code-review', 2)
-        A.addApproval('approved', 1)
+        A.addApproval('Code-Review', 2)
+        A.addApproval('Approved', 1)
 
         client = zuul.rpcclient.RPCClient('127.0.0.1',
                                           self.gearman_server.port)
@@ -3106,13 +3078,13 @@
         A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
         B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
         C = self.fake_gerrit.addFakeChange('org/project', 'master', 'C')
-        A.addApproval('code-review', 2)
-        B.addApproval('code-review', 2)
-        C.addApproval('code-review', 2)
+        A.addApproval('Code-Review', 2)
+        B.addApproval('Code-Review', 2)
+        C.addApproval('Code-Review', 2)
 
-        self.fake_gerrit.addEvent(A.addApproval('approved', 1))
-        self.fake_gerrit.addEvent(B.addApproval('approved', 1))
-        self.fake_gerrit.addEvent(C.addApproval('approved', 1))
+        self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
+        self.fake_gerrit.addEvent(B.addApproval('Approved', 1))
+        self.fake_gerrit.addEvent(C.addApproval('Approved', 1))
 
         self.waitUntilSettled()
 
@@ -3186,13 +3158,13 @@
 
         C.setDependsOn(B, 1)
 
-        A.addApproval('code-review', 2)
-        B.addApproval('code-review', 2)
-        C.addApproval('code-review', 2)
+        A.addApproval('Code-Review', 2)
+        B.addApproval('Code-Review', 2)
+        C.addApproval('Code-Review', 2)
 
-        self.fake_gerrit.addEvent(A.addApproval('approved', 1))
-        self.fake_gerrit.addEvent(B.addApproval('approved', 1))
-        self.fake_gerrit.addEvent(C.addApproval('approved', 1))
+        self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
+        self.fake_gerrit.addEvent(B.addApproval('Approved', 1))
+        self.fake_gerrit.addEvent(C.addApproval('Approved', 1))
 
         self.waitUntilSettled()
 
@@ -3247,8 +3219,8 @@
         "Test that the RPC client returns errors for promotion"
         self.executor_server.hold_jobs_in_build = True
         A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
-        A.addApproval('code-review', 2)
-        self.fake_gerrit.addEvent(A.addApproval('approved', 1))
+        A.addApproval('Code-Review', 2)
+        self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
         self.waitUntilSettled()
 
         client = zuul.rpcclient.RPCClient('127.0.0.1',
@@ -3282,13 +3254,13 @@
         C.setDependsOn(B, 1)
         self.executor_server.failJob('project-test1', A)
 
-        A.addApproval('code-review', 2)
-        B.addApproval('code-review', 2)
-        C.addApproval('code-review', 2)
+        A.addApproval('Code-Review', 2)
+        B.addApproval('Code-Review', 2)
+        C.addApproval('Code-Review', 2)
 
-        self.fake_gerrit.addEvent(A.addApproval('approved', 1))
-        self.fake_gerrit.addEvent(B.addApproval('approved', 1))
-        self.fake_gerrit.addEvent(C.addApproval('approved', 1))
+        self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
+        self.fake_gerrit.addEvent(B.addApproval('Approved', 1))
+        self.fake_gerrit.addEvent(C.addApproval('Approved', 1))
         self.waitUntilSettled()
 
         # Only A and B will have their merge jobs queued because
@@ -3374,13 +3346,13 @@
 
         self.executor_server.failJob('project-test1', A)
 
-        A.addApproval('code-review', 2)
-        B.addApproval('code-review', 2)
-        C.addApproval('code-review', 2)
+        A.addApproval('Code-Review', 2)
+        B.addApproval('Code-Review', 2)
+        C.addApproval('Code-Review', 2)
 
-        self.fake_gerrit.addEvent(A.addApproval('approved', 1))
-        self.fake_gerrit.addEvent(B.addApproval('approved', 1))
-        self.fake_gerrit.addEvent(C.addApproval('approved', 1))
+        self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
+        self.fake_gerrit.addEvent(B.addApproval('Approved', 1))
+        self.fake_gerrit.addEvent(C.addApproval('Approved', 1))
         self.waitUntilSettled()
 
         # Only A and B will have their merge jobs queued because
@@ -3436,8 +3408,8 @@
         self.executor_server.hold_jobs_in_build = True
 
         A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
-        A.addApproval('code-review', 2)
-        self.fake_gerrit.addEvent(A.addApproval('approved', 1))
+        A.addApproval('Code-Review', 2)
+        self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
         self.waitUntilSettled()
 
         self.assertEqual(len(self.executor_client.builds), 1)
@@ -3467,14 +3439,14 @@
     def test_footer_message(self):
         "Test a pipeline's footer message is correctly added to the report."
         A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
-        A.addApproval('code-review', 2)
+        A.addApproval('Code-Review', 2)
         self.executor_server.failJob('project-test1', A)
-        self.fake_gerrit.addEvent(A.addApproval('approved', 1))
+        self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
         self.waitUntilSettled()
 
         B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
-        B.addApproval('code-review', 2)
-        self.fake_gerrit.addEvent(B.addApproval('approved', 1))
+        B.addApproval('Code-Review', 2)
+        self.fake_gerrit.addEvent(B.addApproval('Approved', 1))
         self.waitUntilSettled()
 
         self.assertEqual(2, len(self.smtp_messages))
@@ -3554,9 +3526,9 @@
 
         # Check a test failure isn't reported to SMTP
         A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
-        A.addApproval('code-review', 2)
+        A.addApproval('Code-Review', 2)
         self.executor_server.failJob('project-test1', A)
-        self.fake_gerrit.addEvent(A.addApproval('approved', 1))
+        self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
         self.waitUntilSettled()
 
         self.assertEqual(3, len(self.history))  # 3 jobs
@@ -3568,10 +3540,10 @@
         B.addPatchset(['conflict'])
         C = self.fake_gerrit.addFakeChange('org/project', 'master', 'C')
         C.addPatchset(['conflict'])
-        B.addApproval('code-review', 2)
-        C.addApproval('code-review', 2)
-        self.fake_gerrit.addEvent(B.addApproval('approved', 1))
-        self.fake_gerrit.addEvent(C.addApproval('approved', 1))
+        B.addApproval('Code-Review', 2)
+        C.addApproval('Code-Review', 2)
+        self.fake_gerrit.addEvent(B.addApproval('Approved', 1))
+        self.fake_gerrit.addEvent(C.addApproval('Approved', 1))
         self.waitUntilSettled()
 
         self.assertEqual(6, len(self.history))  # A and B jobs
@@ -3588,10 +3560,10 @@
         A.addPatchset(['conflict'])
         B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
         B.addPatchset(['conflict'])
-        A.addApproval('code-review', 2)
-        B.addApproval('code-review', 2)
-        self.fake_gerrit.addEvent(A.addApproval('approved', 1))
-        self.fake_gerrit.addEvent(B.addApproval('approved', 1))
+        A.addApproval('Code-Review', 2)
+        B.addApproval('Code-Review', 2)
+        self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
+        self.fake_gerrit.addEvent(B.addApproval('Approved', 1))
         self.waitUntilSettled()
 
         self.assertEqual(3, len(self.history))  # A jobs
@@ -3609,8 +3581,8 @@
         "Test that the RPC client can get a list of running jobs"
         self.executor_server.hold_jobs_in_build = True
         A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
-        A.addApproval('code-review', 2)
-        self.fake_gerrit.addEvent(A.addApproval('approved', 1))
+        A.addApproval('Code-Review', 2)
+        self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
         self.waitUntilSettled()
 
         client = zuul.rpcclient.RPCClient('127.0.0.1',
@@ -3690,8 +3662,8 @@
         "Test cross-repo dependencies"
         A = self.fake_gerrit.addFakeChange('org/project1', 'master', 'A')
         B = self.fake_gerrit.addFakeChange('org/project2', 'master', 'B')
-        A.addApproval('code-review', 2)
-        B.addApproval('code-review', 2)
+        A.addApproval('Code-Review', 2)
+        B.addApproval('Code-Review', 2)
 
         AM2 = self.fake_gerrit.addFakeChange('org/project1', 'master', 'AM2')
         AM1 = self.fake_gerrit.addFakeChange('org/project1', 'master', 'AM1')
@@ -3719,7 +3691,7 @@
         A.data['commitMessage'] = '%s\n\nDepends-On: %s\n' % (
             A.subject, B.data['id'])
 
-        self.fake_gerrit.addEvent(A.addApproval('approved', 1))
+        self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
         self.waitUntilSettled()
 
         self.assertEqual(A.data['status'], 'NEW')
@@ -3729,8 +3701,8 @@
             connection.maintainCache([])
 
         self.executor_server.hold_jobs_in_build = True
-        B.addApproval('approved', 1)
-        self.fake_gerrit.addEvent(A.addApproval('approved', 1))
+        B.addApproval('Approved', 1)
+        self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
         self.waitUntilSettled()
 
         self.executor_server.release('.*-merge')
@@ -3760,18 +3732,18 @@
         B = self.fake_gerrit.addFakeChange('org/project2', 'master', 'B')
         C = self.fake_gerrit.addFakeChange('org/project2', 'mp', 'C')
         C.data['id'] = B.data['id']
-        A.addApproval('code-review', 2)
-        B.addApproval('code-review', 2)
-        C.addApproval('code-review', 2)
+        A.addApproval('Code-Review', 2)
+        B.addApproval('Code-Review', 2)
+        C.addApproval('Code-Review', 2)
 
         # A Depends-On: B+C
         A.data['commitMessage'] = '%s\n\nDepends-On: %s\n' % (
             A.subject, B.data['id'])
 
         self.executor_server.hold_jobs_in_build = True
-        B.addApproval('approved', 1)
-        C.addApproval('approved', 1)
-        self.fake_gerrit.addEvent(A.addApproval('approved', 1))
+        B.addApproval('Approved', 1)
+        C.addApproval('Approved', 1)
+        self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
         self.waitUntilSettled()
 
         self.executor_server.release('.*-merge')
@@ -3800,18 +3772,18 @@
         A = self.fake_gerrit.addFakeChange('org/project1', 'master', 'A')
         B = self.fake_gerrit.addFakeChange('org/project2', 'master', 'B')
         C = self.fake_gerrit.addFakeChange('org/project2', 'master', 'C')
-        A.addApproval('code-review', 2)
-        B.addApproval('code-review', 2)
-        C.addApproval('code-review', 2)
+        A.addApproval('Code-Review', 2)
+        B.addApproval('Code-Review', 2)
+        C.addApproval('Code-Review', 2)
 
         # A Depends-On: B+C
         A.data['commitMessage'] = '%s\n\nDepends-On: %s\nDepends-On: %s\n' % (
             A.subject, B.data['id'], C.data['id'])
 
         self.executor_server.hold_jobs_in_build = True
-        B.addApproval('approved', 1)
-        C.addApproval('approved', 1)
-        self.fake_gerrit.addEvent(A.addApproval('approved', 1))
+        B.addApproval('Approved', 1)
+        C.addApproval('Approved', 1)
+        self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
         self.waitUntilSettled()
 
         self.executor_server.release('.*-merge')
@@ -3839,8 +3811,8 @@
         "Test cross-repo dependencies in unshared gate queues"
         A = self.fake_gerrit.addFakeChange('org/project1', 'master', 'A')
         B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
-        A.addApproval('code-review', 2)
-        B.addApproval('code-review', 2)
+        A.addApproval('Code-Review', 2)
+        B.addApproval('Code-Review', 2)
 
         # A Depends-On: B
         A.data['commitMessage'] = '%s\n\nDepends-On: %s\n' % (
@@ -3848,8 +3820,8 @@
 
         # A and B do not share a queue, make sure that A is unable to
         # enqueue B (and therefore, A is unable to be enqueued).
-        B.addApproval('approved', 1)
-        self.fake_gerrit.addEvent(A.addApproval('approved', 1))
+        B.addApproval('Approved', 1)
+        self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
         self.waitUntilSettled()
 
         self.assertEqual(A.data['status'], 'NEW')
@@ -3859,7 +3831,7 @@
         self.assertEqual(len(self.history), 0)
 
         # Enqueue and merge B alone.
-        self.fake_gerrit.addEvent(B.addApproval('approved', 1))
+        self.fake_gerrit.addEvent(B.addApproval('Approved', 1))
         self.waitUntilSettled()
 
         self.assertEqual(B.data['status'], 'MERGED')
@@ -3867,7 +3839,7 @@
 
         # Now that B is merged, A should be able to be enqueued and
         # merged.
-        self.fake_gerrit.addEvent(A.addApproval('approved', 1))
+        self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
         self.waitUntilSettled()
 
         self.assertEqual(A.data['status'], 'MERGED')
@@ -3877,23 +3849,23 @@
         "Test reverse cross-repo dependencies"
         A = self.fake_gerrit.addFakeChange('org/project1', 'master', 'A')
         B = self.fake_gerrit.addFakeChange('org/project2', 'master', 'B')
-        A.addApproval('code-review', 2)
-        B.addApproval('code-review', 2)
+        A.addApproval('Code-Review', 2)
+        B.addApproval('Code-Review', 2)
 
         # A Depends-On: B
 
         A.data['commitMessage'] = '%s\n\nDepends-On: %s\n' % (
             A.subject, B.data['id'])
 
-        self.fake_gerrit.addEvent(A.addApproval('approved', 1))
+        self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
         self.waitUntilSettled()
 
         self.assertEqual(A.data['status'], 'NEW')
         self.assertEqual(B.data['status'], 'NEW')
 
         self.executor_server.hold_jobs_in_build = True
-        A.addApproval('approved', 1)
-        self.fake_gerrit.addEvent(B.addApproval('approved', 1))
+        A.addApproval('Approved', 1)
+        self.fake_gerrit.addEvent(B.addApproval('Approved', 1))
         self.waitUntilSettled()
 
         self.executor_server.release('.*-merge')
@@ -3917,8 +3889,8 @@
         "Test cross-repo dependency cycles"
         A = self.fake_gerrit.addFakeChange('org/project1', 'master', 'A')
         B = self.fake_gerrit.addFakeChange('org/project2', 'master', 'B')
-        A.addApproval('code-review', 2)
-        B.addApproval('code-review', 2)
+        A.addApproval('Code-Review', 2)
+        B.addApproval('Code-Review', 2)
 
         # A -> B -> A (via commit-depends)
 
@@ -3927,7 +3899,7 @@
         B.data['commitMessage'] = '%s\n\nDepends-On: %s\n' % (
             B.subject, A.data['id'])
 
-        self.fake_gerrit.addEvent(A.addApproval('approved', 1))
+        self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
         self.waitUntilSettled()
 
         self.assertEqual(A.reported, 0)
@@ -3940,15 +3912,15 @@
         self.init_repo("org/unknown", tag='init')
         A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
         B = self.fake_gerrit.addFakeChange('org/unknown', 'master', 'B')
-        A.addApproval('code-review', 2)
-        B.addApproval('code-review', 2)
+        A.addApproval('Code-Review', 2)
+        B.addApproval('Code-Review', 2)
 
         # A Depends-On: B
         A.data['commitMessage'] = '%s\n\nDepends-On: %s\n' % (
             A.subject, B.data['id'])
 
-        B.addApproval('approved', 1)
-        self.fake_gerrit.addEvent(A.addApproval('approved', 1))
+        B.addApproval('Approved', 1)
+        self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
         self.waitUntilSettled()
 
         # Unknown projects cannot share a queue with any other
@@ -3966,13 +3938,13 @@
         # event triggers a gerrit query to update the change, we get
         # the information that it was merged.
         B.setMerged()
-        self.fake_gerrit.addEvent(B.addApproval('approved', 1))
+        self.fake_gerrit.addEvent(B.addApproval('Approved', 1))
         self.waitUntilSettled()
         self.assertEqual(len(self.history), 0)
 
         # Now that B is merged, A should be able to be enqueued and
         # merged.
-        self.fake_gerrit.addEvent(A.addApproval('approved', 1))
+        self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
         self.waitUntilSettled()
 
         self.assertEqual(A.data['status'], 'MERGED')
@@ -4419,10 +4391,10 @@
                                            'master', 'A')
         B = self.fake_gerrit.addFakeChange('org/one-job-project',
                                            'master', 'B')
-        A.addApproval('code-review', 2)
-        B.addApproval('code-review', 2)
-        self.fake_gerrit.addEvent(A.addApproval('approved', 1))
-        self.fake_gerrit.addEvent(B.addApproval('approved', 1))
+        A.addApproval('Code-Review', 2)
+        B.addApproval('Code-Review', 2)
+        self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
+        self.fake_gerrit.addEvent(B.addApproval('Approved', 1))
         self.waitUntilSettled()
 
         self.assertEqual(A.data['status'], 'MERGED')
@@ -4466,8 +4438,8 @@
 
         self.fake_nodepool.paused = True
         A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
-        A.addApproval('code-review', 2)
-        self.fake_gerrit.addEvent(A.addApproval('approved', 1))
+        A.addApproval('Code-Review', 2)
+        self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
         self.waitUntilSettled()
 
         self.zk.client.stop()
@@ -4483,8 +4455,8 @@
 
         self.fake_nodepool.paused = True
         A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
-        A.addApproval('code-review', 2)
-        self.fake_gerrit.addEvent(A.addApproval('approved', 1))
+        A.addApproval('Code-Review', 2)
+        self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
         self.waitUntilSettled()
 
         req = self.fake_nodepool.getNodeRequests()[0]
@@ -4528,8 +4500,8 @@
 
         self.executor_server.hold_jobs_in_build = True
         A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
-        A.addApproval('code-review', 2)
-        self.fake_gerrit.addEvent(A.addApproval('approved', 1))
+        A.addApproval('Code-Review', 2)
+        self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
         self.waitUntilSettled()
 
 
@@ -4550,8 +4522,8 @@
         self.executor_server.hold_jobs_in_build = True
         change = self.fake_gerrit.addFakeChange(
             'org/project', 'master', 'change')
-        change.addApproval('code-review', 2)
-        self.fake_gerrit.addEvent(change.addApproval('approved', 1))
+        change.addApproval('Code-Review', 2)
+        self.fake_gerrit.addEvent(change.addApproval('Approved', 1))
 
         self.waitUntilSettled()
         self.assertEqual([b.name for b in self.builds], ['A'])
@@ -4608,11 +4580,11 @@
         self.executor_server.hold_jobs_in_build = True
         change = self.fake_gerrit.addFakeChange(
             'org/project', 'master', 'change')
-        change.addApproval('code-review', 2)
+        change.addApproval('Code-Review', 2)
 
         self.executor_server.failJob('C', change)
 
-        self.fake_gerrit.addEvent(change.addApproval('approved', 1))
+        self.fake_gerrit.addEvent(change.addApproval('Approved', 1))
 
         self.waitUntilSettled()
         self.assertEqual([b.name for b in self.builds], ['A'])
@@ -4767,21 +4739,19 @@
         A = self.fake_gerrit.addFakeChange(project, 'master', 'A')
         B = self.fake_gerrit.addFakeChange(project, 'master', 'B')
         C = self.fake_gerrit.addFakeChange(project, 'master', 'C')
-        A.addApproval('code-review', 2)
-        B.addApproval('code-review', 2)
-        C.addApproval('code-review', 2)
-        self.fake_gerrit.addEvent(A.addApproval('approved', 1))
-        self.fake_gerrit.addEvent(B.addApproval('approved', 1))
-        self.fake_gerrit.addEvent(C.addApproval('approved', 1))
+        A.addApproval('Code-Review', 2)
+        B.addApproval('Code-Review', 2)
+        C.addApproval('Code-Review', 2)
+        self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
+        self.fake_gerrit.addEvent(B.addApproval('Approved', 1))
+        self.fake_gerrit.addEvent(C.addApproval('Approved', 1))
         self.waitUntilSettled()
 
         build = self.builds[-1]
-        ref = self.getParameter(build, 'ZUUL_REF')
-
         path = os.path.join(build.jobdir.src_root, 'review.example.com',
                             project)
         repo = git.Repo(path)
-        repo_messages = [c.message.strip() for c in repo.iter_commits(ref)]
+        repo_messages = [c.message.strip() for c in repo.iter_commits()]
         repo_messages.reverse()
 
         self.executor_server.hold_jobs_in_build = False
@@ -4831,12 +4801,12 @@
             'org/project-merge-branches', 'mp', 'B')
         C = self.fake_gerrit.addFakeChange(
             'org/project-merge-branches', 'mp', 'C')
-        A.addApproval('code-review', 2)
-        B.addApproval('code-review', 2)
-        C.addApproval('code-review', 2)
-        self.fake_gerrit.addEvent(A.addApproval('approved', 1))
-        self.fake_gerrit.addEvent(B.addApproval('approved', 1))
-        self.fake_gerrit.addEvent(C.addApproval('approved', 1))
+        A.addApproval('Code-Review', 2)
+        B.addApproval('Code-Review', 2)
+        C.addApproval('Code-Review', 2)
+        self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
+        self.fake_gerrit.addEvent(B.addApproval('Approved', 1))
+        self.fake_gerrit.addEvent(C.addApproval('Approved', 1))
         self.waitUntilSettled()
 
         self.executor_server.release('.*-merge')
@@ -4847,13 +4817,12 @@
         self.waitUntilSettled()
 
         build = self.builds[-1]
-        self.assertEqual(self.getParameter(build, 'ZUUL_BRANCH'), 'mp')
-        ref = self.getParameter(build, 'ZUUL_REF')
+        self.assertEqual(build.parameters['zuul']['branch'], 'mp')
         path = os.path.join(build.jobdir.src_root, 'review.example.com',
                             'org/project-merge-branches')
         repo = git.Repo(path)
 
-        repo_messages = [c.message.strip() for c in repo.iter_commits(ref)]
+        repo_messages = [c.message.strip() for c in repo.iter_commits()]
         repo_messages.reverse()
         correct_messages = [
             'initial commit',
@@ -4877,28 +4846,24 @@
             'org/project-merge-branches', 'mp', 'B')
         C = self.fake_gerrit.addFakeChange(
             'org/project-merge-branches', 'master', 'C')
-        A.addApproval('code-review', 2)
-        B.addApproval('code-review', 2)
-        C.addApproval('code-review', 2)
-        self.fake_gerrit.addEvent(A.addApproval('approved', 1))
-        self.fake_gerrit.addEvent(B.addApproval('approved', 1))
-        self.fake_gerrit.addEvent(C.addApproval('approved', 1))
+        A.addApproval('Code-Review', 2)
+        B.addApproval('Code-Review', 2)
+        C.addApproval('Code-Review', 2)
+        self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
+        self.fake_gerrit.addEvent(B.addApproval('Approved', 1))
+        self.fake_gerrit.addEvent(C.addApproval('Approved', 1))
         self.waitUntilSettled()
 
         job_A = None
         for job in self.builds:
             if 'project-merge' in job.name:
                 job_A = job
-        ref_A = self.getParameter(job_A, 'ZUUL_REF')
-        commit_A = self.getParameter(job_A, 'ZUUL_COMMIT')
-        self.log.debug("Got Zuul ref for change A: %s" % ref_A)
-        self.log.debug("Got Zuul commit for change A: %s" % commit_A)
 
         path = os.path.join(job_A.jobdir.src_root, 'review.example.com',
                             'org/project-merge-branches')
         repo = git.Repo(path)
         repo_messages = [c.message.strip()
-                         for c in repo.iter_commits(ref_A)]
+                         for c in repo.iter_commits()]
         repo_messages.reverse()
         correct_messages = [
             'initial commit', 'add content from fixture', 'A-1']
@@ -4911,16 +4876,11 @@
         for job in self.builds:
             if 'project-merge' in job.name:
                 job_B = job
-        ref_B = self.getParameter(job_B, 'ZUUL_REF')
-        commit_B = self.getParameter(job_B, 'ZUUL_COMMIT')
-        self.log.debug("Got Zuul ref for change B: %s" % ref_B)
-        self.log.debug("Got Zuul commit for change B: %s" % commit_B)
 
         path = os.path.join(job_B.jobdir.src_root, 'review.example.com',
                             'org/project-merge-branches')
         repo = git.Repo(path)
-        repo_messages = [c.message.strip()
-                         for c in repo.iter_commits(ref_B)]
+        repo_messages = [c.message.strip() for c in repo.iter_commits()]
         repo_messages.reverse()
         correct_messages = [
             'initial commit', 'add content from fixture', 'mp commit', 'B-1']
@@ -4933,15 +4893,11 @@
         for job in self.builds:
             if 'project-merge' in job.name:
                 job_C = job
-        ref_C = self.getParameter(job_C, 'ZUUL_REF')
-        commit_C = self.getParameter(job_C, 'ZUUL_COMMIT')
-        self.log.debug("Got Zuul ref for change C: %s" % ref_C)
-        self.log.debug("Got Zuul commit for change C: %s" % commit_C)
+
         path = os.path.join(job_C.jobdir.src_root, 'review.example.com',
                             'org/project-merge-branches')
         repo = git.Repo(path)
-        repo_messages = [c.message.strip()
-                         for c in repo.iter_commits(ref_C)]
+        repo_messages = [c.message.strip() for c in repo.iter_commits()]
 
         repo_messages.reverse()
         correct_messages = [
@@ -5337,6 +5293,7 @@
 
 
 class TestSemaphoreInRepo(ZuulTestCase):
+    config_file = 'zuul-connections-gerrit-and-github.conf'
     tenant_config_file = 'config/in-repo/main.yaml'
 
     def test_semaphore_in_repo(self):
@@ -5384,12 +5341,12 @@
 
         self.executor_server.hold_jobs_in_build = True
 
-        A.addApproval('code-review', 2)
-        B.addApproval('code-review', 2)
-        C.addApproval('code-review', 2)
-        self.fake_gerrit.addEvent(A.addApproval('approved', 1))
-        self.fake_gerrit.addEvent(B.addApproval('approved', 1))
-        self.fake_gerrit.addEvent(C.addApproval('approved', 1))
+        A.addApproval('Code-Review', 2)
+        B.addApproval('Code-Review', 2)
+        C.addApproval('Code-Review', 2)
+        self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
+        self.fake_gerrit.addEvent(B.addApproval('Approved', 1))
+        self.fake_gerrit.addEvent(C.addApproval('Approved', 1))
         self.waitUntilSettled()
 
         # check that the layout in a queue item still has max value of 1
diff --git a/tests/unit/test_v3.py b/tests/unit/test_v3.py
index 3e0dc15..2d68089 100644
--- a/tests/unit/test_v3.py
+++ b/tests/unit/test_v3.py
@@ -31,8 +31,8 @@
 
     def test_multiple_tenants(self):
         A = self.fake_gerrit.addFakeChange('org/project1', 'master', 'A')
-        A.addApproval('code-review', 2)
-        self.fake_gerrit.addEvent(A.addApproval('approved', 1))
+        A.addApproval('Code-Review', 2)
+        self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
         self.waitUntilSettled()
         self.assertEqual(self.getJobFromHistory('project1-test1').result,
                          'SUCCESS')
@@ -47,8 +47,8 @@
                          "A should *not* transit tenant-two gate")
 
         B = self.fake_gerrit.addFakeChange('org/project2', 'master', 'B')
-        B.addApproval('code-review', 2)
-        self.fake_gerrit.addEvent(B.addApproval('approved', 1))
+        B.addApproval('Code-Review', 2)
+        self.fake_gerrit.addEvent(B.addApproval('Approved', 1))
         self.waitUntilSettled()
         self.assertEqual(self.getJobFromHistory('python27',
                                                 'org/project2').result,
@@ -70,12 +70,13 @@
 class TestInRepoConfig(ZuulTestCase):
     # A temporary class to hold new tests while others are disabled
 
+    config_file = 'zuul-connections-gerrit-and-github.conf'
     tenant_config_file = 'config/in-repo/main.yaml'
 
     def test_in_repo_config(self):
         A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
-        A.addApproval('code-review', 2)
-        self.fake_gerrit.addEvent(A.addApproval('approved', 1))
+        A.addApproval('Code-Review', 2)
+        self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
         self.waitUntilSettled()
         self.assertEqual(self.getJobFromHistory('project-test1').result,
                          'SUCCESS')
@@ -108,8 +109,8 @@
                      'playbooks/project-test2.yaml': in_repo_playbook}
         A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
                                            files=file_dict)
-        A.addApproval('code-review', 2)
-        self.fake_gerrit.addEvent(A.addApproval('approved', 1))
+        A.addApproval('Code-Review', 2)
+        self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
         self.waitUntilSettled()
         self.assertEqual(A.data['status'], 'MERGED')
         self.assertEqual(A.reported, 2,
@@ -125,8 +126,8 @@
         # Now that the config change is landed, it should be live for
         # subsequent changes.
         B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
-        B.addApproval('code-review', 2)
-        self.fake_gerrit.addEvent(B.addApproval('approved', 1))
+        B.addApproval('Code-Review', 2)
+        self.fake_gerrit.addEvent(B.addApproval('Approved', 1))
         self.waitUntilSettled()
         self.assertEqual(self.getJobFromHistory('project-test2').result,
                          'SUCCESS')
@@ -239,8 +240,8 @@
                      'playbooks/project-test2.yaml': in_repo_playbook}
         A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
                                            files=file_dict)
-        A.addApproval('approved', 1)
-        self.fake_gerrit.addEvent(A.addApproval('code-review', 2))
+        A.addApproval('Approved', 1)
+        self.fake_gerrit.addEvent(A.addApproval('Code-Review', 2))
         self.waitUntilSettled()
 
         items = gate_pipeline.getAllItems()
@@ -279,8 +280,8 @@
         self.create_branch('org/project', 'stable')
         A = self.fake_gerrit.addFakeChange('org/project', 'stable', 'A',
                                            files=file_dict)
-        A.addApproval('code-review', 2)
-        self.fake_gerrit.addEvent(A.addApproval('approved', 1))
+        A.addApproval('Code-Review', 2)
+        self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
         self.waitUntilSettled()
         self.assertEqual(A.data['status'], 'MERGED')
         self.assertEqual(A.reported, 2,
@@ -294,8 +295,8 @@
 
         # The config change should not affect master.
         B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
-        B.addApproval('code-review', 2)
-        self.fake_gerrit.addEvent(B.addApproval('approved', 1))
+        B.addApproval('Code-Review', 2)
+        self.fake_gerrit.addEvent(B.addApproval('Approved', 1))
         self.waitUntilSettled()
         self.assertHistory([
             dict(name='project-test2', result='SUCCESS', changes='1,1'),
@@ -304,8 +305,8 @@
         # The config change should be live for further changes on
         # stable.
         C = self.fake_gerrit.addFakeChange('org/project', 'stable', 'C')
-        C.addApproval('code-review', 2)
-        self.fake_gerrit.addEvent(C.addApproval('approved', 1))
+        C.addApproval('Code-Review', 2)
+        self.fake_gerrit.addEvent(C.addApproval('Approved', 1))
         self.waitUntilSettled()
         self.assertHistory([
             dict(name='project-test2', result='SUCCESS', changes='1,1'),
@@ -378,8 +379,8 @@
         file_dict = {'.zuul.yaml': in_repo_conf}
         A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
                                            files=file_dict)
-        A.addApproval('code-review', 2)
-        self.fake_gerrit.addEvent(A.addApproval('approved', 1))
+        A.addApproval('Code-Review', 2)
+        self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
         self.waitUntilSettled()
 
         self.assertEqual(A.data['status'], 'NEW')
@@ -399,8 +400,8 @@
         file_dict = {'zuul.yaml': in_repo_conf}
         A = self.fake_gerrit.addFakeChange('common-config', 'master', 'A',
                                            files=file_dict)
-        A.addApproval('code-review', 2)
-        self.fake_gerrit.addEvent(A.addApproval('approved', 1))
+        A.addApproval('Code-Review', 2)
+        self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
         self.waitUntilSettled()
 
         self.assertEqual(A.data['status'], 'NEW')
@@ -419,8 +420,8 @@
         file_dict = {'.zuul.yaml': in_repo_conf}
         A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
                                            files=file_dict)
-        A.addApproval('code-review', 2)
-        self.fake_gerrit.addEvent(A.addApproval('approved', 1))
+        A.addApproval('Code-Review', 2)
+        self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
         self.waitUntilSettled()
 
         self.assertEqual(A.data['status'], 'NEW')
@@ -439,8 +440,8 @@
         file_dict = {'.zuul.yaml': in_repo_conf}
         A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
                                            files=file_dict)
-        A.addApproval('code-review', 2)
-        self.fake_gerrit.addEvent(A.addApproval('approved', 1))
+        A.addApproval('Code-Review', 2)
+        self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
         self.waitUntilSettled()
 
         self.assertEqual(A.data['status'], 'NEW')
@@ -459,8 +460,8 @@
         file_dict = {'.zuul.yaml': in_repo_conf}
         A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
                                            files=file_dict)
-        A.addApproval('code-review', 2)
-        self.fake_gerrit.addEvent(A.addApproval('approved', 1))
+        A.addApproval('Code-Review', 2)
+        self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
         self.waitUntilSettled()
 
         self.assertEqual(A.data['status'], 'NEW')
@@ -479,8 +480,8 @@
         file_dict = {'.zuul.yaml': in_repo_conf}
         A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
                                            files=file_dict)
-        A.addApproval('code-review', 2)
-        self.fake_gerrit.addEvent(A.addApproval('approved', 1))
+        A.addApproval('Code-Review', 2)
+        self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
         self.waitUntilSettled()
 
         self.assertEqual(A.data['status'], 'NEW')
@@ -504,8 +505,8 @@
         file_dict = {'.zuul.yaml': in_repo_conf}
         A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
                                            files=file_dict)
-        A.addApproval('code-review', 2)
-        self.fake_gerrit.addEvent(A.addApproval('approved', 1))
+        A.addApproval('Code-Review', 2)
+        self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
         self.waitUntilSettled()
 
         self.assertEqual(A.data['status'], 'NEW')
@@ -532,8 +533,8 @@
         file_dict = {'.zuul.yaml': in_repo_conf}
         A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
                                            files=file_dict)
-        A.addApproval('code-review', 2)
-        self.fake_gerrit.addEvent(A.addApproval('approved', 1))
+        A.addApproval('Code-Review', 2)
+        self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
         self.waitUntilSettled()
 
         self.assertEqual(A.data['status'], 'NEW')
@@ -559,8 +560,8 @@
         file_dict = {'.zuul.yaml': downstream_repo_conf}
         A = self.fake_gerrit.addFakeChange('org/project1', 'master', 'A',
                                            files=file_dict)
-        A.addApproval('code-review', 2)
-        self.fake_gerrit.addEvent(A.addApproval('approved', 1))
+        A.addApproval('Code-Review', 2)
+        self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
         self.waitUntilSettled()
 
         self.assertEqual(A.data['status'], 'MERGED')
@@ -585,8 +586,8 @@
         file_dict = {'.zuul.yaml': upstream_repo_conf}
         B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B',
                                            files=file_dict)
-        B.addApproval('code-review', 2)
-        self.fake_gerrit.addEvent(B.addApproval('approved', 1))
+        B.addApproval('Code-Review', 2)
+        self.fake_gerrit.addEvent(B.addApproval('Approved', 1))
         self.waitUntilSettled()
 
         self.assertEqual(B.data['status'], 'MERGED')
@@ -605,54 +606,70 @@
     tenant_config_file = 'config/ansible/main.yaml'
 
     def test_playbook(self):
+        # Keep the jobdir around so we can inspect contents if an
+        # assert fails.
+        self.executor_server.keep_jobdir = True
+        # Output extra ansible info so we might see errors.
+        self.executor_server.verbose = True
+        # Add a site variables file, used by check-vars
+        path = os.path.join(FIXTURE_DIR, 'config', 'ansible',
+                            'variables.yaml')
+        self.config.set('executor', 'variables', path)
         A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
         self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
         self.waitUntilSettled()
         build_timeout = self.getJobFromHistory('timeout')
-        self.assertEqual(build_timeout.result, 'TIMED_OUT')
+        with self.jobLog(build_timeout):
+            self.assertEqual(build_timeout.result, 'TIMED_OUT')
         build_faillocal = self.getJobFromHistory('faillocal')
-        self.assertEqual(build_faillocal.result, 'FAILURE')
+        with self.jobLog(build_faillocal):
+            self.assertEqual(build_faillocal.result, 'FAILURE')
         build_failpost = self.getJobFromHistory('failpost')
-        self.assertEqual(build_failpost.result, 'POST_FAILURE')
+        with self.jobLog(build_failpost):
+            self.assertEqual(build_failpost.result, 'POST_FAILURE')
         build_check_vars = self.getJobFromHistory('check-vars')
-        self.assertEqual(build_check_vars.result, 'SUCCESS')
+        with self.jobLog(build_check_vars):
+            self.assertEqual(build_check_vars.result, 'SUCCESS')
         build_hello = self.getJobFromHistory('hello-world')
-        self.assertEqual(build_hello.result, 'SUCCESS')
+        with self.jobLog(build_hello):
+            self.assertEqual(build_hello.result, 'SUCCESS')
         build_python27 = self.getJobFromHistory('python27')
-        self.assertEqual(build_python27.result, 'SUCCESS')
-        flag_path = os.path.join(self.test_root, build_python27.uuid + '.flag')
-        self.assertTrue(os.path.exists(flag_path))
-        copied_path = os.path.join(self.test_root, build_python27.uuid +
-                                   '.copied')
-        self.assertTrue(os.path.exists(copied_path))
-        failed_path = os.path.join(self.test_root, build_python27.uuid +
-                                   '.failed')
-        self.assertFalse(os.path.exists(failed_path))
-        pre_flag_path = os.path.join(self.test_root, build_python27.uuid +
-                                     '.pre.flag')
-        self.assertTrue(os.path.exists(pre_flag_path))
-        post_flag_path = os.path.join(self.test_root, build_python27.uuid +
-                                      '.post.flag')
-        self.assertTrue(os.path.exists(post_flag_path))
-        bare_role_flag_path = os.path.join(self.test_root,
-                                           build_python27.uuid +
-                                           '.bare-role.flag')
-        self.assertTrue(os.path.exists(bare_role_flag_path))
+        with self.jobLog(build_python27):
+            self.assertEqual(build_python27.result, 'SUCCESS')
+            flag_path = os.path.join(self.test_root,
+                                     build_python27.uuid + '.flag')
+            self.assertTrue(os.path.exists(flag_path))
+            copied_path = os.path.join(self.test_root, build_python27.uuid +
+                                       '.copied')
+            self.assertTrue(os.path.exists(copied_path))
+            failed_path = os.path.join(self.test_root, build_python27.uuid +
+                                       '.failed')
+            self.assertFalse(os.path.exists(failed_path))
+            pre_flag_path = os.path.join(self.test_root, build_python27.uuid +
+                                         '.pre.flag')
+            self.assertTrue(os.path.exists(pre_flag_path))
+            post_flag_path = os.path.join(self.test_root, build_python27.uuid +
+                                          '.post.flag')
+            self.assertTrue(os.path.exists(post_flag_path))
+            bare_role_flag_path = os.path.join(self.test_root,
+                                               build_python27.uuid +
+                                               '.bare-role.flag')
+            self.assertTrue(os.path.exists(bare_role_flag_path))
+            secrets_path = os.path.join(self.test_root,
+                                        build_python27.uuid + '.secrets')
+            with open(secrets_path) as f:
+                self.assertEqual(f.read(), "test-username test-password")
 
-        secrets_path = os.path.join(self.test_root,
-                                    build_python27.uuid + '.secrets')
-        with open(secrets_path) as f:
-            self.assertEqual(f.read(), "test-username test-password")
-
-        msg = A.messages[0]
-        success = "{} https://success.example.com/zuul-logs/{}"
-        fail = "{} https://failure.example.com/zuul-logs/{}"
-        self.assertIn(success.format("python27", build_python27.uuid), msg)
-        self.assertIn(fail.format("faillocal", build_faillocal.uuid), msg)
-        self.assertIn(success.format("check-vars", build_check_vars.uuid), msg)
-        self.assertIn(success.format("hello-world", build_hello.uuid), msg)
-        self.assertIn(fail.format("timeout", build_timeout.uuid), msg)
-        self.assertIn(fail.format("failpost", build_failpost.uuid), msg)
+            msg = A.messages[0]
+            success = "{} https://success.example.com/zuul-logs/{}"
+            fail = "{} https://failure.example.com/zuul-logs/{}"
+            self.assertIn(success.format("python27", build_python27.uuid), msg)
+            self.assertIn(fail.format("faillocal", build_faillocal.uuid), msg)
+            self.assertIn(success.format("check-vars",
+                                         build_check_vars.uuid), msg)
+            self.assertIn(success.format("hello-world", build_hello.uuid), msg)
+            self.assertIn(fail.format("timeout", build_timeout.uuid), msg)
+            self.assertIn(fail.format("failpost", build_failpost.uuid), msg)
 
 
 class TestPrePlaybooks(AnsibleZuulTestCase):
@@ -706,6 +723,7 @@
     # sure we exercise that code, in this test we allow Zuul to create
     # keys for the project on startup.
     create_project_keys = True
+    config_file = 'zuul-connections-gerrit-and-github.conf'
     tenant_config_file = 'config/in-repo/main.yaml'
 
     def test_key_generation(self):
@@ -918,3 +936,15 @@
         self.assertIn('- data-return-relative '
                       'http://example.com/test/log/url/docs/index.html',
                       A.messages[-1])
+
+
+class TestDiskAccounting(AnsibleZuulTestCase):
+    config_file = 'zuul-disk-accounting.conf'
+    tenant_config_file = 'config/disk-accountant/main.yaml'
+
+    def test_disk_accountant_kills_job(self):
+        A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
+        self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
+        self.waitUntilSettled()
+        self.assertHistory([
+            dict(name='dd-big-empty-file', result='ABORTED', changes='1,1')])
diff --git a/tests/unit/test_webapp.py b/tests/unit/test_webapp.py
index da027c1..5b6950b 100644
--- a/tests/unit/test_webapp.py
+++ b/tests/unit/test_webapp.py
@@ -31,11 +31,11 @@
         super(TestWebapp, self).setUp()
         self.executor_server.hold_jobs_in_build = True
         A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
-        A.addApproval('code-review', 2)
-        self.fake_gerrit.addEvent(A.addApproval('approved', 1))
+        A.addApproval('Code-Review', 2)
+        self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
         B = self.fake_gerrit.addFakeChange('org/project1', 'master', 'B')
-        B.addApproval('code-review', 2)
-        self.fake_gerrit.addEvent(B.addApproval('approved', 1))
+        B.addApproval('Code-Review', 2)
+        self.fake_gerrit.addEvent(B.addApproval('Approved', 1))
         self.waitUntilSettled()
         self.port = self.webapp.server.socket.getsockname()[1]
 
diff --git a/tests/unit/test_zuultrigger.py b/tests/unit/test_zuultrigger.py
index 476cb74..3c4dead 100644
--- a/tests/unit/test_zuultrigger.py
+++ b/tests/unit/test_zuultrigger.py
@@ -31,17 +31,17 @@
         A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
         B1 = self.fake_gerrit.addFakeChange('org/project', 'master', 'B1')
         B2 = self.fake_gerrit.addFakeChange('org/project', 'master', 'B2')
-        A.addApproval('code-review', 2)
-        B1.addApproval('code-review', 2)
-        B2.addApproval('code-review', 2)
-        A.addApproval('verified', 1)    # required by gate
-        B1.addApproval('verified', -1)  # should go to check
-        B2.addApproval('verified', 1)   # should go to gate
-        B1.addApproval('approved', 1)
-        B2.addApproval('approved', 1)
+        A.addApproval('Code-Review', 2)
+        B1.addApproval('Code-Review', 2)
+        B2.addApproval('Code-Review', 2)
+        A.addApproval('Verified', 1)    # required by gate
+        B1.addApproval('Verified', -1)  # should go to check
+        B2.addApproval('Verified', 1)   # should go to gate
+        B1.addApproval('Approved', 1)
+        B2.addApproval('Approved', 1)
         B1.setDependsOn(A, 1)
         B2.setDependsOn(A, 1)
-        self.fake_gerrit.addEvent(A.addApproval('approved', 1))
+        self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
         # Jobs are being held in build to make sure that 3,1 has time
         # to enqueue behind 1,1 so that the test is more
         # deterministic.
@@ -85,8 +85,8 @@
         B.addPatchset({'conflict': 'bar'})
         D.addPatchset({'conflict2': 'foo'})
         E.addPatchset({'conflict2': 'bar'})
-        A.addApproval('code-review', 2)
-        self.fake_gerrit.addEvent(A.addApproval('approved', 1))
+        A.addApproval('Code-Review', 2)
+        self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
         self.waitUntilSettled()
 
         self.assertEqual(len(self.history), 1)
@@ -112,8 +112,8 @@
         # configuration.
         self.sched.reconfigure(self.config)
 
-        D.addApproval('code-review', 2)
-        self.fake_gerrit.addEvent(D.addApproval('approved', 1))
+        D.addApproval('Code-Review', 2)
+        self.fake_gerrit.addEvent(D.addApproval('Approved', 1))
         self.waitUntilSettled()
 
         self.assertEqual(len(self.history), 2)
diff --git a/tox.ini b/tox.ini
index a3f018f..cc5ea58 100644
--- a/tox.ini
+++ b/tox.ini
@@ -27,8 +27,12 @@
 commands = bindep test
 
 [testenv:pep8]
-# streamer is python3 only, so we need to run flake8 in python3
-commands = flake8 {posargs}
+# --ignore-missing-imports tells mypy to not try to follow imported modules
+# out of the current tree. As you might expect, we don't want to run static
+# type checking on the world - just on ourselves.
+commands =
+  flake8 {posargs}
+  mypy --ignore-missing-imports zuul
 
 [testenv:cover]
 commands =
diff --git a/zuul/ansible/action/add_host.pyi b/zuul/ansible/action/add_host.pyi
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/zuul/ansible/action/add_host.pyi
diff --git a/zuul/ansible/action/asa_config.pyi b/zuul/ansible/action/asa_config.pyi
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/zuul/ansible/action/asa_config.pyi
diff --git a/zuul/ansible/action/asa_template.pyi b/zuul/ansible/action/asa_template.pyi
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/zuul/ansible/action/asa_template.pyi
diff --git a/zuul/ansible/action/assemble.pyi b/zuul/ansible/action/assemble.pyi
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/zuul/ansible/action/assemble.pyi
diff --git a/zuul/ansible/action/copy.pyi b/zuul/ansible/action/copy.pyi
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/zuul/ansible/action/copy.pyi
diff --git a/zuul/ansible/action/dellos10_config.pyi b/zuul/ansible/action/dellos10_config.pyi
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/zuul/ansible/action/dellos10_config.pyi
diff --git a/zuul/ansible/action/dellos6_config.pyi b/zuul/ansible/action/dellos6_config.pyi
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/zuul/ansible/action/dellos6_config.pyi
diff --git a/zuul/ansible/action/dellos9_config.pyi b/zuul/ansible/action/dellos9_config.pyi
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/zuul/ansible/action/dellos9_config.pyi
diff --git a/zuul/ansible/action/eos_config.pyi b/zuul/ansible/action/eos_config.pyi
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/zuul/ansible/action/eos_config.pyi
diff --git a/zuul/ansible/action/eos_template.pyi b/zuul/ansible/action/eos_template.pyi
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/zuul/ansible/action/eos_template.pyi
diff --git a/zuul/ansible/action/fetch.pyi b/zuul/ansible/action/fetch.pyi
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/zuul/ansible/action/fetch.pyi
diff --git a/zuul/ansible/action/include_vars.pyi b/zuul/ansible/action/include_vars.pyi
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/zuul/ansible/action/include_vars.pyi
diff --git a/zuul/ansible/action/ios_config.pyi b/zuul/ansible/action/ios_config.pyi
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/zuul/ansible/action/ios_config.pyi
diff --git a/zuul/ansible/action/ios_template.pyi b/zuul/ansible/action/ios_template.pyi
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/zuul/ansible/action/ios_template.pyi
diff --git a/zuul/ansible/action/iosxr_config.pyi b/zuul/ansible/action/iosxr_config.pyi
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/zuul/ansible/action/iosxr_config.pyi
diff --git a/zuul/ansible/action/iosxr_template.pyi b/zuul/ansible/action/iosxr_template.pyi
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/zuul/ansible/action/iosxr_template.pyi
diff --git a/zuul/ansible/action/junos_config.pyi b/zuul/ansible/action/junos_config.pyi
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/zuul/ansible/action/junos_config.pyi
diff --git a/zuul/ansible/action/junos_template.pyi b/zuul/ansible/action/junos_template.pyi
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/zuul/ansible/action/junos_template.pyi
diff --git a/zuul/ansible/action/net_config.pyi b/zuul/ansible/action/net_config.pyi
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/zuul/ansible/action/net_config.pyi
diff --git a/zuul/ansible/action/net_template.pyi b/zuul/ansible/action/net_template.pyi
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/zuul/ansible/action/net_template.pyi
diff --git a/zuul/ansible/action/network.pyi b/zuul/ansible/action/network.pyi
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/zuul/ansible/action/network.pyi
diff --git a/zuul/ansible/action/normal.pyi b/zuul/ansible/action/normal.pyi
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/zuul/ansible/action/normal.pyi
diff --git a/zuul/ansible/action/nxos_config.pyi b/zuul/ansible/action/nxos_config.pyi
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/zuul/ansible/action/nxos_config.pyi
diff --git a/zuul/ansible/action/nxos_template.pyi b/zuul/ansible/action/nxos_template.pyi
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/zuul/ansible/action/nxos_template.pyi
diff --git a/zuul/ansible/action/ops_config.pyi b/zuul/ansible/action/ops_config.pyi
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/zuul/ansible/action/ops_config.pyi
diff --git a/zuul/ansible/action/ops_template.pyi b/zuul/ansible/action/ops_template.pyi
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/zuul/ansible/action/ops_template.pyi
diff --git a/zuul/ansible/action/patch.pyi b/zuul/ansible/action/patch.pyi
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/zuul/ansible/action/patch.pyi
diff --git a/zuul/ansible/action/script.pyi b/zuul/ansible/action/script.pyi
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/zuul/ansible/action/script.pyi
diff --git a/zuul/ansible/action/sros_config.pyi b/zuul/ansible/action/sros_config.pyi
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/zuul/ansible/action/sros_config.pyi
diff --git a/zuul/ansible/action/synchronize.pyi b/zuul/ansible/action/synchronize.pyi
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/zuul/ansible/action/synchronize.pyi
diff --git a/zuul/ansible/action/template.pyi b/zuul/ansible/action/template.pyi
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/zuul/ansible/action/template.pyi
diff --git a/zuul/ansible/action/unarchive.pyi b/zuul/ansible/action/unarchive.pyi
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/zuul/ansible/action/unarchive.pyi
diff --git a/zuul/ansible/action/vyos_config.pyi b/zuul/ansible/action/vyos_config.pyi
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/zuul/ansible/action/vyos_config.pyi
diff --git a/zuul/ansible/action/win_copy.pyi b/zuul/ansible/action/win_copy.pyi
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/zuul/ansible/action/win_copy.pyi
diff --git a/zuul/ansible/action/win_template.pyi b/zuul/ansible/action/win_template.pyi
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/zuul/ansible/action/win_template.pyi
diff --git a/zuul/ansible/callback/zuul_stream.py b/zuul/ansible/callback/zuul_stream.py
index 9622f24..078e1c9 100644
--- a/zuul/ansible/callback/zuul_stream.py
+++ b/zuul/ansible/callback/zuul_stream.py
@@ -284,6 +284,19 @@
         # Log an extra blank line to get space after each task
         self._log("")
 
+    def v2_runner_on_skipped(self, result):
+        reason = result._result.get('skip_reason')
+        if reason:
+            # No reason means it's an item, which we'll log differently
+            self._log_message(result, status='skipping', msg=reason)
+
+    def v2_runner_item_on_skipped(self, result):
+        reason = result._result.get('skip_reason')
+        if reason:
+            self._log_message(result, status='skipping', msg=reason)
+        else:
+            self._log_message(result, status='skipping')
+
     def v2_runner_on_ok(self, result):
         if (self._play.strategy == 'free'
                 and self._last_task_banner != result._task._uuid):
diff --git a/zuul/ansible/lookup/_banned.pyi b/zuul/ansible/lookup/_banned.pyi
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/zuul/ansible/lookup/_banned.pyi
diff --git a/zuul/ansible/lookup/consul_kv.pyi b/zuul/ansible/lookup/consul_kv.pyi
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/zuul/ansible/lookup/consul_kv.pyi
diff --git a/zuul/ansible/lookup/credstash.pyi b/zuul/ansible/lookup/credstash.pyi
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/zuul/ansible/lookup/credstash.pyi
diff --git a/zuul/ansible/lookup/csvfile.pyi b/zuul/ansible/lookup/csvfile.pyi
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/zuul/ansible/lookup/csvfile.pyi
diff --git a/zuul/ansible/lookup/dig.pyi b/zuul/ansible/lookup/dig.pyi
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/zuul/ansible/lookup/dig.pyi
diff --git a/zuul/ansible/lookup/dnstxt.pyi b/zuul/ansible/lookup/dnstxt.pyi
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/zuul/ansible/lookup/dnstxt.pyi
diff --git a/zuul/ansible/lookup/env.pyi b/zuul/ansible/lookup/env.pyi
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/zuul/ansible/lookup/env.pyi
diff --git a/zuul/ansible/lookup/etcd.pyi b/zuul/ansible/lookup/etcd.pyi
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/zuul/ansible/lookup/etcd.pyi
diff --git a/zuul/ansible/lookup/file.pyi b/zuul/ansible/lookup/file.pyi
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/zuul/ansible/lookup/file.pyi
diff --git a/zuul/ansible/lookup/fileglob.pyi b/zuul/ansible/lookup/fileglob.pyi
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/zuul/ansible/lookup/fileglob.pyi
diff --git a/zuul/ansible/lookup/filetree.pyi b/zuul/ansible/lookup/filetree.pyi
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/zuul/ansible/lookup/filetree.pyi
diff --git a/zuul/ansible/lookup/first_found.pyi b/zuul/ansible/lookup/first_found.pyi
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/zuul/ansible/lookup/first_found.pyi
diff --git a/zuul/ansible/lookup/hashi_valut.pyi b/zuul/ansible/lookup/hashi_valut.pyi
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/zuul/ansible/lookup/hashi_valut.pyi
diff --git a/zuul/ansible/lookup/ini.pyi b/zuul/ansible/lookup/ini.pyi
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/zuul/ansible/lookup/ini.pyi
diff --git a/zuul/ansible/lookup/keyring.pyi b/zuul/ansible/lookup/keyring.pyi
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/zuul/ansible/lookup/keyring.pyi
diff --git a/zuul/ansible/lookup/lastpass.pyi b/zuul/ansible/lookup/lastpass.pyi
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/zuul/ansible/lookup/lastpass.pyi
diff --git a/zuul/ansible/lookup/lines.pyi b/zuul/ansible/lookup/lines.pyi
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/zuul/ansible/lookup/lines.pyi
diff --git a/zuul/ansible/lookup/mongodb.pyi b/zuul/ansible/lookup/mongodb.pyi
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/zuul/ansible/lookup/mongodb.pyi
diff --git a/zuul/ansible/lookup/password.pyi b/zuul/ansible/lookup/password.pyi
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/zuul/ansible/lookup/password.pyi
diff --git a/zuul/ansible/lookup/passwordstore.pyi b/zuul/ansible/lookup/passwordstore.pyi
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/zuul/ansible/lookup/passwordstore.pyi
diff --git a/zuul/ansible/lookup/pipe.pyi b/zuul/ansible/lookup/pipe.pyi
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/zuul/ansible/lookup/pipe.pyi
diff --git a/zuul/ansible/lookup/redis_kv.pyi b/zuul/ansible/lookup/redis_kv.pyi
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/zuul/ansible/lookup/redis_kv.pyi
diff --git a/zuul/ansible/lookup/shelvefile.pyi b/zuul/ansible/lookup/shelvefile.pyi
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/zuul/ansible/lookup/shelvefile.pyi
diff --git a/zuul/ansible/lookup/template.pyi b/zuul/ansible/lookup/template.pyi
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/zuul/ansible/lookup/template.pyi
diff --git a/zuul/ansible/lookup/url.pyi b/zuul/ansible/lookup/url.pyi
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/zuul/ansible/lookup/url.pyi
diff --git a/zuul/cmd/executor.py b/zuul/cmd/executor.py
index 6a1a214..06ef0ba 100755
--- a/zuul/cmd/executor.py
+++ b/zuul/cmd/executor.py
@@ -82,7 +82,7 @@
 
             self.log.info("Starting log streamer")
             streamer = zuul.lib.log_streamer.LogStreamer(
-                self.user, '0.0.0.0', self.finger_port, self.jobroot_dir)
+                self.user, '0.0.0.0', self.finger_port, self.job_dir)
 
             # Keep running until the parent dies:
             pipe_read = os.fdopen(pipe_read)
@@ -111,15 +111,15 @@
 
         self.user = get_default(self.config, 'executor', 'user', 'zuul')
 
-        if self.config.has_option('executor', 'jobroot_dir'):
-            self.jobroot_dir = os.path.expanduser(
-                self.config.get('executor', 'jobroot_dir'))
-            if not os.path.isdir(self.jobroot_dir):
-                print("Invalid jobroot_dir: {jobroot_dir}".format(
-                    jobroot_dir=self.jobroot_dir))
+        if self.config.has_option('executor', 'job_dir'):
+            self.job_dir = os.path.expanduser(
+                self.config.get('executor', 'job_dir'))
+            if not os.path.isdir(self.job_dir):
+                print("Invalid job_dir: {job_dir}".format(
+                    job_dir=self.job_dir))
                 sys.exit(1)
         else:
-            self.jobroot_dir = tempfile.gettempdir()
+            self.job_dir = tempfile.gettempdir()
 
         self.setup_logging('executor', 'log_config')
         self.log = logging.getLogger("zuul.Executor")
@@ -134,7 +134,7 @@
 
         ExecutorServer = zuul.executor.server.ExecutorServer
         self.executor = ExecutorServer(self.config, self.connections,
-                                       jobdir_root=self.jobroot_dir,
+                                       jobdir_root=self.job_dir,
                                        keep_jobdir=self.args.keep_jobdir,
                                        log_streaming_port=self.finger_port)
         self.executor.start()
diff --git a/zuul/configloader.py b/zuul/configloader.py
index 7640dfc..3fc10b8 100644
--- a/zuul/configloader.py
+++ b/zuul/configloader.py
@@ -762,20 +762,6 @@
 
         precedence = vs.Any('normal', 'low', 'high')
 
-        approval = vs.Schema({'username': str,
-                              'email-filter': str,
-                              'email': str,
-                              'older-than': str,
-                              'newer-than': str,
-                              }, extra=vs.ALLOW_EXTRA)
-
-        require = {'approval': to_list(approval),
-                   'open': bool,
-                   'current-patchset': bool,
-                   'status': to_list(str)}
-
-        reject = {'approval': to_list(approval)}
-
         window = vs.All(int, vs.Range(min=0))
         window_floor = vs.All(int, vs.Range(min=1))
         window_type = vs.Any('linear', 'exponential')
@@ -785,8 +771,6 @@
                     vs.Required('manager'): manager,
                     'precedence': precedence,
                     'description': str,
-                    'require': require,
-                    'reject': reject,
                     'success-message': str,
                     'failure-message': str,
                     'merge-failure-message': str,
diff --git a/zuul/driver/__init__.py b/zuul/driver/__init__.py
index c78283d..5193fe6 100644
--- a/zuul/driver/__init__.py
+++ b/zuul/driver/__init__.py
@@ -33,7 +33,7 @@
     The class or instance attribute **name** must be provided as a string.
 
     """
-    name = None
+    name = None  # type: str
 
     def reconfigure(self, tenant):
         """Called when a tenant is reconfigured.
diff --git a/zuul/driver/bubblewrap/__init__.py b/zuul/driver/bubblewrap/__init__.py
index 3609a71..e8209f1 100644
--- a/zuul/driver/bubblewrap/__init__.py
+++ b/zuul/driver/bubblewrap/__init__.py
@@ -23,6 +23,8 @@
 import subprocess
 import sys
 
+from typing import Dict, List  # flake8: noqa
+
 from zuul.driver import (Driver, WrapperInterface)
 
 
@@ -70,7 +72,7 @@
     name = 'bubblewrap'
     log = logging.getLogger("zuul.BubblewrapDriver")
 
-    mounts_map = {'rw': [], 'ro': []}
+    mounts_map = {'rw': [], 'ro': []}  # type: Dict[str, List]
 
     def __init__(self):
         self.bwrap_command = self._bwrap_command()
@@ -81,8 +83,8 @@
     def stop(self):
         pass
 
-    def setMountsMap(self, state_dir, ro_dirs=[], rw_dirs=[]):
-        self.mounts_map = {'ro': ro_dirs, 'rw': [state_dir] + rw_dirs}
+    def setMountsMap(self, ro_dirs=[], rw_dirs=[]):
+        self.mounts_map = {'ro': ro_dirs, 'rw': rw_dirs}
 
     def getPopen(self, **kwargs):
         # Set zuul_dir if it was not passed in
@@ -180,12 +182,16 @@
     driver = BubblewrapDriver()
 
     parser = argparse.ArgumentParser()
+    parser.add_argument('--ro-bind', nargs='+')
+    parser.add_argument('--rw-bind', nargs='+')
     parser.add_argument('work_dir')
     parser.add_argument('run_args', nargs='+')
     cli_args = parser.parse_args()
 
     ssh_auth_sock = os.environ.get('SSH_AUTH_SOCK')
 
+    driver.setMountsMap(cli_args.ro_bind, cli_args.rw_bind)
+
     popen = driver.getPopen(work_dir=cli_args.work_dir,
                             ssh_auth_sock=ssh_auth_sock)
     x = popen(cli_args.run_args)
diff --git a/zuul/driver/gerrit/gerritconnection.py b/zuul/driver/gerrit/gerritconnection.py
index 8f8465a..63f3093 100644
--- a/zuul/driver/gerrit/gerritconnection.py
+++ b/zuul/driver/gerrit/gerritconnection.py
@@ -80,7 +80,7 @@
             patchset = data.get('patchSet')
             if patchset:
                 event.patch_number = patchset.get('number')
-                event.refspec = patchset.get('ref')
+                event.ref = patchset.get('ref')
             event.approvals = data.get('approvals', [])
             event.comment = data.get('comment')
         refupdate = data.get('refUpdate')
@@ -418,7 +418,7 @@
         files = []
         for ps in data['patchSets']:
             if ps['number'] == change.patchset:
-                change.refspec = ps['ref']
+                change.ref = ps['ref']
                 for f in ps.get('files', []):
                     files.append(f['file'])
             if int(ps['number']) > int(max_ps):
@@ -581,7 +581,7 @@
                             continue
                         elif label['status'] in ['NEED', 'REJECT']:
                             # It may be our own rejection, so we ignore
-                            if label['label'].lower() not in allow_needs:
+                            if label['label'] not in allow_needs:
                                 return False
                             continue
                         else:
diff --git a/zuul/driver/gerrit/gerritmodel.py b/zuul/driver/gerrit/gerritmodel.py
index 818d260..b96ed4c 100644
--- a/zuul/driver/gerrit/gerritmodel.py
+++ b/zuul/driver/gerrit/gerritmodel.py
@@ -24,11 +24,6 @@
 EMPTY_GIT_REF = '0' * 40  # git sha of all zeros, used during creates/deletes
 
 
-def normalize_category(name):
-    name = name.lower()
-    return re.sub(' ', '-', name)
-
-
 class GerritChange(Change):
     def __init__(self, project):
         super(GerritChange, self).__init__(project)
@@ -66,23 +61,22 @@
 class GerritApprovalFilter(object):
     def __init__(self, required_approvals=[], reject_approvals=[]):
         self._required_approvals = copy.deepcopy(required_approvals)
-        self.required_approvals = self._tidy_approvals(required_approvals)
+        self.required_approvals = self._tidy_approvals(
+            self._required_approvals)
         self._reject_approvals = copy.deepcopy(reject_approvals)
-        self.reject_approvals = self._tidy_approvals(reject_approvals)
+        self.reject_approvals = self._tidy_approvals(self._reject_approvals)
 
     def _tidy_approvals(self, approvals):
         for a in approvals:
             for k, v in a.items():
                 if k == 'username':
                     a['username'] = re.compile(v)
-                elif k in ['email', 'email-filter']:
+                elif k == 'email':
                     a['email'] = re.compile(v)
                 elif k == 'newer-than':
                     a[k] = time_to_seconds(v)
                 elif k == 'older-than':
                     a[k] = time_to_seconds(v)
-            if 'email-filter' in a:
-                del a['email-filter']
         return approvals
 
     def _match_approval_required_approval(self, rapproval, approval):
@@ -109,7 +103,7 @@
             else:
                 if not isinstance(v, list):
                     v = [v]
-                if (normalize_category(approval['description']) != k or
+                if (approval['description'] != k or
                         int(approval['value']) not in v):
                     return False
         return True
@@ -281,8 +275,8 @@
         for category, value in self.event_approvals.items():
             matches_approval = False
             for eapp in event.approvals:
-                if (normalize_category(eapp['description']) == category and
-                    int(eapp['value']) == int(value)):
+                if (eapp['description'] == category and
+                        int(eapp['value']) == int(value)):
                     matches_approval = True
             if not matches_approval:
                 return False
diff --git a/zuul/driver/gerrit/gerritsource.py b/zuul/driver/gerrit/gerritsource.py
index 4571cc1..e41859e 100644
--- a/zuul/driver/gerrit/gerritsource.py
+++ b/zuul/driver/gerrit/gerritsource.py
@@ -82,7 +82,6 @@
 
 
 approval = vs.Schema({'username': str,
-                      'email-filter': str,
                       'email': str,
                       'older-than': str,
                       'newer-than': str,
diff --git a/zuul/driver/gerrit/gerrittrigger.py b/zuul/driver/gerrit/gerrittrigger.py
index 706b7df..cfedd4e 100644
--- a/zuul/driver/gerrit/gerrittrigger.py
+++ b/zuul/driver/gerrit/gerrittrigger.py
@@ -77,7 +77,6 @@
     variable_dict = v.Schema(dict)
 
     approval = v.Schema({'username': str,
-                         'email-filter': str,
                          'email': str,
                          'older-than': str,
                          'newer-than': str,
diff --git a/zuul/driver/github/githubconnection.py b/zuul/driver/github/githubconnection.py
index ff113ce..ba063fb 100644
--- a/zuul/driver/github/githubconnection.py
+++ b/zuul/driver/github/githubconnection.py
@@ -40,6 +40,12 @@
 PREVIEW_JSON_ACCEPT = 'application/vnd.github.machine-man-preview+json'
 
 
+def _sign_request(body, secret):
+    signature = 'sha1=' + hmac.new(
+        secret.encode('utf-8'), body, hashlib.sha1).hexdigest()
+    return signature
+
+
 class UTC(datetime.tzinfo):
     """UTC"""
 
@@ -263,7 +269,7 @@
     def _validate_signature(self, request):
         secret = self.connection.connection_config.get('webhook_token', None)
         if secret is None:
-            return True
+            raise RuntimeError("webhook_token is required")
 
         body = request.body
         try:
@@ -272,13 +278,12 @@
             raise webob.exc.HTTPUnauthorized(
                 'Please specify a X-Hub-Signature header with secret.')
 
-        payload_signature = 'sha1=' + hmac.new(secret.encode('utf-8'),
-                                               body,
-                                               hashlib.sha1).hexdigest()
+        payload_signature = _sign_request(body, secret)
 
         self.log.debug("Payload Signature: {0}".format(str(payload_signature)))
         self.log.debug("Request Signature: {0}".format(str(request_signature)))
-        if str(payload_signature) != str(request_signature):
+        if not hmac.compare_digest(
+            str(payload_signature), str(request_signature)):
             raise webob.exc.HTTPUnauthorized(
                 'Request signature does not match calculated payload '
                 'signature. Check that secret is correct.')
@@ -299,7 +304,7 @@
                                                       event.change_number)
         event.updated_at = pr_body.get('updated_at')
         event.branch = base.get('ref')
-        event.refspec = "refs/pull/" + str(pr_body.get('number')) + "/head"
+        event.ref = "refs/pull/" + str(pr_body.get('number')) + "/head"
         event.patch_number = head.get('sha')
 
         event.title = pr_body.get('title')
@@ -601,7 +606,7 @@
 
         self.log.info("Updating %s" % (change,))
         change.pr = self.getPull(change.project.name, change.number)
-        change.refspec = "refs/pull/%s/head" % change.number
+        change.ref = "refs/pull/%s/head" % change.number
         change.branch = change.pr.get('base').get('ref')
         change.files = change.pr.get('files')
         change.title = change.pr.get('title')
diff --git a/zuul/driver/github/githubmodel.py b/zuul/driver/github/githubmodel.py
index db119f0..ffd1c3f 100644
--- a/zuul/driver/github/githubmodel.py
+++ b/zuul/driver/github/githubmodel.py
@@ -68,8 +68,8 @@
                  reject_reviews=[]):
         self._required_reviews = copy.deepcopy(required_reviews)
         self._reject_reviews = copy.deepcopy(reject_reviews)
-        self.required_reviews = self._tidy_reviews(required_reviews)
-        self.reject_reviews = self._tidy_reviews(reject_reviews)
+        self.required_reviews = self._tidy_reviews(self._required_reviews)
+        self.reject_reviews = self._tidy_reviews(self._reject_reviews)
         self.required_statuses = required_statuses
 
     def _tidy_reviews(self, reviews):
diff --git a/zuul/driver/sql/sqlreporter.py b/zuul/driver/sql/sqlreporter.py
index 214b667..aca1b06 100644
--- a/zuul/driver/sql/sqlreporter.py
+++ b/zuul/driver/sql/sqlreporter.py
@@ -41,14 +41,14 @@
         with self.connection.engine.begin() as conn:
             change = getattr(item.change, 'number', '')
             patchset = getattr(item.change, 'patchset', '')
-            refspec = getattr(item.change, 'refspec', item.change.newrev)
+            ref = getattr(item.change, 'ref', '')
             buildset_ins = self.connection.zuul_buildset_table.insert().values(
                 zuul_ref=item.current_build_set.ref,
                 pipeline=item.pipeline.name,
                 project=item.change.project.name,
                 change=change,
                 patchset=patchset,
-                ref=refspec,
+                ref=ref,
                 score=self.result_score,
                 message=self._formatItemReport(
                     item, with_jobs=False),
diff --git a/zuul/driver/zuul/__init__.py b/zuul/driver/zuul/__init__.py
index 08612dc..0f6ec7d 100644
--- a/zuul/driver/zuul/__init__.py
+++ b/zuul/driver/zuul/__init__.py
@@ -82,7 +82,7 @@
         event.branch = change.branch
         event.change_url = change.url
         event.patch_number = change.patchset
-        event.refspec = change.refspec
+        event.ref = change.ref
         self.sched.addEvent(event)
 
     def _createParentChangeEnqueuedEvents(self, change, pipeline):
@@ -104,7 +104,7 @@
         event.branch = change.branch
         event.change_url = change.url
         event.patch_number = change.patchset
-        event.refspec = change.refspec
+        event.ref = change.ref
         self.sched.addEvent(event)
 
     def getTrigger(self, connection_name, config=None):
diff --git a/zuul/driver/zuul/zuultrigger.py b/zuul/driver/zuul/zuultrigger.py
index 628687e..7757a31 100644
--- a/zuul/driver/zuul/zuultrigger.py
+++ b/zuul/driver/zuul/zuultrigger.py
@@ -43,20 +43,11 @@
 
 
 def getSchema():
-    approval = v.Schema({'username': str,
-                         'email-filter': str,
-                         'email': str,
-                         'older-than': str,
-                         'newer-than': str,
-                         }, extra=v.ALLOW_EXTRA)
-
     zuul_trigger = {
         v.Required('event'):
         scalar_or_list(v.Any('parent-change-enqueued',
                              'project-change-merged')),
         'pipeline': scalar_or_list(str),
-        'require-approval': scalar_or_list(approval),
-        'reject-approval': scalar_or_list(approval),
     }
 
     return zuul_trigger
diff --git a/zuul/executor/client.py b/zuul/executor/client.py
index beb8964..dfd4225 100644
--- a/zuul/executor/client.py
+++ b/zuul/executor/client.py
@@ -160,6 +160,7 @@
                            ref=item.change.ref,
                            pipeline=pipeline.name,
                            job=job.name,
+                           voting=job.voting,
                            project=project,
                            tenant=tenant.name,
                            jobtags=sorted(job.tags))
@@ -168,9 +169,9 @@
         if hasattr(item.change, 'tag'):
             zuul_params['tag'] = item.change.tag
         if hasattr(item.change, 'number'):
-            zuul_params['change'] = item.change.number
+            zuul_params['change'] = str(item.change.number)
         if hasattr(item.change, 'patchset'):
-            zuul_params['patchset'] = item.change.patchset
+            zuul_params['patchset'] = str(item.change.patchset)
         if hasattr(item.change, 'oldrev') and item.change.oldrev:
             zuul_params['oldrev'] = item.change.oldrev
         if hasattr(item.change, 'newrev') and item.change.newrev:
@@ -183,66 +184,15 @@
                 canonical_hostname=i.change.project.canonical_hostname,
                 canonical_name=i.change.project.canonical_name)
             if hasattr(i.change, 'number'):
-                d['change'] = i.change.number
+                d['change'] = str(i.change.number)
             if hasattr(i.change, 'patchset'):
-                d['patchset'] = i.change.number
+                d['patchset'] = str(i.change.patchset)
             if hasattr(i.change, 'branch'):
                 d['branch'] = i.change.branch
             zuul_params['items'].append(d)
 
         # Legacy environment variables
-        params = dict(ZUUL_UUID=uuid,
-                      ZUUL_PROJECT=item.change.project.name)
-        params['ZUUL_PIPELINE'] = pipeline.name
-        params['ZUUL_URL'] = item.current_build_set.zuul_url
-        params['ZUUL_VOTING'] = job.voting and '1' or '0'
-        if hasattr(item.change, 'refspec'):
-            changes_str = '^'.join(
-                ['%s:%s:%s' % (i.change.project.name, i.change.branch,
-                               i.change.refspec)
-                 for i in all_items])
-            params['ZUUL_BRANCH'] = item.change.branch
-            params['ZUUL_CHANGES'] = changes_str
-            params['ZUUL_REF'] = ('refs/zuul/%s/%s' %
-                                  (item.change.branch,
-                                   item.current_build_set.ref))
-            params['ZUUL_COMMIT'] = item.current_build_set.commit
-
-            zuul_changes = ' '.join(['%s,%s' % (i.change.number,
-                                                i.change.patchset)
-                                     for i in all_items])
-            params['ZUUL_CHANGE_IDS'] = zuul_changes
-            params['ZUUL_CHANGE'] = str(item.change.number)
-            params['ZUUL_PATCHSET'] = str(item.change.patchset)
-        if hasattr(item.change, 'ref') and item.change.ref is not None:
-            params['ZUUL_REFNAME'] = item.change.ref
-            params['ZUUL_OLDREV'] = item.change.oldrev
-            params['ZUUL_NEWREV'] = item.change.newrev
-
-            params['ZUUL_REF'] = item.change.ref
-            params['ZUUL_COMMIT'] = item.change.newrev
-
-        # This is what we should be heading toward for parameters:
-
-        # required:
-        # ZUUL_UUID
-        # ZUUL_REF (/refs/zuul/..., /refs/tags/foo, master)
-        # ZUUL_COMMIT
-
-        # optional:
-        # ZUUL_PROJECT
-        # ZUUL_PIPELINE
-
-        # optional (changes only):
-        # ZUUL_BRANCH
-        # ZUUL_CHANGE
-        # ZUUL_CHANGE_IDS
-        # ZUUL_PATCHSET
-
-        # optional (ref updated only):
-        # ZUUL_OLDREV
-        # ZUUL_NEWREV
-
+        params = dict()
         params['job'] = job.name
         params['timeout'] = job.timeout
         params['items'] = merger_items
diff --git a/zuul/executor/server.py b/zuul/executor/server.py
index ef5363c..b306e75 100644
--- a/zuul/executor/server.py
+++ b/zuul/executor/server.py
@@ -55,6 +55,88 @@
     pass
 
 
+class DiskAccountant(object):
+    ''' A single thread to periodically run du and monitor a base directory
+
+    Whenever the accountant notices a dir over limit, it will call the
+    given func with an argument of the job directory. That function
+    should be used to remediate the problem, generally by killing the
+    job producing the disk bloat). The function will be called every
+    time the problem is noticed, so it should be handled synchronously
+    to avoid stacking up calls.
+    '''
+    log = logging.getLogger("zuul.ExecutorDiskAccountant")
+
+    def __init__(self, jobs_base, limit, func, cache_dir, usage_func=None):
+        '''
+        :param str jobs_base: absolute path name of dir to be monitored
+        :param int limit: maximum number of MB allowed to be in use in any one
+                          subdir
+        :param callable func: Function to call with overlimit dirs
+        :param str cache_dir: absolute path name of dir to be passed as the
+                              first argument to du. This will ensure du does
+                              not count any hardlinks to files in this
+                              directory against a single job.
+        :param callable usage_func: Optional function to call with usage
+                                    for every dir _NOT_ over limit
+        '''
+        # Don't cross the streams
+        if cache_dir == jobs_base:
+            raise Exception("Cache dir and jobs dir cannot be the same")
+        self.thread = threading.Thread(target=self._run,
+                                       name='executor-diskaccountant')
+        self.thread.daemon = True
+        self._running = False
+        self.jobs_base = jobs_base
+        self.limit = limit
+        self.func = func
+        self.cache_dir = cache_dir
+        self.usage_func = usage_func
+        self.stop_event = threading.Event()
+
+    def _run(self):
+        while self._running:
+            # Walk job base
+            before = time.time()
+            du = subprocess.Popen(
+                ['du', '-m', '--max-depth=1', self.cache_dir, self.jobs_base],
+                stdout=subprocess.PIPE, stderr=subprocess.DEVNULL)
+            for line in du.stdout:
+                (size, dirname) = line.rstrip().split()
+                dirname = dirname.decode('utf8')
+                if dirname == self.jobs_base or dirname == self.cache_dir:
+                    continue
+                if os.path.dirname(dirname) == self.cache_dir:
+                    continue
+                size = int(size)
+                if size > self.limit:
+                    self.log.info(
+                        "{job} is using {size}MB (limit={limit})"
+                        .format(size=size, job=dirname, limit=self.limit))
+                    self.func(dirname)
+                elif self.usage_func:
+                    self.log.debug(
+                        "{job} is using {size}MB (limit={limit})"
+                        .format(size=size, job=dirname, limit=self.limit))
+                    self.usage_func(dirname, size)
+            du.wait()
+            after = time.time()
+            # Sleep half as long as that took, or 1s, whichever is longer
+            delay_time = max((after - before) / 2, 1.0)
+            self.stop_event.wait(delay_time)
+
+    def start(self):
+        self._running = True
+        self.thread.start()
+
+    def stop(self):
+        self._running = False
+        self.stop_event.set()
+        # We join here to avoid whitelisting the thread -- if it takes more
+        # than 5s to stop in tests, there's a problem.
+        self.thread.join(timeout=5)
+
+
 class Watchdog(object):
     def __init__(self, timeout, function, args):
         self.timeout = timeout
@@ -443,6 +525,8 @@
                                       '/var/lib/zuul/executor-git')
         self.default_username = get_default(self.config, 'executor',
                                             'default_username', 'zuul')
+        self.disk_limit_per_job = int(get_default(self.config, 'executor',
+                                                  'disk_limit_per_job', 250))
         self.merge_email = get_default(self.config, 'merger', 'git_user_email')
         self.merge_name = get_default(self.config, 'merger', 'git_user_name')
         execution_wrapper_name = get_default(self.config, 'executor',
@@ -486,6 +570,10 @@
             pass
 
         self.job_workers = {}
+        self.disk_accountant = DiskAccountant(self.jobdir_root,
+                                              self.disk_limit_per_job,
+                                              self.stopJobByJobdir,
+                                              self.merge_root)
 
     def _getMerger(self, root, logger=None):
         if root != self.merge_root:
@@ -530,6 +618,7 @@
         self.executor_thread = threading.Thread(target=self.run_executor)
         self.executor_thread.daemon = True
         self.executor_thread.start()
+        self.disk_accountant.start()
 
     def register(self):
         self.executor_worker.registerFunction("executor:execute")
@@ -540,6 +629,7 @@
 
     def stop(self):
         self.log.debug("Stopping")
+        self.disk_accountant.stop()
         self._running = False
         self._command_running = False
         self.command_socket.stop()
@@ -675,23 +765,30 @@
     def finishJob(self, unique):
         del(self.job_workers[unique])
 
+    def stopJobByJobdir(self, jobdir):
+        unique = os.path.basename(jobdir)
+        self.stopJobByUnique(unique)
+
     def stopJob(self, job):
         try:
             args = json.loads(job.arguments)
             self.log.debug("Stop job with arguments: %s" % (args,))
             unique = args['uuid']
-            job_worker = self.job_workers.get(unique)
-            if not job_worker:
-                self.log.debug("Unable to find worker for job %s" % (unique,))
-                return
-            try:
-                job_worker.stop()
-            except Exception:
-                self.log.exception("Exception sending stop command "
-                                   "to worker:")
+            self.stopJobByUnique(unique)
         finally:
             job.sendWorkComplete()
 
+    def stopJobByUnique(self, unique):
+        job_worker = self.job_workers.get(unique)
+        if not job_worker:
+            self.log.debug("Unable to find worker for job %s" % (unique,))
+            return
+        try:
+            job_worker.stop()
+        except Exception:
+            self.log.exception("Exception sending stop command "
+                               "to worker:")
+
     def cat(self, job):
         args = json.loads(job.arguments)
         task = self.update(args['connection'], args['project'])
@@ -757,6 +854,12 @@
                                             '~/.ssh/id_rsa')
         self.ssh_agent = SshAgent()
 
+        self.executor_variables_file = None
+
+        if self.executor_server.config.has_option('executor', 'variables'):
+            self.executor_variables_file = self.executor_server.config.get(
+                'executor', 'variables')
+
     def run(self):
         self.running = True
         self.thread = threading.Thread(target=self.execute)
@@ -812,8 +915,7 @@
 
         # Make sure all projects used by the job are updated...
         for project in args['projects']:
-            self.log.debug("Job %s: updating project %s" %
-                           (self.job.unique, project))
+            self.log.debug("Updating project %s" % (project,))
             tasks.append(self.executor_server.update(
                 project['connection'], project['name']))
             projects.add((project['connection'], project['name']))
@@ -827,8 +929,7 @@
             repos += playbook['roles']
 
         for repo in repos:
-            self.log.debug("Job %s: updating playbook or role %s" %
-                           (self.job.unique, repo))
+            self.log.debug("Updating playbook or role %s" % (repo,))
             key = (repo['connection'], repo['project'])
             if key not in projects:
                 tasks.append(self.executor_server.update(*key))
@@ -837,7 +938,7 @@
         for task in tasks:
             task.wait()
 
-        self.log.debug("Job %s: git updates complete" % (self.job.unique,))
+        self.log.debug("Git updates complete")
         merger = self.executor_server._getMerger(self.jobdir.src_root,
                                                  self.log)
         repos = {}
@@ -848,7 +949,7 @@
                                   project['name'])
             repos[project['canonical_name']] = repo
 
-        merge_items = [i for i in args['items'] if i.get('refspec')]
+        merge_items = [i for i in args['items'] if i.get('number')]
         if merge_items:
             if not self.doMergeChanges(merger, merge_items,
                                        args['repo_state']):
@@ -1370,11 +1471,15 @@
                               '%s_ro_dirs' % opt_prefix)
         rw_dirs = get_default(self.executor_server.config, 'executor',
                               '%s_rw_dirs' % opt_prefix)
-        state_dir = get_default(self.executor_server.config, 'executor',
-                                'state_dir', '/var/lib/zuul', expand_user=True)
         ro_dirs = ro_dirs.split(":") if ro_dirs else []
         rw_dirs = rw_dirs.split(":") if rw_dirs else []
-        self.executor_server.execution_wrapper.setMountsMap(state_dir, ro_dirs,
+
+        ro_dirs.append(self.executor_server.ansible_dir)
+
+        if self.executor_variables_file:
+            ro_dirs.append(self.executor_variables_file)
+
+        self.executor_server.execution_wrapper.setMountsMap(ro_dirs,
                                                             rw_dirs)
 
         popen = self.executor_server.execution_wrapper.getPopen(
@@ -1419,6 +1524,7 @@
             if timeout:
                 watchdog.stop()
                 self.log.debug("Stopped watchdog")
+            self.log.debug("Stopped disk job killer")
 
         with self.proc_lock:
             self.proc = None
@@ -1476,6 +1582,9 @@
             % playbook.canonical_name_and_path])
         cmd.extend(['-e', 'zuul_execution_branch=%s' % str(playbook.branch)])
 
+        if self.executor_variables_file is not None:
+            cmd.extend(['-e@%s' % self.executor_variables_file])
+
         result, code = self.runAnsible(
             cmd=cmd, timeout=timeout,
             config_file=playbook.ansible_config,
diff --git a/zuul/lib/yamlutil.py b/zuul/lib/yamlutil.py
index 2419906..2c84b06 100644
--- a/zuul/lib/yamlutil.py
+++ b/zuul/lib/yamlutil.py
@@ -13,7 +13,8 @@
 from yaml import YAMLObject, YAMLError  # noqa: F401
 
 try:
-    from yaml import cyaml
+    # Explicit type ignore to deal with provisional import failure
+    from yaml import cyaml  # type: ignore
     import _yaml
     SafeLoader = cyaml.CSafeLoader
     SafeDumper = cyaml.CSafeDumper
diff --git a/zuul/merger/merger.py b/zuul/merger/merger.py
index 93340fa..c5d1f2a 100644
--- a/zuul/merger/merger.py
+++ b/zuul/merger/merger.py
@@ -225,9 +225,9 @@
         except AssertionError:
             origin.fetch(ref)
 
-    def fetchFrom(self, repository, refspec):
+    def fetchFrom(self, repository, ref):
         repo = self.createRepoObject()
-        repo.git.fetch(repository, refspec)
+        repo.git.fetch(repository, ref)
 
     def createZuulRef(self, ref, commit='HEAD'):
         repo = self.createRepoObject()
@@ -391,11 +391,11 @@
         try:
             mode = item['merge_mode']
             if mode == zuul.model.MERGER_MERGE:
-                commit = repo.merge(item['refspec'])
+                commit = repo.merge(item['ref'])
             elif mode == zuul.model.MERGER_MERGE_RESOLVE:
-                commit = repo.merge(item['refspec'], 'resolve')
+                commit = repo.merge(item['ref'], 'resolve')
             elif mode == zuul.model.MERGER_CHERRY_PICK:
-                commit = repo.cherryPick(item['refspec'])
+                commit = repo.cherryPick(item['ref'])
             else:
                 raise Exception("Unsupported merge mode: %s" % mode)
         except git.GitCommandError:
@@ -410,9 +410,10 @@
         return commit
 
     def _mergeItem(self, item, recent, repo_state):
-        self.log.debug("Processing refspec %s for project %s/%s / %s ref %s" %
-                       (item['refspec'], item['connection'],
-                        item['project'], item['branch'], item['ref']))
+        self.log.debug("Processing ref %s for project %s/%s / %s uuid %s" %
+                       (item['ref'], item['connection'],
+                        item['project'], item['branch'],
+                        item['buildset_uuid']))
         repo = self.getRepo(item['connection'], item['project'])
         key = (item['connection'], item['project'], item['branch'])
 
@@ -451,7 +452,7 @@
             zuul_ref = None
             try:
                 repo = self.getRepo(connection, project)
-                zuul_ref = branch + '/' + item['ref']
+                zuul_ref = branch + '/' + item['buildset_uuid']
                 if not repo.getCommitFromRef(zuul_ref):
                     repo.createZuulRef(zuul_ref, mrc)
             except Exception:
diff --git a/zuul/model.py b/zuul/model.py
index ed77864..ed50164 100644
--- a/zuul/model.py
+++ b/zuul/model.py
@@ -1841,12 +1841,10 @@
         patchset = None
         oldrev = None
         newrev = None
-        refspec = None
         branch = None
         if hasattr(self.change, 'number'):
             number = self.change.number
             patchset = self.change.patchset
-            refspec = self.change.refspec
         if hasattr(self.change, 'newrev'):
             oldrev = self.change.oldrev
             newrev = self.change.newrev
@@ -1860,9 +1858,9 @@
         return dict(project=project.name,
                     connection=connection_name,
                     merge_mode=self.current_build_set.getMergeMode(),
-                    refspec=refspec,
+                    ref=self.change.ref,
                     branch=branch,
-                    ref=self.current_build_set.ref,
+                    buildset_uuid=self.current_build_set.uuid,
                     number=number,
                     patchset=patchset,
                     oldrev=oldrev,
@@ -1951,7 +1949,6 @@
         self.number = None
         self.url = None
         self.patchset = None
-        self.refspec = None
 
         self.needs_changes = []
         self.needed_by_changes = []
@@ -2008,6 +2005,7 @@
         # common
         self.type = None
         self.branch_updated = False
+        self.ref = None
         # For management events (eg: enqueue / promote)
         self.tenant_name = None
         self.project_hostname = None
@@ -2019,12 +2017,10 @@
         self.change_number = None
         self.change_url = None
         self.patch_number = None
-        self.refspec = None
         self.branch = None
         self.comment = None
         self.state = None
         # ref-updated
-        self.ref = None
         self.oldrev = None
         self.newrev = None
         # For events that arrive with a destination pipeline (eg, from
diff --git a/zuul/sphinx/__init__.py b/zuul/sphinx/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/zuul/sphinx/__init__.py
diff --git a/zuul/sphinx/zuul.py b/zuul/sphinx/zuul.py
new file mode 100644
index 0000000..a4fb127
--- /dev/null
+++ b/zuul/sphinx/zuul.py
@@ -0,0 +1,120 @@
+# Copyright 2017 Red Hat, Inc.
+#
+# 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.
+
+from sphinx import addnodes
+from sphinx.domains import Domain
+from sphinx.directives import ObjectDescription
+
+
+class ZuulConfigObject(ObjectDescription):
+    object_names = {
+        'attr': 'attribute',
+        'configobject': 'configuration object',
+    }
+
+    def get_path(self):
+        obj = self.env.ref_context.get('zuul:configobject')
+        attr_path = self.env.ref_context.get('zuul:attr_path', [])
+        path = []
+        if obj:
+            path.append(obj)
+        if attr_path:
+            path.extend(attr_path)
+        return path
+
+    @property
+    def parent_pathname(self):
+        return '.'.join(self.get_path())
+
+    @property
+    def full_pathname(self):
+        name = self.names[-1].lower()
+        return '.'.join(self.get_path() + [name])
+
+    def add_target_and_index(self, name, sig, signode):
+        targetname = self.objtype + '-' + self.full_pathname
+        if targetname not in self.state.document.ids:
+            signode['names'].append(targetname)
+            signode['ids'].append(targetname)
+            signode['first'] = (not self.names)
+            self.state.document.note_explicit_target(signode)
+
+        objname = self.object_names.get(self.objtype, self.objtype)
+        if self.parent_pathname:
+            indextext = '%s (%s of %s)' % (name, objname,
+                                           self.parent_pathname)
+        else:
+            indextext = '%s (%s)' % (name, objname)
+        self.indexnode['entries'].append(('single', indextext,
+                                          targetname, '', None))
+
+
+class ZuulConfigobjectDirective(ZuulConfigObject):
+    has_content = True
+
+    def before_content(self):
+        self.env.ref_context['zuul:configobject'] = self.names[-1]
+
+    def handle_signature(self, sig, signode):
+        signode += addnodes.desc_name(sig, sig)
+        return sig
+
+
+class ZuulAttrDirective(ZuulConfigObject):
+    has_content = True
+
+    option_spec = {
+        'required': lambda x: x,
+    }
+
+    def before_content(self):
+        path = self.env.ref_context.setdefault('zuul:attr_path', [])
+        path.append(self.names[-1])
+
+    def after_content(self):
+        path = self.env.ref_context.get('zuul:attr_path')
+        if path:
+            path.pop()
+
+    def handle_signature(self, sig, signode):
+        path = self.get_path()
+        for x in path:
+            signode += addnodes.desc_addname(x + '.', x + '.')
+        signode += addnodes.desc_name(sig, sig)
+        if 'required' in self.options:
+            signode += addnodes.desc_annotation(' (required)', ' (required)')
+        return sig
+
+
+class ZuulValueDirective(ZuulConfigObject):
+    has_content = True
+
+    def handle_signature(self, sig, signode):
+        signode += addnodes.desc_name(sig, sig)
+        return sig
+
+
+class ZuulDomain(Domain):
+    name = 'zuul'
+    label = 'Zuul'
+
+    directives = {
+        'configobject': ZuulConfigobjectDirective,
+        'attr': ZuulAttrDirective,
+        'value': ZuulValueDirective,
+    }
+
+
+def setup(app):
+    app.add_domain(ZuulDomain)