Capturing screenshots on CI tasks using CircleCI

When running continuous build tasks it can be useful to include screenshots of any GUI apps so that they maybe be saved as assets along with any other build results.

The information below uses CircleCI, but requirements and setup should be similar for other CI providers.

First the circle.yml config file will need some additions, add the contents of the sections below into any configuration that exists already.

dependencies:
  override:
    - sudo apt-get update && sudo apt-get install wmctrl fluxbox x11-apps
    - sudo /usr/bin/killall Xvfb
    - sudo /sbin/start-stop-daemon --start --quiet --pidfile /tmp/custom_xvfb_1.pid --make-pidfile --background --exec /usr/bin/Xvfb -- :99 -screen 0 4000x1800x24
    - fluxbox > /dev/null 2>&1:
        background: true
test:
  override:
    - ./screenshotExample.sh

The lines above perform the following tasks:

  • Get the latest update sites for debian.
  • Install the wmctrl, fluxbox and x11-apps packages (x11-apps is only required for example below).
  • Stop the current framebuffer server.
  • Start a new framebuffer server with the require config.
  • Start the fluxbox window manager in the background.
  • Run the example script to take the screenshot.

The fluxbox window manager was chosen as it is small and quick to install, some even smaller window managers do not allow you to manage windows using wmctrl. The CircleCI background option is used here to stop a warning being shown.

We start a new framebuffer server as then the screen dimensions can be specified, as this is in memory only the resolution can be as large as you need.

Next, a script is needed to run all the required tasks to take a screen shot.

#/bin/bash
set -e

echo "Example screenshot script..."

xeyes &

BACKGROUND_PID=$!
sleep 10
if ! ps -p ${BACKGROUND_PID} ; then
  echo "Problem with GUI app, see error above."
  exit 1
fi

xwininfo -tree -root
WIN_IDENT="feh"
RESOURCE_ID=`xwininfo -tree -root | grep ${WIN_IDENT} | cut -f 1 -d '"' | sed "s/ //g"`
echo "Got window Resource ID of: ${RESOURCE_ID}"
wmctrl -i -r ${RESOURCE_ID} -b toggle,maximized_vert,maximized_horz

echo "Taking screenshot of window..."
xwd -id ${RESOURCE_ID} | convert xwd:- ${CIRCLE_ARTIFACTS}/dag_screenshot.png

echo "Killing PID: ${BACKGROUND_PID}..."
kill -HUP $!

echo "...Done"

The above script does the following:

  • Starts the GUI app in the background.
  • Captures the PID of the app so it can be killed later.
  • Waits 10 seconds then checks if the app has started up.
  • Displays all the window manager resource info for debugging (see below).
  • Gets the resource ID for the correct window currently being displayed.
  • Maximise the window.
  • Take a screenshot of the window and convert it to a PNG.
  • Kill the GUI app.

The tricky part is finding out the value for the WIN_IDENT variable. Using the output from the xwininfo -tree -root command all the windows displayed on the framebuffer will be detailed, fluxbox gives them all quit short identifiers, but there should only be a few to choose from.

The resulting screenshot is saved in the CIRCLE_ARTIFACTS directory so it can be found above the console output after the build has finished.

Last updated: 30/05/2017