Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
46 commits
Select commit Hold shift + click to select a range
e7af4b2
Initial plan
Copilot Dec 27, 2025
75b148e
Add Wokwi ESP32 simulation testing with Playwright
Copilot Dec 27, 2025
f8f82ea
Update package-lock.json with Playwright dependencies
Copilot Dec 27, 2025
34e5ca3
Improve Wokwi workflow: better logging, error handling, and CommonJS …
Copilot Dec 27, 2025
1a66a9a
Add WOKWI_CLI_TOKEN environment variable to workflow
Copilot Dec 28, 2025
685c75d
Fix wokwi-cli invocation to use current directory instead of diagram.…
Copilot Dec 28, 2025
ae0b312
Export WOKWI_CLI_TOKEN before running simulator script
Copilot Dec 28, 2025
9c0bb96
Add debug step to verify WOKWI_CLI_TOKEN is set before running simulator
Copilot Dec 28, 2025
e2abadc
Rename cdata-test.js to wokwi-test.js to avoid conflict with mdev branch
Copilot Jan 1, 2026
603322a
Merge branch 'mdev' into copilot/verify-wokwi-ci-integration
softhack007 Jan 1, 2026
2c2c590
post-merge fixup
softhack007 Jan 1, 2026
d1a4530
Fix npm test to avoid running Playwright tests with Node test runner
Copilot Jan 1, 2026
9597449
adding [env:esp32_V4_wokwi_debug]
softhack007 Jan 1, 2026
915b766
Switch to esp32_V4_wokwi_debug build and improve debug output collection
Copilot Jan 1, 2026
ebe23c3
Add boot validation scenarios for quick firmware testing
Copilot Jan 1, 2026
6f3c788
Handle WebSocket connection errors gracefully in boot validation
Copilot Jan 1, 2026
be458e3
Fix Wokwi CLI path issue in boot validation step
Copilot Jan 1, 2026
2a36ce6
fix outout redirection in CI script
softhack007 Jan 1, 2026
ac9d3f8
try with tee
softhack007 Jan 1, 2026
45f225c
Revert "try with tee"
softhack007 Jan 1, 2026
fb80167
Add required 'name' field to Wokwi scenario files
Copilot Jan 1, 2026
135ac80
Fix scenario step key: use 'wait' instead of 'sleep'
Copilot Jan 1, 2026
c4584a5
Fix scenario step key: use 'delay' with time units instead of 'wait'
Copilot Jan 1, 2026
326a7e3
Fix README.md scenario example to use correct Wokwi format
Copilot Jan 2, 2026
6ccf8a1
Optimize CI workflow: move Playwright install after boot check and co…
Copilot Jan 2, 2026
9fceaf0
Add firmware verification before boot check scenario
Copilot Jan 2, 2026
41e442c
Enable serial monitor in diagram.json and add firmware verification
Copilot Jan 2, 2026
4011ec3
wokwi: connect serial monitor, additional gdbServerPort
softhack007 Jan 2, 2026
665beca
Fix JSON syntax error in diagram.json - remove trailing comma
Copilot Jan 2, 2026
1edd268
Add bootloader and partitions support for ESP32 filesystem
Copilot Jan 2, 2026
f2fc3eb
use wokwi WiFi
softhack007 Jan 26, 2026
b3ba1cc
port 9080 (instead of 8080)
softhack007 Jan 26, 2026
efa7cca
add simulated neoPixel on GPIO 4
softhack007 Jan 26, 2026
397f901
experimental
softhack007 Jan 26, 2026
558d3de
Improve partition file handling and add comprehensive debugging
Copilot Jan 27, 2026
63d37f3
more experiments
softhack007 Jan 27, 2026
aa2063f
timeout tweak
softhack007 Jan 27, 2026
c2c4afc
Switch to combined firmware image approach for Wokwi
Copilot Jan 27, 2026
a8021b5
Improve bootloader and partitions file detection in prepare-firmware.sh
Copilot Jan 27, 2026
cbd726f
Fix YAML syntax error in workflow - proper Python heredoc indentation
Copilot Jan 27, 2026
4ad90ba
Fix prepare-firmware.sh - redirect debug output to stderr
Copilot Jan 27, 2026
48252aa
Fix run-simulator.sh to check for firmware-combined.bin
Copilot Jan 27, 2026
1224506
Add firmware-combined.bin to uploaded artifacts
Copilot Jan 27, 2026
846159a
disable websockets in wokwi build
softhack007 Jan 27, 2026
a726141
Enable enhanced debug logging for network troubleshooting
Copilot Jan 27, 2026
dcc2e56
Fix debug log capture - separate stdout and stderr streams
Copilot Jan 27, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
301 changes: 301 additions & 0 deletions .github/workflows/wokwi-test.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,301 @@
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 combined firmware image exists (recommended approach for Wokwi)
echo "Checking for combined firmware image..."
if [ ! -f "firmware-combined.bin" ]; then
echo "❌ ERROR: firmware-combined.bin not found in $(pwd)"
echo "Available files:"
ls -la
exit 1
fi
echo "✅ firmware-combined.bin found ($(du -h firmware-combined.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 combined firmware image structure
echo ""
echo "Verifying combined firmware image structure..."
python3 <<'EOF'
import sys
try:
with open('firmware-combined.bin', 'rb') as f:
data = f.read()

