forked from lei.chen/myxce
Add python3 + pycapnp/pyyaml/jsonschema/click/pytest/ruff (+pip) to the nix dev shell, wire a new `xceadmin` case into xce-build.sh (schema sync from src/schema/ and src/configs/schema/, pip install by profile, pytest), package-data config so bundled schemas survive a non-editable install, xce-build SKILL.md docs, and ruff format/check hooks matching this repo's stdin-JSON hook convention (not brief.md's env-var sketch, which would have silently no-op'd). Verified live end-to-end inside `nix develop ./src` for both the default (editable) and release (pinned) profiles; found and fixed 3 real bugs along the way (missing pip, PEP 668 externally-managed- environment, missing package-data for release-profile bundling) — logged as bug-1458/1459/1460. Requirements: 5.5, 8.1, 8.2, 8.6
174 lines
7.1 KiB
Bash
Executable file
174 lines
7.1 KiB
Bash
Executable file
#!/usr/bin/env bash
|
|
set -euo pipefail
|
|
|
|
COMPONENT="${1:-all}"
|
|
|
|
# Build PROFILE controls the meson buildtype + sanitizer (and the default build
|
|
# dir, so the variants never clobber each other):
|
|
# asan (default) debug + AddressSanitizer → xce.build (unit-test CI)
|
|
# debug debug, NO sanitizer (-O0 -g3 -fno-inline -fno-omit-frame-
|
|
# pointer) → build.dbg (gdb / core dumps)
|
|
# release release -O3, no sanitizer → build.release (soak / perf)
|
|
#
|
|
# Why `debug` exists (bug-1286): some crashes are heisenbugs that ASAN perturbs
|
|
# away (different allocator/layout → no SIGSEGV) and that gdb-on-release turns
|
|
# into a timeout/hang. The non-ASAN -O0 -g3 build reproduces them AND yields a
|
|
# fully symbolized backtrace under gdb — the only way to root-cause that class.
|
|
#
|
|
# Arg parsing is backward-compatible: arg2 may be a profile keyword OR a legacy
|
|
# build_dir; arg3 is an optional explicit build_dir override.
|
|
case "${2:-}" in
|
|
asan|debug|release) PROFILE="$2"; BUILD_DIR="${3:-}" ;;
|
|
"") PROFILE="asan"; BUILD_DIR="" ;;
|
|
*) PROFILE="asan"; BUILD_DIR="$2" ;; # legacy: arg2 = build_dir
|
|
esac
|
|
|
|
if [ -z "${BUILD_DIR:-}" ]; then
|
|
case "$PROFILE" in
|
|
asan) BUILD_DIR="xce.build" ;;
|
|
debug) BUILD_DIR="build.dbg" ;;
|
|
release) BUILD_DIR="build.release" ;;
|
|
esac
|
|
fi
|
|
|
|
# RUN_TESTS: the unit suites are ASAN-oriented (leak detection) and the meson
|
|
# test harness is fragile on this sandbox's overlay fs (bug-924 fdatasync). Only
|
|
# the `asan` profile runs them; `debug`/`release` are BUILD-ONLY — their purpose
|
|
# is a binary to drive under gdb / a soak, not a test run. Run a suite directly
|
|
# against those binaries when you want it (it is overlay-fs sensitive).
|
|
case "$PROFILE" in
|
|
asan) MESON_OPTS=(--buildtype=debug -Db_sanitize=address); RUN_TESTS=1 ;;
|
|
debug) MESON_OPTS=(--buildtype=debug -Db_sanitize=none); RUN_TESTS=0 ;;
|
|
release) MESON_OPTS=(--buildtype=release -Db_sanitize=none); RUN_TESTS=0 ;;
|
|
esac
|
|
|
|
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
|
SRC_DIR="$(cd "$SCRIPT_DIR/.." && pwd)"
|
|
|
|
cd "$SRC_DIR"
|
|
|
|
usage() {
|
|
echo "Usage: $0 [component] [profile|build_dir] [build_dir]"
|
|
echo "Components: all (default), lib, controller, scheduler, worker, apiserver, xcecli, xceadmin"
|
|
echo "Profiles: asan (default), debug (non-ASAN -O0 -g3, for gdb/cores), release"
|
|
exit 1
|
|
}
|
|
|
|
setup_build() {
|
|
echo "=== Clean build: $BUILD_DIR (profile=$PROFILE) ==="
|
|
rm -rf "$BUILD_DIR"
|
|
meson setup "$BUILD_DIR" "${MESON_OPTS[@]}"
|
|
}
|
|
|
|
case "$COMPONENT" in
|
|
lib)
|
|
setup_build
|
|
echo "=== Building lib + tests ==="
|
|
meson compile -C "$BUILD_DIR" xcelib_test
|
|
if [ "$RUN_TESTS" = 1 ]; then
|
|
echo "=== Running lib tests ==="
|
|
meson test -C "$BUILD_DIR" "libxce test" --print-errorlogs
|
|
fi
|
|
;;
|
|
controller)
|
|
setup_build
|
|
echo "=== Building lib + controller + tests ==="
|
|
meson compile -C "$BUILD_DIR" xce_controller controller_unit_test controller/xce_test
|
|
if [ "$RUN_TESTS" = 1 ]; then
|
|
echo "=== Running controller tests ==="
|
|
meson test -C "$BUILD_DIR" --suite controller --print-errorlogs
|
|
fi
|
|
;;
|
|
scheduler)
|
|
setup_build
|
|
echo "=== Building lib + scheduler + tests ==="
|
|
meson compile -C "$BUILD_DIR" xce_scheduler sched_test
|
|
if [ "$RUN_TESTS" = 1 ]; then
|
|
echo "=== Running scheduler tests ==="
|
|
"./$BUILD_DIR/scheduler/testsuite/sched_test"
|
|
fi
|
|
;;
|
|
worker)
|
|
setup_build
|
|
echo "=== Building lib + worker ==="
|
|
meson compile -C "$BUILD_DIR" xcecd xcecd_worker xrun
|
|
echo "=== Worker built (no unit tests registered) ==="
|
|
;;
|
|
apiserver)
|
|
setup_build
|
|
echo "=== Building lib + apiserver + xcecli ==="
|
|
meson compile -C "$BUILD_DIR" apiserver xcecli
|
|
if [ "$RUN_TESTS" = 1 ]; then
|
|
echo "=== Running frontend Go unit tests ==="
|
|
cd frontend && make test
|
|
fi
|
|
;;
|
|
xcecli)
|
|
setup_build
|
|
echo "=== Building xcecli ==="
|
|
meson compile -C "$BUILD_DIR" xcecli
|
|
if [ "$RUN_TESTS" = 1 ]; then
|
|
echo "=== Running xcecli Go unit tests ==="
|
|
cd frontend/xcecli && CGO_ENABLED=0 go test ./... -count=1
|
|
fi
|
|
;;
|
|
xceadmin)
|
|
# Python — no meson, dispatched by this case statement alone (design
|
|
# review correction: xceadmin is deliberately NOT wired into
|
|
# src/meson.build/meson.options, see .kiro/specs/admin-config-tool/
|
|
# design.md, File Structure Plan). Ignores $BUILD_DIR/$MESON_OPTS;
|
|
# $PROFILE only selects editable vs. pinned pip install below.
|
|
XCEADMIN_DIR="$SRC_DIR/xceadmin"
|
|
SCHEMA_DST="$XCEADMIN_DIR/src/xcecommon/schema_files"
|
|
echo "=== Syncing xceadmin bundled schemas ==="
|
|
mkdir -p "$SCHEMA_DST/json"
|
|
cp "$SRC_DIR/schema/controller.capnp" "$SCHEMA_DST/controller.capnp"
|
|
cp "$SRC_DIR/schema/c.capnp" "$SCHEMA_DST/c.capnp"
|
|
cp "$SRC_DIR/configs/schema/"*.schema.json "$SCHEMA_DST/json/"
|
|
cd "$XCEADMIN_DIR"
|
|
# nix's python3 site-packages lives under the read-only /nix/store,
|
|
# so `pip install` (editable or pinned) can't target it directly —
|
|
# it refuses with "externally-managed-environment" (PEP 668). Use a
|
|
# throwaway venv that inherits the nix-provided pycapnp/pyyaml/
|
|
# jsonschema/click/pytest (--system-site-packages) so pip only ever
|
|
# has to install xceadmin itself, never rebuild those from PyPI.
|
|
# Recreated on every invocation for a clean, reproducible install —
|
|
# same philosophy as setup_build's `rm -rf "$BUILD_DIR"` above.
|
|
VENV_DIR="$XCEADMIN_DIR/.venv"
|
|
rm -rf "$VENV_DIR"
|
|
python3 -m venv --system-site-packages "$VENV_DIR"
|
|
if [ "$PROFILE" = "release" ]; then
|
|
echo "=== Building xceadmin Python package (pinned, non-editable) ==="
|
|
"$VENV_DIR/bin/pip" install . --quiet
|
|
else
|
|
echo "=== Building xceadmin Python package (editable) ==="
|
|
"$VENV_DIR/bin/pip" install -e . --quiet
|
|
fi
|
|
echo "=== Running xceadmin tests ==="
|
|
"$VENV_DIR/bin/python" -m pytest tests/ -v
|
|
echo "=== Done: xceadmin (profile=$PROFILE) ==="
|
|
exit 0
|
|
;;
|
|
all)
|
|
setup_build
|
|
echo "=== Building all components ==="
|
|
meson compile -C "$BUILD_DIR"
|
|
if [ "$RUN_TESTS" = 1 ]; then
|
|
echo "=== Running all C tests ==="
|
|
meson test -C "$BUILD_DIR" --print-errorlogs
|
|
echo "=== Running scheduler test (manual) ==="
|
|
"./$BUILD_DIR/scheduler/testsuite/sched_test"
|
|
echo "=== Running frontend Go unit tests ==="
|
|
cd frontend && make test
|
|
fi
|
|
;;
|
|
*)
|
|
usage
|
|
;;
|
|
esac
|
|
|
|
if [ "$RUN_TESTS" != 1 ]; then
|
|
echo "=== Skipped tests (profile=$PROFILE — build only). Binary in $BUILD_DIR; run a suite directly, e.g. ASAN_OPTIONS=detect_leaks=0 ./$BUILD_DIR/controller/controller_unit_test ==="
|
|
fi
|
|
|
|
echo "=== Done: $COMPONENT (profile=$PROFILE, dir=$BUILD_DIR) ==="
|