Skip to content

experimental

experimental #59

Workflow file for this run

name: Wokwi ESP32 Simulation Test
on:
push:
branches: [ "mdev", "copilot/**" ]
pull_request:
branches: [ "mdev" ]
workflow_dispatch:
jobs:
wokwi-test:
name: Test WLED with Wokwi Simulator
runs-on: ubuntu-22.04
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Cache pip
uses: actions/cache@v4
with:
path: ~/.cache/pip
key: ${{ runner.os }}-pip-${{ hashFiles('**/requirements.txt') }}
restore-keys: |
${{ runner.os }}-pip-
- name: Cache PlatformIO
uses: actions/cache@v4
with:
path: ~/.platformio
key: ${{ runner.os }}-pio-esp32_V4_wokwi_debug
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: '3.9'
- name: Install PlatformIO
run: pip install -r requirements.txt
- name: Set up Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'npm'
- name: Install Node.js dependencies
run: npm ci
- name: Build web UI
run: npm run build
- name: Build firmware for ESP32
env:
WLED_RELEASE: True
run: pio run -e esp32_V4_wokwi_debug
- name: Install Wokwi CLI
run: |
curl -L https://wokwi.com/ci/install.sh | sh
echo "Wokwi CLI installed to: $HOME/.wokwi-ci/bin/"
ls -la "$HOME/.wokwi-ci/bin/" || echo "Directory not found"
export PATH="$HOME/.wokwi-ci/bin:$PATH"
wokwi-cli --version || echo "Warning: wokwi-cli not accessible"
- name: Prepare firmware for Wokwi
run: ./test/wokwi/prepare-firmware.sh esp32_V4_wokwi_debug
- name: Debug - Verify token is set
run: |
if [ -z "$WOKWI_CLI_TOKEN" ]; then
echo "❌ ERROR: WOKWI_CLI_TOKEN is not set"
echo "Please configure WOKWI_CLI_TOKEN as a repository secret"
exit 1
else
echo "✅ WOKWI_CLI_TOKEN is set (length: ${#WOKWI_CLI_TOKEN} characters)"
fi
env:
WOKWI_CLI_TOKEN: ${{ secrets.WOKWI_CLI_TOKEN }}
- name: Quick boot validation with scenario
working-directory: test/wokwi
env:
WOKWI_CLI_TOKEN: ${{ secrets.WOKWI_CLI_TOKEN }}
run: |
# Create log directory
mkdir -p logs
# Add Wokwi CLI to PATH for this step
export PATH="$HOME/.wokwi-ci/bin:$PATH"
# Verify firmware files exist
echo "Checking for firmware files..."
if [ ! -f "firmware.bin" ]; then
echo "❌ ERROR: firmware.bin not found in $(pwd)"
echo "Available files:"
ls -la
exit 1
fi
echo "✅ firmware.bin found ($(du -h firmware.bin | cut -f1))"
if [ -f "firmware.elf" ]; then
echo "✅ firmware.elf found ($(du -h firmware.elf | cut -f1))"
else
echo "⚠️ firmware.elf not found (optional for simulation)"
fi
# Verify firmware can be read and has valid ESP32 header
echo ""
echo "Firmware file details:"
ls -lh firmware.bin firmware.elf 2>/dev/null || true
echo ""
echo "Firmware.bin first 64 bytes (hex):"
hexdump -C firmware.bin | head -4 || echo "Cannot read firmware.bin"
echo "Note: ESP32 firmware should start with magic byte 0xe9"
echo ""
echo "Running quick boot check scenario (15 seconds)..."
echo "Wokwi CLI location: $(which wokwi-cli || echo 'NOT FOUND')"
echo "Wokwi CLI version:"
wokwi-cli --version || echo "Warning: Could not get version"
echo ""
# Run boot check with increased timeout to account for startup time
# Using 30 second timeout for a 15 second scenario to allow for network delays
# Capture serial output (stdout) and Wokwi CLI diagnostics (stderr) separately
if wokwi-cli --timeout 30000 --scenario scenarios/boot-check.yaml . > logs/boot-check-serial.log 2>logs/boot-check.log; then
echo "✅ Boot check passed - firmware boots without crashes"
echo ""
echo "=== Boot check serial output (last 50 lines) ==="
tail -50 logs/boot-check-serial.log
echo ""
echo "=== Boot check CLI log (last 50 lines) ==="
tail -50 logs/boot-check.log
else
EXIT_CODE=$?
echo "❌ Boot check failed with exit code $EXIT_CODE"
echo ""
echo "=== Boot check CLI log ==="
cat logs/boot-check.log
echo ""
echo "=== Boot check serial output ==="
cat logs/boot-check-serial.log
# Check if it's a WebSocket connection error (code 1006)
if grep -q "code 1006" logs/boot-check.log || grep -q "Connection.*closed" logs/boot-check.log; then
echo ""
echo "⚠️ WebSocket connection error detected (code 1006)"
echo "This is typically a transient network issue with Wokwi's API."
echo "The workflow will continue with the full simulation test."
echo "If this persists, check Wokwi service status or network connectivity."
# Don't fail - this might be a transient issue
else
# Other errors should fail the build
exit 1
fi
fi
- name: Install Playwright browsers
run: npx playwright install --with-deps chromium
- name: Start Wokwi simulator in background
env:
WOKWI_CLI_TOKEN: ${{ secrets.WOKWI_CLI_TOKEN }}
run: |
cd test/wokwi
# Create log directory
mkdir -p logs
# Export the token so it's available to child processes
export WOKWI_CLI_TOKEN
# Start simulator in background with a 180 second timeout
# Wokwi CLI outputs to stderr, serial output goes to stdout
WOKWI_TIMEOUT=300 ./run-simulator.sh >logs/serial.log 2>&1 &
WOKWI_PID=$!
echo "WOKWI_PID=$WOKWI_PID" >> $GITHUB_ENV
echo "Started Wokwi simulator with PID $WOKWI_PID"
# Wait for simulator to start and web server to be ready
echo "Waiting for WLED web server to be ready..."
max_wait=240
elapsed=0
while [ $elapsed -lt $max_wait ]; do
if curl -s -f http://localhost:9080 > /dev/null 2>&1; then
echo "✅ Web server is ready on port 9080 after $elapsed seconds!"
break
fi
if curl -s -f http://localhost:8080 > /dev/null 2>&1; then
echo "✅ Web server is ready on port 8080 after $elapsed seconds!"
break
fi
if ! kill -0 $WOKWI_PID 2>/dev/null; then
echo "❌ Error: Wokwi simulator process died"
echo ""
echo "=== Last 100 lines of Wokwi CLI log ==="
tail -100 logs/wokwi.log || true
echo ""
echo "=== Last 100 lines of Serial output ==="
tail -100 logs/serial.log || true
exit 1
fi
echo "Still waiting... ($elapsed seconds)"
sleep 5
elapsed=$((elapsed + 5))
done
if [ $elapsed -ge $max_wait ]; then
echo "❌ Error: Web server did not start within $max_wait seconds"
echo ""
echo "=== Last 100 lines of Wokwi CLI log ==="
tail -100 logs/wokwi.log || true
echo ""
echo "=== Last 100 lines of Serial output ==="
tail -100 logs/serial.log || true
kill $WOKWI_PID || true
exit 1
fi
echo "WLED is ready for testing!"
echo ""
echo "=== First 50 lines of Serial output ==="
head -50 logs/serial.log || true
- name: Run Playwright tests
run: npm run test:wokwi
env:
CI: true
- name: Upload Playwright report
uses: actions/upload-artifact@v4
if: always()
with:
name: playwright-report
path: playwright-report/
retention-days: 7
- name: Stop Wokwi simulator
if: always()
run: |
if [ ! -z "$WOKWI_PID" ]; then
kill $WOKWI_PID || true
fi
- name: Upload test results
uses: actions/upload-artifact@v4
if: always()
with:
name: wokwi-test-results
path: |
test/wokwi/logs/
test-results/
playwright-report/
retention-days: 7