Files
2026-05-18 11:56:47 +05:30

170 lines
5.4 KiB
Bash

#!/usr/bin/env bash
# Phase 0 aggregator — runs every check in .github/workflows/ci.yml locally and
# reports a single pass/fail summary. Use this as the "did I set everything up
# right?" one-liner for new teammates.
#
# Pieces run, in order:
# 1. Rule R2 boundary (scripts/check_pdfium_boundary.sh)
# 2. Engine (cmake configure + build + ctest)
# 3. Gateway (pip install -e [dev] + ruff + pytest, in gateway/)
# 4. WASM hello-world (cmake configure + build + node hello.test.mjs)
#
# Skips (not failures) are reported when a toolchain isn't present — e.g. no
# Emscripten on PATH skips WASM. Each piece runs independently; a failure in
# one does not abort later pieces.
#
# Usage:
# ./scripts/test_phase0.sh # auto-pick preset by OS
# ./scripts/test_phase0.sh linux-asan # override preset
# PHASE0_BINARY_DIR=/tmp/build ./scripts/test_phase0.sh
# SKIP_WASM=1 ./scripts/test_phase0.sh
#
# Compatible with bash 3.2 (macOS default) — uses parallel indexed arrays
# instead of associative arrays.
set -uo pipefail # NOT -e: we want to collect failures, not abort on first
REPO_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
cd "${REPO_ROOT}"
PRESET="${1:-}"
if [[ -z "${PRESET}" ]]; then
case "$(uname -s)" in
Darwin*) PRESET=macos-debug ;;
*) PRESET=linux-debug ;;
esac
fi
BINARY_DIR="${PHASE0_BINARY_DIR:-}"
STEPS=()
STATUSES=()
LAST_STATUS=PASS
record() {
STEPS+=("$1")
STATUSES+=("$2")
LAST_STATUS="$2"
}
run_step() {
local name="$1"; shift
echo
echo ">> [${name}]"
if "$@"; then
record "${name}" PASS
echo " [${name}] OK"
else
local rc=$?
record "${name}" FAIL
echo " [${name}] FAILED (exit ${rc})"
fi
}
skip_step() {
local name="$1"
local reason="$2"
echo
echo ">> [${name}] SKIPPED: ${reason}"
record "${name}" SKIP
}
echo "Phase 0 aggregator — preset='${PRESET}'${BINARY_DIR:+ binaryDir='${BINARY_DIR}'}"
# --- 1. Rule R2 boundary -----------------------------------------------------
run_step 'R2 boundary' bash "${REPO_ROOT}/scripts/check_pdfium_boundary.sh"
# --- 2. Engine ---------------------------------------------------------------
engine_configure() {
if [[ -n "${BINARY_DIR}" ]]; then cmake --preset "${PRESET}" -B "${BINARY_DIR}";
else cmake --preset "${PRESET}"; fi
}
engine_build() {
if [[ -n "${BINARY_DIR}" ]]; then cmake --build "${BINARY_DIR}";
else cmake --build --preset "${PRESET}"; fi
}
engine_test() {
if [[ -n "${BINARY_DIR}" ]]; then ctest --test-dir "${BINARY_DIR}" --output-on-failure;
else ctest --preset "${PRESET}"; fi
}
if [[ "${SKIP_ENGINE:-0}" == "1" ]]; then
skip_step 'engine' 'requested via SKIP_ENGINE=1'
elif [[ -z "${VCPKG_ROOT:-}" ]]; then
skip_step 'engine' 'VCPKG_ROOT not set — run scripts/bootstrap.sh first (and re-source your shell rc)'
else
run_step 'engine configure' engine_configure
if [[ "${LAST_STATUS}" == PASS ]]; then
run_step 'engine build' engine_build
if [[ "${LAST_STATUS}" == PASS ]]; then
run_step 'engine test' engine_test
else
skip_step 'engine test' 'build failed'
fi
else
skip_step 'engine build' 'configure failed'
skip_step 'engine test' 'configure failed'
fi
fi
# --- 3. Gateway --------------------------------------------------------------
PY=""
if command -v python3 >/dev/null 2>&1; then PY="$(command -v python3)";
elif command -v python >/dev/null 2>&1; then PY="$(command -v python)"; fi
if [[ "${SKIP_GATEWAY:-0}" == "1" ]]; then
skip_step 'gateway' 'requested via SKIP_GATEWAY=1'
elif [[ -z "${PY}" ]]; then
skip_step 'gateway' 'python/python3 not on PATH'
else
pushd gateway >/dev/null
run_step 'gateway install' "${PY}" -m pip install --quiet -e ".[dev]"
if [[ "${LAST_STATUS}" == PASS ]]; then
run_step 'gateway lint' "${PY}" -m ruff check .
run_step 'gateway format' "${PY}" -m ruff format --check .
run_step 'gateway pytest' "${PY}" -m pytest
fi
popd >/dev/null
fi
# --- 4. WASM hello-world -----------------------------------------------------
if [[ "${SKIP_WASM:-0}" == "1" ]]; then
skip_step 'wasm' 'requested via SKIP_WASM=1'
elif ! command -v emcc >/dev/null 2>&1; then
skip_step 'wasm' 'emcc not on PATH — source emsdk_env.sh first'
elif ! command -v node >/dev/null 2>&1; then
skip_step 'wasm' 'node not on PATH'
else
run_step 'wasm configure' cmake --preset wasm
if [[ "${LAST_STATUS}" == PASS ]]; then
run_step 'wasm build' cmake --build --preset wasm
if [[ "${LAST_STATUS}" == PASS ]]; then
run_step 'wasm test' node wasm/hello.test.mjs
else
skip_step 'wasm test' 'build failed'
fi
else
skip_step 'wasm build' 'configure failed'
skip_step 'wasm test' 'configure failed'
fi
fi
# --- Summary ----------------------------------------------------------------
echo
echo '================ Phase 0 summary ================'
pad=0
for s in "${STEPS[@]}"; do
if (( ${#s} > pad )); then pad=${#s}; fi
done
any_fail=0
for i in "${!STEPS[@]}"; do
printf " %-${pad}s %s\n" "${STEPS[$i]}" "${STATUSES[$i]}"
if [[ "${STATUSES[$i]}" == FAIL ]]; then any_fail=1; fi
done
echo '================================================='
if [[ "${any_fail}" -ne 0 ]]; then
echo 'Phase 0: FAIL'
exit 1
fi
echo 'Phase 0: PASS'
exit 0