saltylab-firmware/.gitea/workflows/social-tests-ci.yml
sl-jetson ee8438fd04
Some checks failed
social-bot integration tests / Lint (flake8 + pep257) (push) Failing after 3m58s
social-bot integration tests / Lint (flake8 + pep257) (pull_request) Failing after 3m3s
social-bot integration tests / Core integration tests (mock sensors, no GPU) (push) Has been skipped
social-bot integration tests / Core integration tests (mock sensors, no GPU) (pull_request) Has been skipped
social-bot integration tests / Latency profiling (GPU, Orin) (push) Has been cancelled
social-bot integration tests / Latency profiling (GPU, Orin) (pull_request) Has been cancelled
feat(tests): social-bot integration test suite (Issue #108)
Add saltybot_social_tests package with full pytest + launch_testing harness:

- test_launch.py: start social_test.launch.py, verify all nodes up within 30s
- test_topic_rates.py: measure topic Hz over 3s window vs. minimum SLAs
- test_services.py: /social/enroll, /social/nav/set_mode, person CRUD, mood query
- test_gpu_memory.py: total allocation < 6 GB, no leak over 30s
- test_latency.py: inject→transcript→LLM→TTS state-machine SLA profiling
- test_shutdown.py: no zombies, GPU memory released, audio device freed
- test_helpers.py: TopicRateChecker, NodeChecker, ServiceChecker, GpuMemoryChecker
- mock_sensors.py: camera/faces/fused/persons/uwb publishers at correct rates
- social_test.launch.py: CI-mode launch (no mic/speaker, mock sensors auto-started)
- conftest.py + pytest.ini: gpu_required / full_stack / stack_running markers
- docker/Dockerfile.ci + docker-compose.ci.yml: CPU-only CI container
- docker/entrypoint-ci.sh: launch stack + wait 10s + run pytest
- bags/record_social_test.sh + bags/README.md: rosbag recording for replay
- .gitea/workflows/social-tests-ci.yml: lint + core-tests + latency-gpu jobs

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-02 08:50:22 -05:00

240 lines
8.2 KiB
YAML

# .gitea/workflows/social-tests-ci.yml
# Gitea Actions CI pipeline for social-bot integration tests (Issue #108)
#
# Triggers: push or PR to main, and any branch matching sl-jetson/*
#
# Jobs:
# 1. lint — flake8 + pep257 on saltybot_social_tests
# 2. core-tests — launch + topic + services + GPU-budget + shutdown (no GPU)
# 3. latency — end-to-end latency profiling (GPU runner, optional)
name: social-bot integration tests
on:
push:
branches:
- main
- "sl-jetson/**"
paths:
- "jetson/ros2_ws/src/saltybot_social/**"
- "jetson/ros2_ws/src/saltybot_social_tests/**"
- "jetson/ros2_ws/src/saltybot_social_msgs/**"
- "jetson/ros2_ws/src/saltybot_social_nav/**"
- "jetson/ros2_ws/src/saltybot_social_face/**"
- "jetson/ros2_ws/src/saltybot_social_tracking/**"
- ".gitea/workflows/social-tests-ci.yml"
pull_request:
branches:
- main
paths:
- "jetson/ros2_ws/src/saltybot_social*/**"
- ".gitea/workflows/social-tests-ci.yml"
env:
ROS_DOMAIN_ID: "108"
SOCIAL_TEST_FULL: "0"
SOCIAL_STACK_RUNNING: "1"
jobs:
# ── 1. Lint ──────────────────────────────────────────────────────────────────
lint:
name: Lint (flake8 + pep257)
runs-on: ubuntu-latest
container:
image: ros:humble-ros-base-jammy
steps:
- uses: actions/checkout@v4
- name: Install lint tools
run: |
pip3 install --no-cache-dir flake8 pydocstyle
- name: flake8 — saltybot_social_tests
run: |
flake8 \
jetson/ros2_ws/src/saltybot_social_tests/saltybot_social_tests/ \
jetson/ros2_ws/src/saltybot_social_tests/test/ \
--max-line-length=100 \
--ignore=E501,W503 \
--exclude=__pycache__
- name: pep257 — saltybot_social_tests
run: |
pydocstyle \
jetson/ros2_ws/src/saltybot_social_tests/saltybot_social_tests/ \
jetson/ros2_ws/src/saltybot_social_tests/test/ \
--add-ignore=D100,D104,D205,D400 \
--match='(?!test_helpers|mock_sensors).*\.py' || true
# ── 2. Core integration tests (no GPU) ───────────────────────────────────────
core-tests:
name: Core integration tests (mock sensors, no GPU)
needs: lint
runs-on: ubuntu-latest
container:
image: ros:humble-ros-base-jammy
env:
ROS_DOMAIN_ID: "108"
SOCIAL_TEST_FULL: "0"
SOCIAL_STACK_RUNNING: "1"
PYTHONUNBUFFERED: "1"
steps:
- uses: actions/checkout@v4
- name: Install dependencies
run: |
apt-get update -q && apt-get install -y --no-install-recommends \
ros-humble-launch-testing \
ros-humble-launch-testing-ros \
ros-humble-vision-msgs \
ros-humble-tf2-ros \
ros-humble-tf2-geometry-msgs \
ros-humble-cv-bridge \
ros-humble-nav-msgs \
ros-humble-std-srvs \
procps \
&& rm -rf /var/lib/apt/lists/*
pip3 install --no-cache-dir "pytest>=7.0" "pytest-timeout>=2.1"
- name: Build workspace
run: |
. /opt/ros/humble/setup.bash
cd /
# Symlink source into a temp workspace to avoid long paths
mkdir -p /ros2_ws/src
for pkg in saltybot_social_msgs saltybot_social saltybot_social_face \
saltybot_social_nav saltybot_social_enrollment \
saltybot_social_tracking saltybot_social_personality \
saltybot_social_tests; do
ln -sfn \
"$GITHUB_WORKSPACE/jetson/ros2_ws/src/$pkg" \
"/ros2_ws/src/$pkg"
done
cd /ros2_ws
colcon build \
--packages-select \
saltybot_social_msgs \
saltybot_social \
saltybot_social_face \
saltybot_social_nav \
saltybot_social_enrollment \
saltybot_social_tracking \
saltybot_social_personality \
saltybot_social_tests \
--symlink-install \
--event-handlers console_cohesion+
- name: Launch test stack (background)
run: |
. /opt/ros/humble/setup.bash
. /ros2_ws/install/setup.bash
ros2 daemon start || true
ros2 launch saltybot_social_tests social_test.launch.py \
enable_speech:=false enable_llm:=false enable_tts:=false \
&
echo "LAUNCH_PID=$!" >> "$GITHUB_ENV"
# Wait for stack to come up
sleep 15
- name: Run core tests
run: |
. /opt/ros/humble/setup.bash
. /ros2_ws/install/setup.bash
pytest \
"$GITHUB_WORKSPACE/jetson/ros2_ws/src/saltybot_social_tests/test/" \
-v \
--timeout=120 \
--tb=short \
-m "not gpu_required and not full_stack and not slow" \
--junit-xml=test-results-core.xml \
-k "not test_latency_sla and not test_shutdown"
- name: Shutdown test stack
if: always()
run: |
[ -n "${LAUNCH_PID:-}" ] && kill -SIGTERM "$LAUNCH_PID" 2>/dev/null || true
sleep 3
- name: Run shutdown tests
run: |
. /opt/ros/humble/setup.bash
. /ros2_ws/install/setup.bash
pytest \
"$GITHUB_WORKSPACE/jetson/ros2_ws/src/saltybot_social_tests/test/test_shutdown.py" \
-v --timeout=60 --tb=short \
--junit-xml=test-results-shutdown.xml
- name: Upload test results
if: always()
uses: actions/upload-artifact@v4
with:
name: test-results-core
path: test-results-*.xml
# ── 3. GPU latency tests (Orin runner, optional) ──────────────────────────────
latency-gpu:
name: Latency profiling (GPU, Orin)
needs: core-tests
runs-on: [self-hosted, orin, gpu]
if: github.ref == 'refs/heads/main' || contains(github.event.pull_request.labels.*.name, 'run-gpu-tests')
env:
ROS_DOMAIN_ID: "108"
SOCIAL_TEST_FULL: "1"
SOCIAL_TEST_SPEECH: "0"
SOCIAL_STACK_RUNNING: "1"
steps:
- uses: actions/checkout@v4
- name: Build workspace (Orin)
run: |
. /opt/ros/humble/setup.bash
cd /ros2_ws
colcon build \
--packages-select saltybot_social_tests saltybot_social \
--symlink-install
- name: Launch full stack (with LLM, no speech/TTS)
run: |
. /opt/ros/humble/setup.bash
. /ros2_ws/install/setup.bash
SOCIAL_TEST_FULL=1 \
ros2 launch saltybot_social_tests social_test.launch.py \
enable_speech:=false enable_tts:=false \
&
echo "LAUNCH_PID=$!" >> "$GITHUB_ENV"
sleep 20
- name: GPU memory check
run: |
. /opt/ros/humble/setup.bash
. /ros2_ws/install/setup.bash
SOCIAL_STACK_RUNNING=1 \
GPU_BASELINE_MB=$(nvidia-smi --query-gpu=memory.used --format=csv,noheader,nounits) \
pytest \
"$GITHUB_WORKSPACE/jetson/ros2_ws/src/saltybot_social_tests/test/test_gpu_memory.py" \
-v --timeout=120 --tb=short \
--junit-xml=test-results-gpu.xml
- name: Latency profiling
run: |
. /opt/ros/humble/setup.bash
. /ros2_ws/install/setup.bash
SOCIAL_TEST_FULL=1 SOCIAL_STACK_RUNNING=1 \
pytest \
"$GITHUB_WORKSPACE/jetson/ros2_ws/src/saltybot_social_tests/test/test_latency.py" \
-v --timeout=300 --tb=short \
--junit-xml=test-results-latency.xml
- name: Shutdown
if: always()
run: |
[ -n "${LAUNCH_PID:-}" ] && kill -SIGTERM "$LAUNCH_PID" 2>/dev/null || true
sleep 5
- name: Upload GPU results
if: always()
uses: actions/upload-artifact@v4
with:
name: test-results-gpu
path: test-results-*.xml