size_mb = len(data) / 1024 / 1024
print(f"✓ Image size: {len(data)} bytes ({size_mb:.2f} MB)")

# Check bootloader at 0x1000
if len(data) > 0x1000 and data[0x1000] == 0xe9:
print("✓ Bootloader found at 0x1000 (magic byte: 0xe9)")
else:
print("⚠ Bootloader magic byte not found at 0x1000")
sys.exit(1)

# Check partition table at 0x8000
if len(data) > 0x8000 and data[0x8000:0x8002] == b'\xaa\x50':
print("✓ Partition table found at 0x8000 (magic: 0xaa50)")
else:
print("⚠ Partition table magic not found at 0x8000")
sys.exit(1)

# Check application at 0x10000
if len(data) > 0x10000 and data[0x10000] == 0xe9:
print("✓ Application found at 0x10000 (magic byte: 0xe9)")
else:
print("⚠ Application magic byte not found at 0x10000")
sys.exit(1)

print("✅ Combined firmware image structure is valid")

except Exception as e:
print(f"❌ ERROR verifying combined image: {e}")
sys.exit(1)
EOF

if [ $? -ne 0 ]; then
echo "❌ Combined firmware image verification failed"
echo "Hex dump of first 256 bytes:"
hexdump -C firmware-combined.bin | head -16
exit 1
fi

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

# Add PATH for wokwi-cli
export PATH="$HOME/.wokwi-ci/bin:$PATH"

# Start simulator in background with a 90 second timeout
# Serial output (stdout) goes to serial.log
# Wokwi CLI diagnostics (stderr) including debug logs go to wokwi.log
WOKWI_TIMEOUT=90 ./run-simulator.sh >logs/serial.log 2>logs/wokwi.log &
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
max_wait=50
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
echo ""
echo "=== Wokwi CLI debug log (network traffic) ==="
tail -100 logs/wokwi.log || echo "No wokwi.log available"

- 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/wokwi/firmware-combined.bin
test-results/
playwright-report/
retention-days: 7
15 changes: 15 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -28,3 +28,18 @@ compile_commands.json
/wled00/wled00.ino.cpp
/wled00/html_*.h
_codeql_detected_source_root

# Playwright and test artifacts
/test-results/
/playwright-report/
/playwright/.cache/

# Wokwi runtime files
/test/wokwi/firmware.bin
/test/wokwi/firmware.elf
/test/wokwi/firmware-combined.bin
/test/wokwi/bootloader.bin
/test/wokwi/partitions.bin
/test/wokwi/.wokwi/
/test/wokwi/logs/

Loading
Loading