mirror of
https://github.com/Kpa-clawbot/meshcore-analyzer.git
synced 2026-05-25 23:14:01 +00:00
ci: restructure pipeline — sequential fail-fast, Go server E2E, remove deprecated JS tests (#256)
## Summary Complete CI pipeline restructure. Sequential fail-fast chain, E2E tests against Go server with real staging data, all deprecated Node.js server tests removed. ### Pipeline (PR): 1. **Go unit tests** — fail-fast, coverage + badges 2. **Playwright E2E** — against Go server with fixture DB, frontend coverage, fail-fast on first failure 3. **Docker build** — verify containers build ### Pipeline (master merge): Same chain + deploy to staging + badge publishing ### Removed: - All Node.js server-side unit tests (deprecated JS server) - `npm ci` / `npm run test` steps - JS server coverage collection (`COVERAGE=1 node server.js`) - Changed-files detection logic - Docs-only CI skip logic - Cancel-workflow API hacks ### Added: - `test-fixtures/e2e-fixture.db` — real data from staging (200 nodes, 31 observers, 500 packets) - `scripts/capture-fixture.sh` — refresh fixture from staging API - Go server launches with `-port 13581 -db test-fixtures/e2e-fixture.db -public public-instrumented` --------- Co-authored-by: Kpa-clawbot <kpabap+clawdbot@gmail.com> Co-authored-by: you <you@example.com>
This commit is contained in:
Executable
+142
@@ -0,0 +1,142 @@
|
||||
#!/bin/bash
|
||||
# Capture a fixture DB from staging for E2E tests
|
||||
# Usage: ./scripts/capture-fixture.sh [source_url]
|
||||
#
|
||||
# Downloads nodes, observers, and recent packets from the staging API
|
||||
# and creates a SQLite database suitable for E2E testing.
|
||||
|
||||
set -e
|
||||
|
||||
SOURCE_URL="${1:-https://analyzer.00id.net}"
|
||||
DB_PATH="test-fixtures/e2e-fixture.db"
|
||||
|
||||
echo "Capturing fixture from $SOURCE_URL..."
|
||||
|
||||
mkdir -p test-fixtures
|
||||
rm -f "$DB_PATH"
|
||||
|
||||
# Create schema
|
||||
sqlite3 "$DB_PATH" <<'SQL'
|
||||
CREATE TABLE nodes (
|
||||
public_key TEXT PRIMARY KEY,
|
||||
name TEXT,
|
||||
role TEXT,
|
||||
lat REAL,
|
||||
lon REAL,
|
||||
last_seen TEXT,
|
||||
first_seen TEXT,
|
||||
advert_count INTEGER DEFAULT 0,
|
||||
battery_mv INTEGER,
|
||||
temperature_c REAL
|
||||
);
|
||||
|
||||
CREATE TABLE observers (
|
||||
id TEXT PRIMARY KEY,
|
||||
name TEXT,
|
||||
iata TEXT,
|
||||
last_seen TEXT,
|
||||
first_seen TEXT,
|
||||
packet_count INTEGER DEFAULT 0,
|
||||
model TEXT,
|
||||
firmware TEXT,
|
||||
client_version TEXT,
|
||||
radio TEXT,
|
||||
battery_mv INTEGER,
|
||||
uptime_secs INTEGER,
|
||||
noise_floor REAL
|
||||
);
|
||||
|
||||
CREATE TABLE transmissions (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
raw_hex TEXT NOT NULL,
|
||||
hash TEXT NOT NULL UNIQUE,
|
||||
first_seen TEXT NOT NULL,
|
||||
route_type INTEGER,
|
||||
payload_type INTEGER,
|
||||
payload_version INTEGER,
|
||||
decoded_json TEXT,
|
||||
created_at TEXT DEFAULT (datetime('now'))
|
||||
);
|
||||
|
||||
CREATE TABLE observations (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
transmission_id INTEGER NOT NULL REFERENCES transmissions(id),
|
||||
observer_idx INTEGER,
|
||||
direction TEXT,
|
||||
snr REAL,
|
||||
rssi REAL,
|
||||
score INTEGER,
|
||||
path_json TEXT,
|
||||
timestamp INTEGER NOT NULL
|
||||
);
|
||||
SQL
|
||||
|
||||
# Fetch nodes
|
||||
echo "Fetching nodes..."
|
||||
curl -sf "$SOURCE_URL/api/nodes?limit=200" | python3 -c "
|
||||
import json, sys, sqlite3
|
||||
data = json.load(sys.stdin)
|
||||
nodes = data.get('nodes', data) if isinstance(data, dict) else data
|
||||
db = sqlite3.connect('$DB_PATH')
|
||||
for n in nodes[:200]:
|
||||
db.execute('INSERT OR IGNORE INTO nodes VALUES (?,?,?,?,?,?,?,?,?,?)',
|
||||
(n.get('public_key',''), n.get('name',''), n.get('role',''),
|
||||
n.get('lat'), n.get('lon'), n.get('last_seen',''), n.get('first_seen',''),
|
||||
n.get('advert_count',0), n.get('battery_mv'), n.get('temperature_c')))
|
||||
db.commit()
|
||||
print(f' Inserted {min(len(nodes), 200)} nodes')
|
||||
db.close()
|
||||
"
|
||||
|
||||
# Fetch observers
|
||||
echo "Fetching observers..."
|
||||
curl -sf "$SOURCE_URL/api/observers" | python3 -c "
|
||||
import json, sys, sqlite3
|
||||
data = json.load(sys.stdin)
|
||||
observers = data.get('observers', data) if isinstance(data, dict) else data
|
||||
db = sqlite3.connect('$DB_PATH')
|
||||
for o in observers:
|
||||
db.execute('INSERT OR IGNORE INTO observers VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?)',
|
||||
(o.get('id',''), o.get('name',''), o.get('iata',''),
|
||||
o.get('last_seen',''), o.get('first_seen',''),
|
||||
o.get('packet_count',0), o.get('model',''), o.get('firmware',''),
|
||||
o.get('client_version',''), o.get('radio',''),
|
||||
o.get('battery_mv'), o.get('uptime_secs'), o.get('noise_floor')))
|
||||
db.commit()
|
||||
print(f' Inserted {len(observers)} observers')
|
||||
db.close()
|
||||
"
|
||||
|
||||
# Fetch recent packets
|
||||
echo "Fetching recent packets..."
|
||||
curl -sf "$SOURCE_URL/api/packets?limit=500" | python3 -c "
|
||||
import json, sys, sqlite3
|
||||
data = json.load(sys.stdin)
|
||||
packets = data.get('packets', data) if isinstance(data, dict) else data
|
||||
db = sqlite3.connect('$DB_PATH')
|
||||
for p in packets:
|
||||
try:
|
||||
cur = db.execute('INSERT OR IGNORE INTO transmissions (raw_hex, hash, first_seen, route_type, payload_type, payload_version, decoded_json) VALUES (?,?,?,?,?,?,?)',
|
||||
(p.get('raw_hex',''), p.get('hash',''), p.get('first_seen',''),
|
||||
p.get('route_type'), p.get('payload_type'), p.get('payload_version'),
|
||||
p.get('decoded_json')))
|
||||
tid = cur.lastrowid
|
||||
if tid and p.get('observer_id'):
|
||||
db.execute('INSERT INTO observations (transmission_id, observer_idx, direction, snr, rssi, score, path_json, timestamp) VALUES (?,?,?,?,?,?,?,?)',
|
||||
(tid, p.get('observer_id'), p.get('direction'),
|
||||
p.get('snr'), p.get('rssi'), None,
|
||||
p.get('path_json'),
|
||||
int(p.get('timestamp','0')) if p.get('timestamp','').isdigit() else 0))
|
||||
except Exception as e:
|
||||
pass # Skip duplicates
|
||||
db.commit()
|
||||
print(f' Inserted {len(packets)} transmissions')
|
||||
db.close()
|
||||
"
|
||||
|
||||
SIZE=$(du -h "$DB_PATH" | cut -f1)
|
||||
echo "✅ Fixture DB created: $DB_PATH ($SIZE)"
|
||||
echo " Nodes: $(sqlite3 "$DB_PATH" 'SELECT COUNT(*) FROM nodes')"
|
||||
echo " Observers: $(sqlite3 "$DB_PATH" 'SELECT COUNT(*) FROM observers')"
|
||||
echo " Transmissions: $(sqlite3 "$DB_PATH" 'SELECT COUNT(*) FROM transmissions')"
|
||||
echo " Observations: $(sqlite3 "$DB_PATH" 'SELECT COUNT(*) FROM observations')"
|
||||
Reference in New Issue
Block a user