Release Notes

In Development

New Features

  • The action “promote” is now available via the tenant-scoped REST API using the zuul cli.

  • Builds in the SQL reporter have a “held” attribute set to True if the build triggered a autohold request. Builds can be filtered by held status.

  • Subdirectories of zuul.d or .zuul.d can be ignored when reading configuration by placing a .zuul.ignore file inside them.

  • The find module is now allowed to run on the executor.

  • Changes can now be dequeued via the Github checks API. If a github reporter is configured to use the checks API, all running checks will provide a custom “Abort” action.

  • Zuul now respects GitHub review requirements when enqueuing into gate pipelines. This works for and GitHub Enterprise starting with version 2.21.0.

  • Jobs may specify the new intermediate flag to note they may only be inherited by abstract jobs. This can be useful if building a job hierarchy where wish to limit where a base job is instantiated.

  • The builds/ and buildset/ API endpoints now include information about retried builds. They are called non-final as those are all builds that were retried at least once and thus weren’t visible to the user so far.

    The builds/ API can filter those retried builds and you might exclude them from API result by setting final=false in the API request.

  • Host key checking is now disabled for a host in the generated Ansible inventory if host-key-checking is set to False in the corresponding nodepool config.

Upgrade Notes

  • Support for Ansible 2.7 has been removed.

  • If using a SQL reporter, the zuul_builds table will be updated with a new ‘held’ column. The zuul-scheduler and zuul-web services need to be restarted together for the change to take effect.

  • Previously the SqlReporter would record the job name in the database in place of the url if the url was empty. This has now been updated to store a null in the database for that case. Zuul will automatically run a database migration to correct old values.

  • Support for running Zuul under Python 3.5 has been dropped.

  • As further integration with the web interface is planned, the web.root setting in zuul.conf is marked required and future releases may error if it is missing. Please add it to your configuration now. See tenant.web-root for additional information about whitelabel tenants.

Bug Fixes



This is expected to be the last 3.x release of Zuul (barring any unanticipated bugfix releases).

The next release of Zuul, 4.0.0, will require the following deployment changes:

  • TLS ZooKeeper connections

  • Network connectivity from all components to ZooKeeper

  • A SQL database

These features are supported now, so it is important that you take this time to switch your ZooKeeper connection to use TLS, and configure a SQL connection. Even though only some Zuul components connect to ZooKeeper today, you should ensure that the [zookeeper] section is present in zuul.conf for all components, and that they have network connectivity to the ZooKeeper servers. Doing so will make the upgrade to 4.0.0 seamless.

These changes are in support of ongoing work to enable multiple scheduler processes for scaling and availability. After the 4.0.0 release, it is anticipated that further upgrades to Zuul made in support of this work will be done with minimal disruption in the course of normal releases.

New Features

  • Pipelines now provide a pipeline.dequeue reporter action so that reporters may run whenever an item is dequeued. The dequeue reporters will only apply if the item wasn’t a success or failure.

  • Support for generating dynamic Badges has been added.

  • The annotation levels for the file comments reported via Github checks API are now configurable in zuul_return. Each file comment entry can provide an optional level parameter [info|warning|error] that will be picked up by the Github reporter.

    For more details on how to provide file comments from Zuul, see the documentation of the Return Values.

  • Zuul now matches tag items against their containing branches. This makes it simpler to have release jobs in-tree. See job.branches for details.

  • The zuul-executor now also pauses all merger related tasks when it’s paused. Further the zuul-merger can also be paused by running zuul-merger pause.

  • The serial pipeline manager has been added. It is designed to handle serialized deployment pipelines where supercedent is unsuitable in the case that not all jobs run on every merge.

  • Add new timezone selector in web interface

  • Zuul now supports a TLS secured connection to ZooKeeper.

Upgrade Notes

  • Support for Ansible 2.6 has been removed.

  • Ansible 2.7 is now deprecated since it only receives security updates and will be end of life soon.

  • Zuul now defaults to Ansible 2.9 if no version is specified.

  • With GitHub the Zuul app now requires permissions to read/write check runs.

  • The default behavior of the tools/ helper script is now to strip incoming input of leading and trailing whitespace. A new --no-strip option has been added to support people with secrets that contain valid leading or trailing whitespace.

  • Please configure your Zuul to use TLS secured connection. Running Zuul with an unsecured connection to ZooKeeper is deprecated and will be unsupported in a future release. See zookeeper for details.

