Files
luci-app-zt-gateway/mise.toml
Malar Invention 581d625044 fix: routing ip rule missing after reboot, busybox compat, skill restructure
Routing fixes (2026-07-14):
- Add missing ip rule 'from 10.11.13.0/24 lookup 100' to hotplug ifup case
- Add UCI network rule persistence so netifd restores it on boot
- Verify ip rule exists in zt-gateway-switch do_force/do_graceful
- Fix BRIDGE_PORTS auto-detect: use /proc/net/dev instead of broken
  awk-over-ip pipeline (busybox awk mishandles exit in compound if)
- Validate bridge port candidate exists as network interface
- Fix setup-routing: use dev br-zt not dev ztX (ZT iface has no IP
  when enslaved to bridge, causing 'Nexthop has invalid gateway')
- Replace ip rule replace (GNU-only) with del+add for busybox

Infrastructure:
- Fix deploy:install stdin starvation: ssh/scp consume pipe data in
  find|while loop; add </dev/null to prevent truncation
- Move luci-dev skill from root/ to skills/ with .agents/skills/ symlink
- Add policy routing and busybox gotcha sections to SKILL.md
- Add diagnostics doc for the routing fix session
2026-07-14 18:01:30 +05:30

118 lines
3.6 KiB
TOML

[tools]
node = "22.17.0"
[tasks.setup]
description = "Install Node deps and Playwright browsers"
run = """
if [ ! -d node_modules ]; then npm install; fi
npx playwright install chromium
"""
[tasks."docker:build"]
description = "Build OpenWRT LuCI image with podman (seccomp bypass for apk)"
run = "podman build --security-opt seccomp=unconfined -t zt-gateway-luci:dev -f Dockerfile.openwrt ."
[tasks."docker:up"]
description = "Build image + start the full test stack (router + ZT gateways + LuCI)"
depends = ["docker:build"]
run = "docker compose up -d"
[tasks."docker:down"]
description = "Stop the test stack"
run = "docker compose down"
[tasks."docker:logs"]
description = "View OpenWRT LuCI container logs"
run = "docker compose logs -f openwrt-luci"
[tasks."docker:shell"]
description = "Open shell in the OpenWRT LuCI container"
run = "docker compose exec openwrt-luci sh"
[tasks."test:e2e"]
description = "Run Playwright E2E tests (assumes stack is up)"
depends = ["setup"]
run = "npx playwright test"
[tasks."test:e2e:ui"]
description = "Run Playwright tests in interactive UI mode"
depends = ["setup"]
run = "npx playwright test --ui"
[tasks."test:e2e:headed"]
description = "Run Playwright tests in headed (visible) browser"
depends = ["setup"]
run = "npx playwright test --headed"
[tasks."test:e2e:debug"]
description = "Run Playwright tests in debug mode"
depends = ["setup"]
run = "npx playwright test --debug"
[tasks."inspect"]
description = "Start stack and open headed browser for manual inspection"
depends = ["docker:up"]
run = "npx playwright open chromium http://localhost:8080/cgi-bin/luci/admin/services/zt-gateway"
[tasks."reset"]
description = "Reset gateway state to amsterdam (default) via docker exec"
run = """
docker exec openwrt-luci /usr/sbin/zt-gateway-switch 10.99.12.3 force
docker exec openwrt-luci sh -c "uci set zt-gateway.global.active_gateway=amsterdam && uci commit zt-gateway" || true
"""
[tasks.ci]
description = "Full CI: build stack + install browsers + run E2E"
depends = ["docker:up", "setup"]
run = "npx playwright test"
# ===============================
# Deployment
# ===============================
[tasks."deploy:install"]
description = "SCP app files to an OpenWrt device and restart services"
run = '''
set -e
HOST="${HOST:-root@192.168.15.1}"
echo "==> Checking connectivity to ${HOST}..."
if ! ssh -o ConnectTimeout=5 -o BatchMode=yes "$HOST" true 2>/dev/null; then
echo "ERROR: Cannot reach ${HOST}. Check SSH access."
echo " ssh-copy-id ${HOST} # if needed"
exit 1
fi
echo " ${HOST} is reachable."
echo "==> Uploading files..."
# Auto-discover files from root/ and htdocs/, map to device paths.
# root/usr/sbin/foo → /usr/sbin/foo
# htdocs/luci-static/... → /www/luci-static/...
UPLOADED=0
find root/ htdocs/ -type f | sort | while IFS= read -r src; do
case "$src" in
root/*) dest="/${src#root/}" ;;
htdocs/*) dest="/www/${src#htdocs/}" ;;
*) echo "SKIP: $src (unknown prefix)"; continue ;;
esac
destdir="${dest%/*}"
ssh -q "$HOST" mkdir -p "$destdir" </dev/null
scp -O -q "$src" "$HOST:$dest" </dev/null
echo " ${src#./}"
UPLOADED=$((UPLOADED + 1))
done
echo "==> Setting permissions..."
ssh -q "$HOST" find /usr/sbin -name 'zt-gateway-*' -exec chmod +x {} +
echo "==> Clearing LuCI cache and restarting services..."
ssh -q "$HOST" rm -rf /tmp/luci-* 2>/dev/null || true
ssh -q "$HOST" /etc/init.d/rpcd restart
ssh -q "$HOST" /etc/init.d/uhttpd restart
DEVICE_IP=$(echo "$HOST" | sed 's/.*@//')
echo ""
echo "==> Done! Open: http://${DEVICE_IP}/cgi-bin/luci/admin/services/zt-gateway"
'''