Files
schwert_und_magie_on_pebble/docs/publish.md
T
2026-06-27 12:13:48 +02:00

286 lines
10 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Publishing guide
Steps to generate signing credentials and publish both apps. See
`docs/architecture.md` for what each app does and `CLAUDE.md` for build
commands.
## 1. .gitignore
Keystore files and credential properties must never be committed. Already
added to `.gitignore`:
```
*.jks
*.keystore
keystore.properties
```
If you generate a keystore with a different name/extension, add that
specific path too — don't rely on a broad glob you might forget to check.
## 2. Android companion app → Google Play
### 2.1 Generate an upload keystore
```bash
keytool -genkeypair -v \
-keystore SchwertUndMagieOnPebbleCompanionApp/release.keystore \
-alias sum-release \
-keyalg RSA -keysize 2048 -validity 10000
```
`keytool` will prompt for a keystore password, a key password (can be the
same), and your name/org details for the certificate (these become public
metadata in the signed APK, not secret). Store the keystore file and both
passwords in a password manager — **losing this keystore means you can never
publish an update to the same Play Store listing again** under the same app;
Google cannot recover or reset it for you.
### 2.2 Store credentials in a gitignored properties file
Create `SchwertUndMagieOnPebbleCompanionApp/keystore.properties` (already
gitignored, never commit it):
```properties
storeFile=release.keystore
storePassword=<keystore password>
keyAlias=sum-release
keyPassword=<key password>
```
### 2.3 Wire the signing config
Add to `SchwertUndMagieOnPebbleCompanionApp/app/build.gradle.kts`, near the
top:
```kotlin
import java.util.Properties
val keystoreProps = Properties().apply {
rootProject.file("keystore.properties").takeIf { it.exists() }
?.reader()?.use { load(it) }
}
```
Inside the `android { }` block:
```kotlin
signingConfigs {
create("release") {
keystoreProps["storeFile"]?.let { storeFile = file(it as String) }
storePassword = keystoreProps["storePassword"] as String?
keyAlias = keystoreProps["keyAlias"] as String?
keyPassword = keystoreProps["keyPassword"] as String?
}
}
buildTypes {
release {
signingConfig = signingConfigs.getByName("release")
// ...existing isMinifyEnabled / proguardFiles
}
}
```
This degrades gracefully (null signing config values) on any machine without
`keystore.properties` — CI or a contributor's checkout — rather than failing
the whole Gradle configuration.
### 2.4 Build the release bundle
```bash
cd SchwertUndMagieOnPebbleCompanionApp
./gradlew bundleRelease # produces app/build/outputs/bundle/release/app-release.aab
./gradlew assembleRelease # produces app/build/outputs/apk/release/app-release.apk, for sideload testing
```
Play Store requires the **AAB** (`bundleRelease` output), not the APK — Play
re-packages per-device APKs from it (including ABI splits, so `arm64-v8a`/
`x86_64` native VICE libraries each ship only to matching devices).
### 2.5 Play Console setup (one-time, per app listing)
1. Enroll in the Google Play Developer program (one-time account fee).
2. Create the app in Play Console, set its package name
(`de.ladkau.schwertundmagieonpebblecompanionapp`) — this is permanent.
3. **App content**: privacy policy URL, content rating questionnaire, data
safety form (declare what data the app collects — this app's only network
activity is the loopback HTTP server talking to Core for Pebble, so
"no data collected/shared" likely applies, but fill out the form yourself).
4. **Store listing**: title, short/full description, icon (512×512 PNG),
feature graphic (1024×500), phone screenshots (min 2, current device's
actual aspect ratio).
5. Enroll in **Play App Signing** when prompted on first upload — Google
re-signs your AAB with its own key for distribution; your upload keystore
(§2.1) only needs to be kept for *future uploads to this listing*, not for
the keys end users' devices actually trust.
6. Upload the AAB to an **internal testing** track first, verify the install
works on a real device, then promote to closed/open testing or production.
### 2.6 Versioning for future releases
Bump both fields in `app/build.gradle.kts` before every release build:
```kotlin
versionCode = 2 // must strictly increase on every Play Store upload
versionName = "1.1" // user-visible, free-form
```
## 3. Android companion app → F-Droid
F-Droid is a community-run FOSS app catalogue that builds apps from source on
its own infrastructure and signs them with its own key. The companion app is a
good fit: it is open source, ships no proprietary binaries in the repo, and the
copyrighted ROM and disk files are handled entirely at runtime by the user.
### 3.1 Inclusion policy check
F-Droid's key requirement is that everything needed to build the app is in the
repo and is free/open-source. Verify:
- VICE 3.8 source is GPLv2 (tarball in `res/`). ✓
- nibtools source is GPLv2 (tarball in `res/`). ✓
- No prebuilt binaries committed (`.a`/`.so` files are build outputs in
`.gitignore`). ✓
- No non-free SDKs or closed-source dependencies in `build.gradle.kts`. ✓
- C64 ROMs and game disks are not bundled — user-supplied at runtime. ✓
### 3.2 Prepare the fdroiddata metadata file
F-Droid apps are registered by adding a YAML file to the
[fdroiddata](https://gitlab.com/fdroid/fdroiddata) repository. Fork it, then
create `metadata/de.ladkau.schwertundmagieonpebblecompanionapp.yml`:
```yaml
Categories:
- Games
License: GPL-2.0-or-later
AuthorName: Matthias Ladkau
SourceCode: https://github.com/<your-repo>
IssueTracker: https://github.com/<your-repo>/issues
AutoName: Schwert und Magie on Pebble
RepoType: git
Repo: https://github.com/<your-repo>
Builds:
- versionName: '1.0'
versionCode: 1
commit: <git-tag-or-sha>
subdir: SchwertUndMagieOnPebbleCompanionApp
gradle:
- release
ndk: 30.0.14904198
prebuild:
- bash app/src/main/jni/build_vice.sh
- bash app/src/main/jni/build_nibtools.sh
AutoUpdateMode: None
UpdateCheckMode: None
```
Key points:
- `subdir` points to the Gradle project root (where `gradlew` lives).
- `gradle: [release]` tells F-Droid to run `./gradlew assembleRelease`.
- `ndk` must match the `ndkVersion` in `app/build.gradle.kts`
(`30.0.14904198`). F-Droid's build server installs the requested NDK version
automatically.
- `prebuild` runs the VICE and nibtools cross-compilation before Gradle
invokes CMake. The `NDK` environment variable is set by F-Droid's build
server, matching what `build_vice.sh` and `build_nibtools.sh` expect.
- F-Droid signs with its own key, so `keystore.properties` is not needed on
the build server. The signing config in `build.gradle.kts` degrades
gracefully when the file is absent.
### 3.3 Test the build locally with fdroid-server
Before submitting, reproduce the F-Droid build environment locally:
```bash
# Install fdroid-server (Debian/Ubuntu)
sudo apt install fdroidserver
# In the fdroiddata checkout:
fdroid build de.ladkau.schwertundmagieonpebblecompanionapp --latest
```
This runs the build inside a Docker container that mirrors the F-Droid build
server. A successful local build means the merge request is very likely to
pass.
### 3.4 Submit the merge request
Push your `metadata/` addition to your fdroiddata fork and open a merge
request against `gitlab.com/fdroid/fdroiddata`. The F-Droid team reviews the
metadata and, if the build passes on their infrastructure, merges it and
includes the app in the next index update (published roughly weekly).
### 3.5 Versioning for F-Droid updates
Each new release requires a new `Builds` entry in the metadata file with an
incremented `versionCode` and the corresponding git commit or tag. `versionCode`
must match the value in `app/build.gradle.kts`.
## 5. Pebble watch app → Rebble app store / direct distribution
The official Pebble app store shut down years ago; the community-run
**Rebble** store is the closest equivalent today, alongside the 2025 Core
Devices relaunch of Pebble hardware. Check Rebble's current developer portal
directly for their exact submission flow and requirements — that's outside
this repo and changes independently of it.
### 5.1 Build the artifact
```bash
cd SchwertUndMagieOnPebbleWatchApp
pebble build # produces build/SchwertUndMagieOnPebbleWatchApp.pbw
```
The `.pbw` is the complete distributable — it bundles all target platforms
(`aplite`/`basalt`/`chalk`/`diorite`/`emery`/`flint`/`gabbro`) declared in
`package.json`. There is no signing step analogous to Android; Pebble apps
are not cryptographically signed by the developer.
### 5.2 Direct distribution (no store)
Anyone with the `.pbw` file and Core for Pebble installed can sideload it —
this is the lowest-friction path and doesn't depend on any third party's
store being operational. This watch app is tightly coupled to the companion
app's HTTP bridge (see `docs/architecture.md` §1), so it's not really
meaningful as a standalone listing anyway — distribute both together.
### 5.3 Store submission (if Rebble's process applies)
Expect to need: an app icon resource (not yet configured in `package.json`
there's no `icon`/menu-icon entry currently, only the in-app `IMAGE_SPLASH`
bitmap), a short description, and screenshots per platform. Generate
screenshots the same way used during development:
```bash
pebble install --emulator emery --vnc
pebble screenshot --vnc --no-open docs/screenshots/emery.png
```
(repeat per target platform you want a store screenshot for).
### 5.4 Versioning
Bump `version` in `SchwertUndMagieOnPebbleWatchApp/package.json` before each
release build.
## 6. Pre-publish checklist
- [ ] Release keystore generated, passwords saved in a password manager, both
gitignored (§1, §2.1)
- [ ] `keystore.properties` exists locally and is **not** tracked by git
- [ ] `./gradlew bundleRelease` succeeds and installs/runs on a real device
from the resulting AAB (test via `bundletool` or Play internal testing)
- [ ] Play Console store listing content complete (icon, screenshots,
privacy policy, content rating, data safety form)
- [ ] F-Droid metadata YAML created and `fdroid build` passes locally (§3)
- [ ] `pebble build` succeeds for all target platforms; `.pbw` sideloads and
runs correctly against the signed companion app build
- [ ] `versionCode`/`versionName` (Android) and `version` (Pebble) bumped