2290 lines
48 KiB
ReStructuredText
2290 lines
48 KiB
ReStructuredText
. display in 68x24
|
|
.. display in 88x24
|
|
|
|
.. pygments yaml? (only file breaks (---) tinted)
|
|
.. slide on high level v3 changes
|
|
.. slide on nodepool
|
|
|
|
.. transition:: dissolve
|
|
:duration: 0.4
|
|
|
|
Test Slide
|
|
==========
|
|
.. hidetitle::
|
|
|
|
.. ansi:: images/testslide.ans
|
|
|
|
Preshow
|
|
=======
|
|
.. hidetitle::
|
|
|
|
.. ansi:: images/cursor.ans images/cursor2.ans
|
|
|
|
Zuul
|
|
====
|
|
.. hidetitle::
|
|
.. ansi:: images/title.ans
|
|
|
|
Important Links
|
|
===============
|
|
|
|
* https://opendev.org/zuul
|
|
* https://zuul-ci.org/docs/zuul
|
|
* https://zuul-ci.org/docs/zuul-jobs/
|
|
* https://docs.openstack.org/infra/openstack-zuul-jobs/
|
|
* freenode:#zuul
|
|
* https://opendev.org/inaugust/inaugust.com/src/branch/master/src/zuulv3/tutorial.rst
|
|
|
|
Overview
|
|
========
|
|
|
|
* Discussion of concepts
|
|
* Installation of software
|
|
* Configurting Zuul
|
|
* Writing jobs
|
|
|
|
Please Ask Questions
|
|
====================
|
|
|
|
Installation of Software
|
|
========================
|
|
|
|
Ways to Install Zuul
|
|
====================
|
|
|
|
* Windmill: https://opendev.org/windmill/windmill/
|
|
* Software Factory: https://softwarefactory-project.io/
|
|
* Puppet: https://opendev.org/opendev/puppet-zuul/
|
|
* Containers: https://hub.docker.com/_/zuul/
|
|
|
|
Today we'll be using Containers with docker-compose
|
|
===================================================
|
|
|
|
Getting Started
|
|
===============
|
|
|
|
While we talk about other things ...
|
|
|
|
* Install docker, docker-compose, git-review
|
|
|
|
Debian/Ubuntu:
|
|
|
|
::
|
|
|
|
apt-get install docker-compose git git-review
|
|
|
|
Red Hat / SuSE
|
|
|
|
::
|
|
|
|
yum install docker-compose git git-review
|
|
|
|
* mkdir -p ~/src/opendev.org/zuul
|
|
* cd ~/src/opendev.org/zuul
|
|
* git clone https://opendev.org/zuul/zuul
|
|
* cd zuul
|
|
* cd doc/source/admin/examples
|
|
* docker-compose up
|
|
|
|
Output in docker-compose window
|
|
===============================
|
|
|
|
* All services running with debug logging to stdout
|
|
* Tons of information will have been output - including some errors
|
|
* Zuul connects to Gerrit before it's fully configured
|
|
* As it becomes configured, Zuul notices and becomes happy
|
|
* Once happy, it should stablize and become idle
|
|
|
|
We'll come back to this
|
|
=======================
|
|
|
|
It's going to do a bunch of network - and this is a conference.
|
|
|
|
Red Hat
|
|
=======
|
|
.. hidetitle::
|
|
.. container:: handout
|
|
i work for
|
|
|
|
.. ansi:: images/redhat.ans
|
|
|
|
OpenStack
|
|
=========
|
|
.. hidetitle::
|
|
.. ansi:: images/openstack.ans
|
|
|
|
OpenDev
|
|
=======
|
|
|
|
::
|
|
|
|
"most insane CI infrastructure I've ever been a part of"
|
|
|
|
-- Alex Gaynor
|
|
|
|
"OpenStack Infra are like the SpaceX of CI"
|
|
|
|
-- Emily Dunham
|
|
|
|
Zuul
|
|
====
|
|
.. hidetitle::
|
|
.. ansi:: images/zuul.ans
|
|
|
|
|
|
What Zuul does
|
|
==============
|
|
|
|
* "Speculative Future State"
|
|
* multiple repositories
|
|
* integrated deliverable
|
|
* gated commits
|
|
* testing like deployment
|
|
|
|
Our Use Case
|
|
============
|
|
|
|
OpenStack Is
|
|
============
|
|
|
|
* Federated
|
|
* Distributed
|
|
* Large
|
|
|
|
Federated
|
|
=========
|
|
|
|
* Hundreds of involved companies
|
|
* Hundreds of sub-projects
|
|
* "One" deliverable
|
|
* Union of priorities/use cases
|
|
* "Decisions are made by those who show up"
|
|
|
|
Impact of being Federated
|
|
=========================
|
|
|
|
* No company can appoint people to positions in the project
|
|
* The project cannot fire anyone
|
|
* Heavy reliance on consensus
|
|
* CI system doesn't assume anyone is "in charge"
|
|
|
|
Distributed
|
|
===========
|
|
|
|
* There is no office
|
|
* Contributor base is global
|
|
* Multitude of contributor backgrounds
|
|
|
|
Impact of being Distributed
|
|
===========================
|
|
|
|
* Tooling must empower all contributors, regardless of background,
|
|
skill level or cultural context
|
|
* Heavy preference for text-based communication
|
|
* Cannot assume US-centric needs or solutions
|
|
|
|
Sound like anybody's Day Job?
|
|
=============================
|
|
|
|
* Multiple silos
|
|
* Competing management chains
|
|
* Junior/Senior Devs, "Architects", Security Teams, Frontend/Backend
|
|
* Spread across locations
|
|
* "One" product
|
|
|
|
Large numbers of
|
|
================
|
|
|
|
* Contributors (\~2k in any given 6 month period)
|
|
* Changes
|
|
* Code Repositories (2139 as of this morning)
|
|
|
|
Not Bragging About Scale
|
|
========================
|
|
|
|
OpenStack Scale Comparison
|
|
==========================
|
|
|
|
* 2KJPH (2,000 jobs per hour)
|
|
* Build Nodes from 16 Regions of 5 Public and 4 Private OpenStack Clouds
|
|
* Rackspace, Internap, OVH, Vexxhost, CityCloud
|
|
* Linaro (ARM), Limestone, Packethost, Fortnebula
|
|
* 10,000 changes merged per month
|
|
|
|
OpenStack Scale Comparison
|
|
==========================
|
|
|
|
* 2KJPH (2,000 jobs per hour)
|
|
* Build Nodes from 16 Regions of 5 Public and 4 Private OpenStack Clouds
|
|
* Rackspace, Internap, OVH, Vexxhost, CityCloud
|
|
* Linaro (ARM), Limestone, Packethost, Fortnebula
|
|
* 10,000 changes merged per month
|
|
|
|
* By comparison, our friends at the amazing project Ansible received
|
|
13,000 changes and had merged 8,000 of them in its first 4 years.
|
|
|
|
Impact of scale
|
|
===============
|
|
|
|
* Empower teams to take care of themselves (distributed)
|
|
* Efficiency gained from shared solutions (centralized)
|
|
* Empower teams to do what they want (distributed)
|
|
* Enforce common standards or requirements (centralized)
|
|
* Zuul supports per-repo config, central config, and multiple tenants
|
|
|
|
One Zuul install is all you need for an entire Enterprise
|
|
=========================================================
|
|
|
|
One Zuul install is all you need for an entire Enterprise
|
|
=========================================================
|
|
|
|
* 7 "admins" run Zuul for OpenDev supporting 2500+ devs
|
|
* None are 100% full-time on Zuul
|
|
* Team could handle another 2500+ devs
|
|
|
|
Who Is Running Zuul?
|
|
====================
|
|
|
|
* Zuul is in production for OpenStack for 7 years (in OpenStack VMs)
|
|
|
|
Also running at:
|
|
|
|
* BMW (control plane in OpenShift)
|
|
* GoDaddy (control plane in Kubernetes)
|
|
* GoodMoney (control plane in EKS, adding GKE)
|
|
* Le Bon Coin
|
|
* Volvo
|
|
* Western Digital
|
|
* Easystack
|
|
* TungstenFabric
|
|
* Huawei OpenLab
|
|
* IBM
|
|
* Red Hat
|
|
* others ...
|
|
|
|
Developer Process In a Nutshell
|
|
===============================
|
|
|
|
* Code Review - nobody has direct commit/push access
|
|
* Gated Commits - nobody has submit permission
|
|
* Every change gated on Code Analysis, Unit Tests, Functional Tests
|
|
and End to End Integration Tests
|
|
* Run all tests (at least) twice:
|
|
* on patchset upload
|
|
* between change approval and merge
|
|
|
|
OpenStack Developer Workflow
|
|
============================
|
|
.. container:: handout
|
|
|
|
* Who has submitted a patch?
|
|
* Who wants to?
|
|
* (Who is here because the name of this talk is weird?)
|
|
|
|
::
|
|
|
|
Hack Review Test
|
|
========= ========== ==========
|
|
|
|
push approve
|
|
+-------------+ +-------------+
|
|
| | | |
|
|
+------+--+ +--v----+--+ +--v-------+
|
|
| | | | | |
|
|
| $EDITOR | | Gerrit | | Zuul |
|
|
| | | | | |
|
|
+------^--+ +--+----^--+ +--+-------+
|
|
| | | |
|
|
+-------------+ +-------------+
|
|
clone merge
|
|
|
|
Gerrit
|
|
======
|
|
.. hidetitle::
|
|
.. container:: handout
|
|
|
|
explain patch upload, zuul runs, test results displayed in gerrit
|
|
this is all the interface to zuul users need to see
|
|
|
|
switch to actual gertty screenshot
|
|
|
|
also show zuul status page
|
|
|
|
but zuul is doing a lot of work behind the scenes, and if you look
|
|
closer, this is what you see
|
|
|
|
.. ansi:: images/color-gertty.ans
|
|
|
|
Zuul in a nutshell
|
|
==================
|
|
|
|
* Listens for code events
|
|
* Prepares appropriate job config and git repo states
|
|
* Allocates nodes for test jobs
|
|
* Pushes git repo states to nodes
|
|
* Runs user-defined Ansible playbooks
|
|
* Collects/reports results
|
|
* Potentially merges change
|
|
|
|
All in Service of Gating
|
|
========================
|
|
|
|
No Tests / Manual Tests
|
|
=======================
|
|
|
|
* No test automation exists or ...
|
|
* Developer runs test suite before pushing code
|
|
* Prone to developer skipping tests for "trivial" changes
|
|
* Doesn't scale organizationally
|
|
|
|
Periodic Testing
|
|
================
|
|
|
|
* Developers push changes directly to shared branch
|
|
* CI system runs tests from time to time - report if things still work
|
|
* "Who broke the build?"
|
|
* Leads to hacks like NVIE model
|
|
|
|
Post-Merge Testing
|
|
==================
|
|
|
|
* Developers push changes directly to shared branch
|
|
* CI system is triggered by push - reports if push broke something
|
|
* Frequently batched / rolled up
|
|
* Easier to diagnose which change broke things
|
|
* Reactive - the bad changes are already in
|
|
|
|
Pre-Review Testing
|
|
==================
|
|
|
|
* Changes are pushed to code review (Gerrit Change, GitHub PR, etc)
|
|
* CI system is triggered by code review change creation
|
|
* Test results inform review decisions
|
|
* Proactive - testing code before it lands
|
|
* Reviewers can get bored waiting for tests
|
|
* Only tests code as written, not potential result of merging code
|
|
|
|
Gating
|
|
======
|
|
|
|
* Changes are pushed to code review
|
|
* Gating system is triggered by code review approval
|
|
* Gating system merges code IFF tests pass
|
|
* Proactive - testing code before it lands
|
|
* Future state resulting from merge of code is tested
|
|
* Reviewers can fire-and-forget safely
|
|
|
|
Mix and Match
|
|
=============
|
|
|
|
* Zuul supports all of those modes
|
|
* Zuul users frequently combine them
|
|
* Run pre-review (check) and gating (gate) on each change
|
|
* Post-merge/post-tag for release/publication automation
|
|
* Periodic for catching bitrot
|
|
|
|
Pipelines in Zuul
|
|
=================
|
|
|
|
* In other systems, a "pipeline" is per-job - triger, content, report
|
|
* In Zuul, a Pipeline describes a shared general workflow for changes
|
|
* Triggers
|
|
* Requirements
|
|
* Reporters
|
|
* Job *content* is separate from triggering/reporting
|
|
* Projects add Jobs to Pipelines
|
|
* Same Job can be used in multiple Pipelines - and by multiple Projects
|
|
|
|
Check Jobs
|
|
==========
|
|
|
|
* Run on patchset upload
|
|
* Verify patch as written
|
|
* Avoid wasting reviewer time on broken changes
|
|
|
|
check pipeline
|
|
==============
|
|
|
|
.. code:: yaml
|
|
|
|
- pipeline:
|
|
name: check
|
|
manager: independent
|
|
precedence: low
|
|
require:
|
|
gerrit:
|
|
open: True
|
|
current-patchset: True
|
|
trigger:
|
|
gerrit:
|
|
- event: patchset-created
|
|
- event: change-restored
|
|
- event: comment-added
|
|
comment: (?i)^(Patch Set [0-9]+:)?( [\w\\+-]*)*(\n\n)?\s*recheck
|
|
- event: comment-added
|
|
require-approval:
|
|
- Verified: [-1, -2]
|
|
username: zuul
|
|
approval:
|
|
- Workflow: 1
|
|
success:
|
|
gerrit:
|
|
Verified: 1
|
|
failure:
|
|
gerrit:
|
|
Verified: -1
|
|
|
|
Gate Triggering in Gerrit
|
|
=========================
|
|
|
|
* Gate jobs run between Code Review Approval and Merging
|
|
* "Workflow" Label in Gerrit
|
|
* Approvers have ability to vote +1 in Workflow
|
|
* Nobody sees the Submit button
|
|
* Zuul runs Gate jobs on Workflow+1 - Merges on Success
|
|
|
|
gate pipeline
|
|
=============
|
|
|
|
.. code:: yaml
|
|
|
|
- pipeline:
|
|
name: gate
|
|
manager: dependent
|
|
post-review: True
|
|
require:
|
|
gerrit:
|
|
open: True
|
|
current-patchset: True
|
|
approval:
|
|
- Workflow: 1
|
|
trigger:
|
|
gerrit:
|
|
- event: comment-added
|
|
approval:
|
|
- Workflow: 1
|
|
start:
|
|
gerrit:
|
|
Verified: 0
|
|
success:
|
|
gerrit:
|
|
Verified: 2
|
|
submit: true
|
|
failure:
|
|
gerrit:
|
|
Verified: -2
|
|
|
|
Multi-repository integration
|
|
============================
|
|
|
|
* Multiple source repositories are needed for deliverable
|
|
* Future state to be tested is the future state of all involved repos
|
|
|
|
To test proposed future state
|
|
=============================
|
|
|
|
* Get tip of each project. Merge appropriate change(s). Test.
|
|
* Changes must be serialized, otherwise state under test is invalid.
|
|
* Integrated deliverable repos share serialized queue
|
|
|
|
Speculative Execution
|
|
=====================
|
|
|
|
* Correct parallel processing of serialized future states
|
|
* Create virtual serial queue of changes for each deliverable
|
|
* Assume each change will pass its tests
|
|
* Test successive changes with previous changes applied to starting state
|
|
|
|
Nearest Non-Failing Change
|
|
==========================
|
|
|
|
(aka 'The Jim Blair Algorithm')
|
|
|
|
* If a change fails, move it aside
|
|
* Cancel all test jobs behind it in the queue
|
|
* Reparent queue items on the nearest non-failing change
|
|
* Restart tests with new state
|
|
|
|
Zuul Simulation
|
|
===============
|
|
.. transition:: pan
|
|
.. container:: handout
|
|
|
|
* todo
|
|
|
|
.. ansi:: images/zsim-00.ans
|
|
|
|
Zuul Simulation
|
|
===============
|
|
.. transition:: cut
|
|
.. container:: handout
|
|
|
|
* todo
|
|
|
|
.. ansi:: images/zsim-01.ans
|
|
|
|
Zuul Simulation
|
|
===============
|
|
.. transition:: cut
|
|
.. container:: handout
|
|
|
|
* todo
|
|
|
|
.. ansi:: images/zsim-02.ans
|
|
|
|
Zuul Simulation
|
|
===============
|
|
.. transition:: cut
|
|
.. container:: handout
|
|
|
|
* todo
|
|
|
|
.. ansi:: images/zsim-03.ans
|
|
|
|
Zuul Simulation
|
|
===============
|
|
.. transition:: cut
|
|
.. container:: handout
|
|
|
|
* todo
|
|
|
|
.. ansi:: images/zsim-04.ans
|
|
|
|
Zuul Simulation
|
|
===============
|
|
.. transition:: cut
|
|
.. container:: handout
|
|
|
|
* todo
|
|
|
|
.. ansi:: images/zsim-05.ans
|
|
|
|
Zuul Simulation
|
|
===============
|
|
.. transition:: cut
|
|
.. container:: handout
|
|
|
|
* todo
|
|
|
|
.. ansi:: images/zsim-06.ans
|
|
|
|
Zuul Simulation
|
|
===============
|
|
.. transition:: cut
|
|
.. container:: handout
|
|
|
|
* todo
|
|
|
|
.. ansi:: images/zsim-07.ans
|
|
|
|
Zuul Simulation
|
|
===============
|
|
.. transition:: cut
|
|
.. container:: handout
|
|
|
|
* todo
|
|
|
|
.. ansi:: images/zsim-08.ans
|
|
|
|
Zuul Simulation
|
|
===============
|
|
.. transition:: cut
|
|
.. container:: handout
|
|
|
|
* todo
|
|
|
|
.. ansi:: images/zsim-09.ans
|
|
|
|
Zuul Simulation
|
|
===============
|
|
.. transition:: cut
|
|
.. container:: handout
|
|
|
|
* todo
|
|
|
|
.. ansi:: images/zsim-10.ans
|
|
|
|
Zuul Simulation
|
|
===============
|
|
.. transition:: cut
|
|
.. container:: handout
|
|
|
|
* todo
|
|
|
|
.. ansi:: images/zsim-11.ans
|
|
|
|
Zuul Simulation
|
|
===============
|
|
.. transition:: cut
|
|
.. container:: handout
|
|
|
|
* todo
|
|
|
|
.. ansi:: images/zsim-12.ans
|
|
|
|
Zuul Simulation
|
|
===============
|
|
.. transition:: cut
|
|
.. container:: handout
|
|
|
|
* todo
|
|
|
|
.. ansi:: images/zsim-13.ans
|
|
|
|
Zuul Simulation
|
|
===============
|
|
.. transition:: cut
|
|
.. container:: handout
|
|
|
|
* todo
|
|
|
|
.. ansi:: images/zsim-14.ans
|
|
|
|
Zuul Simulation
|
|
===============
|
|
.. transition:: cut
|
|
.. container:: handout
|
|
|
|
* todo
|
|
|
|
.. ansi:: images/zsim-15.ans
|
|
|
|
Zuul Simulation
|
|
===============
|
|
.. transition:: cut
|
|
.. container:: handout
|
|
|
|
* todo
|
|
|
|
.. ansi:: images/zsim-16.ans
|
|
|
|
Zuul Simulation
|
|
===============
|
|
.. transition:: cut
|
|
.. container:: handout
|
|
|
|
* todo
|
|
|
|
.. ansi:: images/zsim-17.ans
|
|
|
|
Zuul Simulation
|
|
===============
|
|
.. transition:: cut
|
|
.. container:: handout
|
|
|
|
* todo
|
|
|
|
.. ansi:: images/zsim-18.ans
|
|
|
|
Zuul Simulation
|
|
===============
|
|
.. transition:: cut
|
|
.. container:: handout
|
|
|
|
* todo
|
|
|
|
.. ansi:: images/zsim-19.ans
|
|
|
|
Zuul Simulation
|
|
===============
|
|
.. transition:: cut
|
|
.. container:: handout
|
|
|
|
* todo
|
|
|
|
.. ansi:: images/zsim-20.ans
|
|
|
|
Zuul Simulation
|
|
===============
|
|
.. transition:: cut
|
|
.. container:: handout
|
|
|
|
* todo
|
|
|
|
.. ansi:: images/zsim-21.ans
|
|
|
|
Zuul Simulation
|
|
===============
|
|
.. transition:: cut
|
|
.. container:: handout
|
|
|
|
* todo
|
|
|
|
.. ansi:: images/zsim-22.ans
|
|
|
|
Explicit Cross-Project Dependencies
|
|
===================================
|
|
|
|
* Developers can mark changes as being dependent
|
|
* Depends-On: footer - in commit or PR
|
|
* Zuul uses depends-on when constructing virtual serial queue
|
|
* Will not merge changes in gate before depends-on changes
|
|
* Works cross-repo AND cross-source
|
|
|
|
Sources
|
|
=======
|
|
|
|
* Gerrit
|
|
* Github
|
|
* Pagure
|
|
* Git
|
|
* Bitbucket (in-review) - https://review.opendev.org/#/c/657837
|
|
* Gitlab (in-development) - https://review.opendev.org/#/c/685990/
|
|
|
|
Cross Source
|
|
============
|
|
|
|
.. code:: yaml
|
|
|
|
trigger:
|
|
gerrit:
|
|
- event: patchset-created
|
|
- event: change-restored
|
|
- event: comment-added
|
|
comment: (?i)^(Patch Set [0-9]+:)?( [\w\\+-]*)*(\n\n)?\s*recheck
|
|
github:
|
|
- event: pull_request
|
|
action:
|
|
- opened
|
|
- changed
|
|
- reopened
|
|
- event: pull_request
|
|
action: comment
|
|
comment: (?i)^\s*recheck\s*$
|
|
start:
|
|
github:
|
|
status: pending
|
|
comment: false
|
|
success:
|
|
gerrit:
|
|
Verified: 1
|
|
github:
|
|
status: 'success'
|
|
failure:
|
|
gerrit:
|
|
Verified: -1
|
|
github:
|
|
status: 'failure'
|
|
|
|
Cross Source
|
|
============
|
|
|
|
* Explicit Dependency between projects from different sources
|
|
* Change to Zuul that depends on change to Gerrit
|
|
* https://review.opendev.org/#/c/680778/
|
|
|
|
::
|
|
|
|
commit 737d61c116ff5f32770ef72e2dd82a031ab32591
|
|
Author: James E. Blair <jeblair@redhat.com>
|
|
Date: Mon Aug 19 14:58:20 2020 -0700
|
|
|
|
Add Support for Gerrit Checks Plugin
|
|
|
|
Depends-On: https://gerrit-review.googlesource.com/c/plugins/checks/+/232079
|
|
Change-Id: I8e5903f4429c5a1273a6120e0d09c57169e8f938
|
|
|
|
|
|
Lock Step Changes
|
|
=================
|
|
|
|
* Circular Dependencies are not supported on purpose
|
|
* Rolling upgrades across interdependent services
|
|
* HOWEVER - many valid use cases (go/rust/c++) - support expected
|
|
|
|
Configuring Zuul
|
|
================
|
|
|
|
* Zuul Manages Git Repos
|
|
* Zuul Jobs are configured in Git Repos
|
|
* Zuul Job Content is self-testing
|
|
|
|
Projects
|
|
========
|
|
|
|
* A "Project" is a git repo
|
|
|
|
Config Project vs. Untrusted Project
|
|
====================================
|
|
|
|
config project
|
|
|
|
* special project containing project admin content
|
|
* has access to features that are normally restricted
|
|
* job changes are not applied speculatively
|
|
|
|
untrusted project
|
|
|
|
* most projects
|
|
* some actions (like executing code on localhost) are blocked
|
|
* job changes are applied speculatively
|
|
|
|
Config Files vs. Directories
|
|
============================
|
|
|
|
* Zuul reads in-repo config from:
|
|
``.zuul.yaml``, ``zuul.yaml``, ``zuul.d`` or ``.zuul.d``
|
|
* For projects with substantial zuul config, like ``zuul-config``
|
|
``zuul.d`` directory is likely best.
|
|
* The directories are read run-parts style.
|
|
* Recommended practice is splitting by type of object
|
|
|
|
Live Configuration Changes
|
|
==========================
|
|
|
|
.. container:: handout
|
|
|
|
Zuul is a distributed system, with a distributed configuration.
|
|
|
|
Zuul's config is in git - but something has to tell it where the repos are
|
|
|
|
.. code:: yaml
|
|
|
|
- tenant:
|
|
name: openstack
|
|
source:
|
|
gerrit:
|
|
config-projects:
|
|
- opendev/project-config
|
|
untrusted-projects:
|
|
- zuul/zuul-jobs
|
|
- zuul/zuul
|
|
- zuul/nodepool
|
|
- openstack/openstacksdk
|
|
github:
|
|
untrusted-projects:
|
|
- include: []
|
|
projects:
|
|
- ansible/ansible
|
|
|
|
Zuul Startup
|
|
============
|
|
|
|
* Read config file (main.yaml)
|
|
|
|
Zuul Startup
|
|
============
|
|
|
|
* Read config file
|
|
* Ask mergers for branches of each repo
|
|
|
|
.. ansi:: images/startup1.ans
|
|
|
|
Zuul Startup
|
|
============
|
|
|
|
* Read config file
|
|
* Ask mergers for branches of each repo
|
|
* Ask mergers for .zuul.yaml for each branch
|
|
|
|
of each repo
|
|
|
|
.. ansi:: images/startup2.ans
|
|
|
|
When .zuul.yaml Changes
|
|
=======================
|
|
|
|
.. container:: progressive
|
|
|
|
* Zuul looks for changes to .zuul.yaml
|
|
* Asks mergers for updated content
|
|
* Splices into configuration used for that change
|
|
* Works with cross-repo dependencies
|
|
|
|
("This change depends on a change to the job definition")
|
|
|
|
|
|
Zuul Architecture
|
|
=================
|
|
|
|
Zuul is comprised of several services (mostly python3)
|
|
|
|
* zuul-scheduler
|
|
* zuul-executor
|
|
* zuul-merger
|
|
* zuul-web
|
|
* zuul-fingergw
|
|
* zuul-dashboard (javascript/react)
|
|
* zuul-proxy (c++)
|
|
* nodepool-launcher
|
|
* nodepool-builder
|
|
* RDBMS
|
|
* Gearman
|
|
* Zookeeper
|
|
* zuul-registry (coming soon)
|
|
|
|
Where Does Job Content Run?
|
|
===========================
|
|
|
|
Nodepool
|
|
========
|
|
|
|
* A separate service that works very closely with *Zuul*
|
|
* *Zuul* requires *Nodepool* but *Nodepool* can be used independently
|
|
* Creates and destroys zero or more node resources
|
|
* Resources can include VMs, Containers, COE contexts or Bare Metals
|
|
* Static driver for allocating pre-existing nodes to jobs
|
|
* Optionally periodically builds images and uploads to clouds
|
|
|
|
(Remember that 2,000 jobs per hour number?)
|
|
|
|
Nodepool Launcher
|
|
=================
|
|
|
|
Where build nodes should come from
|
|
|
|
* OpenStack
|
|
* Static
|
|
* Kubernetes Pod
|
|
* Kubernetes Namespace
|
|
* AWS
|
|
|
|
In work / coming soon:
|
|
|
|
* Azure
|
|
* GCE
|
|
|
|
Nodepool Builder
|
|
================
|
|
|
|
Optionally periodically build and upload new base images
|
|
|
|
* OpenStack
|
|
|
|
How do you use this thing?
|
|
==========================
|
|
.. transition:: tilt
|
|
.. hidetitle::
|
|
.. figlet:: Configuration
|
|
|
|
Human Roles
|
|
===========
|
|
|
|
* Deployer
|
|
* Project Admin
|
|
* End User
|
|
|
|
Deployer Config
|
|
===============
|
|
|
|
Zuul: Connection, Triggers, Reporters
|
|
Nodepool: Launcher and Builder Config
|
|
|
|
Connection Plugins
|
|
==================
|
|
|
|
Describes how Zuul connects to external systems
|
|
|
|
* Gerrit
|
|
* Github
|
|
* Pagure
|
|
* git
|
|
* mqtt
|
|
* smtp
|
|
* sql
|
|
|
|
Trigger Plugins
|
|
===============
|
|
|
|
Input to Zuul for use in causing jobs to run
|
|
|
|
* Gerrit
|
|
* Github
|
|
* Pagure
|
|
* git
|
|
* zuul
|
|
|
|
Reporter Plugins
|
|
================
|
|
|
|
Where Zuul should send information about jobs
|
|
|
|
* Gerrit
|
|
* Github
|
|
* Pagure
|
|
* mqtt
|
|
* smtp
|
|
* sql
|
|
|
|
Admin Role
|
|
==========
|
|
|
|
* What sources, triggers and reporters
|
|
* What projects Zuul manages
|
|
* What node labels are available
|
|
* *Everything* else is Job Content
|
|
|
|
Demo Installation using docker-compose
|
|
======================================
|
|
|
|
Remember this?
|
|
|
|
* Install docker, docker-compose, git-review
|
|
|
|
Debian/Ubuntu:
|
|
|
|
::
|
|
|
|
apt-get install docker-compose git git-review
|
|
|
|
Red Hat / SuSE
|
|
|
|
::
|
|
|
|
yum install docker-compose git git-review
|
|
|
|
* mkdir -p ~/src/opendev.org/zuul
|
|
* cd ~/src/opendev.org/zuul
|
|
* git clone https://opendev.org/zuul/zuul
|
|
* cd zuul
|
|
* cd doc/source/admin/examples
|
|
* docker-compose up
|
|
|
|
What's Running
|
|
==============
|
|
|
|
* Zookeeper
|
|
* Gerrit
|
|
* Nodepool Launcher
|
|
* Zuul Scheduler
|
|
* Zuul Web Server
|
|
* Zuul Executor
|
|
* Apache HTTPD
|
|
* A container to use as a 'static' build node
|
|
|
|
How they're connected
|
|
=====================
|
|
|
|
* End Users talk to Gerrit and Apache HTTPD
|
|
* Zuul Scheduler talks to Gerrit
|
|
* Nodepool Launcher, Zuul Scheduler, Zuul Web talk to Zookeeper
|
|
* Zuul Executor talks to Zuul Scheduler (using Gearman)
|
|
|
|
Initial provided config
|
|
=======================
|
|
|
|
* docker-compose has plumbed in basic config ``etc_zuul/zuul.conf``
|
|
and ``etc_zuul/main.yaml``
|
|
* Gerrit Connection named "gerrit"
|
|
* Zuul user for that connection
|
|
* Git connection named "opendev.org" for ``zuul-jobs`` standard library
|
|
|
|
Initial tenant
|
|
==============
|
|
|
|
* Zuul is (always) multi-tenant
|
|
* Example config contains a tenant called ``example-tenant``
|
|
* Three projects in the ``example-tenant`` tenant:
|
|
``zuul-config``, ``test1``, ``test2``
|
|
* Three projects are also in gerrit ready to use
|
|
|
|
zuul.conf
|
|
=========
|
|
|
|
::
|
|
|
|
[gearman]
|
|
server=scheduler
|
|
|
|
[gearman_server]
|
|
start=true
|
|
|
|
[zookeeper]
|
|
hosts=zk
|
|
|
|
[scheduler]
|
|
tenant_config=/etc/zuul/main.yaml
|
|
|
|
[web]
|
|
listen_address=0.0.0.0
|
|
|
|
[executor]
|
|
private_key_file=/var/ssh/nodepool
|
|
default_username=root
|
|
|
|
zuul.conf part 2
|
|
================
|
|
|
|
::
|
|
|
|
[connection "gerrit"]
|
|
name=gerrit
|
|
driver=gerrit
|
|
server=gerrit
|
|
sshkey=/var/ssh/zuul
|
|
user=zuul
|
|
password=secret
|
|
baseurl=http://gerrit:8080
|
|
auth_type=basic
|
|
|
|
[connection "zuul-ci.org"]
|
|
name=zuul-ci
|
|
driver=git
|
|
baseurl=https://opendev.org/
|
|
|
|
main.yaml
|
|
=========
|
|
|
|
::
|
|
|
|
- tenant:
|
|
name: example-tenant
|
|
source:
|
|
gerrit:
|
|
config-projects:
|
|
- zuul-config
|
|
untrusted-projects:
|
|
- test1
|
|
- test2
|
|
zuul-ci.org:
|
|
untrusted-projects:
|
|
- zuul-jobs:
|
|
include:
|
|
- job
|
|
|
|
Running Dashboard
|
|
=================
|
|
|
|
http://localhost:9000
|
|
|
|
Jobs
|
|
====
|
|
|
|
* Define node types needed from nodepool
|
|
* Define which ansible playbooks to run
|
|
* Jobs may be defined centrally or in the repo being tested
|
|
* Jobs have contextual variants that simplify configuration
|
|
* Jobs definitions support inheritance
|
|
|
|
Job Libraries
|
|
=============
|
|
|
|
* Zuul jobs are all defined in git repositories
|
|
* Designed to be directly shared across zuul installations
|
|
* Standard library: https://opendev.org/zuul/zuul-jobs
|
|
* Zuul installs should add ``zuul-jobs`` to their config
|
|
* As changes land in ``zuul-jobs`` - Zuul installs will get them automatically
|
|
|
|
Local Job Libraries
|
|
===================
|
|
|
|
* Jobs specific to local project, but meant to be shared
|
|
* https://opendev.org/openstack/openstack-zuul-jobs
|
|
* https://github.com/ansible/zuul-jobs
|
|
* https://opendev.org/openstack/devstack (here be dragons)
|
|
|
|
Simple Job
|
|
==========
|
|
|
|
.. code:: yaml
|
|
|
|
- job:
|
|
name: tox
|
|
pre-run: playbooks/setup-tox.yaml
|
|
run: playbooks/tox.yaml
|
|
post-run: playbooks/fetch-tox-output.yaml
|
|
|
|
What about job content?
|
|
=======================
|
|
|
|
* Written in Ansible
|
|
* Ansible is excellent at running one or more tasks in one or more places
|
|
* The answer to "how do I" is almost always "Ansible"
|
|
|
|
Playbooks
|
|
=========
|
|
|
|
* Jobs run playbooks
|
|
* Allocated nodes from nodepool are provided in Ansible Inventory
|
|
* Playbooks may be defined centrally or in the repo being tested
|
|
* Playbooks can use roles from current or other Zuul repos
|
|
* Playbooks are not allowed to execute content on 'localhost'
|
|
* *Note*: localhost restriction may go away soon
|
|
|
|
Simple Playbook Example
|
|
=======================
|
|
|
|
* playbooks/tox.yaml
|
|
|
|
.. code:: yaml
|
|
|
|
- hosts: ubuntu-bionic
|
|
tasks:
|
|
- name: Run tox
|
|
args:
|
|
chdir: "{{ zuul_work_dir }}"
|
|
shell: "tox -e{{ tox_envlist }}"
|
|
|
|
Job Inheritance
|
|
===============
|
|
|
|
All Zuuls have a base job
|
|
|
|
.. code:: yaml
|
|
|
|
- job:
|
|
name: base
|
|
parent: null
|
|
description: |
|
|
The base job for Zuul.
|
|
timeout: 1800
|
|
nodeset:
|
|
nodes:
|
|
- name: primary
|
|
label: ubuntu-bionic
|
|
pre-run: playbooks/base/pre.yaml
|
|
post-run:
|
|
- playbooks/base/post-ssh.yaml
|
|
- playbooks/base/post-logs.yaml
|
|
secrets:
|
|
- site_logs
|
|
|
|
Logging
|
|
=======
|
|
|
|
* Zuul doesn't know about logging - only about URLs to report
|
|
* Job Ansible content does *something* with logs
|
|
* Job content tells Zuul what URL(s) to report to user
|
|
* Allows for some really cool patterns
|
|
|
|
Live Web Preview
|
|
================
|
|
|
|
* For static websites, publish built content and report url
|
|
|
|
https://review.opendev.org/#/c/635716/
|
|
|
|
https://zuul.opendev.org/t/zuul/build/2ef4ceb232a2467ab56be726f31928ef
|
|
|
|
https://470ff2d7584ecc192d95-20fcf28638b4f38abf523a12606af55d.ssl.cf1.rackcdn.com/635716/12/check/zuul-build-dashboard/2ef4ceb/npm/html
|
|
|
|
Project Admin Role
|
|
==================
|
|
|
|
* Base job(s)
|
|
* Pre-playbooks for local environment
|
|
* Post-playbooks - where do logs and artifacts go?
|
|
* Shared trusted publication jobs
|
|
|
|
Simple Job Inheritance
|
|
======================
|
|
|
|
.. code:: yaml
|
|
|
|
- job:
|
|
name: tox-py36
|
|
parent: tox
|
|
vars:
|
|
tox_envlist: py36
|
|
|
|
Inheritance Works Like An Onion
|
|
===============================
|
|
|
|
* pre-run playbooks run in order of inheritance
|
|
* run playbook of job runs
|
|
* post-run playbooks run in reverse order of inheritance
|
|
* If pre-run playbooks fail, job is re-tried
|
|
* All post-run playbooks run - as far as pre-run playbooks got
|
|
|
|
Inheritance Example
|
|
===================
|
|
|
|
For tox-py36 job
|
|
|
|
* base pre-run playbooks/base/pre.yaml
|
|
* tox pre-run playbooks/setup-tox.yaml
|
|
* tox run playbooks/tox.yaml
|
|
* tox post-run playbooks/fetch-tox-output.yaml
|
|
* base post-run playbooks/base/post-ssh.yaml
|
|
* base post-run playbooks/base/post-logs.yaml
|
|
|
|
Simple Job Variant
|
|
==================
|
|
|
|
.. code:: yaml
|
|
|
|
- job:
|
|
name: tox-py36
|
|
branches: stable/mitaka
|
|
nodeset:
|
|
- name: ubuntu-trusty
|
|
label: ubuntu-trusty
|
|
|
|
Nodesets for Multi-node Jobs
|
|
============================
|
|
|
|
.. code:: yaml
|
|
|
|
- nodeset:
|
|
name: ceph-cluster
|
|
nodes:
|
|
- name: controller
|
|
label: centos-7
|
|
- name: compute1
|
|
label: fedora-28
|
|
- name: compute2
|
|
label: fedora-28
|
|
groups:
|
|
- name: ceph-osd
|
|
nodes:
|
|
- controller
|
|
- name: ceph-monitor
|
|
nodes:
|
|
- controller
|
|
- compute1
|
|
- compute2
|
|
|
|
Multi-node Job
|
|
==============
|
|
|
|
* nodesets are provided to Ansible for jobs in inventory
|
|
|
|
.. code:: yaml
|
|
|
|
- job:
|
|
name: ceph-multinode
|
|
nodeset: ceph-cluster
|
|
run: playbooks/install-ceph.yaml
|
|
|
|
Multi-node Ceph Job Content
|
|
===========================
|
|
|
|
.. code:: yaml
|
|
|
|
- hosts: all
|
|
roles:
|
|
- install-ceph
|
|
|
|
- hosts: ceph-osd
|
|
roles:
|
|
- start-ceph-osd
|
|
|
|
- hosts: ceph-monitor
|
|
roles:
|
|
- start-ceph-monitor
|
|
|
|
- hosts: all
|
|
roles:
|
|
- do-something-interesting
|
|
|
|
Projects
|
|
========
|
|
|
|
* Projects are git repositories
|
|
* Specify a set of jobs for each pipeline
|
|
* golang git repo naming as been adopted:
|
|
|
|
::
|
|
|
|
zuul@ubuntu-bionic:~$ find /home/zuul/src -mindepth 3 -maxdepth 3 -type d
|
|
/home/zuul/src/opendev.org/openstack/openstacksdk
|
|
/home/zuul/src/opendev.org/zuul/zuul
|
|
/home/zuul/src/github.com/ansible/ansible
|
|
/home/zuul/src/gerrit.googlesource.com/gerrit
|
|
|
|
Project Config
|
|
==============
|
|
|
|
* Specify a set of jobs for each pipeline
|
|
|
|
.. code:: yaml
|
|
|
|
- project:
|
|
check:
|
|
jobs:
|
|
- openstack-tox-py36
|
|
- openstack-tox-docs
|
|
gate:
|
|
jobs:
|
|
- openstack-tox-py36
|
|
- openstack-tox-docs
|
|
|
|
Project with Local Variant
|
|
==========================
|
|
|
|
.. code:: yaml
|
|
|
|
- project:
|
|
check:
|
|
jobs:
|
|
- openstack-tox-py27
|
|
- openstack-tox-py35
|
|
- openstack-tox-py36:
|
|
voting: false
|
|
- openstack-tox-docs
|
|
gate:
|
|
jobs:
|
|
- openstack-tox-py27
|
|
- openstack-tox-py35
|
|
- openstack-tox-docs
|
|
|
|
Project with More Local Variants
|
|
================================
|
|
|
|
.. code:: yaml
|
|
|
|
- project:
|
|
check:
|
|
jobs:
|
|
- openstack-tox-py27
|
|
- openstack-tox-py35
|
|
- openstack-tox-py36:
|
|
voting: false
|
|
- openstack-tox-docs:
|
|
files: '^docs/.*$'
|
|
|
|
Project with Many Local Variants
|
|
================================
|
|
|
|
.. code:: yaml
|
|
|
|
- project:
|
|
check:
|
|
jobs:
|
|
- openstack-tox-py27:
|
|
nodeset:
|
|
- name: centos-7
|
|
label: centos-7
|
|
- openstack-tox-py27:
|
|
branches: stable/newton
|
|
nodeset:
|
|
- name: ubuntu-trusty
|
|
label: ubuntu-trusty
|
|
- openstack-tox-py35
|
|
- openstack-tox-py36:
|
|
voting: false
|
|
- openstack-tox-docs:
|
|
files: '^docs/.*$'
|
|
|
|
Project With Central and Local Config
|
|
=====================================
|
|
|
|
.. code:: yaml
|
|
|
|
# In opendev.org/openstack/project-config:
|
|
- project:
|
|
name: openstack/nova
|
|
templates:
|
|
- openstack-tox-jobs
|
|
|
|
.. code:: yaml
|
|
|
|
# In opendev.org/openstack/nova/.zuul.yaml:
|
|
- project:
|
|
check:
|
|
- nova-placement-functional-devstack
|
|
|
|
Project with Job Dependencies
|
|
=============================
|
|
|
|
Full DAG of Job Dependencies
|
|
|
|
.. code:: yaml
|
|
|
|
- project:
|
|
release:
|
|
jobs:
|
|
- build-artifacts
|
|
- upload-tarball:
|
|
dependencies: build-artifacts
|
|
- upload-pypi:
|
|
dependencies: build-artifacts
|
|
- notify-mirror:
|
|
dependencies:
|
|
- upload-tarball
|
|
- upload-pypi
|
|
|
|
|
|
Speculative Container Images
|
|
============================
|
|
|
|
* Build container images based on non-published images from other changes
|
|
* Test built container images in gate jobs
|
|
* Promote exact image from gate after merge
|
|
* Soft Dependencies - use artifact from another job only if it was built
|
|
* https://zuul-ci.org/docs/zuul-jobs/docker-image.html
|
|
|
|
Playbooks
|
|
=========
|
|
|
|
* Jobs run playbooks
|
|
* Playbooks may be defined centrally or in the repo being tested
|
|
* Playbooks can use roles from current or other Zuul repos or Galaxy
|
|
* Playbooks are not allowed to execute content on 'localhost'
|
|
|
|
Test Like Production
|
|
====================
|
|
|
|
If you use Ansible for deployment, your test and deployment processes
|
|
and playbooks are the same
|
|
|
|
What if you don't use Ansible?
|
|
==============================
|
|
|
|
OpenStack Infra Control Plane uses Puppet (for now)
|
|
===================================================
|
|
|
|
.. code:: yaml
|
|
|
|
OpenDev Control Plane uses some Puppet (for now)
|
|
================================================
|
|
|
|
.. code:: yaml
|
|
|
|
- name: Install puppet
|
|
shell: ./install_puppet.sh
|
|
args:
|
|
chdir: "{{ ansible_user_dir }}/src/opendev.org/opendev/system-config"
|
|
become: yes
|
|
|
|
- name: Copy manifest
|
|
copy:
|
|
src: manifest.pp
|
|
dest: "{{ ansible_user_dir }}/manifest.pp"
|
|
|
|
- name: Run puppet
|
|
puppet:
|
|
manifest: "{{ ansible_user_dir }}/manifest.pp"
|
|
become: yes
|
|
|
|
Secrets
|
|
=======
|
|
|
|
* Inspired by Kubernetes Secrets API
|
|
* Projects can add named encrypted secrets to their .zuul.yaml file
|
|
* Jobs can request to use secrets by name
|
|
* Jobs using secrets are not reconfigured speculatively
|
|
* Secrets can only be used by the same project they are defined in
|
|
* Public key per project:
|
|
``{{ zuul_url }}/{{ tenant }}/{{ project }}.pub``
|
|
|
|
::
|
|
GET https://zuul.opendev.org/api/tenant/openstack/key/openstack/openstacksdk.pub
|
|
|
|
Secret Example (note, no admins had to enable this)
|
|
===================================================
|
|
|
|
.. code:: yaml
|
|
|
|
# In opendev.org/openstack/loci/.zuul.yaml:
|
|
- secret:
|
|
name: loci_docker_login
|
|
data:
|
|
user: loci-username
|
|
password: !encrypted/pkcs1-oaep
|
|
- gUEX4eY3JAk/Xt7Evmf/hF7xr6HpNRXTibZjrKTbmI4QYHlzEBrBbHey27Pt/eYvKKeKw
|
|
hk8MDQ4rNX7ZK1v+CKTilUfOf4AkKYbe6JFDd4z+zIZ2PAA7ZedO5FY/OnqrG7nhLvQHE
|
|
5nQrYwmxRp4O8eU5qG1dSrM9X+bzri8UnsI7URjqmEsIvlUqtybQKB9qQXT4d6mOeaKGE
|
|
5h6Ydkb9Zdi4Qh+GpCGDYwHZKu1mBgVK5M1G6NFMy1DYz+4NJNkTRe9J+0TmWhQ/KZSqo
|
|
4ck0x7Tb0Nr7hQzV8SxlwkaCTLDzvbiqmsJPLmzXY2jry6QsaRCpthS01vnj47itoZ/7p
|
|
taH9CoJ0Gl7AkaxsrDSVjWSjatTQpsy1ub2fuzWHH4ASJFCiu83Lb2xwYts++r8ZSn+mA
|
|
hbEs0GzPI6dIWg0u7aUsRWMOB4A+6t2IOJibVYwmwkG8TjHRXxVCLH5sY+i3MR+NicR9T
|
|
IZFdY/AyH6vt5uHLQDU35+5n91pUG3F2lyiY5aeMOvBL05p27GTMuixR5ZoHcvSoHHtCq
|
|
7Wnk21iHqmv/UnEzqUfXZOque9YP386RBWkshrHd0x3OHUfBK/WrpivxvIGBzGwMr2qAj
|
|
/AhJsfDXKBBbhGOGk1u5oBLjeC4SRnAcIVh1+RWzR4/cAhOuy2EcbzxaGb6VTM=
|
|
|
|
Secret Example
|
|
==============
|
|
|
|
.. code:: yaml
|
|
|
|
# In opendev.org/openstack/loci/.zuul.yaml:
|
|
- job:
|
|
name: publish-loci-cinder
|
|
parent: loci-cinder
|
|
post-run: playbooks/push
|
|
secrets:
|
|
- loci_docker_login
|
|
|
|
# In opendev.org/openstack/loci/playbooks/push.yaml:
|
|
- hosts: all
|
|
tasks:
|
|
- include_vars: vars.yaml
|
|
|
|
- name: Push project to DockerHub
|
|
block:
|
|
- command: docker login -u {{ loci_docker_login.user }} -p {{ loci_docker_login.password }}
|
|
no_log: True
|
|
- command: docker push openstackloci/{{ project }}:{{ branch }}-{{ item.name }}
|
|
with_items: "{{ distros }}"
|
|
|
|
Back to our Install
|
|
===================
|
|
|
|
Zuul Containers
|
|
===============
|
|
|
|
* Published on every commit
|
|
* Application/Process containers
|
|
* Built using Speculative Containers
|
|
* Config / Data should be bind-mounted in
|
|
|
|
Container Philosophy
|
|
====================
|
|
|
|
* As minimal as possible
|
|
* OS inside of container does not matter
|
|
|
|
zuul/zuul-executor
|
|
==================
|
|
|
|
* In k8s, zuul-executor must be run in privileged pod
|
|
* Uses bubblewrap for unprivileged sanboxing
|
|
* Restriction may be lifted in the future
|
|
|
|
Release Management
|
|
==================
|
|
|
|
* Zuul is a CI system
|
|
* C stands for "Continuous"
|
|
* It is run Continuously Delivered and Deployed upstream
|
|
* Releases are tagged from code run upstream
|
|
* There is no intent to have a 'stable' release
|
|
* 'stable' is a synonym for "old and buggy"
|
|
* **NOTE** container images are not currently tagged
|
|
|
|
zuul/zuul-scheduler
|
|
===================
|
|
|
|
* SPOF
|
|
* We're working on it
|
|
* Recommend running scheduler from tags
|
|
|
|
Let's Do Something with Our Zuul
|
|
================================
|
|
|
|
Gerrit Account
|
|
==============
|
|
|
|
* Need a user account to interact with Gerrit
|
|
* Gerrit is configured in dev mode - no passwords required
|
|
* Visit http://localhost:8080
|
|
* Click "New Account"
|
|
* Skip entering anything, click "settings"
|
|
* Enter username in Username field (match your local laptop user)
|
|
* Enter Full Name
|
|
* Click "Save Changes"
|
|
|
|
More Gerrit Account
|
|
===================
|
|
|
|
* Scroll down to Email Addresses
|
|
* Enter email address in "New email address" field
|
|
* Click "Send Verification"
|
|
* Gerrit is in Developer Mode, will not send email
|
|
* Scroll down to "SSH Keys"
|
|
* Copy ``~/.ssh/id_rsa.pub`` contents into "New SSH Key" field
|
|
* Click "Add New SSH Key"
|
|
* Reload the page in your browser
|
|
|
|
Config Repo
|
|
===========
|
|
|
|
* ``zuul-config`` is a trusted ``config-repo``
|
|
* Security and functionality of system depend on this repo
|
|
* Limit its contents to minimum required
|
|
|
|
Setting up Gating
|
|
=================
|
|
|
|
* We want to have changes to ``zuul-config`` be gated
|
|
* We need to define pipelines: ``check`` and ``gate``
|
|
* Need to attach ``zuul-config`` to them
|
|
* Start with builtin ``noop`` job (always return success)
|
|
* Use regex to attach all projects to ``check`` and ``gate``
|
|
|
|
Pipeline Definitions
|
|
====================
|
|
|
|
* Zuul has no built-in workflow definitions, let's add ``check`` and ``gate``
|
|
|
|
check pipeline
|
|
==============
|
|
|
|
::
|
|
|
|
- pipeline:
|
|
name: check
|
|
description: |
|
|
Newly uploaded patchsets enter this pipeline to receive an
|
|
initial +/-1 Verified vote.
|
|
manager: independent
|
|
require:
|
|
gerrit:
|
|
open: True
|
|
current-patchset: True
|
|
trigger:
|
|
gerrit:
|
|
- event: patchset-created
|
|
- event: change-restored
|
|
comment: (?i)^(Patch Set [0-9]+:)?( [\w\\+-]*)*(\n\n)?\s*recheck
|
|
success:
|
|
gerrit:
|
|
Verified: 1
|
|
mysql:
|
|
failure:
|
|
gerrit:
|
|
Verified: -1
|
|
mysql:
|
|
|
|
gate pipeline
|
|
=============
|
|
|
|
::
|
|
|
|
- pipeline:
|
|
name: gate
|
|
description: |
|
|
Changes that have been approved are enqueued in order in this
|
|
pipeline, and if they pass tests, will be merged.
|
|
manager: dependent
|
|
post-review: True
|
|
require:
|
|
gerrit:
|
|
open: True
|
|
current-patchset: True
|
|
approval:
|
|
- Workflow: 1
|
|
trigger:
|
|
gerrit:
|
|
- event: comment-added
|
|
approval:
|
|
- Workflow: 1
|
|
start:
|
|
gerrit:
|
|
Verified: 0
|
|
success:
|
|
gerrit:
|
|
Verified: 2
|
|
submit: true
|
|
mysql:
|
|
failure:
|
|
gerrit:
|
|
Verified: -2
|
|
mysql:
|
|
|
|
Add the pipeline definitions
|
|
============================
|
|
|
|
.. code-block:: bash
|
|
|
|
cd ~/src
|
|
git clone http://localhost:8080/zuul-config
|
|
cd zuul-config
|
|
mkdir zuul.d
|
|
cp ~/src/opendev.org/zuul/zuul/doc/source/admin/examples/zuul-config/zuul.d/pipelines.yaml zuul.d
|
|
|
|
Shared Project Pipeline Definition
|
|
==================================
|
|
|
|
In ``examples/zuul-config/zuul.d/projects.yaml``
|
|
|
|
.. code-block:: yaml
|
|
|
|
- project:
|
|
name: ^.*$
|
|
check:
|
|
jobs: []
|
|
gate:
|
|
jobs: []
|
|
|
|
- project:
|
|
name: zuul-config
|
|
check:
|
|
jobs:
|
|
- noop
|
|
gate:
|
|
jobs:
|
|
- noop
|
|
|
|
Attach the projects to the pipelines
|
|
====================================
|
|
|
|
.. code-block:: bash
|
|
|
|
cp ~/src/opendev.org/zuul/zuul/doc/source/admin/examples/zuul-config/zuul.d/projects.yaml zuul.d
|
|
|
|
Commit the changes and push up for review
|
|
=========================================
|
|
|
|
.. code-block:: bash
|
|
|
|
git add zuul.d
|
|
git commit
|
|
git review
|
|
|
|
Force merging bootstrap config
|
|
==============================
|
|
|
|
* Zuul is running with no config, so it won't do anything
|
|
* For this change (and this change only) we will bypass gating
|
|
|
|
Reviewing normally
|
|
==================
|
|
|
|
* visit http://localhost:8080/#/c/zuul-config/+/1001/
|
|
* click reply
|
|
* vote +2 Code Review +1 Approved
|
|
|
|
Verified +2 is Missing
|
|
======================
|
|
|
|
Verified +2 is what we have zuul configured to do.
|
|
|
|
::
|
|
success:
|
|
gerrit:
|
|
Verified: 2
|
|
submit: true
|
|
|
|
|
|
Bypassing Gating
|
|
================
|
|
|
|
* visit http://localhost:8080/
|
|
* Click avatar in Upper Right
|
|
* Click Sign Out
|
|
* Click Sign In
|
|
* Click 'admin'
|
|
* Click on change you uploaded
|
|
* Click Reply...
|
|
* Vote +2 Verified (normal users do not see this)
|
|
* Click submit (normal users do not see this)
|
|
* Click avatar in Upper Right
|
|
* Click Sign Out
|
|
* Click Sign In
|
|
* click your username
|
|
|
|
Dashboard
|
|
=========
|
|
|
|
http://localhost:9000/t/example-tenant/status
|
|
|
|
Add Job to a repo
|
|
=================
|
|
|
|
Clone the test1 repo
|
|
====================
|
|
|
|
::
|
|
|
|
cd ~/src
|
|
git clone http://localhodsts:8080/test1
|
|
cd test1
|
|
|
|
Simple debug playbook
|
|
=====================
|
|
|
|
.. code:: yaml
|
|
|
|
- hosts: all
|
|
tasks:
|
|
- debug:
|
|
msg: Hello world!
|
|
|
|
Add the playbook to our repo
|
|
============================
|
|
|
|
::
|
|
|
|
mkdir playbooks
|
|
cp ~/src/opendev.org/zuul/zuul/doc/source/admin/examples/test1/playbooks/testjob.yaml playbooks
|
|
git add playbooks/testjob.yaml
|
|
|
|
Simple Zuul Job
|
|
===============
|
|
|
|
::
|
|
|
|
- job:
|
|
name: testjob
|
|
run: playbooks/testjob.yaml
|
|
|
|
- project:
|
|
check:
|
|
jobs:
|
|
- testjob
|
|
gate:
|
|
jobs:
|
|
- testjob
|
|
|
|
Add it to the .zuul.yaml
|
|
========================
|
|
|
|
This is a normal repo, let's use .zuul.yaml
|
|
|
|
::
|
|
cp ~/src/opendev.org/zuul/zuul/doc/source/admin/examples/test1/zuul.yaml .zuul.yaml
|
|
git add .zuul.yaml
|
|
|
|
Submit the change for review
|
|
============================
|
|
|
|
.. code-block:: shell
|
|
|
|
git add .zuul.yaml playbooks
|
|
git commit -m "Add test Zuul job"
|
|
git review
|
|
|
|
Then check http://localhost:8080/dashboard/self
|
|
|
|
Where are the logs?
|
|
===================
|
|
|
|
Base Job
|
|
========
|
|
|
|
* Every Zuul installation must define a ``base`` job
|
|
* Push git repos to build node
|
|
* Publish logs/artifacts
|
|
* Any local specific setup
|
|
* Goes in config repo - because it impacts EVERY job
|
|
|
|
Minimal Base Job
|
|
================
|
|
|
|
.. code:: yaml
|
|
|
|
- job:
|
|
name: base
|
|
parent: null
|
|
nodeset:
|
|
nodes:
|
|
- name: ubuntu-bionic
|
|
label: ubuntu-bionic
|
|
|
|
|
|
Minimal Base Job
|
|
================
|
|
|
|
::
|
|
|
|
cd ~/src/zuul-config
|
|
cp ~/src/examples/zuul-config/zuul.d/jobs.yaml zuul.d
|
|
|
|
Base pre Playbook
|
|
=================
|
|
|
|
* Using roles from zuul-jobs repo
|
|
* Creates a per-build ssh key
|
|
* Copies git repos to test node
|
|
|
|
.. code:: yaml
|
|
|
|
- hosts: all
|
|
roles:
|
|
- add-build-sshkey
|
|
- prepare-workspace
|
|
|
|
Base pre Playbook
|
|
=================
|
|
|
|
::
|
|
|
|
mkdir -p playbooks/base
|
|
cp ~/src/opendev.org/zuul/zuul/doc/source/admin/examples/zuul-config/playbooks/base/pre.yaml playbooks/base
|
|
|
|
|
|
Base post-ssh playbook
|
|
======================
|
|
|
|
* Removes the per-build ssh key from the pre playbook
|
|
|
|
.. code:: yaml
|
|
|
|
- hosts: all
|
|
roles:
|
|
- remove-build-sshkey
|
|
|
|
Base post-ssh playbook
|
|
======================
|
|
|
|
::
|
|
|
|
cp ~/src/opendev.org/zuul/zuul/doc/source/admin/examples/zuul-config/playbooks/base/post-ssh playbooks/base
|
|
|
|
Base post-logs playbook
|
|
=======================
|
|
|
|
* Quickstart is running Apache server for log content
|
|
* Volume mounted at /srv/static/logs (default for upload-logs)
|
|
* Tells Zuul where the logs can be found
|
|
|
|
.. code:: yaml
|
|
|
|
- hosts: localhost
|
|
gather_facts: False
|
|
roles:
|
|
- role: upload-logs
|
|
zuul_log_url: "http://localhost:8000"
|
|
|
|
Base post-ssh playbook
|
|
======================
|
|
|
|
::
|
|
|
|
cp ~/src/opendev.org/zuul/zuul/doc/source/admin/examples/zuul-config/playbooks/base/post-logs playbooks/base
|
|
|
|
Update Base Job
|
|
===============
|
|
|
|
.. code:: yaml
|
|
|
|
- job:
|
|
name: base
|
|
parent: null
|
|
description: |
|
|
The recommended base job.
|
|
|
|
All jobs ultimately inherit from this. It runs a pre-playbook
|
|
which copies all of the job's prepared git repos on to all of
|
|
the nodes in the nodeset.
|
|
|
|
It also sets a default timeout value (which may be overidden).
|
|
pre-run: playbooks/base/pre.yaml
|
|
post-run:
|
|
- playbooks/base/post-ssh.yaml
|
|
- playbooks/base/post-logs.yaml
|
|
roles:
|
|
- zuul: zuul/zuul-jobs
|
|
timeout: 1800
|
|
nodeset:
|
|
nodes:
|
|
- name: ubuntu-bionic
|
|
label: ubuntu-bionic
|
|
|
|
Update Base Job
|
|
===============
|
|
|
|
::
|
|
|
|
cp ~/src/examples/zuul-config/zuul.d/jobs2.yaml zuul.d
|
|
|
|
Commit and Push for Review
|
|
==========================
|
|
|
|
::
|
|
|
|
git add playbooks zuul.d/jobs.yaml
|
|
git commit -m "Update Zuul base job"
|
|
git review
|
|
|
|
Land Change
|
|
===========
|
|
|
|
* Visit http://localhost:8080/dashboard/self
|
|
* Should be a Verified +1 vote from Zuul
|
|
* Click Reply
|
|
* Vote: Code-Review +2 and Workflow +1
|
|
* Click Send
|
|
* Wait a bit, then reload, change should be merged
|
|
|
|
Recheck the test1 change
|
|
========================
|
|
|
|
* Visit http://localhost:8080/dashboard/self
|
|
* Click Reply
|
|
" Comment "recheck"
|
|
* Click Send
|
|
|
|
Job Now Running with Updated Base Job
|
|
=====================================
|
|
|
|
* Should get a link to log location
|
|
* Check out Zuul Dashboard
|
|
|
|
Zuul tests syntax automatically
|
|
===============================
|
|
|
|
* Edit zuul/jobs.yaml
|
|
* Change ``parent: null`` to ``parent: broken``
|
|
* git commit ; git review
|
|
* Check out the review in gerrit ... there should be errors!
|
|
|
|
Job configs are shared
|
|
======================
|
|
|
|
::
|
|
|
|
cd ~/src
|
|
git clone http://localhost:8080/test2
|
|
cd test2
|
|
|
|
Add testjob to test2 repo
|
|
=========================
|
|
|
|
::
|
|
|
|
cp ~/src/opendev.org/zuul/zuul/doc/source/admin/examples/test1/zuul.yaml .zuul.yaml
|
|
git add .zuul.yaml
|
|
git commit -a -m"Added testjob to test2 repo"
|
|
git review
|
|
|
|
Where's the job?
|
|
================
|
|
|
|
* Check http://localhost:8080/dashboard/self
|
|
* Look at error from zuul
|
|
* This is a job for cross-project depends!
|
|
|
|
Add Depends-On footer
|
|
=====================
|
|
|
|
::
|
|
|
|
git commit -a --amend
|
|
|
|
* Add a blank line then
|
|
|
|
::
|
|
|
|
Depends-On: http://localhost:8080/c/test1/+/1
|
|
|
|
* Then resubmit
|
|
|
|
::
|
|
|
|
git review
|
|
|
|
Let's Add a Secret
|
|
==================
|
|
|
|
* Edit .zuul.yaml - name the secret and the field
|
|
|
|
::
|
|
|
|
cd ~/src/test1
|
|
echo "my-secret" | ~/src/opendev.org/zuul/zuul/tools/encrypt_secret.py --tenant example-tenant http://localhost:9000 test1 >> .zuul.yaml
|
|
|
|
|
|
Secret Name
|
|
===========
|
|
|
|
.. code-block:: yaml
|
|
|
|
- secret:
|
|
name: amazing_secret
|
|
data:
|
|
name: !encrypted/pkcs1-oaep
|
|
|
|
Add secret to job
|
|
=================
|
|
|
|
.. code-block:: yaml
|
|
|
|
- job:
|
|
name: testjob
|
|
run: playbooks/testjob.yaml
|
|
secrets:
|
|
- amazing_secret
|
|
|
|
Print the secret in the job
|
|
===========================
|
|
|
|
* *NOTE* This is dumb
|
|
* Edit playbooks/testjob.yaml
|
|
|
|
.. code-block:: yaml
|
|
|
|
- hosts: all
|
|
tasks:
|
|
- debug:
|
|
msg: "Hello {{ amazing_secret.name }}!"
|
|
|
|
Commit and push for review
|
|
==========================
|
|
|
|
::
|
|
|
|
git commit -a -m"Added a secret"
|
|
git review
|
|
|
|
Change test2 to depend on the secret change
|
|
===========================================
|
|
|
|
::
|
|
|
|
git commit -a --amend
|
|
|
|
* Change the Depends-On line
|
|
|
|
::
|
|
|
|
Depends-On: http://localhost:8080/c/test1/+/2
|
|
|
|
* Then resubmit
|
|
|
|
::
|
|
|
|
git review
|
|
|
|
Let's go look at the outputs!
|
|
=============================
|
|
|
|
Add a job with run-test-command
|
|
===============================
|
|
|
|
* What if you don't want a playbook?
|
|
* Role 'run-test-command' in zuul-jobs
|
|
|
|
.. code-block:: yaml
|
|
|
|
- job:
|
|
parent: run-test-command
|
|
name: simple-test-job
|
|
vars:
|
|
test_command: exit 0
|
|
|
|
Add to the project pipeline config
|
|
==================================
|
|
|
|
.. code-block:: yaml
|
|
|
|
- project:
|
|
check:
|
|
jobs:
|
|
- testjob
|
|
- simple-test-job
|
|
gate:
|
|
jobs:
|
|
- testjob
|
|
- simple-test-job
|
|
|
|
|
|
Commit and Push Up
|
|
==================
|
|
|
|
::
|
|
|
|
git commit -a -m"Added a simple test job"
|
|
git review
|
|
|
|
What's wrong?
|
|
=============
|
|
|
|
Add required-projects
|
|
=====================
|
|
|
|
* Edit .zuul.yaml
|
|
|
|
.. code-block:: yaml
|
|
|
|
- job:
|
|
parent: run-test-command
|
|
name: simple-test-job
|
|
vars:
|
|
test_command: "find {{ ansible_user_dir }}"
|
|
required-projects:
|
|
- test1
|
|
- test2
|
|
|
|
Important Links
|
|
===============
|
|
|
|
* https://opendev.org/zuul
|
|
* https://zuul-ci.org/docs/zuul
|
|
* https://zuul-ci.org/docs/zuul-jobs/
|
|
* https://docs.openstack.org/infra/openstack-zuul-jobs/
|
|
* freenode:#zuul
|
|
* https://opendev.org/inaugust/inaugust.com/src/branch/master/src/zuulv3/tutorial.rst
|