I was trying to explain how our team did workflow to a former colleague last week and I so I started thinking about all the different workflows I’ve dealt with in my career. This one is by far my favorite, although I know it’s not git which everyone loves, I’m curious what workflows other groups use with launchpad. Take a look at this one and let me know, can our team do anything better, can yours?
First a brief note about our team at Canonical. We work on “premium” customer-facing projects, typically on ARM based hardware. We are downstream from Ubuntu for the most part, and although we do send fixes upstream when it makes sense, often we make customizations to packages that cannot go upstream. I’ll use a real-world example for this workflow explanation, we have a platform where we want to remove the user list, help menu entry, and the logout menu enty from the session indicator, so we needed to modify indicator-session to do so.
Setup a Shared Master (mainline)
Grab the source for indicator-session for the distroseries we’re based on, precise in this case. We usually grab it from launchpad or apt-get source if launchpad’s precise copy is out of date. This code gets pushed to lp:~project-team/project/indicator-session. This is now the master/mainline version. Everyone on the team has write access to this, provided they follow team rules.
Setting Up My Local Branch
I have a pbuilder already setup for our project usually, so my first step is to setup my local tree. I like to use a two level hierarchy here so that builds don’t “pollute” my main project area where I have dozens of different branches checked out. So I setup a subdirectory and checkout a copy to master.
cd ~/Projects/project-precise-amd64 mkdir indicator-session cd indicator-session bzr branch lp:~project-team/project/indicator-session master
Now I branch master, if this wasn’t a fresh checkout, I would bzr pull in master first.
bzr branch master remove-buttons
At this point we make fixes or whatever changes are needed. The package is built, changes are tested, and lintian is run (this one gets forgotten many times).
We have a few goals to meet for changes, we don’t always succeed, but here they are:
- No new lintian errors, if it’s a new package that we made, 0 is better.
- If the package has unit tests, add a new test case to cover what we just fixed/changed.
- Patches should have minimal DEP3 headers.
- Coding style should follow upstream.
- No new compiler warnings without explanation.
- Good changelog entries with bug numbers if applicable. Entries should list what files were modified. Distroseries set to UNRELEASED still (more on why later).
A note on lintian, Jenkins is capable of rejecting packages with lintian errors. We have this disabled because we need to fix the errors that crept in first when we didn’t follow this rule.
Push to a Remote Branch for Review
We code review everything we do, so the next step is to make the branch public for a review.
bzr commit -m "good message, usually we just use the changelog entry" --fixes lp:BUGNUM bzr push lp:~project-team/project/indicator-session-remove-buttons
Setup a Code Review
Everything is reviewed and all reviews are sent to the team, though the onus is on the submitter to ping appropriate people if they don’t get a timely review. For code reviews, everyone is expected to provide a good explanation of what they’re doing and what testing was done.
We also have one of the “enhancements” here as we have a Jenkins instance (similar to this one) setup for some projects and Jenkins gets to “vote” on the review. Packages that fail to build or fail unit tests are marked as “Rejected” in the review by Jenkins.
Merge Back to Master
After the review is approved, the code submitter merges the code and commits it up to the mainline. I’m paranoid about master changing, although the push will fail if it did, so I always update it first.
We have to also fix the distroseries back. We do this on our team because it reduces the chance that someone will dput a package that is built from a local or non-master branch. If somone were to try and dput the changes file built from the remove-buttons branch, it would fail. We really want the archive to only have packages built from master, it’s more repeatable and easier to track changes.
cd ~/Projects/project-precise-amd64/indicator-session cd master bzr pull bzr merge ../remove-buttons dch -e (modify distroseries from UNRELEASED to precise) debcommit -r bzr push :parent
Jenkins Does dput
Our team is slowly moving into the world of Jenkins and build/test automation, so we have Jenkins watching the master branch for interesting projects and it will manage the dput for us. This also provides a final round of build testing before we dput.
Some teams have autolanding setup, that is when the review is approved, the Jenkins instance will do the merge. For now, we’ve kept a human in the loop.
Update the Bug
It is annoying to look at a bug 3 months after you fixed it and wonder what version it’s fixed in. Although the debian/changelog tracks this, we generally always add a bug comment saying when a bug was fixed. For the most part people usually just paste the relevant changelog entry into the bug and make sure it’s marked as Fix Committed.