ci(lesavka): reuse headless display wrapper across gates

This commit is contained in:
Brad Stein 2026-05-19 20:22:37 -03:00
parent e55243f42b
commit e1429f0609
7 changed files with 31 additions and 15 deletions

15
scripts/ci/headless_run.sh Executable file
View File

@ -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[@]}"
}

View File

@ -3,6 +3,7 @@
set -euo pipefail set -euo pipefail
ROOT=$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")/../.." && pwd) ROOT=$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")/../.." && pwd)
source "${ROOT}/scripts/ci/headless_run.sh"
cd "$ROOT" cd "$ROOT"
if [[ "${LESAVKA_ALLOW_DISRUPTIVE_INPUT_TESTS:-0}" != "1" ]]; then if [[ "${LESAVKA_ALLOW_DISRUPTIVE_INPUT_TESTS:-0}" != "1" ]]; then
@ -38,4 +39,4 @@ INPUT_TESTS=(
cargo fmt --all -- --check cargo fmt --all -- --check
cargo check -q -p lesavka_client --bin lesavka-client cargo check -q -p lesavka_client --bin lesavka-client
cargo check -q -p lesavka_server --bin lesavka-server 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[@]}"

View File

@ -3,6 +3,7 @@
set -euo pipefail set -euo pipefail
ROOT_DIR=$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd) ROOT_DIR=$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)
source "${ROOT_DIR}/scripts/ci/headless_run.sh"
REPORT_DIR="${ROOT_DIR}/target/media-reliability-gate" REPORT_DIR="${ROOT_DIR}/target/media-reliability-gate"
TEST_LOG="${REPORT_DIR}/cargo-test.log" TEST_LOG="${REPORT_DIR}/cargo-test.log"
SUMMARY_JSON="${REPORT_DIR}/summary.json" SUMMARY_JSON="${REPORT_DIR}/summary.json"
@ -54,11 +55,11 @@ status=0
set +e set +e
{ {
echo '==> client camera profile/unit guards' 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]} camera_status=${PIPESTATUS[0]}
echo echo
echo '==> media reliability contract tests' 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]} contract_status=${PIPESTATUS[0]}
if [[ "${camera_status}" -ne 0 || "${contract_status}" -ne 0 ]]; then if [[ "${camera_status}" -ne 0 || "${contract_status}" -ne 0 ]]; then
exit 1 exit 1

View File

@ -3,6 +3,7 @@
set -euo pipefail set -euo pipefail
ROOT_DIR=$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd) ROOT_DIR=$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)
source "${ROOT_DIR}/scripts/ci/headless_run.sh"
REPORT_DIR="${ROOT_DIR}/target/performance-gate" REPORT_DIR="${ROOT_DIR}/target/performance-gate"
TEST_LOG="${REPORT_DIR}/cargo-test.log" TEST_LOG="${REPORT_DIR}/cargo-test.log"
METRICS_FILE="${REPORT_DIR}/metrics.prom" METRICS_FILE="${REPORT_DIR}/metrics.prom"
@ -32,7 +33,7 @@ PERFORMANCE_TESTS=(
start_seconds=$(date +%s) start_seconds=$(date +%s)
status=0 status=0
set +e 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]} status=${PIPESTATUS[0]}
set -e set -e
duration_seconds=$(($(date +%s) - start_seconds)) duration_seconds=$(($(date +%s) - start_seconds))

View File

@ -2,6 +2,7 @@
set -euo pipefail set -euo pipefail
ROOT_DIR=$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd) ROOT_DIR=$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)
source "${ROOT_DIR}/scripts/ci/headless_run.sh"
REPORT_DIR="${ROOT_DIR}/target/quality-gate" REPORT_DIR="${ROOT_DIR}/target/quality-gate"
COVERAGE_LCOV="${REPORT_DIR}/coverage.lcov" COVERAGE_LCOV="${REPORT_DIR}/coverage.lcov"
SUMMARY_TXT="${REPORT_DIR}/summary.txt" SUMMARY_TXT="${REPORT_DIR}/summary.txt"
@ -199,7 +200,8 @@ status=0
# Several integration contracts intentionally mutate process environment and # Several integration contracts intentionally mutate process environment and
# probe singleton runtime state. Keep coverage collection serial so per-file # probe singleton runtime state. Keep coverage collection serial so per-file
# percentages stay stable enough to serve as a baseline gate. # 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' 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 json
import os import os

View File

@ -3,6 +3,7 @@
set -euo pipefail set -euo pipefail
ROOT_DIR=$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd) ROOT_DIR=$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)
source "${ROOT_DIR}/scripts/ci/headless_run.sh"
REPORT_DIR="${ROOT_DIR}/target/test-gate" REPORT_DIR="${ROOT_DIR}/target/test-gate"
TEST_LOG="${REPORT_DIR}/cargo-test.log" TEST_LOG="${REPORT_DIR}/cargo-test.log"
SUMMARY_JSON="${REPORT_DIR}/summary.json" SUMMARY_JSON="${REPORT_DIR}/summary.json"
@ -27,14 +28,8 @@ build_url=${BUILD_URL:-}
start_seconds=$(date +%s) start_seconds=$(date +%s)
status=0 status=0
set +e set +e
cargo_test_cmd=(cargo test --workspace --all-targets --no-fail-fast --color never) export RUST_TEST_THREADS="${RUST_TEST_THREADS:-1}"
if [[ -z "${DISPLAY:-}" && "${LESAVKA_CI_HEADLESS_GTK:-1}" != "0" ]] && command -v xvfb-run >/dev/null 2>&1; then lesavka_ci_run_headless cargo test --workspace --all-targets --no-fail-fast --color never 2>&1 | tee "${TEST_LOG}"
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}"
status=${PIPESTATUS[0]} status=${PIPESTATUS[0]}
set -e set -e
end_seconds=$(date +%s) end_seconds=$(date +%s)

View File

@ -3,6 +3,7 @@
set -euo pipefail set -euo pipefail
ROOT=$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")/../.." && pwd) ROOT=$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")/../.." && pwd)
source "${ROOT}/scripts/ci/headless_run.sh"
cd "$ROOT" cd "$ROOT"
VIDEO_TESTS=( VIDEO_TESTS=(
@ -24,10 +25,10 @@ VIDEO_IGNORE_REGEX='(^|/)(common/src/(hid|paste|process_metrics)\.rs|server/src/
cargo fmt --all -- --check cargo fmt --all -- --check
cargo check -q -p lesavka_client --bin lesavka-client cargo check -q -p lesavka_client --bin lesavka-client
cargo check -q -p lesavka_server --bin lesavka-server 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 clean --workspace
cargo llvm-cov --workspace "${VIDEO_TESTS[@]}" \ lesavka_ci_run_headless cargo llvm-cov --workspace "${VIDEO_TESTS[@]}" \
--ignore-filename-regex "$VIDEO_IGNORE_REGEX" \ --ignore-filename-regex "$VIDEO_IGNORE_REGEX" \
--fail-under-lines 95 \ --fail-under-lines 95 \
--summary-only --summary-only