[#31] Add injection of build info
Provides infrastructure to help us track exactly what build of the app is running. This provides the ability to implement a number of features in the future - Displaying build version in an About screen - Automatically versioning with Git commit count as an incrementing version number - Injection of secrets, API keys, or other behaviors into the build so that the app can leverage them at runtime. The secrets can be securely stored as environment variables (e.g. on CI), so they don't need to be committed to the repository.
This commit is contained in:
parent
c5f3a44340
commit
f3c425e68a
|
@ -0,0 +1,78 @@
|
|||
import java.text.SimpleDateFormat
|
||||
import java.util.*
|
||||
|
||||
plugins {
|
||||
kotlin("multiplatform")
|
||||
id("zcash.kotlin-multiplatform-build-conventions")
|
||||
}
|
||||
|
||||
// Injects build information
|
||||
// Note timestamp is not currently injected because it effectively disables the cache since it
|
||||
// changes with every build
|
||||
val generateBuildConfigTask = tasks.create("buildConfig") {
|
||||
val generatedDir = "$buildDir/generated"
|
||||
|
||||
val gitInfo = co.electriccoin.zcash.Git.newInfo(parent!!.projectDir)
|
||||
//val buildTimestamp = newIso8601Timestamp()
|
||||
|
||||
inputs.property("gitSha", gitInfo.sha)
|
||||
inputs.property("gitCommitCount", gitInfo.commitCount)
|
||||
//inputs.property("buildTimestamp", buildTimestamp)
|
||||
|
||||
outputs.dir(File(generatedDir))
|
||||
|
||||
doLast {
|
||||
val outputFile = File("$generatedDir/co/electriccoin/zcash/build/BuildConfig.kt")
|
||||
outputFile.parentFile.mkdirs()
|
||||
|
||||
// To add timestamp, add this to the output below
|
||||
// import kotlinx.datetime.Instant
|
||||
// import kotlinx.datetime.toInstant
|
||||
// val buildTimestamp: Instant = "$buildTimestamp".toInstant()
|
||||
outputFile.writeText(
|
||||
"""
|
||||
// Generated file
|
||||
package co.electriccoin.zcash.build
|
||||
|
||||
const val gitSha: String = "${gitInfo.sha}"
|
||||
const val gitCommitCount: Int = ${gitInfo.commitCount}
|
||||
""".trimIndent()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
kotlin {
|
||||
jvm()
|
||||
sourceSets {
|
||||
getByName("commonMain") {
|
||||
dependencies {
|
||||
kotlin.srcDir(generateBuildConfigTask)
|
||||
//api(libs.kotlinx.datetime)
|
||||
}
|
||||
}
|
||||
getByName("commonTest") {
|
||||
dependencies {
|
||||
implementation(kotlin("test"))
|
||||
}
|
||||
}
|
||||
getByName("jvmMain") {
|
||||
dependencies {
|
||||
}
|
||||
}
|
||||
getByName("jvmTest") {
|
||||
dependencies {
|
||||
implementation(kotlin("test"))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Current ISO 8601 timestamp.
|
||||
*/
|
||||
fun newIso8601Timestamp(): String {
|
||||
val formatter = SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSSZ").apply {
|
||||
timeZone = TimeZone.getTimeZone("UTC")
|
||||
}
|
||||
return formatter.format(Date())
|
||||
}
|
|
@ -0,0 +1,19 @@
|
|||
import org.jetbrains.kotlin.konan.properties.loadProperties
|
||||
|
||||
plugins {
|
||||
`java-gradle-plugin`
|
||||
`kotlin-dsl`
|
||||
}
|
||||
|
||||
repositories {
|
||||
mavenCentral()
|
||||
}
|
||||
|
||||
dependencies {
|
||||
val rootProperties = getRootProperties()
|
||||
|
||||
implementation("org.eclipse.jgit:org.eclipse.jgit:${rootProperties.getProperty("JGIT_VERSION")}")
|
||||
}
|
||||
|
||||
// A slightly gross way to use the root gradle.properties as the single source of truth for version numbers
|
||||
fun getRootProperties() = loadProperties(File(project.projectDir.parentFile, "gradle.properties").path)
|
|
@ -0,0 +1,22 @@
|
|||
package co.electriccoin.zcash
|
||||
|
||||
import org.eclipse.jgit.api.Git
|
||||
import org.eclipse.jgit.lib.ObjectId
|
||||
import java.io.File
|
||||
|
||||
object Git {
|
||||
// Get the info for the current branch
|
||||
private const val HEAD = "HEAD"
|
||||
|
||||
fun newInfo(workingDirectory: File): GitInfo {
|
||||
val git = Git.open(workingDirectory)
|
||||
val repository = git.repository
|
||||
|
||||
val head: ObjectId = repository.resolve(HEAD)
|
||||
val count = git.log().call().count()
|
||||
|
||||
return GitInfo(ObjectId.toString(head), count)
|
||||
}
|
||||
}
|
||||
|
||||
data class GitInfo(val sha: String, val commitCount: Int)
|
|
@ -23,6 +23,7 @@ The main entrypoints of the application are:
|
|||
The logical components of the app are implemented as a number of Gradle modules.
|
||||
|
||||
* app — Compiles all of the modules together into the final application. This module contains minimal actual code. Note that the Java package structure for this module is under `cash.z.ecc.app` while the Android package name is `cash.z.ecc`.
|
||||
* build-info-lib — Collects information from the build environment (e.g. Git SHA, Git commit count) and compiles them into the application. Can also be used for injection of API keys or other secrets.
|
||||
* ui-lib — User interface that the user interacts with. This contains 99% of the UI code, along with localizations, icons, and other assets.
|
||||
* preference
|
||||
* preference-api-lib — Multiplatform interfaces for key-value storage of preferences
|
||||
|
|
|
@ -49,6 +49,7 @@ ANDROID_GRADLE_PLUGIN_VERSION=7.0.3
|
|||
DETEKT_VERSION=1.18.1
|
||||
GRADLE_VERSIONS_PLUGIN_VERSION=0.38.0
|
||||
KTLINT_VERSION=0.42.1
|
||||
JGIT_VERSION=5.12.0.202106070339-r
|
||||
|
||||
ANDROIDX_ACTIVITY_VERSION=1.3.1
|
||||
ANDROIDX_ANNOTATION_VERSION=1.2.0
|
||||
|
|
|
@ -121,6 +121,7 @@ rootProject.name = "zcash-android-app"
|
|||
includeBuild("build-conventions")
|
||||
|
||||
include("app")
|
||||
include("build-info-lib")
|
||||
include("preference-api-lib")
|
||||
include("preference-impl-android-lib")
|
||||
include("test-lib")
|
||||
|
|
Loading…
Reference in New Issue