The repository grew ~64MB a release and never gave any of it back: at build 14 that was 762MB in public/ and 590MB in .git, stored twice on the VPS. The cost nobody had counted was the image — public/ is copied into it, so a deploy built 1.3GB of nginx, and Coolify keeps the old ones for rollback. That is what filled the server's root filesystem and failed a push with "no space left on device". Nothing ever asks for an older build on purpose, so release.py now deletes all but the newest three of each kind once the new one is staged. Each kind is counted on its own: Linux is published rarely, and latest-linux.tar.gz has to keep resolving through the releases that skip it. Both symlinks point at the build just staged, which is the highest numbered one, so they survive the prune by construction and /manifest.json never named anything but the newest. This trims the working tree to 200MB. It does not shrink .git, which still holds all fourteen builds; pruning that rewrites history and is a separate decision. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
70 lines
2.7 KiB
Markdown
70 lines
2.7 KiB
Markdown
# 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"
|
|
```
|
|
|
|
Add `--linux ../amber-adult/build/linux/x64/release/bundle` to publish the
|
|
desktop build with it. Off by default: it is another ~34MB per release, and the
|
|
desktop has no self-updater to feed — it exists so a source can be checked
|
|
without walking to the television.
|
|
|
|
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**, and only the newest `KEEP_BUILDS` (3) of each
|
|
kind are kept — the release script deletes the rest. At ~34MB each that is the
|
|
cheaper trade against standing up artifact storage for one app, but only while
|
|
the working tree stays small: every artifact in `public/` is also copied into
|
|
the image nginx serves, so a release used to build a 1.3GB image. Trimming
|
|
does not shrink `.git`, which still holds every past build; that history is
|
|
disposable, since only the newest artifact is ever fetched.
|
|
|
|
## Downloading by hand
|
|
|
|
| | |
|
|
|---|---|
|
|
| Android | `https://media-updates.petruzalekr.cz/latest.apk` |
|
|
| Linux x64 | `https://media-updates.petruzalekr.cz/latest-linux.tar.gz` |
|
|
|
|
Both are symlinks the release script repoints, so the addresses never change.
|
|
The last three builds of each kind stay reachable under their own
|
|
`media-<build>.apk` / `media-linux-<build>.tar.gz` names, which is what lets a
|
|
device midway through a download survive a release. Older ones are gone from
|
|
`public/` and answer 404.
|
|
|
|
The Linux tarball unpacks to `amber-adult/`; run `./amber-adult/amber_adult`.
|
|
**It needs libmpv on the system** — media_kit loads it at runtime rather than
|
|
bundling it, so on Arch that is the `mpv` package and on Debian
|
|
`libmpv2`. Nothing warns about its absence up front; the app starts and
|
|
playback fails.
|
|
|
|
Only Android updates itself. The desktop build is replaced by downloading a
|
|
newer tarball.
|
|
|
|
## The manifest
|
|
|
|
```json
|
|
{
|
|
"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.
|