[#42] Add app deployment process

This enables deployment to Google Play internal testing.

Note these changes cannot be fully tested until the signing and API keys are in place.  Non-deployed builds are continuing to work as expected (e.g. `./gradlew assemble`)
This commit is contained in:
Carter Jernigan 2021-12-02 15:18:17 -05:00 committed by GitHub
parent 010e1a857b
commit f738666cd2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 107 additions and 2 deletions

View File

@ -4,6 +4,7 @@ plugins {
id("kotlin-parcelize")
id("androidx.navigation.safeargs")
id("zcash.android-build-conventions")
id("com.github.triplet.play")
}
val packageName = "cash.z.ecc"
@ -11,8 +12,11 @@ val packageName = "cash.z.ecc"
android {
defaultConfig {
applicationId = packageName
versionCode = 1
versionName = "1.0"
// If Google Play deployment is triggered, then these are placeholders which are overwritten
// when the deployment runs
versionCode = project.property("ZCASH_VERSION_CODE").toString().toInt()
versionName = project.property("ZCASH_VERSION_NAME").toString()
}
compileOptions {
@ -100,3 +104,48 @@ dependencies {
}
}
}
val googlePlayServiceKeyFilePath = project.property("ZCASH_GOOGLE_PLAY_SERVICE_KEY_FILE_PATH").toString()
if (googlePlayServiceKeyFilePath.isNotEmpty()) {
// Update the versionName to reflect bumps in versionCode
androidComponents {
val versionCodeOffset = 0 // Change this to zero the final digit of the versionName
onVariants { variant ->
for (output in variant.outputs) {
val processedVersionCode = output.versionCode.map { playVersionCode ->
val defaultVersionName = project.property("ZCASH_VERSION_NAME").toString()
// Version names will look like `myCustomVersionName.123`
playVersionCode?.let {
val delta = it - versionCodeOffset
if (delta < 0) {
defaultVersionName
} else {
"$defaultVersionName.$delta"
}
} ?: defaultVersionName
}
output.versionName.set(processedVersionCode)
}
}
}
configure<com.github.triplet.gradle.play.PlayPublisherExtension> {
serviceAccountCredentials.set(File(googlePlayServiceKeyFilePath))
// For safety, only allow deployment to internal testing track
track.set("internal")
// Automatically manage version incrementing
resolutionStrategy.set(com.github.triplet.gradle.androidpublisher.ResolutionStrategy.AUTO)
val deployMode = project.property("ZCASH_GOOGLE_PLAY_DEPLOY_MODE").toString()
if ("build" == deployMode) {
releaseStatus.set(com.github.triplet.gradle.androidpublisher.ReleaseStatus.DRAFT)
// Prevent upload; only generates a build with the correct version number
commit.set(false)
} else if ("deploy" == deployMode) {
releaseStatus.set(com.github.triplet.gradle.androidpublisher.ReleaseStatus.COMPLETED)
}
}
}

40
docs/Deployment.md Normal file
View File

@ -0,0 +1,40 @@
# Signing
To create a release build, signing must be configured. The following Gradle properties must be set:
1. `ZCASH_RELEASE_KEYSTORE_PATH`
1. `ZCASH_RELEASE_KEYSTORE_PASSWORD`
1. `ZCASH_RELEASE_KEY_ALIAS`
1. `ZCASH_RELEASE_KEY_ALIAS_PASSWORD`
1. Run `./gradlew :app:assembleRelease` to create a signed release APK, which can be tested and easily installed on an emulator or test device. _Note that this APK cannot be deployed, because Google Play requires deployment in AAB format. APK, however, is easier to manage for manually creating a build for testing._
Note that although these are called "release" keys, they may actually be the "upload" key if Google Play Signing is being used.
# Deployment
After signing is configured, it is possible to then configure deployment to Google Play.
## Automated Deployment
Automated deployment to Google Play configured with the [Gradle Play Publisher plugin](https://github.com/Triple-T/gradle-play-publisher).
To perform a deployment:
1. Configure a Google Cloud service API key with the correct permissions
1. Configure Gradle properties
1. `ZCASH_GOOGLE_PLAY_SERVICE_KEY_FILE_PATH` - Set to the path of the service key in JSON format
1. `ZCASH_GOOGLE_PLAY_DEPLOY_MODE` - Set to `deploy`
1. Run the Gradle task `./gradlew :app:publishBundle`
To generate a build with a correct version that can be deployed manually later:
1. Configure a Google Cloud service API key with the correct permissions
1. Configure Gradle properties
1. `ZCASH_GOOGLE_PLAY_SERVICE_KEY_FILE_PATH` - Set to the path of the service key in JSON format
1. `ZCASH_GOOGLE_PLAY_DEPLOY_MODE` - Set to `build` (this is the default value)
1. Run the Gradle tasks `./gradlew :app:processReleaseVersionCodes :app:bundleRelease`
Note that the above instructions are for repeat deployments. If you do not yet have an app listing, you'll need to create that manually.
Note that the artifacts can be manually saved from their output directory under the app/build directory
## Manual Deployment
To manually deploy a build of the app
1. Configure Gradle properties
1. `ZCASH_VERSION_CODE` - Set to the integer version code of the app. A simple monotonically increasing number is recommended.1
1. `ZCASH_VERSION_NAME` - Set to a human-readable version number, such as 1.0.1.
1. Run the Gradle task `./gradlew :app:bundleRelease`
1. Collect the build artifacts under `app/build` and manually deploy them through the Google Play web interface

View File

@ -28,6 +28,12 @@ IS_USE_TEST_ORCHESTRATOR=true
# Optionally disable minification
IS_MINIFY_ENABLED=true
# If ZCASH_GOOGLE_PLAY_SERVICE_KEY_FILE_PATH is set and the deployment task is triggered, then
# VERSION_CODE is effectively ignored VERSION_NAME is suffixed with the version code.
# If not using automated Google Play deployment, then these serve as the actual version numbers.
ZCASH_VERSION_CODE=1
ZCASH_VERSION_NAME=0.1
# Set keystore details to enable build signing. Typically these
# are overridden via ~/.gradle/gradle.properties to allow secure injection.
# Debug keystore is useful if using Google Maps or Firebase, which require API keys to be linked
@ -39,6 +45,13 @@ ZCASH_RELEASE_KEYSTORE_PASSWORD=
ZCASH_RELEASE_KEY_ALIAS=
ZCASH_RELEASE_KEY_ALIAS_PASSWORD=
# Optionally set the Google Play Service Key path to enable deployment
ZCASH_GOOGLE_PLAY_SERVICE_KEY_FILE_PATH=
# Can be one of {build, deploy}.
# Build can be used to generate a version number for the next release, but does not ultimately create a release on Google Play.
# Deploy commits the build on Google Play, creating a new release
ZCASH_GOOGLE_PLAY_DEPLOY_MODE=build
# Versions
ANDROID_MIN_SDK_VERSION=24
ANDROID_TARGET_SDK_VERSION=31
@ -51,6 +64,7 @@ DETEKT_VERSION=1.19.0
GRADLE_VERSIONS_PLUGIN_VERSION=0.39.0
KTLINT_VERSION=0.43.1
JGIT_VERSION=5.12.0.202106070339-r
PLAY_PUBLISHER_PLUGIN_VERSION_MATCHER=3.6.0
ANDROIDX_ACTIVITY_VERSION=1.4.0
ANDROIDX_ANNOTATION_VERSION=1.3.0

View File

@ -6,10 +6,12 @@ pluginManagement {
val detektVersion = extra["DETEKT_VERSION"].toString()
val gradleVersionsPluginVersion = extra["GRADLE_VERSIONS_PLUGIN_VERSION"].toString()
val kotlinVersion = extra["KOTLIN_VERSION"].toString()
val playPublisherVersion = extra["PLAY_PUBLISHER_PLUGIN_VERSION_MATCHER"].toString()
kotlin("jvm") version (kotlinVersion)
kotlin("multiplatform") version (kotlinVersion)
id("com.github.ben-manes.versions") version (gradleVersionsPluginVersion) apply (false)
id("com.github.triplet.play") version (playPublisherVersion) apply (false)
id("io.gitlab.arturbosch.detekt") version (detektVersion) apply (false)
}
}