Release Signing

Signing a Capacitor Release Build

With Play App Signing (Play App Signing) you sign releases with an upload key, which proves to Google that an upload comes from you. Create it outside the project, with the password in an environment variable:

Creating BookNest's upload keyShell
mkdir -p ~/keys
keytool -genkeypair -v -keystore ~/keys/booknest-upload.jks -alias upload \
  -keyalg RSA -keysize 2048 -validity 10000 \
  -dname "CN=BookNest Upload, O=Example Books, C=MY" \
  -storepass "$BOOKNEST_STORE_PASS" -keypass "$BOOKNEST_STORE_PASS"
Output
Generating 2,048 bit RSA key pair and self-signed certificate (SHA384withRSA) with a validity
  of 10,000 days
   for: CN=BookNest Upload, O=Example Books, C=MY
[Storing /home/dev/keys/booknest-upload.jks]

Play wants an RSA upload key of at least 2048 bits. Gradle 19,597 reads it through android/keystore.properties, four lines (storeFile, storePassword, keyAlias, keyPassword) kept out of Git 1,932 ; a CI job writes that file from its secret store (CI Pipelines):

android/app/build.gradle: the release signing configGroovy
def keyProps = new Properties()
def keyFile = rootProject.file('keystore.properties')
if (keyFile.exists()) keyFile.withInputStream { keyProps.load(it) }
android {
    signingConfigs {
        release {
            if (keyFile.exists()) {
                storeFile file(keyProps['storeFile'])
                storePassword keyProps['storePassword']
                keyAlias keyProps['keyAlias']
                keyPassword keyProps['keyPassword']
            }
        }
    }
}

The release build type then adds if (keyFile.exists()) signingConfig signingConfigs.release; without the file, release builds come out unsigned. Capacitor 243,123 's android/.gitignore ships with #*.jks and #*.keystore commented out, so BookNest uncomments both and adds keystore.properties.