app
service-kicad
Public Made by Adomby adom
Shared headless KiCad 10: DRC, ERC, SVG/Gerber/STEP export, Altium library conversion, symbol/footprint/3D-model lookup. Every Adom tool shells to this CLI instead of calling the HTTP API directly.
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182
#!/usr/bin/env bash
# service-kicad watchdog — run by cron every 2 minutes on the
# production container. Pulls origin/main, rebuilds on new commits,
# and health-checks the running service.
#
# Kill uses /proc/PID/exe readlink instead of pkill -f path matching,
# which broke when the process was started from a different path than
# the installed binary (and pkill -x fails because the 17-char binary
# name gets truncated to 15 in /proc/PID/comm).
set -uo pipefail
REPO_DIR="$HOME/service-kicad"
BINARY="/usr/local/bin/service-kicad-api"
CLI_BINARY="/usr/local/bin/service-kicad"
HEALTH_URL="http://127.0.0.1:8780/health"
LOG="${SERVICE_KICAD_LOG:-/var/log/service-kicad.log}"
kill_api() {
local pids
pids=$(pgrep -f "service-kicad-api" 2>/dev/null | grep -v "^$$\$" || true)
for pid in $pids; do
local exe
exe=$(readlink "/proc/$pid/exe" 2>/dev/null || true)
if [[ "$exe" == *service-kicad-api* ]]; then
kill "$pid" 2>/dev/null || true
sleep 1
kill -0 "$pid" 2>/dev/null && kill -9 "$pid" 2>/dev/null || true
fi
done
}
launch_api() {
[ -f /etc/default/service-kicad ] && { set -a; . /etc/default/service-kicad; set +a; }
nohup "$BINARY" >> "$LOG" 2>&1 &
}
cd "$REPO_DIR" || exit 1
# 1. Check for new commits.
#
# `git fetch` MUST surface its own failure — without this guard, an
# auth-rotated container silently logs `fatal: could not read Username
# for 'https://github.com'` then proceeds with stale LOCAL/REMOTE SHAs
# (both still point at the old HEAD), the equality test trivially
# passes, and the rebuild branch never fires. Symptom: weeks of
# "no-op" watchdog runs while origin/main races ahead. Exit 1 here
# triggers cron stderr so the next failure is loud, not silent.
if ! git fetch origin main --quiet 2>&1; then
echo "[$(date -Is)] FETCH FAILED — verify ~/.git-credentials and origin URL"
exit 1
fi
LOCAL_SHA=$(git rev-parse HEAD)
REMOTE_SHA=$(git rev-parse origin/main)
if [ "$LOCAL_SHA" != "$REMOTE_SHA" ]; then
echo "[$(date -Is)] origin moved $LOCAL_SHA → $REMOTE_SHA — rebuilding"
git reset --hard origin/main
if cargo build --release --bin service-kicad-api --bin service-kicad 2>&1 | tail -20; then
sudo install target/release/service-kicad-api "$BINARY"
sudo install target/release/service-kicad "$CLI_BINARY"
kill_api
launch_api
echo "[$(date -Is)] rebuilt + relaunched"
else
echo "[$(date -Is)] REBUILD FAILED — keeping old binary"
exit 1
fi
fi
# 2. Health check — relaunch if down
if ! curl -sf "$HEALTH_URL" | jq -e '.ok' > /dev/null 2>&1; then
echo "[$(date -Is)] health check failed, relaunching"
kill_api
launch_api
sleep 2
if curl -sf "$HEALTH_URL" | jq -e '.ok' > /dev/null 2>&1; then
echo "[$(date -Is)] recovered"
else
echo "[$(date -Is)] STILL UNHEALTHY after relaunch"
fi
fi