Files
schwert_und_magie_on_pebble/docs/publish.md
T
ml eee068a500 Wire keystore signing config; trim publish.md
- Read keystore.properties at Gradle config time; wire signingConfig into
  the release build type (degrades gracefully when the file is absent)
2026-06-27 12:04:55 +02:00

6.8 KiB
Raw Blame History

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

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):

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:

import java.util.Properties

val keystoreProps = Properties().apply {
    rootProject.file("keystore.properties").takeIf { it.exists() }
        ?.reader()?.use { load(it) }
}

Inside the android { } block:

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

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:

versionCode = 2      // must strictly increase on every Play Store upload
versionName = "1.1"  // user-visible, free-form

3. 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.

3.1 Build the artifact

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.

3.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.

3.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:

pebble install --emulator emery --vnc
pebble screenshot --vnc --no-open docs/screenshots/emery.png

(repeat per target platform you want a store screenshot for).

3.4 Versioning

Bump version in SchwertUndMagieOnPebbleWatchApp/package.json before each release build.

4. 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)
  • 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