Documentation

Signing

A project's own signing key, committed with it, so every machine signs the same way.

Usage

whitehall keystore init [manifest] [--path <file>]
$ whitehall keystore init
  Generating keys/app.keystore
 Fingerprint A3:09:CC:3A:34:70:...
       Wrote [signing] in whitehall.toml

init generates a keystore into the project and writes [signing] in whitehall.toml, creating the file in a tool's directory that has none. The default path is keys/app.keystore; --path moves it, relative to the project root. It refuses if [signing] is already there, or if the path it would write to exists: an identity is not something a second run should replace.

[signing]

[signing]
keystore = "keys/app.keystore"    # relative to the project; commit it
alias = "myapp"
# password_env = "WHITEHALL_KEYSTORE_PASSWORD"   # the default
KeyMeans
keystoreThe keystore, relative to the project root. Commit it
aliasThe key's alias inside the keystore. init uses the project's name
password_envThe environment variable holding the password. Default WHITEHALL_KEYSTORE_PASSWORD. One password covers the store and the key

Why commit a key

Without [signing], the first --release build generates ~/.whitehall/release.keystore and every later build on that machine reuses it. For one laptop that is the zero-config answer. For two it is the wrong one: a teammate, a fresh clone or a CI runner generates its own keystore, and Android refuses to install one machine's build over the other's with an error that names the package, not the cause (INSTALL_FAILED_UPDATE_INCOMPATIBLE).

With [signing], every machine that clones the project signs identically. The same keystore signs debug and release, so a debug build installs over a release build and back. [signing] wins outright over the per-machine environment variables (WHITEHALL_KEYSTORE_PATH, WHITEHALL_KEYSTORE_PASSWORD, WHITEHALL_KEY_ALIAS, WHITEHALL_KEY_PASSWORD); those remain for a keystore a project already has, or a runner that should not receive the file.

The password

The password travels out of band: it is read from the variable password_env names. Set it in your shell or in CI's secret store. Do not put it in a .env file — those feed $env and are compiled into the APK, which is where a keystore password must never go. When the variable is not set, the well-known default whitehall is used, which is the password init generates the keystore with.

Release builds

whitehall build --release       # dist/app-release.apk, signed
whitehall package . --release -o myapp.apk

Every build prints what it signed with: Signed <fingerprint> (<source>). Google's APIs want that SHA-1 registered. To read it from the keystore yourself:

keytool -list -v -keystore keys/app.keystore
If you use Play App Signing, Google re-signs the app, and the fingerprint that matters is the app signing certificate in Play Console under Setup, App signing. Registering the upload key instead is the classic failure: local release builds work, and auth breaks the moment the app ships through Play.

See Also