/gnome-shell-pod

:package: A Podman container which runs GNOME Shell in xvfb

Primary LanguageShellMIT LicenseMIT

📦 Run GNOME Shell in a Container!

ℹ️ I want to thank @amezin for his awesome contributions, which made it possible to transition the images from Ubuntu to Fedora.

The Idea

Developing high-quality GNOME Shell extensions is challenging due to various reasons. One major issues is the lack of continuous integration possibilities. So I thought: Why not try getting GNOME Shell running on the runners of GitHub Actions?

Anyway, here is what already works:

  • Multiple containers for various GNOME Shell versions:
  • Choose display manager:
    • Wayland
    • X11
  • You can launch other applications, such as gnome-control-center.
  • You can make "screenshots" of GNOME Shell and transfer them to host memory.
  • You can install a GNOME Shell extension from host memory and enable it.
  • You can use xdotool to interact with the extension.
  • All of this works locally and on the GitHub hosted runners!

How Does It Work?

A user called "gnomeshell" will auto-login via systemd-logind.service.d and run gnome-shell on xvfb. The framebuffer of xvfb is mapped to a file which can be copied to host memory and converted to an image. This way we can actually make "screenshots" of GNOME Shell!

How Do I Use It?

I wrote a series of blog posts in order to explain how I use these containers for continuous integration test of my GNOME Shell extensions. For some in-depth examples, you may want to read those:

  1. Bundling the Extension
  2. Automated Release Publishing
  3. Automated Tests with GitHub Actions

Below, you'll find some simple examples to get you started. You will need to install imagemagick (for converting the xvfb framebuffer image) and, obviously, Podman. On Ubuntu-like distributions you can install them with this command:

sudo apt-get install imagemagick podman

Basic Usage

If you want to play around with GNOME Shell inside the pod, use these commands:

# Run the container in interactive mode. This will automatically login the
# gnomeshell user.
podman run --rm --cap-add=SYS_NICE --cap-add=IPC_LOCK --cap-add=CAP_SYS_ADMIN -ti ghcr.io/schneegans/gnome-shell-pod-33

# Start GNOME Shell.
systemctl --user start "gnome-xsession@:99"

# For example, you can run this command inside the container:
DISPLAY=:99 gnome-control-center

Now use another terminal on your host to capture and display a screenshot.

# Copy the framebuffer of xvfb.
podman cp $(podman ps -q -n 1):/opt/Xvfb_screen0 .

# Convert it to jpeg.
convert xwd:Xvfb_screen0 capture.jpg

# And finally display the image.
# This way we can see that GNOME Shell is actually up and running!
eog capture.jpg

You can kill the gnome-control-center with Ctrl+C in the container and then poweroff the container with poweroff.

Detached Mode

In this example we will download some pictures inside the container and make GNOME Shell use one of them as background image. The gnomeshell user can run passwordless sudo, so you can simply install packages. podman exec --user gnomeshell can be used to run arbitrary commands inside the running container. However, many commands interacting with GNOME Shell will require a connection to the D-Bus. To make this easier, the images contain a /local/bin/set-env.sh script, which sets all required environment variables.

# Run the container in detached mode.
POD=$(podman run --rm --cap-add=SYS_NICE --cap-add=IPC_LOCK --cap-add=CAP_SYS_ADMIN -td ghcr.io/schneegans/gnome-shell-pod-33)

do_in_pod() {
  podman exec --user gnomeshell --workdir /home/gnomeshell "${POD}" set-env.sh "$@"
}

# Install the gnome-backgrounds package.
do_in_pod sudo dnf -y install gnome-backgrounds

# Set GNOME Shell's background image. This requires a D-Bus connection,
# so we wrap the command in the set-env.sh script.
do_in_pod gsettings set org.gnome.desktop.background picture-uri \
          "file:///usr/share/backgrounds/gnome/adwaita-day.jpg"

# Wait until the user bus is available.
do_in_pod wait-user-bus.sh

# Start GNOME Shell.
do_in_pod systemctl --user start "gnome-xsession@:99"

# Wait some time until GNOME Shell has been started.
sleep 3

# Now make a screenshot and show it!
podman cp ${POD}:/opt/Xvfb_screen0 . && \
       convert xwd:Xvfb_screen0 capture.jpg && \
       eog capture.jpg

# Now we can stop the container again.
podman stop ${POD}

:octocat: Contributing

Commits should start with a Capital letter and should be written in present tense (e.g. 🎉 Add cool new feature instead of 🎉 Added cool new feature). You should also start your commit message with one applicable emoji. This does not only look great but also makes you rethink what to add to a commit. Make many but small commits!

Emoji Description
🎉 :tada: When you added a cool new feature.
🔧 :wrench: When you added a piece of code.
🎨 :art: When you improved / added assets like themes.
🚀 :rocket: When you improved performance.
📝 :memo: When you wrote documentation.
🪲 :beetle: When you fixed a bug.
🔀 :twisted_rightwards_arrows: When you merged a branch.
🔥 :fire: When you removed something.
🚚 :truck: When you moved / renamed something.