Security Issues

  • Zuul no longer adds environment variables starting with the ZUUL_ prefix to ansibles environment which could result in secrets being exposed.

Bug Fixes

  • In some cases (such as when an older version of kubectl is present on the executor, or the kubectl on the executor is from OpenShift), streaming logs from Kubernetes or OpenShift pods did not work. The log streaming system has been corrected to work with a wider range of kubectl versions and error logging has been improved.


New Features

  • The Github driver can now report file comments via Github checks API. If a github reporter is configured to use the checks API, file comments provided via zuul_return will automatically be reported to the pull request in Github.

    For more details on how to provide file comments from Zuul, see the documentation of the Return Values.

Upgrade Notes

  • Kubectl and socat must now be installed on Zuul executors if using Kubernetes or OpenShift pod resources from Nodepool. Additionally, Nodepool version 3.12.0 or later is required, and the “start-zuul-console” role from zuul-jobs should be run in the pre-playbook of your base job.

Deprecation Notes

  • Running the zuul processes with the -d switch to enforce running in foreground is now deprecated. Switch to use -f instead for this purpose. The -d switch will change to just enable debug logging in the future.

Security Issues

  • The add_host host-vars blacklist is no longer effective for trusted playbook.

Bug Fixes

  • Previously, no output from shell or command tasks on pods was placed in the job output; that has been corrected and streaming output is now available.


New Features

  • The Github driver now has a basic support for the Github checks API. To enable reporting build results via the checks API one can configure the the new pipeline.<reporter>.<github source>.check attribute on the Github reporter. It’s also possible to trigger on a requested or completed check_run.

    To be able to use the checks API, zuul must be authenticated as Github app. For more information about the necessary requirements, please see the GitHub driver documentation.

Security Issues

  • The add_host module attributes that can be used to bypass localhost command execution are now also blacklisted using extra-vars to prevent abuse through untrusted host_vars.


Bug Fixes

  • When using GitHub app authentication the fallback to anonymous access was broken for repositories not having installed the zuul app.


New Features

Upgrade Notes

  • The default for <gerrit connection>.auth_type has changed from digest to basic. Digest authentication has not been supported in Gerrit since version 2.15.

    If your Zuul connects to an older version of Gerrit via HTTP authentication, you may now need to explicitly set this value.

Deprecation Notes

  • Authentication: the JWT driver “RS256withJWKS” is deprecated in favor of the “OpenIDConnect” driver. The “OpenIDConnect” driver simplifies configuration for administrators and is better aligned with OIDC configuration discovery conventions.


Bug Fixes

  • Files matcher has been fixed to act like irrelevant files matcher when no files are present in the tested change, i.e. it now matches such empty changes instead of rejecting them.


New Features

  • Zuul now supports triggering a smart reconfiguration by using the command zuul-scheduler smart-reconfigure.

Upgrade Notes

  • Zuul no longer supports Ansible 2.5 for running jobs.


New Features

  • Zuul now supports Ansible 2.9 for running jobs.

Upgrade Notes

  • The default version of Ansible used by Zuul jobs has been changed to 2.8. See job.ansible-version for more information.

  • As a result of switching to Ansible 2.8, it is possible for the ansible_python_interpreter version of your nodeset to change to ‘auto’. This could result in your jobs now running under a different version of python than prior to this release. See Ansible and Python 3 for additional info.

  • Ansible 2.6 for Zuul jobs has been marked deprecated and will be removed in a future release.


New Features

Upgrade Notes

  • The Gerrit driver now has an additional option, pipeline.reporter.<gerrit reporter>.comment which may be used to suppress reporting job results as review comments. Due to the configuration syntax for Gerrit reporters, the word “comment” may no longer be used as a review label.

Other Notes

  • The –id option to both the autohold-delete and autohold-info zuul CLI commands has been removed.


Bug Fixes

  • Fixed a regression where changes with a failing job with soft dependencies would remain in the queue indefinitely.


