# .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
