Bamboo, Docker and Arch packaging problems
Today, after a long history of trial and error, I managed to let bamboo, docker and arch makepkg finally work together. This was way more effort than should be necessary, but for those that might find themselves in a similar situation, I decided to share my mileage.
Bamboo and Docker
So, as of recent, bamboo allows you to run your jobs on docker. This sounds really nice, especially for me, because it allows you to specify a clean environment to build packages in. I don’t want my bamboo machine to slowly collect all build dependencies, nor do I want to create a server farm of build environments.
The idea
The idea with bamboo and docker is, you give it a base image, and all your scripts run automatically on this base image. For me, this allows me to create an image with all build requirements pre-installed, so I only need to call makepkg. Simple right? Well, not really.
The reality
Bamboo works perfectly with docker. My older direct cmake invoking approach worked directly after getting my base image to the right state with dependencies. But, there was an interesting issue. Because of the way bamboo uses bitbucket and forwards the directory, somehow you can’t rely on git describe inside docker anymore. That’s a bit of a problem as I use tags to describe my versions. But ok.
The bigger problem shows up when I actually tried to switch from raw cmake to makepkg for arch package building. I wanted to use makepkg so I can get my pkg file all ready to go and you’d expect this would work in an arch base docker. Well, yes, the base image (with my dependencies added on top of it) are fine but how it’s ran is not. makepkg cannot be run as root.
Root root root
Yes, the docker image uses root. A lot of docker images are using root, makepkg won’t fly with that.
Try 1
After a long search, I thought I found the solution: using USER
to set the docker user.
Well, in theory this works, because it’s stored allongside the image, so makepkg (or any other command to be executed) will be ran under the specified user. However, this won’t work with bamboo, why? Because it runs its initialisation scripts with -u root
. Yes, so the directories you get from docker are basically owned by root. So anything using the configured USER
will fail on permissions. Not only that, certain other non -u root
steps in bamboo also fail. Very ugly.
Try 2
Next approach, accept the root start, but inside the docker, start dropping privileges using su-exec
. This stops the complaint by makepkg
but, oh no, it’s in root owned space. Well, let’s chown
stuff. Nope, it might seem to be owned by someone else, but still only root may touch.
Try 3
Well, last try is best try. It’s cumbersome but, in the end it worked. Start as root, chmod
the bamboo provided stuff (necessary as permissions are really tight). Next as our regular user, use its home directory to create the actual build directory. Copy over as our regular user the required files. cd
into it and run makepkg. Finally copy over our result as root back into bamboo accessible space.
Finally, this works. But, if bamboo could run docker steps without root, this would be much easier.
The result of all this hard work can be found here
Note that this does some additional things.
Solution
Prepare
In order to get a good version, we do the following:
- Get the source
- Initialize any submodules (because bamboo doesn’t really do that reliably)
- Go peek into the source to get our git version
- Remove any bloat, like bamboo-specs
- Move the dist dir outside, we need it later but source tarball doesn’t (really)
- Put it into a VERSION file for CMake later on
- Rename the dir to project-VERSION because most packagers expect the folder to match the tarball
- Tarball it up, excluding any hidden files because these are likely unimportant
- Modify the PKGBUILD file
- Replace VERSION with what we learned
- Replace md5-{filename}-md5 by the actual md5 hashes of all the created files
- Let bamboo extract artifacts
- source tarball
- distribute files to use by packaging tools
This makes a nice clean tarball which can be used by the package specifications defined in ‘dist’
Build Arch
Next, we have enough to build the arch package
- Get the tarball and dist
- Create our temp directory in ‘/home/builder/temp’
- Chmod everything in bamboo directory to be world readable
- As the builder user
- Copy over all of the files in bamboo to ‘/home/builder/temp’
- Invoke ‘makepkg’
- Back to root, copy over the generated pkg
- Let bamboo extract artifacts
- the generated pkg
This can be extended easily to custom recipes for other distributions. And since the source is in a separate stage, all distros can be rebuilt in parallel, just as jobs generally run.