New Features

  • Added the pipeline.enqueue reporter action so that reporters may be run when an item is enqueued into a pipeline.

  • Added the reporter action so that reporters may be run when an item is dequeued into a pipeline without having run any jobs.

  • A new zuul CLI command, autohold-info, has been added to retrieve full details for an existing autohold request.

  • Autohold requests are now stored in ZooKeeper, rather than in memory. As a result of this change, a new zuul CLI command, autohold-delete has been added to remove existing requests.

  • New scheduler options, max_hold_expiration and default_hold_expiration, are added to control how long nodes held for an autohold request remain available. The max_hold_expiration option defaults to 0, which means the held nodes will not automatically expire, and default_hold_expiration defaults to the value of max_hold_expiration.

Upgrade Notes

  • The Gerrit driver will now perform query actions over HTTP if an HTTP password is configured. In this situation, the SSH connection is now only used for receiving events. The HTTP password is not required, but it is recommended since it provides more reporting options (including line comments).


New Features

  • The maximum starting builds depending on cpu cores can be limited using executor.max_starting_builds configuration.

Security Issues

  • The synchronize rsh rsync_opts is now prohibited for security reasons as it could be used to circumvent executor host command execution restrictions.

Bug Fixes

  • Under specific conditions Zuul could fail to properly update git repos causing it to fall back to testing master. If jobs were meant to run against commits other than current master this lead to testing the wrong commit. Zuul now correctly updates repos and should test the correct commit in all cases.

    Specifically this could happen if a new branch was created off a commit in an existing branch. Then the first proposed change to this new branch would be tested against master instead.


Bug Fixes

  • Fixed Zuul dashboard not loading properly due to javascript dependencies missing.


New Features

  • Allow users to perform tenant-scoped, privileged actions either through zuul-web’s REST API or zuul’s client, based on the JWT standard. The users need a valid bearer token to perform such actions; the scope is set by matching conditions on tokens’ claims; these conditions can be defined in zuul’s tenant configuration file. Zuul supports token signing and validation using the HS256 or RS256 algorithms. External JWKS are also supported for token validation only. Current tenant-scoped actions are “autohold”, “enqueue” and “dequeue”.

  • Config projects may now add any job to any project’s pipelines, regardless of the setting of allowed-projets (including the implicit setting of allowed-projects on jobs with secrets in untrusted projects).

  • It is now possible to select the merge method GitHub uses to merge a Pull Request to the base branch.

  • A new option, tenant.untrusted-projects.<project>.extra-config-paths has been added to allow an admin to indicate that Zuul should load extra configuration data from a specific project in a tenant.

    This feature may be useful to allow a project that primarily holds shared jobs or roles to include additional in-repo configuration for its own testing (which may not be relevant to other users of the project).

  • The merge-mode squash-merge is now supported for Github.

  • The job.cleanup-run attribute has been added to enable a new cleanup phase to be performed after a job execution.

  • Support for the Pagure code review system has been added.

  • Pipelines may now indicate that they supercede other pipelines with the pipeline.supercedes attribute.

    When a change is enqueued in a pipeline which supercedes others, it will be removed from the other pipelines. For example, a gate pipeline may supercede a check pipeline so that test resources are not spent running near-duplicate jobs simultaneously.

Upgrade Notes

  • If unprotected branches are excluded on a project they now also get filtered out from jobs.

  • The default value for the executor.job_dir configuration setting has been changed from /tmp to /var/lib/zuul/builds. It is important for executor.job_dir and executor.git_dir to be located on the same filesystem, so this change increases the chances that they end up on the same filesystem in most default configurations.

    The builds subdirectory will be created if it does not exist, however, /var/lib/zuul at least must exist and be writable by the Zuul user.

  • Jobs with file matchers will now automatically match if the configuration of the job is changed. This means that the Zuul configuration file no longer needs to be included in the list of files to match in order for changes to job configuration to be self-testing.

    To keep the old behavior, set job.match-on-config-updates to False.


New Features

  • Zuul now supports ansible 2.8 for running jobs.

  • Zuul now reports resource usage statistics if they are provided by nodepool.

    The following statistics are emitted:

    • zuul.nodepool.resources.tenant.{tenant}.{resource}: Gauge with the currently used resources by tenant and counter with the summed usage by tenant. e.g. cpu seconds

    • zuul.nodepool.resources.project.{project}.{resource}: Gauge with the currently used resources by project and counter with the summed usage by project. e.g. cpu seconds


