docs: setup files and the client, shared and CI docs describe what is (#6277)

.dockerignore, .gitignore, deploy/initdb, ci-requirements.md,
client/README.md, shared/README.md and two web/scripts test names: dates,
issue/rule/spike ids and the stories behind each exclusion removed.

Corrected:
- client/README.md: the dev lane bundles its own APK; :main no longer
  exists; main bundles the recorded sidecar instead of re-deriving the
  version name. Its smoke-test step wrote a bare "v0.2.0", which the
  server rejects as a sidecar that is not JSON; it now writes the JSON
  shape, which the README documents.
- ci-requirements.md: one workflow, not four; the android lane builds no
  debug APK; main reads the recorded sidecar.
- .gitignore: CI fills client/ on every image build, not tag releases only.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-10-23 13:04:02 -04:00
co-authored by Claude Opus 5.5
parent 557887bb07
commit c96231106f
7 changed files with 68 additions and 82 deletions
+38 -25
View File
@@ -1,45 +1,58 @@
# Bundled client assets
Holds the Android APK (`minstrel.apk` + `minstrel.apk.version`) that the
server serves via `/api/client/version` and `/api/client/apk` for the
in-app update flow (#397).
Holds the Android APK (`minstrel.apk`) and its version sidecar
(`minstrel.apk.version`) that the server serves via `/api/client/version`
and `/api/client/apk` for the in-app update flow.
## Production
CI populates this directory in `release.yml` (no Flutter — the client is
native Android, built by the `android-release` job):
CI fills this directory in `release.yml` before every image build:
- **Tag release (`v*`):** the `android-release` job builds + signs the
APK, uploads it as a workflow artifact, and attaches it to the Gitea
release as `minstrel-<TAG>.apk`. The `image-release` job
(`needs: android-release`) downloads that artifact into this directory
as `minstrel.apk` and writes the computed versionName to
`minstrel.apk.version`.
- **Main push (non-tag `:latest` / `:main`):** no APK is built, but the
image still moves `:latest`, so `image-release` pulls the most-recent
release's signed APK from the Gitea API and reconstructs its exact
versionName — keeping the in-app update channel alive on `:latest`
instead of stripping it until the next tag.
- **Dev push (`:dev`) and tag release (`v*`):** the `android-release` job
builds and signs the APK and uploads it as a workflow artifact;
`image-release` downloads it here as `minstrel.apk` and writes the
sidecar from that build's version outputs. A tag release also attaches
both files to the Gitea release.
- **Main push (`:latest` + `:<sha>`):** no APK is built, but the image
still moves `:latest`, so `image-release` downloads the most recent
release's APK and the sidecar recorded beside it. `:latest` keeps its
update channel between releases.
Either way, `docker buildx build` bakes both files into the image via
`COPY client/ /app/client/`.
## The sidecar
`minstrel.apk.version` is JSON:
```json
{"name": "2026.10.23.1200", "code": 3549060, "channel": "dev"}
```
- `name` is the version name the app shows.
- `code` is the ordering key Android installs by. `null` means unknown,
and clients then compare names.
- `channel` says which lane built it.
A sidecar that is not valid JSON, or has no `name`, is an error rather
than a blank version.
## Development
Empty directory works fine — the endpoints return 404 and the Android
update banner stays hidden ("no update channel" graceful degradation).
An empty directory works fine: the endpoints return 404 and the Android
update banner stays hidden.
To smoke-test the update flow locally, drop a real APK + a version
file into this directory:
To smoke-test the update flow locally, drop a real APK and a sidecar into
this directory:
```sh
cp /path/to/app-release.apk client/minstrel.apk
echo "v0.2.0" > client/minstrel.apk.version
echo '{"name":"2099.01.01.0000","code":null,"channel":"dev"}' > client/minstrel.apk.version
```
## Why a directory and not embed.FS?
The APK is 30-60 MB. Embedding bloats the Go binary and slows
`go build` for everyone, even when the APK isn't being changed.
File-on-disk also lets operators override at runtime via volume
mount on `/app/client/` if they want to ship their own build.
The APK is 30-60 MB. Embedding bloats the Go binary and slows `go build`
for everyone, even when the APK isn't being changed. File-on-disk also
lets an admin override it at runtime with a volume mount on
`/app/client/` to ship their own build.