Files
wadamesh/scripts/deploy-reports.sh
T
Kaj SchittecatandClaude Opus 5 3729c821b3 reports: a test matrix a beta can be promoted on
A beta goes stable today because it has been out a while and nobody shouted.
With 13 board images, most of them in hands we never hear from, "nobody
shouted" mostly means nobody with that board was listening. This makes the
evidence explicit: testers report per board per tag from the device, and the
promote decision reads off a grid.

The device cannot talk to GitHub itself. TLS does not fit (mbedTLS wants ~30 KB
of heap for a handshake and ~5 KB survives Wi-Fi association on the 2 MB
boards), and a token in a GPL image is a token everybody has. So the split is:

  * Structured test reports go to a small service on the firmware VPS over the
    plain HTTP the device already speaks, and it holds the only write
    credential. SQLite is the database; the per-tag tracking issue is rendered
    from it and rewritten in place, so GitHub can be down or rebuilt at will.
  * Bug reports do not come through here at all. The device draws a QR that
    opens .github/ISSUE_TEMPLATE/bug.yml prefilled with board, version and
    diagnostics, and the reporter files it under their own GitHub account:
    right attribution, GitHub's own spam controls, no token.

Green needs two separate devices whose owners ran the build for a day or more.
A board nobody runs cannot go green and does not block a promote; a board
somebody runs and has not vouched for does. That rule is the whole point: it
distinguishes untested from unowned, which "nobody shouted" cannot.

wadamesh.com/beta.html renders the same JSON for the promote decision.

Two things found while deploying, both repo-vs-box drift that would have bitten
somebody eventually:

  * The repo's copy of the firmware vhost was missing /apps/ and /bringup/,
    which had been added on the box and never committed. Deploying it would
    have 404'd the Lua app and language store for every device. The repo copy
    is now taken from the box, and the deploy script refuses to push a vhost
    that has fewer locations than the live one.
  * The repo's tile-transcode unit named a venv interpreter that does not exist
    on the box (python3.14 there has no ensurepip, so venv cannot bootstrap pip
    at all). The live unit uses the system python; the repo now says so too.

The firmware side (the report page, the QR, the opt-in ping) is not in this
commit.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-23 11:06:07 +02:00

92 lines
3.9 KiB
Bash
Executable File

#!/usr/bin/env bash
# wadamesh report service deploy: install/refresh the beta test-report service
# (deploy/report-service.py) on the firmware VPS, behind the existing
# firmware.wadamesh.com vhost at /report/.
#
# What it does, all of it idempotent:
# * rsyncs the service into /opt/wadamesh-reports
# * checks flask + requests are importable by the system python
# * installs the systemd unit, enables and restarts it
# * refreshes the firmware vhost (which now proxies /report/) and reloads nginx
#
# The SQLite database at /opt/wadamesh-reports/reports.db is never touched, so a
# redeploy keeps every report.
#
# Usage:
# WADAMESH_VPS=user@your-vps scripts/deploy-reports.sh
# WADAMESH_VPS=user@your-vps scripts/deploy-reports.sh --dry-run
#
# The GitHub token is NOT deployed by this script and is not in the repo. It
# lives on the box in /etc/wadamesh-reports.env:
#
# WADA_GH_TOKEN=<token> # fine-grained, this repo only, issues: read+write
# WADA_GH_REPO=ALLFATHER-BV/wadamesh
#
# Without it the service runs normally and simply never publishes to GitHub, so
# reports are still collected and the site still shows them.
set -euo pipefail
ROOT="$(cd "$(dirname "$0")/.." && pwd)"
DEST="${WADAMESH_VPS:?set WADAMESH_VPS=user@host}"
APP_DIR="${WADAMESH_REPORTS_PATH:-/opt/wadamesh-reports}"
# Same escape hatch rsync has: the VPS key is not the default identity here.
# SSH="ssh -i ~/.ssh/your_key" RSYNC_RSH="$SSH" scripts/deploy-reports.sh
SSH="${SSH:-ssh}"
if [ "${1:-}" = "--dry-run" ]; then
echo "would deploy:"
echo " $ROOT/deploy/report-service.py -> $DEST:$APP_DIR/"
echo " $ROOT/deploy/wadamesh-reports.service -> $DEST:/etc/systemd/system/"
echo " $ROOT/deploy/nginx/firmware.wadamesh.com.conf -> $DEST:/etc/nginx/sites-available/firmware.wadamesh.com.conf"
exit 0
fi
python3 - "$ROOT/deploy/report-service.py" <<'PY'
import ast, sys
ast.parse(open(sys.argv[1]).read()) # never ship a file that will not import
print("report-service.py parses")
PY
# The vhost on the box has drifted ahead of the repo before (/apps/ and
# /bringup/ were added live and never committed). Pushing a stale copy would
# 404 the app store, so compare first and stop rather than overwrite.
LIVE_CONF=$($SSH "$DEST" "cat /etc/nginx/sites-available/firmware.wadamesh.com.conf" 2>/dev/null || true)
for needed in $(printf '%s\n' "$LIVE_CONF" | grep -oE 'location [=~ ]*/[a-z.-]+/?' | sort -u); do
if ! grep -qF "$needed" "$ROOT/deploy/nginx/firmware.wadamesh.com.conf"; then
echo "ABORT: the live vhost has '$needed' and the repo copy does not." >&2
echo "Pull the live file into deploy/nginx/ first, then re-add your changes." >&2
exit 1
fi
done
$SSH "$DEST" "mkdir -p $APP_DIR"
rsync -avz "$ROOT/deploy/report-service.py" "$DEST:$APP_DIR/"
rsync -avz "$ROOT/deploy/wadamesh-reports.service" "$DEST:/etc/systemd/system/wadamesh-reports.service"
# The live name carries the .conf suffix and is what sites-enabled points at.
# Getting this wrong writes a file nginx never reads, and the /report/ proxy
# silently does not exist.
rsync -avz "$ROOT/deploy/nginx/firmware.wadamesh.com.conf" \
"$DEST:/etc/nginx/sites-available/firmware.wadamesh.com.conf"
$SSH "$DEST" bash -s <<EOF
set -e
# No venv: this box's python3.14 has no ensurepip, so venv cannot bootstrap pip.
# flask and requests come from apt and are already in use by the tile service.
if ! /usr/bin/python3 -c 'import flask, requests' 2>/dev/null; then
echo "installing flask and requests from apt"
apt-get update -qq && apt-get install -y -qq python3-flask python3-requests
fi
systemctl daemon-reload
systemctl enable --now wadamesh-reports
systemctl restart wadamesh-reports
sleep 1
nginx -t && systemctl reload nginx
systemctl is-active wadamesh-reports
EOF
echo
echo "deployed. checking the live endpoint:"
curl -fsS "http://firmware.wadamesh.com/report/health" && echo
echo
echo 'publishes:false means no GitHub token on the box yet (see the header of this script).'