Bug Fixes

  • Fixed a memory leak introduced in 3.8.0.


New Features

  • The artifacts returned by parent jobs are now also available in child jobs of the same buildset.

Security Issues

  • Fixed a bug where config (trusted) layout updates could be used pre-merge as a dynamically loaded layout. This could happen if Zuul was running with config errors that originated from outside of the config (trusted) repo. A logic error allowed code to fall through and return the trusted layout in this case.

    Users should upgrade.

Bug Fixes

  • Jobs which use the job.requires attribute and fail to have their requirements met are now recorded as “FAILED” rather than “SKIPPED”. This can happen if an earlier job which is expected to produce artifacts fails to do so due to an error.


Bug Fixes

  • When using Ansible 2.7 the uri module crashed with a module failure.


New Features

  • The ansible_python_interpreter variable is now whitelisted for the add_host task.

  • Zuul now supports ansible 2.6 for running jobs.

  • Zuul now supports ansible 2.7 for running jobs.

  • Jobs may now specify which ansible version is used to run them. The ansible version to use can now be specified by job.ansible-version.

Upgrade Notes

  • The user value in the [fingergw] configuration section previously defaulted to zuul, but now is unset by default, which will cause fingergw not to drop privileges. It is recommended that this value be explicitly set to an unprivileged user.

  • In order to support several ansible versions installed simultaneously Zuul now handles them itself in virtual environments. By default Zuul installs the needed ansible versions on startup so there is no further user action required. However it is recommended to pre-install the ansible environments during installation by invoking zuul-manage-ansible.

  • The hosts value in the [zookeeper] configuration section previously defaulted to localhost:2181, but now is unset by default. This value is required and must be explicitly set (and the documentation has always indicated this).


Security Issues

  • The raw module had not been blocked for local tasks. This could be used to bypass protection and execute commands on the executor.


New Features

  • Artifacts may now include a metadata field for storing arbitrary metadata about the artifacts in the SQL database.

  • The attribute now supports a single or list of playbooks.

  • Support for expressing artifact or other resource dependencies between jobs running on different changes with a dependency relationship (e.g., a container image built in one project and consumed in a second project) has been added via the job.provides and job.requires job attributes.

  • The job.dependencies attribute may now be used to express “soft” dependencies – that is, to indicate a job should run after another completes, but only if it runs at all. For example, a deployment job which should always run, but depends on a build job which only runs if the source code is changed.

Upgrade Notes

  • Service Workers are now disabled by default in the Javascript dashboard. Deployers who wish to enable them need to set REACT_APP_ENABLE_SERVICE_WORKER

  • Zuul recently added the job variable zuul.message. This can contain jinja tags which can cause problems accessing the zuul variable in the job. Because of this the message is now base64 encoded and any job evaluating this variable needs to be changed from {{ zuul.message }} to {{ zuul.message | b64decode }}.


New Features

  • The executor.min_avail_mem setting now takes cgroup limits into account. There is also a new metric zuul.executor.<executor>.pct_used_ram_cgroup available.

  • The job.secrets.pass-to-parent attribute has been added to allow secrets to be made available to playbooks in parent jobs (for example, to allow for jobs which are designed to use secrets, but leave it to child jobs to actually supply them). See also the Secret documentation.

  • The restriction on using known_hosts in playbooks has been lifted.

Upgrade Notes

  • The zuul_return module has been converted to an Ansible action plugin. Job playbooks no longer need to use delegate_to or a localhost only play with this module as action plugin by default run on localhost.

Security Issues

  • Jobs with secrets in untrusted projects now automatically set allowed-projects.

    It is possible to circumvent the use of allowed-projects in untrusted projects by creating a change which Depends-On a change which alters a project definition. This behavior may be unexpected, so documentation has been updated with warnings to avoid relying on it in sensitive cases.

    It may have been possible to expose a secret, or use resources protected by a secret, if a job using a secret was defined in an untrusted project on a system with an independent pre-merge post-review pipeline – that is, a pipeline with post-review set to true, manager set to independent, and which operated on changes before they merged.

    To prevent disclosure or use in this situation, allowed-projects is now automatically set to the current project when a secret is used in a job defined in an untrusted project, and it can not be overridden.

