Check if PyQt Program is starting in Codeberg CI
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.