mirror of
https://github.com/screentinker/screentinker.git
synced 2026-06-15 02:33:15 -06:00
feat(server): make OTA observable - log update-check + apk-download hits (#96)
The OTA was invisible server-side: /api/update/check and /download/apk returned without logging, which is part of why the 1.9.0 auto-relaunch failure went unseen. Log every version check (client version vs latest, update_available, whether an APK is staged) and every APK download (a device actually applying an OTA), keyed on the CF-aware getClientIp so production logs show the real per-device IP behind Cloudflare, not the edge. Observability for the #96 auto-relaunch work (this is how we'll watch the OTA fire during the relaunch testing). Part of #96. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
f06a87f4be
commit
8d03741713
|
|
@ -521,6 +521,11 @@ app.get('/api/update/check', (req, res) => {
|
||||||
const latestVersion = VERSION;
|
const latestVersion = VERSION;
|
||||||
const updateAvailable = currentVersion && currentVersion !== latestVersion;
|
const updateAvailable = currentVersion && currentVersion !== latestVersion;
|
||||||
|
|
||||||
|
// #96: log every version check so the OTA is observable - which devices check in, their
|
||||||
|
// version, and whether they'll update. This diagnosability gap is part of why the 1.9.0
|
||||||
|
// relaunch failure went unseen.
|
||||||
|
console.log(`[ota] update check from ${getClientIp(req)}: client=${currentVersion || 'unknown'} latest=${latestVersion} update_available=${!!updateAvailable} apk=${apkExists ? 'present' : 'MISSING'}`);
|
||||||
|
|
||||||
res.json({
|
res.json({
|
||||||
latest_version: latestVersion,
|
latest_version: latestVersion,
|
||||||
current_version: currentVersion || 'unknown',
|
current_version: currentVersion || 'unknown',
|
||||||
|
|
@ -638,11 +643,15 @@ function resolveApkPath() {
|
||||||
app.get('/download/apk', (req, res) => {
|
app.get('/download/apk', (req, res) => {
|
||||||
const apkPath = resolveApkPath();
|
const apkPath = resolveApkPath();
|
||||||
if (apkPath) {
|
if (apkPath) {
|
||||||
|
// #96: an APK download means a device is actually applying an OTA - log it so the
|
||||||
|
// update is observable end to end (check -> download -> [relaunch]).
|
||||||
|
console.log(`[ota] APK download by ${getClientIp(req)} (${fs.statSync(apkPath).size} bytes) - OTA update in progress`);
|
||||||
res.setHeader('Content-Type', 'application/vnd.android.package-archive');
|
res.setHeader('Content-Type', 'application/vnd.android.package-archive');
|
||||||
res.setHeader('Content-Disposition', 'attachment; filename="ScreenTinker.apk"');
|
res.setHeader('Content-Disposition', 'attachment; filename="ScreenTinker.apk"');
|
||||||
res.setHeader('Cache-Control', 'no-cache');
|
res.setHeader('Cache-Control', 'no-cache');
|
||||||
res.sendFile(apkPath);
|
res.sendFile(apkPath);
|
||||||
} else {
|
} else {
|
||||||
|
console.warn(`[ota] APK download requested by ${getClientIp(req)} but no APK is available (404)`);
|
||||||
res.status(404).send(`<!DOCTYPE html><html><head><title>APK Not Found</title><style>body{font-family:-apple-system,system-ui,sans-serif;display:flex;justify-content:center;align-items:center;min-height:100vh;margin:0;background:#0f172a;color:#e2e8f0}div{text-align:center;max-width:500px;padding:24px}h1{color:#f87171;font-size:24px}code{background:#1e293b;padding:2px 8px;border-radius:4px;font-size:14px}p{line-height:1.6;color:#94a3b8}</style></head><body><div><h1>APK Not Available</h1><p>The Android APK has not been compiled yet. To build it from source:</p><p><code>cd android</code><br><code>./gradlew assembleDebug</code><br><code>cp app/build/outputs/apk/debug/app-debug.apk ../ScreenTinker.apk</code></p><p>See the <a href="/" style="color:#3b82f6">README</a> for full build instructions.</p><p>In Docker, mount a built APK at <code>/data/ScreenTinker.apk</code> (the data dir).</p><p>Alternatively, use the <a href="/player" style="color:#3b82f6">web player</a> in any browser.</p></div></body></html>`);
|
res.status(404).send(`<!DOCTYPE html><html><head><title>APK Not Found</title><style>body{font-family:-apple-system,system-ui,sans-serif;display:flex;justify-content:center;align-items:center;min-height:100vh;margin:0;background:#0f172a;color:#e2e8f0}div{text-align:center;max-width:500px;padding:24px}h1{color:#f87171;font-size:24px}code{background:#1e293b;padding:2px 8px;border-radius:4px;font-size:14px}p{line-height:1.6;color:#94a3b8}</style></head><body><div><h1>APK Not Available</h1><p>The Android APK has not been compiled yet. To build it from source:</p><p><code>cd android</code><br><code>./gradlew assembleDebug</code><br><code>cp app/build/outputs/apk/debug/app-debug.apk ../ScreenTinker.apk</code></p><p>See the <a href="/" style="color:#3b82f6">README</a> for full build instructions.</p><p>In Docker, mount a built APK at <code>/data/ScreenTinker.apk</code> (the data dir).</p><p>Alternatively, use the <a href="/player" style="color:#3b82f6">web player</a> in any browser.</p></div></body></html>`);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue