Gentoo Build Publisher: Running arbitrary commands in a machine's chroot

Gentoo Build Publisher uses buildah containers to build each machine's binary packages. For each machine, the Jenkins build runs arbitrary commands in the respective container. Usually the user does not need to concern themselves with this implementation detail. But sometimes we need to "open up" the container and do something. A typical example for me is when building a new machine and temporarily resolving the initial circular dependencies (I'm looking at you freetype and harfbuzz!).

For backround, the reason Gentoo Build Publisher uses containers instead of chroot is that (buildah) containers give Jenkins the ability to run commands inside the container without giving Jenkins root access. The containers run in their own user namespace, allowing processes to run as if they were root inside the container while running as a non-root user to the host.

At a general level what I really want to do is execute arbitrary commands in a GBP container. This is actually possible and quite easy to do. All that is needed is to create a parametrized Jenkins build and run the command from that build. Here's how to do that.

1. Create a parametrized Jenkins project

This step only has to be done once. Afterward you can use the same Jenkins project to run different commands on different machines.

Log into Jenkins. Hopefully you can remember how to do that. Under the same folder level as your Gentoo machine projects (if you went by the Install Guide it's the root level), click on "+ New Item". On the following page give the build a name, for example "run", and the type will be a "Freestyle project" click the "OK" button.

New Freestyle Project

Next you'll be taken to the "Configure" page. For this page go ahead and enter an description like "Run a command inside a gentoo container". This is free text so use whatever description works for you. The most important items in the "General" section is the "This build is parametrized" button. Enable that option. Once enabled a "Add parameter" dropdown will appear. You will add 2 parameters:

Add Parameters

Add a "String parameter". The name is "machine" and the default value should be the name of one of your machine builds, say "base".

Add machine Parameter

Now add a second "String parameter" (the "Add parameter" dropdown appears under the first parameter). The name is "command" and the default value should be some harmless command to run inside the container. I use "date" for example.

Add command Parameter

Now for the final step. Scroll down to the "Build Steps" section. Click the "Add build step" dropdown and select "Execute shell". You will then get a prompt. Enter the following:

buildah run --volume /proc:/proc "${machine}"-root bash -c "${command}"

Add Execute Shell Step

After this step click the "Save" button. You now have a new Jenkins job called "run".

2. Run commands from the "run" project

This step is to be performed each time you need to run a command inside a machine's container.

Now let's say we have a machine, "babette", that we want execute a command in. From the Jenkins folder listing, click on the "run" project. From there in on the left should appear a "▶️ Build with Parameters" link. Click on that and the build dialog appears which you will see the 2 parameters you configured in step 1. For the "machine" parameter you should enter the name of the machine (container) you want to run (say "babette") and for the "command" field enter any arbitrary command, for example echo hello world. Next click the "▶️ Build" button and the command is scheduled to run in the machine's container.

Run Project

If you click on the build number and the "Console Output" button you will see the output of the command.

Console Outpt

If you're "hello world" test ran successfully you can then move on to more complex commands, say

USE="-harfbuzz" emerge --oneshot --color=n media-libs/freetype

While I rarely need to run a command inside a container, occasionally I do and this is a good way of doing it.