Skip to content

CI/CD Overview & Runner Setup

QED test suites are designed to run on a self-hosted GitHub Actions runner. This page covers why that is required, how to set one up, and how to configure it for both API and UI test execution.


Why a Self-Hosted Runner?

GitHub-hosted runners are ephemeral — they are wiped after every job. This makes them unsuitable for QED for two reasons:

  • Playwright system libraries — Chromium requires a set of native Linux libraries that are not present on GitHub-hosted Ubuntu runners by default. Installing them on every run adds significant overhead.
  • Persistent cache — Gradle dependencies and Playwright browser binaries are large. On a self-hosted runner they persist between runs naturally, without any cache upload/download overhead.

A self-hosted runner on a stable VM is the recommended approach.


Runner Installation

These instructions assume Ubuntu 24.04 LTS. The runner should be installed as a service so it starts automatically on reboot.

Step 1: Create a runner user

It is good practice to run the GitHub Actions runner as a dedicated non-root user:

sudo useradd -m -s /bin/bash runner
sudo usermod -aG sudo runner

Step 2: Download and configure the runner

In GitHub, go to your repository → Settings → Actions → Runners → New self-hosted runner. Select Linux and follow the generated instructions. They will look similar to:

mkdir actions-runner && cd actions-runner
curl -o actions-runner-linux-x64.tar.gz -L https://github.com/actions/runner/releases/download/v2.x.x/actions-runner-linux-x64-2.x.x.tar.gz
tar xzf ./actions-runner-linux-x64.tar.gz
./config.sh --url https://github.com/<your-org>/<your-repo> --token <generated-token>

Step 3: Install as a service

sudo ./svc.sh install
sudo ./svc.sh start

Verify it is running:

sudo ./svc.sh status

The runner should appear as Idle in GitHub under Settings → Actions → Runners.


Java Setup

QED requires Java 22. Install Temurin via SDKMAN or directly:

sudo apt install -y wget apt-transport-https
wget -qO - https://packages.adoptium.net/artifactory/api/gpg/key/public | sudo tee /etc/apt/trusted.gpg.d/adoptium.asc
echo "deb https://packages.adoptium.net/artifactory/deb $(lsb_release -cs) main" | sudo tee /etc/apt/sources.list.d/adoptium.list
sudo apt update
sudo apt install -y temurin-22-jdk
java -version

Playwright System Libraries

UI tests use Playwright to drive Chromium. On Ubuntu 24.04, a set of native system libraries must be installed for Chromium to launch. Without these, the browser will fail to start with a missing library error.

Install the required libraries:

sudo apt install -y \
  libatk1.0-0 \
  libatk-bridge2.0-0 \
  libcups2 \
  libdrm2 \
  libxkbcommon0 \
  libxcomposite1 \
  libxdamage1 \
  libxfixes3 \
  libxrandr2 \
  libgbm1 \
  libpango-1.0-0 \
  libcairo2 \
  libasound2t64 \
  libnspr4 \
  libnss3 \
  libx11-xcb1 \
  libxcb-dri3-0

These only need to be installed once on the runner VM. They persist between runs.


Playwright Browser Binaries

On the first run, Playwright will download Chromium binaries to ~/.cache/ms-playwright. This happens automatically — no manual step is needed. The binaries persist on the self-hosted runner between runs, so subsequent runs are fast.

Do not add a Playwright cache step to your workflow. On a self-hosted runner, caching adds upload/download overhead with no benefit — the binaries already persist on disk.

The same applies to Gradle dependencies — do not add a Gradle cache step to workflows running on a self-hosted runner.


SSH Key for Private Repositories

QED test suites typically depend on private shared repositories (e.g. QED-Shared, QED-Shared-<app>). The runner checks these out during the workflow using an SSH deploy key.

Step 1: Generate a key pair on the runner

ssh-keygen -t ed25519 -C "github-actions-runner" -f ~/.ssh/id_ed25519 -N ""

Step 2: Add the public key as a deploy key

Copy the public key:

cat ~/.ssh/id_ed25519.pub

Add it to each private repository that the runner needs to access: GitHub repo → Settings → Deploy keys → Add deploy key. Enable "Allow read access".

Step 3: Add the private key as a repository secret

Use the GitHub CLI to avoid copy-paste issues with multiline keys:

gh secret set RUNNER_SSH_PRIVATE_KEY --repo <your-org>/<your-repo> < ~/.ssh/id_ed25519

This secret must be present in every repository whose workflow calls a QED test workflow via workflow_call, since secrets: inherit only passes down secrets that exist in the calling repository.


Secrets Configuration

The following secrets are required in any repository that calls a QED UI test workflow. Add them under Settings → Secrets and variables → Actions.

Secret Purpose
RUNNER_SSH_PRIVATE_KEY SSH key for checking out private QED repos
QED_PASSWORD_ADMIN Password for the admin test user
QED_PASSWORD_MANAGER Password for the manager test user
QED_PASSWORD_USER Password for the standard test user
QED_PASSWORD_PARENT Password for the parent test user

Add additional user secrets as needed to match the test users defined in your QED-Shared-<app> module.

For API-only test workflows, only RUNNER_SSH_PRIVATE_KEY is required unless your tests also use authenticated endpoints.


Environment Variables

QED uses the following environment variables at runtime:

Variable Purpose CI value Local value
QED_HEADLESS Controls browser visibility true unset (headed)
QED_PASSWORD_* Test user credentials from secrets from local env or config

QED_HEADLESS defaults to headed mode when unset, so local runs open a real browser window. Setting it to true in the workflow enables headless mode on CI without any code changes.


Environment Key Convention

QED uses short environment keys passed as workflow inputs. The convention used across all workflows is:

Environment Key Also known as
Development dev
Staging stag staging
Pre-production preprod
Production prod

These keys map to entries in your QED project's environment configuration file and must be consistent across your test suite and workflow definitions.