Skip to main content

Check if PyQt Program is starting in Codeberg CI

· 3 min read

Today I got a bug report that one of my programs is not starting. The reason for this is simple: My programs are installed as Python packages. If you use data files, inside a Python package with setuptools, you need to tell setuptools to include the packages. I use a file called MANIFEST.in for that. I had included some new datafiles, but I forgot to add the new files to the MANIFEST.in. I usually start the my Programs directly from the source directory during development, so I don't noticed the Issue, as my source directory had of course the datafiles. I just forgot to test, if the package is working correctly before making a new Release, which was totally my fault. As a consequence I needed to make sure that this doesn't happen again using the CI.

Using automatic tests with e.g. pytest to ensure everything works as it should would be great but unfortunately I haven't find a good way to do this for GUI Applications. So I came up with another idea: I just start the program and after 5 seconds I check if it's still running. If it's running, I can be sure the program has started correctly. This didn't catch any runtime bugs, but it's better than nothing I guess.

I wrote a Python script to do this:

import subprocess
import argparse
import time
import sys


def main() -> None:
parser = argparse.ArgumentParser()
parser.add_argument("--timeout", type=int, default=5, help="Set the timeout")
parser.add_argument("cmdline", nargs="+")
args = parser.parse_args()

program = subprocess.Popen(args.cmdline)

time.sleep(args.timeout)

if program.poll() is None:
print("Program is still running. Killing.")
program.kill()
else:
print("Program is no longer running", file=sys.stderr)
sys.exit(1)


if __name__ == "__main__":
main()

You can simple use this script with python script.py <program>.

But there's one problem for integrating this in the CI: It is a graphical program, so it needs a graphical environment (X11 or Wayland) to run. The CI does not have access to a graphical environment. Luckily theres Xvfb, which is a virtual XServer. The rendering is fully done in memory, so it is perfect for a CI Pipeline. It even comes with a handy script called xvfb-run. This script starts Xvfb, runs the given command in it and closes Xvfb after the command finished.

So let's set the pipeline up:

steps:
check_starting:
image: python:latest
commands:
- apt update
- apt install -y xvfb
- pip install --break-system-packages .
- wget https://codeberg.org/JakobDev/ci-scripts/raw/branch/main/test/check-program-starting.py
- python ./check-program-starting.py xvfb-run jdflatpaksnapshot

Unfortunately PyQt6 from PyPI needs some libraries that are not installed in the container. AFter a lot of trial and error I finally found all needed packages. This is the final working version:

steps:
check_starting:
image: python:latest
commands:
- apt update
- apt install -y libxkbcommon-x11-0 libegl1 libdbus-1-3 libxcb-cursor0 libxcb-icccm4 libxcb-keysyms1 libxcb-shape0 xvfb
- pip install --break-system-packages .
- wget https://codeberg.org/JakobDev/ci-scripts/raw/branch/main/test/check-program-starting.py
- python ./check-program-starting.py xvfb-run jdflatpaksnapshot

Now everything works as expected and I can be sure my Programs are starting when making a new Release.