From 95757544646b98738bc500ca0d23307dcf6716a3 Mon Sep 17 00:00:00 2001 From: Hossain Khan Date: Sat, 28 Jun 2025 13:09:33 -0400 Subject: [PATCH] [UPDATE] Docs to mention f-droid is also now signed --- .github/workflows/fdroid-build.yml | 5 ++- .github/workflows/test-keystore-clean.yml | 40 ++++++++++++++++++----- BUILD_FDROID.md | 6 ++-- keystore/README.md | 20 +++++++++--- metadata/ink.trmnl.android.yml | 2 +- 5 files changed, 55 insertions(+), 18 deletions(-) diff --git a/.github/workflows/fdroid-build.yml b/.github/workflows/fdroid-build.yml index c7ba3d4..74a277d 100644 --- a/.github/workflows/fdroid-build.yml +++ b/.github/workflows/fdroid-build.yml @@ -1,11 +1,14 @@ name: F-Droid Build +# Builds a signed F-Droid APK using the production keystore. +# F-Droid will verify the signature during their reproducible build process. + on: push: branches: [ "main" ] pull_request: branches: [ "main" ] - # This allows manual triggering of the workflow, which results in making F-Droid APK build + # This allows manual triggering of the workflow, which results in making a signed F-Droid APK build # Go to the "Actions" tab the repository, select this workflow, and click the "Run workflow" button to run it manually. workflow_dispatch: diff --git a/.github/workflows/test-keystore-clean.yml b/.github/workflows/test-keystore-clean.yml index 3e05f2a..caee7da 100644 --- a/.github/workflows/test-keystore-clean.yml +++ b/.github/workflows/test-keystore-clean.yml @@ -83,25 +83,47 @@ jobs: # Set up Gradle chmod +x gradlew - # Test the release build (this will use the new signing configuration) - echo "Building release APK with production keystore..." + # Test the standard release build + echo "Building standard release APK with production keystore..." if ./gradlew assembleStandardRelease \ -PKEYSTORE_PASSWORD="${{ secrets.KEYSTORE_PASSWORD }}" \ - -PKEY_ALIAS="${{ secrets.KEY_ALIAS }}" > keystore-test/gradle-build.txt 2>&1; then - echo "✅ Android release build succeeded with production keystore" - echo "✅ APK should be properly signed" + -PKEY_ALIAS="${{ secrets.KEY_ALIAS }}" > keystore-test/gradle-build-standard.txt 2>&1; then + echo "✅ Android standard release build succeeded with production keystore" # Verify the APK exists if [ -f "app/build/outputs/apk/standard/release/app-standard-release.apk" ]; then - echo "✅ Release APK generated successfully" + echo "✅ Standard release APK generated successfully" else - echo "❌ Release APK not found" + echo "❌ Standard release APK not found" exit 1 fi else - echo "❌ Android release build failed" + echo "❌ Android standard release build failed" echo "Build output:" - cat keystore-test/gradle-build.txt + cat keystore-test/gradle-build-standard.txt + exit 1 + fi + + # Test the F-Droid release build + echo "" + echo "Building F-Droid release APK with production keystore..." + if ./gradlew assembleFdroidRelease \ + -PKEYSTORE_PASSWORD="${{ secrets.KEYSTORE_PASSWORD }}" \ + -PKEY_ALIAS="${{ secrets.KEY_ALIAS }}" > keystore-test/gradle-build-fdroid.txt 2>&1; then + echo "✅ Android F-Droid release build succeeded with production keystore" + + # Verify the APK exists + if [ -f "app/build/outputs/apk/fdroid/release/app-fdroid-release.apk" ]; then + echo "✅ F-Droid release APK generated successfully" + echo "✅ Both standard and F-Droid builds are now properly signed" + else + echo "❌ F-Droid release APK not found" + exit 1 + fi + else + echo "❌ Android F-Droid release build failed" + echo "Build output:" + cat keystore-test/gradle-build-fdroid.txt exit 1 fi diff --git a/BUILD_FDROID.md b/BUILD_FDROID.md index e43e87b..4eda97e 100644 --- a/BUILD_FDROID.md +++ b/BUILD_FDROID.md @@ -9,7 +9,7 @@ The app includes specific configurations for F-Droid compatibility: 1. A dedicated `fdroid` product flavor that excludes Google Fonts 2. A specific `fdroidRelease` build type 3. System fonts are used instead of Google Fonts for the F-Droid version -4. The F-Droid build is **not signed** (as per [PR #106](https://github.com/usetrmnl/trmnl-android/pull/106)) - F-Droid handles the signing process +4. The F-Droid build is **signed** with the production keystore for consistency across all distribution channels ## Building the F-Droid Version @@ -19,7 +19,9 @@ To build the F-Droid version locally: ./gradlew assembleFdroidRelease ``` -This will generate an unsigned APK in `app/build/outputs/apk/fdroid/release/` that is suitable for F-Droid submission. Unlike the standard release build, the F-Droid build variant does not have a signing configuration, as F-Droid's build system will handle the signing process. +This will generate a signed APK in `app/build/outputs/apk/fdroid/release/` using the production keystore. The F-Droid build variant now uses the same signing configuration as the standard release build, ensuring consistency across all distribution channels. + +> **Note**: F-Droid's reproducible build process will verify that the APK can be rebuilt with the same signature, ensuring the integrity of the build process. Alternatively, you can use the convenience task: diff --git a/keystore/README.md b/keystore/README.md index 96b26a3..fad65cb 100644 --- a/keystore/README.md +++ b/keystore/README.md @@ -14,15 +14,20 @@ signing the app during development. ## Production Keystore -The production keystore (`trmnl-app-release.keystore`) is used for release builds and is stored as a base64-encoded secret in GitHub Actions. The keystore is decoded during CI/CD builds. +The production keystore (`trmnl-app-release.keystore`) is used for all release builds (both standard and F-Droid flavors) and is stored as a base64-encoded secret in GitHub Actions. The keystore is decoded during CI/CD builds. + +### Build Flavors Using Production Keystore + +- **Standard Release**: Signs APKs for general distribution +- **F-Droid Release**: Signs APKs for F-Droid distribution (F-Droid will verify the signature during their reproducible build process) ### Important Notes About the Production Keystore The production keystore has a specific configuration quirk that's important to understand: - **Store Password**: Used to access the keystore file -- **Key Password**: The keystore was created with a key password, but due to PKCS12 format behavior, the private key is only accessible when jarsigner uses the store password for both store and key access -- **Solution**: The `keyPassword` parameter is intentionally omitted from the Android build configuration, allowing the Android build system to use the store password for both purposes +- **Key Password**: The keystore was created with a key password, but due to PKCS12 format behavior, both `storePassword` and `keyPassword` are set to the same value in the build configuration +- **Solution**: The Android Gradle Plugin requires both passwords to be explicitly set, so we use the store password for both purposes This is a known characteristic of certain PKCS12 keystores where explicit key passwords can cause "key associated with alias not a private key" errors, even when the keystore is completely valid. @@ -30,10 +35,15 @@ This is a known characteristic of certain PKCS12 keystores where explicit key pa The following GitHub Actions secrets are required: - `KEYSTORE_BASE64`: Base64-encoded production keystore file -- `KEYSTORE_PASSWORD`: Password for accessing the keystore +- `KEYSTORE_PASSWORD`: Password for accessing the keystore (used for both store and key access) - `KEY_ALIAS`: Alias of the signing key within the keystore -Note that `KEY_PASSWORD` is not used in the build configuration due to the keystore behavior described above. +### CI/CD Workflows Using Production Keystore + +- **`android-release.yml`**: Builds and signs standard release APKs +- **`fdroid-build.yml`**: Builds and signs F-Droid release APKs + +Both workflows decode the keystore from the base64 secret and provide the necessary environment variables for signing. ## Related Resources - https://developer.android.com/studio/publish/app-signing diff --git a/metadata/ink.trmnl.android.yml b/metadata/ink.trmnl.android.yml index c747759..be52225 100644 --- a/metadata/ink.trmnl.android.yml +++ b/metadata/ink.trmnl.android.yml @@ -41,7 +41,7 @@ Builds: subdir: app gradle: - fdroid - output: build/outputs/apk/fdroid/release/app-fdroid-release-unsigned.apk + output: build/outputs/apk/fdroid/release/app-fdroid-release.apk MaintainerNotes: This app uses the F-Droid flavor for gradle build.