From e1429f06095b0c0c57477b321123d338c7e24b7d Mon Sep 17 00:00:00 2001 From: Brad Stein Date: Tue, 19 May 2026 20:22:37 -0300 Subject: [PATCH] ci(lesavka): reuse headless display wrapper across gates --- scripts/ci/headless_run.sh | 15 +++++++++++++++ scripts/ci/input_transport_gate.sh | 3 ++- scripts/ci/media_reliability_gate.sh | 5 +++-- scripts/ci/performance_gate.sh | 3 ++- scripts/ci/quality_gate.sh | 4 +++- scripts/ci/test_gate.sh | 11 +++-------- scripts/ci/video_downstream_gate.sh | 5 +++-- 7 files changed, 31 insertions(+), 15 deletions(-) create mode 100755 scripts/ci/headless_run.sh diff --git a/scripts/ci/headless_run.sh b/scripts/ci/headless_run.sh new file mode 100755 index 0000000..a422709 --- /dev/null +++ b/scripts/ci/headless_run.sh @@ -0,0 +1,15 @@ +#!/usr/bin/env bash +# Run GUI-adjacent CI commands safely on headless Jenkins agents. + +lesavka_ci_run_headless() { + local cmd=("$@") + + if [[ -z "${DISPLAY:-}" && "${LESAVKA_CI_HEADLESS_GTK:-1}" != "0" ]] && command -v xvfb-run >/dev/null 2>&1; then + cmd=(xvfb-run -a -s "-screen 0 1920x1080x24" "${cmd[@]}") + fi + if command -v dbus-run-session >/dev/null 2>&1; then + cmd=(dbus-run-session -- "${cmd[@]}") + fi + + "${cmd[@]}" +} diff --git a/scripts/ci/input_transport_gate.sh b/scripts/ci/input_transport_gate.sh index 545c838..23ab649 100755 --- a/scripts/ci/input_transport_gate.sh +++ b/scripts/ci/input_transport_gate.sh @@ -3,6 +3,7 @@ set -euo pipefail ROOT=$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")/../.." && pwd) +source "${ROOT}/scripts/ci/headless_run.sh" cd "$ROOT" if [[ "${LESAVKA_ALLOW_DISRUPTIVE_INPUT_TESTS:-0}" != "1" ]]; then @@ -38,4 +39,4 @@ INPUT_TESTS=( cargo fmt --all -- --check cargo check -q -p lesavka_client --bin lesavka-client cargo check -q -p lesavka_server --bin lesavka-server -cargo test -q -p lesavka_tests --features disruptive-input-tests "${INPUT_TESTS[@]}" +lesavka_ci_run_headless cargo test -q -p lesavka_tests --features disruptive-input-tests "${INPUT_TESTS[@]}" diff --git a/scripts/ci/media_reliability_gate.sh b/scripts/ci/media_reliability_gate.sh index d0e8b43..5b58d38 100755 --- a/scripts/ci/media_reliability_gate.sh +++ b/scripts/ci/media_reliability_gate.sh @@ -3,6 +3,7 @@ set -euo pipefail ROOT_DIR=$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd) +source "${ROOT_DIR}/scripts/ci/headless_run.sh" REPORT_DIR="${ROOT_DIR}/target/media-reliability-gate" TEST_LOG="${REPORT_DIR}/cargo-test.log" SUMMARY_JSON="${REPORT_DIR}/summary.json" @@ -54,11 +55,11 @@ status=0 set +e { echo '==> client camera profile/unit guards' - cargo test -p lesavka_client --color never input::camera::tests -- --nocapture + lesavka_ci_run_headless cargo test -p lesavka_client --color never input::camera::tests -- --nocapture camera_status=${PIPESTATUS[0]} echo echo '==> media reliability contract tests' - cargo test -p lesavka_tests --color never "${MEDIA_TESTS[@]}" + lesavka_ci_run_headless cargo test -p lesavka_tests --color never "${MEDIA_TESTS[@]}" contract_status=${PIPESTATUS[0]} if [[ "${camera_status}" -ne 0 || "${contract_status}" -ne 0 ]]; then exit 1 diff --git a/scripts/ci/performance_gate.sh b/scripts/ci/performance_gate.sh index 6949fae..1538a9d 100755 --- a/scripts/ci/performance_gate.sh +++ b/scripts/ci/performance_gate.sh @@ -3,6 +3,7 @@ set -euo pipefail ROOT_DIR=$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd) +source "${ROOT_DIR}/scripts/ci/headless_run.sh" REPORT_DIR="${ROOT_DIR}/target/performance-gate" TEST_LOG="${REPORT_DIR}/cargo-test.log" METRICS_FILE="${REPORT_DIR}/metrics.prom" @@ -32,7 +33,7 @@ PERFORMANCE_TESTS=( start_seconds=$(date +%s) status=0 set +e -cargo test -p lesavka_tests "${PERFORMANCE_TESTS[@]}" --color never 2>&1 | tee "${TEST_LOG}" +lesavka_ci_run_headless cargo test -p lesavka_tests "${PERFORMANCE_TESTS[@]}" --color never 2>&1 | tee "${TEST_LOG}" status=${PIPESTATUS[0]} set -e duration_seconds=$(($(date +%s) - start_seconds)) diff --git a/scripts/ci/quality_gate.sh b/scripts/ci/quality_gate.sh index e56ccc1..fe6d439 100755 --- a/scripts/ci/quality_gate.sh +++ b/scripts/ci/quality_gate.sh @@ -2,6 +2,7 @@ set -euo pipefail ROOT_DIR=$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd) +source "${ROOT_DIR}/scripts/ci/headless_run.sh" REPORT_DIR="${ROOT_DIR}/target/quality-gate" COVERAGE_LCOV="${REPORT_DIR}/coverage.lcov" SUMMARY_TXT="${REPORT_DIR}/summary.txt" @@ -199,7 +200,8 @@ status=0 # Several integration contracts intentionally mutate process environment and # probe singleton runtime state. Keep coverage collection serial so per-file # percentages stay stable enough to serve as a baseline gate. -if RUST_TEST_THREADS="${RUST_TEST_THREADS:-1}" cargo llvm-cov --workspace --all-targets --lcov --output-path "${COVERAGE_LCOV}"; then +export RUST_TEST_THREADS="${RUST_TEST_THREADS:-1}" +if lesavka_ci_run_headless cargo llvm-cov --workspace --all-targets --lcov --output-path "${COVERAGE_LCOV}"; then if python3 - "${COVERAGE_LCOV}" "${BASELINE_JSON}" "${METRICS_FILE}" "${SUMMARY_TXT}" "${ROOT_DIR}" "${COVERAGE_CONTRACT_JSON}" "${branch}" "${commit}" "${build_number}" "${jenkins_job}" <<'PY' import json import os diff --git a/scripts/ci/test_gate.sh b/scripts/ci/test_gate.sh index e83f1cc..86e187d 100755 --- a/scripts/ci/test_gate.sh +++ b/scripts/ci/test_gate.sh @@ -3,6 +3,7 @@ set -euo pipefail ROOT_DIR=$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd) +source "${ROOT_DIR}/scripts/ci/headless_run.sh" REPORT_DIR="${ROOT_DIR}/target/test-gate" TEST_LOG="${REPORT_DIR}/cargo-test.log" SUMMARY_JSON="${REPORT_DIR}/summary.json" @@ -27,14 +28,8 @@ build_url=${BUILD_URL:-} start_seconds=$(date +%s) status=0 set +e -cargo_test_cmd=(cargo test --workspace --all-targets --no-fail-fast --color never) -if [[ -z "${DISPLAY:-}" && "${LESAVKA_CI_HEADLESS_GTK:-1}" != "0" ]] && command -v xvfb-run >/dev/null 2>&1; then - cargo_test_cmd=(xvfb-run -a -s "-screen 0 1920x1080x24" "${cargo_test_cmd[@]}") -fi -if command -v dbus-run-session >/dev/null 2>&1; then - cargo_test_cmd=(dbus-run-session -- "${cargo_test_cmd[@]}") -fi -RUST_TEST_THREADS="${RUST_TEST_THREADS:-1}" "${cargo_test_cmd[@]}" 2>&1 | tee "${TEST_LOG}" +export RUST_TEST_THREADS="${RUST_TEST_THREADS:-1}" +lesavka_ci_run_headless cargo test --workspace --all-targets --no-fail-fast --color never 2>&1 | tee "${TEST_LOG}" status=${PIPESTATUS[0]} set -e end_seconds=$(date +%s) diff --git a/scripts/ci/video_downstream_gate.sh b/scripts/ci/video_downstream_gate.sh index 1e1a435..aa629b8 100755 --- a/scripts/ci/video_downstream_gate.sh +++ b/scripts/ci/video_downstream_gate.sh @@ -3,6 +3,7 @@ set -euo pipefail ROOT=$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")/../.." && pwd) +source "${ROOT}/scripts/ci/headless_run.sh" cd "$ROOT" VIDEO_TESTS=( @@ -24,10 +25,10 @@ VIDEO_IGNORE_REGEX='(^|/)(common/src/(hid|paste|process_metrics)\.rs|server/src/ cargo fmt --all -- --check cargo check -q -p lesavka_client --bin lesavka-client cargo check -q -p lesavka_server --bin lesavka-server -cargo test -q -p lesavka_tests "${VIDEO_TESTS[@]}" +lesavka_ci_run_headless cargo test -q -p lesavka_tests "${VIDEO_TESTS[@]}" cargo llvm-cov clean --workspace -cargo llvm-cov --workspace "${VIDEO_TESTS[@]}" \ +lesavka_ci_run_headless cargo llvm-cov --workspace "${VIDEO_TESTS[@]}" \ --ignore-filename-regex "$VIDEO_IGNORE_REGEX" \ --fail-under-lines 95 \ --summary-only