2026-08-11 21:44:27 +02:00
|
|
|
|
# Releasing a new version
|
|
|
|
|
|
|
|
|
|
|
|
The clock lives in two places: the web app in `public_html/`, which you host
|
|
|
|
|
|
yourself, and the Android app on F-Droid, which is built from a git tag.
|
|
|
|
|
|
|
|
|
|
|
|
**Everything F-Droid needs comes from a tag in this repository.** After the first
|
|
|
|
|
|
release was accepted there is nothing to do in F-Droid's own repo — their bot
|
|
|
|
|
|
watches the tags here and writes the build entry itself. Don't open a merge
|
|
|
|
|
|
request against `fdroiddata` for a new version.
|
|
|
|
|
|
|
|
|
|
|
|
Worked example below bumps 1.0 to 1.1. Substitute your own numbers.
|
|
|
|
|
|
|
|
|
|
|
|
## 1. Make the change
|
|
|
|
|
|
|
|
|
|
|
|
Both versions share one copy of the app. Edit `public_html/index.html` and the
|
|
|
|
|
|
Android build picks it up automatically — the Gradle build reads `public_html/`
|
|
|
|
|
|
directly rather than keeping a second copy, so the two can't drift.
|
|
|
|
|
|
|
|
|
|
|
|
If you changed anything visible, bump the service worker cache or installed web
|
|
|
|
|
|
users will keep the old page:
|
|
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
|
# public_html/sw.js
|
|
|
|
|
|
const CACHE = "bgclock-v18"; # any new value; it only has to differ
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
## 2. Bump the version
|
|
|
|
|
|
|
|
|
|
|
|
In `android/app/build.gradle.kts`:
|
|
|
|
|
|
|
|
|
|
|
|
```kotlin
|
|
|
|
|
|
versionCode = 2 // an integer, +1 every release, never reused
|
|
|
|
|
|
versionName = "1.1" // what people see
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
`versionCode` is what Android uses to decide one version is newer than another.
|
|
|
|
|
|
It must go up every single release, even for a one-character fix.
|
|
|
|
|
|
|
|
|
|
|
|
## 3. Write the changelog
|
|
|
|
|
|
|
|
|
|
|
|
A new file named after the **versionCode**, not the version name:
|
|
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
|
fastlane/metadata/android/en-US/changelogs/2.txt
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
Maximum 500 characters. This is what shows up in F-Droid's "What's New".
|
|
|
|
|
|
|
|
|
|
|
|
## 4. Build it and put it on your phone
|
|
|
|
|
|
|
|
|
|
|
|
```bash
|
|
|
|
|
|
export ANDROID_HOME="$HOME/Android/Sdk" # already in ~/.bashrc
|
|
|
|
|
|
cd android
|
|
|
|
|
|
./gradlew assembleDebug
|
|
|
|
|
|
adb install -r app/build/outputs/apk/debug/app-debug.apk
|
|
|
|
|
|
./gradlew --stop # the daemon holds ~500 MB otherwise
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
Play a real game before tagging. Worth checking specifically: start a match,
|
|
|
|
|
|
make some moves, force-quit from the task switcher and reopen — everything
|
|
|
|
|
|
should come back, paused. That is the check that proves the app's storage is
|
|
|
|
|
|
working, and it fails silently rather than loudly.
|
|
|
|
|
|
|
|
|
|
|
|
## 5. Commit, tag, push
|
|
|
|
|
|
|
|
|
|
|
|
```bash
|
|
|
|
|
|
git add -A
|
|
|
|
|
|
git commit -m "…"
|
|
|
|
|
|
git tag -a v1.1 -m "Backgammon Clock 1.1"
|
|
|
|
|
|
git push
|
|
|
|
|
|
git push origin v1.1
|
|
|
|
|
|
```
|
|
|
|
|
|
|
2026-08-12 10:21:12 +02:00
|
|
|
|
Keep tags in the `v1.1` shape for consistency, but nothing depends on it:
|
|
|
|
|
|
`UpdateCheckMode: Tags` with no pattern matches every tag whatever it's called,
|
|
|
|
|
|
and F-Droid's bot resolves whichever tag it finds to a commit hash before it
|
|
|
|
|
|
writes the build entry.
|
2026-08-11 21:44:27 +02:00
|
|
|
|
|
|
|
|
|
|
Never move or delete a tag that has been pushed — F-Droid may already have built
|
2026-08-12 10:21:12 +02:00
|
|
|
|
it. If a release is wrong, bump the version and release again. (The recipe pins
|
|
|
|
|
|
a hash, so a moved tag can't retroactively change a version they already built;
|
|
|
|
|
|
it would just leave your repo disagreeing with what's on people's phones.)
|
|
|
|
|
|
|
|
|
|
|
|
**If you ever write a build entry by hand**, its `commit:` must be a full 40-char
|
|
|
|
|
|
commit hash — never a tag, never a branch. Tags are mutable, so a tag there means
|
|
|
|
|
|
the thing F-Droid builds and signs can change under them, and they reject it on
|
|
|
|
|
|
sight. This came up on the very first submission and is easy to get wrong,
|
|
|
|
|
|
because `fdroid lint` doesn't check it under `UpdateCheckMode: Tags` — the
|
|
|
|
|
|
pipeline goes green and a human catches it days later. Get the hash with:
|
|
|
|
|
|
|
|
|
|
|
|
```bash
|
|
|
|
|
|
git rev-parse v1.1^{commit} # ^{commit}, or an annotated tag gives you the
|
|
|
|
|
|
# tag object's hash instead of the commit's
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
This doesn't come up in a normal release: the bot writes the entry, and the bot
|
|
|
|
|
|
writes hashes.
|
2026-08-11 21:44:27 +02:00
|
|
|
|
|
|
|
|
|
|
## 6. Wait
|
|
|
|
|
|
|
|
|
|
|
|
Their bot notices the new tag, adds a build entry, and the build server picks it
|
|
|
|
|
|
up on its next cycle. Expect a day or two. Nothing to do.
|
|
|
|
|
|
|
|
|
|
|
|
## Deploying the web version
|
|
|
|
|
|
|
|
|
|
|
|
Separate from all of the above, and manual: upload the six files in
|
|
|
|
|
|
`public_html/` — `index.html`, `manifest.webmanifest`, `sw.js`, `icon-192.png`,
|
|
|
|
|
|
`icon-512.png`, `icon-maskable-512.png` — to the web host. `README.md` and
|
|
|
|
|
|
`RELEASING.md` stay out of it; they live in the repo root for that reason.
|
|
|
|
|
|
|
|
|
|
|
|
## If the screenshots need redoing
|
|
|
|
|
|
|
|
|
|
|
|
`fastlane/metadata/android/en-US/images/phoneScreenshots/` holds five shots at
|
|
|
|
|
|
1170×2532. They are generated from `public_html/index.html` itself with headless
|
|
|
|
|
|
Chromium, not taken on a phone, so they can be regenerated exactly. Two traps if
|
|
|
|
|
|
you do it by hand:
|
|
|
|
|
|
|
|
|
|
|
|
- The capture lands whenever the virtual-time budget runs out, not when your
|
|
|
|
|
|
script finishes — so freeze the render loop (`requestAnimationFrame = () => 0`)
|
|
|
|
|
|
once the frame you want is on screen.
|
|
|
|
|
|
- CSS transitions don't advance under `--virtual-time-budget`, so a panel caught
|
|
|
|
|
|
mid-transition photographs in its *old* colour. Disable transitions in the
|
|
|
|
|
|
screenshot build.
|
|
|
|
|
|
|
|
|
|
|
|
## Reference
|
|
|
|
|
|
|
|
|
|
|
|
- App ID: `nl.hansdezwart.bgclock` — fixed forever; changing it makes a new app.
|
|
|
|
|
|
- F-Droid listing text: `fastlane/metadata/android/en-US/` (title ≤50 chars,
|
|
|
|
|
|
summary ≤80, description ≤4000, changelog ≤500). Only these HTML tags work in
|
|
|
|
|
|
the description: `b big blockquote br cite em i li ol small strike strong sub
|
|
|
|
|
|
sup tt u ul`.
|
|
|
|
|
|
- The original submission: https://gitlab.com/fdroid/fdroiddata/-/merge_requests/45478
|
|
|
|
|
|
- F-Droid signs the APK with their key, not yours. Reproducible builds were
|
|
|
|
|
|
declined at submission and can't be enabled later for this app ID.
|