No description
Find a file
Richard 78f5a44e90 Give the download one permanent address
The manifest names the current artifact and the directory listing is off,
so "where do I download it by hand" could only be answered by reading the
manifest first. latest.apk is a symlink the release script repoints — git
stores it as a path, so it costs bytes rather than another 34MB a
release, and every past build stays reachable under its own name, which
is what lets a device midway through a download survive a release.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-30 18:01:31 +02:00
public Give the download one permanent address 2026-08-30 18:01:31 +02:00
.dockerignore Somewhere for the app to look for a newer version of itself 2026-08-30 03:53:38 +02:00
Dockerfile Somewhere for the app to look for a newer version of itself 2026-08-30 03:53:38 +02:00
nginx.conf Somewhere for the app to look for a newer version of itself 2026-08-30 03:53:38 +02:00
README.md Give the download one permanent address 2026-08-30 18:01:31 +02:00
release.py Give the download one permanent address 2026-08-30 18:01:31 +02:00

media-updates

What the amber-adult app checks at launch to find a newer build of itself.

Two files behind nginx: manifest.json, and the APK it names. No authentication, deliberately — there is no account to check against and the APK holds no secret. The credential in that app is the addon URL, which lives in the device keystore and never leaves it.

Publishing a release

./release.py ../amber-adult/build/app/outputs/flutter-apk/app-release.apk "what changed"

It reads the version and build number out of amber-adult/pubspec.yaml, copies the APK in under a versioned name, writes manifest.json, and commits. Push, and Coolify redeploys.

The APKs are committed. At ~34MB and a handful of releases a year that is the cheaper trade against standing up artifact storage for one app; if the repository ever gets uncomfortable, the history is disposable — only the newest artifact is ever fetched.

Downloading by hand

https://media-updates.petruzalekr.cz/latest.apk always points at the newest build — a symlink the release script repoints, so the address never changes. Every past build stays reachable under its own media-<build>.apk name, which is what lets a device that is midway through a download survive a release.

The manifest

{
  "version": "0.1.0",
  "buildNumber": 1,
  "notes": "…",
  "sha256": "…64 hex…",
  "size": 34210000,
  "url": "https://media-updates.petruzalekr.cz/media-1.apk"
}

The client refuses anything it cannot act on: an equal or older buildNumber, a missing url, or a sha256 that is not 64 characters. The download is checked against that digest before it reaches the installer.