Bug Fixes

  • Untrusted playbooks no longer see ‘Adding hosts ssh with ansible_user to the inventory is prohibited’ when using the add_host Ansible task on localhost.

  • Fixed an issue where a trailing slash on the baseurl of a git driver connection config could cause an indefinite job hang.


New Features

  • Jobs may now return artifact URLs and they will be stored in the SQL database (if configured). See Returning artifact URLs for usage.

  • One or more zuul executors can now be added to a This is helpful if a cloud does not have any public IP addresses for nodepool nodes. Now you’ll be able to have a zuul executor on the same private network as your nodepool nodes.

  • The Ansible inventory file now includes nodepool.host_id variable if the node was launched using the OpenStack Nodepool driver.

  • A new scheduler option, scheduler.relative_priority, can be used to instruct Nodepool to fulfull requests from less-busy projects more quickly.

Upgrade Notes

  • The zuul.nodepool statistics have been moved under zuul.nodepool.requests to allow sub-stats to work correctly. For example zuul.nodepool.requested has become The previously missing label and size counters are now available at zuul.nodepool.requests.<state>.<size|label>. For more info see the monitoring documentation.

  • The zuul-web service now requires access to ZooKeeper, as a result you may need to update your firewall allow access from the service. Additionally, zuul.conf should now contain a zookeeper configuration section.


New Features

  • A job using a semaphore now can configure if it should acquire the it before requesting resources or just before running.

Upgrade Notes

  • The acquiring behavior of jobs with semaphores has been changed. Up to now a job requested resources and aquired the semaphore just before it started to run. However this could lead to a high amount of resource waste. Instead jobs now acquire the semaphore before requesting the resources by default. This behavior can be overridden by jobs using job.semaphore.resources-first if some waste of resources is acceptable.

Security Issues

  • The add_host module options are restricted to a hostname, port, user and password. Previously, malicious options could be used to bypass protection and execute tasks on the executor. Only ssh and kubectl connection are authorized.

Bug Fixes

  • Jobs that encountered unreachable nodes are now correctly detected and retried.


