Repository navigation
Releasing
Releases are built and published by GitHub Actions. Pushing a tag such as v1.3.0 builds the APK,
signs it with the project key stored in repository secrets, verifies the signature, and attaches the
APK and its SHA-256 checksum to a new GitHub release. The release notes are taken from
CHANGELOG.md.
Steps 1–2 are needed once; steps 3–5 for every release.
Skip this if you already have one. Use the same key for every release, forever: Android refuses updates signed with a different key, and users would have to uninstall and lose their settings.
keytool -genkeypair -v \
-keystore release.jks -alias lumen \
-keyalg RSA -keysize 2048 -validity 36500keytool comes with the JDK. Choose strong passwords and store the .jks file and passwords in a
password manager or another safe place outside the repository. If the key is lost, future releases
can't update existing installs.
Encode the keystore as Base64:
# macOS / Linux
base64 -w0 release.jks > release.jks.b64 # macOS: base64 -i release.jks -o release.jks.b64# Windows (PowerShell)
[Convert]::ToBase64String([IO.File]::ReadAllBytes("release.jks")) | Set-Content -NoNewline release.jks.b64In the repository, open Settings → Secrets and variables → Actions → New repository secret and add:
| Secret | Value |
|---|---|
ANDROID_KEYSTORE_BASE64 |
The full contents of release.jks.b64
|
ANDROID_KEYSTORE_PASSWORD |
The keystore password |
ANDROID_KEY_ALIAS |
The key alias (lumen in the example above) |
ANDROID_KEY_PASSWORD |
The key password (often the same as the keystore password) |
Delete release.jks.b64 afterwards. Or set them from the command line with the GitHub CLI:
gh secret set ANDROID_KEYSTORE_BASE64 < release.jks.b64
gh secret set ANDROID_KEYSTORE_PASSWORD
gh secret set ANDROID_KEY_ALIAS
gh secret set ANDROID_KEY_PASSWORDSecrets are never shown in logs, and workflows triggered by pull requests from forks can't read them.
In LumenLauncher/app/build.gradle:
versionCode 4 // +1 every release; Android uses this to decide what's newer
versionName '1.3.0' // shown to people, and must match the tagVersions follow semantic versioning: new features raise the minor number, fixes the patch number.
Add a section at the top of CHANGELOG.md. The heading must contain the version number, because the
release notes are cut from it:
## 1.3.0 — 2026-11-02
- What people will notice, in plain wordsgit commit -am "Release 1.3.0"
git tag -a v1.3.0 -m "1.3.0: short summary"
git push origin main v1.3.0Follow the run under Actions. When it's green, the release appears under Releases with
lumen-v1.3.0.apk and lumen-v1.3.0.apk.sha256.
| Message | Cause and fix |
|---|---|
Missing repository secrets: ... |
One of the four secrets isn't set or is empty. Add it (step 2), then re-run the job from the Actions page |
Tag v1.3.0 does not match versionName 1.2.0 |
The tag and versionName differ. Delete the tag (git push --delete origin v1.3.0 and git tag -d v1.3.0), fix build.gradle, commit, and tag again |
Keystore was tampered with, or password was incorrect |
Wrong ANDROID_KEYSTORE_PASSWORD, or the Base64 value was truncated. Re-encode and paste the whole value |
Cannot recover key / alias not found |
Wrong ANDROID_KEY_PASSWORD or ANDROID_KEY_ALIAS. keytool -list -keystore release.jks shows the alias |
a release with the same tag name already exists |
That version was already published. Bump the version and tag again; don't reuse version numbers |
Builds on branches and pull requests don't need any secrets; they produce an unsigned APK as a build check and upload it as a workflow artifact.
This wiki is generated from the docs/ folder of the repository. To suggest a change, edit the file there and open a pull request.
Using Lumen
Development