New Features

  • A local project key file URI (eg. file:///path/to/ is now supported by the tool. This allows encrypting secrets without directly accessing the Zuul web API to retrieve the project key.

  • Zuul now supports triggering a full reconfiguration by using the command zuul-scheduler full-reconfigure.

  • The Gerrit driver can now (optionally) report via HTTP instead of SSH. In the future, this will be used to report file and line comments (the SSH API only supports review messages).

  • Zuul now supports leaving file comments, though currently only when using the Gerrit driver. See the documentation for zuul_return for details.

  • A job now can pause itself using Return Values and let the child jobs run until they are finished. This can be used to serve some service which can be used by the child jobs.

  • An SSH keypair is now generated for every project and may be used in post-review jobs to access systems which trust that project.

  • The Zuul web dashboard has been rewritten in React.

  • The restriction on using add_host in playbooks has been lifted.

  • A new Build page in the web interface enable displaying a single Build information.

  • A new Notification Drawer and a ConfigErrors page in the web interface enable displaying the config-errors endpoint data.

  • A new Job page in the web interface enable browsing through job configuration.

  • Client certificate locations to be used by winrm connections can be configured now.

Upgrade Notes

  • The Zuul web dashboard is now a single index.html and static offload server needs new rewrite rules. Check the install instruction for backward compatible rewrite rules. Note that serving the web dashboard from a sub-directory requires the application to be rebuilt using the desired homepage location.

Deprecation Notes

  • Signal based triggering of a full reconfiguration via sending SIGHUP to the zuul-scheduler PID is deprecated. Use the command zuul-scheduler full-reconfigure now.


New Features

  • Zuul client got a new command ‘tenant-conf-check’. This command validates the schema of the tenant configuration and exits -1 if errors have been detected.

  • A new Ansible inventory variable zuul.child_jobs which is a list of the first level child jobs to be run after a job has finished successfully.

  • Jobs are now able to use the job.extra-vars which will use the –extra-vars flag when a job runs.

  • Project and project-templates may now create variables via a vars configuration entry. Jobs can access these at runtime in the same manner as job variables.

  • The supercedent pipeline manager has been added. It is designed to make post-merge artifact build pipelines more efficient.

  • The dequeue command has been added to the Zuul CLI. It allows operators to stop a given buildset at will.

  • It is now possible to use zuul_return to skip child jobs. You can use the zuul.child_jobs inventory variable to get a list of child jobs configured to run, then use zuul_return to modify the list. Any child job not in zuul_return zuul.child_jobs will be skipped. See Return Values for examples.

Bug Fixes

  • Project Templates are now branch-aware and behave more like project stanzas. If a template is defined on a branch, it will only apply to changes to that branch.

  • The timer trigger does not enqueue an event for every branch of every project anymore and it now only processes projects actually using the pipeline triggered by a timer.


New Features

  • The GitHub driver can determine the required status checks of pull requests which are needed for entering a gate pipeline. This eliminates the need to hard code required status checks in the gate pipeline and makes interoperation with other GitHub apps much more flexible.

  • Zuul is now ables to start with an invalid configuration. When reading configuration files from project repositories, if an issue is detected, Zuul will store the issue and skip the broken block of configuration. Issues are then reported in the scheduler log at the end of the configuration phase.

  • The json log now also contains the role name and the uuid similar to the task entry.

Upgrade Notes

  • Files (and irrelevant-files) matchers are now overridable. Zuul now uses only branch matchers to collect job variants. Once those variants are collected, they are combined, and the files and irrelevant-files attributes are inherited and overridden as any other job attribute. The final values are used to determine whether the job should ultimately run.

  • Zuul now uses Ansible 2.5.

Security Issues

  • Tobias Henkel (BMW Car IT GmbH) discovered a vulnerability which is fixed in this release. If nodes become offline during the build, the no_log attribute of a task is ignored. If the unreachable error occurred in a task used with a loop variable (e.g., with_items), the contents of the loop items would be printed in the console. This could lead to accidentally leaking credentials or secrets. MITRE has assigned CVE-2018-12557 to this vulnerability.

Bug Fixes

  • Untrusted playbooks no longer see ‘Executing local code is prohibited’ when using the zuul_return Ansible task.


New Features

  • The project.default-branch option is now documented. It has been supported since version 3.0.0, but was omitted from the documentation.

  • Project stanzas now support regex matching of This can be used to apply project pipelines to many projects at once.

Deprecation Notes

  • The merge-mode and default-branch attributes may no longer appear in a Project Template stanza.

Bug Fixes

  • Configuration loading for dynamic configuration changes (i.e., changes to zuul.yaml files) is now significantly more CPU and memory efficient, incurring only a slight penalty compared to normal changes.


New Features

Upgrade Notes

  • The fb-re2 python library is added as a dependency; this may required the installation of the re2 library and header files in order to build.

  • The build start and end times are now stored as UTC in the database. Since there is no localization done on zuul web side, the zuul api also exposes these times as UTC now.

Bug Fixes

  • Story 2001441 is fixed. Failure by one Zuul reporter will not short circuit the reporting of other reporters. This ensures as much information as possible is reported for each change even if some failures occur. Note that the build set status is changed to ‘ERROR’ after the first failed reporter.

  • The script has been adapted to the new zuul-web api routes.


New Features

  • Git repositories will have a origin remote with refs pointing to the previous change in the speculative state.

    This allows jobs to determine the commits that are part of a change, which was not possible before. The remote URL is set to a bogus value which won’t work with git commands that need to talk to the remote repository.

  • PostgreSQL is now officially supported as database backend. See <sql connection> on how to configure database connections.

Upgrade Notes

  • The alembic version table is fixed to being prefixed too. This is necessary when using <sql connection>.table_prefix. However if you are already using table_prefix you will need to rename the table alembic_version to <prefix>alembic_version before starting Zuul. Otherwise zuul will try to create the tables again and fail. If you’re not using table_prefix you can safely ignore this.

Bug Fixes

  • Zuul role repository checkouts now honor job.override-checkout.

    Previously, when a Zuul role was specified for a job, Zuul would usually checkout the master branch, unless that repository appeared in the dependency chain for a patch. It will now follow the usual procedure for determining the branch to check out, including honoring job.override-checkout options.

    This may alter the behavior of currently existing jobs. Depending on circumstances, you may need to set job.override-checkout or copy roles to other branches of projects.