Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions apps/flipcash/app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,14 @@ val bugsnagBuildId: String = providers.exec {
commandLine("git", "rev-parse", "HEAD")
}.standardOutput.asText.get().trim()

// Tracked changes only: CI writes google-services.json, local.properties and the signing key
// into the checkout, all gitignored, so a release build still reads as clean. Reading just the
// exit code keeps the configuration cache from invalidating on every edit to a dirty tree.
val gitTreeDirty: Boolean = providers.exec {
commandLine("git", "diff", "--quiet", "HEAD")
isIgnoreExitValue = true
}.result.get().exitValue != 0

val contributorsSigningConfig = ContributorsSignatory(rootDir)
val appNamespace = "${Gradle.flipcashNamespace}.app.android"

Expand All @@ -61,6 +69,8 @@ android {
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"

buildConfigField("String", "VERSION_NAME", "\"${Packaging.Flipcash.versionName}\"")
buildConfigField("String", "GIT_SHA", "\"$bugsnagBuildId\"")
buildConfigField("Boolean", "GIT_DIRTY", "$gitTreeDirty")
buildConfigField("String", "MIXPANEL_API_KEY", "\"${tryReadProperty(rootProject.rootDir, "MIXPANEL_API_KEY")}\"")
buildConfigField("Boolean", "NOTIFY_ERRORS", "false")

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,9 @@ object AppModule {
@Singleton
fun providesAppVersion(): VersionInfo = VersionInfo(
versionName = BuildConfig.VERSION_NAME,
versionCode = BuildConfig.VERSION_CODE
versionCode = BuildConfig.VERSION_CODE,
commitSha = BuildConfig.GIT_SHA,
isDirty = BuildConfig.GIT_DIRTY,
)

@Provides
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,24 @@ import javax.inject.Inject
class VersionInfo @Inject constructor(
val versionName: String = "",
val versionCode: Int = 0,
)
/** The full commit SHA the build was made from; empty when the build carries none. */
val commitSha: String = "",
/** Whether the build was made with uncommitted changes to tracked files. */
val isDirty: Boolean = false,
) {
/**
* The commit as the version footer shows it: the first [COMMIT_LABEL_LENGTH] characters of
* [commitSha], with `*` appended for a build with uncommitted changes. Null when the
* build carries no commit. The iOS footer uses the same format.
*/
val commitLabel: String?
get() {
if (commitSha.isBlank()) return null
val short = commitSha.trim().take(COMMIT_LABEL_LENGTH)
return if (isDirty) "$short*" else short
}

companion object {
const val COMMIT_LABEL_LENGTH = 10
}
}
4 changes: 3 additions & 1 deletion apps/flipcash/core/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,9 @@

<string name="error_description_failedToCollect">Something went wrong. The cash could not be collected</string>

<string name="subtitle_appVersionInfoFooter">Version %1$s • Build %2$s%3$s</string>
<string name="subtitle_appVersionInfoFooter">Version %1$s • Build %2$s\n%3$s%4$s</string>
<!-- A build that carries no commit SHA; see VersionInfo.commitLabel. -->
<string name="subtitle_appVersionInfoFooterNoCommit">Version %1$s • Build %2$s%3$s</string>

<string name="title_labsAreEmpty">No Beta Features</string>
<string name="subtitle_labsAreEmpty">There are no beta features available right now.</string>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
package com.flipcash.app.core.android

import kotlin.test.Test
import kotlin.test.assertEquals
import kotlin.test.assertNull

class VersionInfoTest {

private val sha = "2acfecffeb1c1e7b8d64b0e3c6b7a1f2d9e0c4a5"

@Test
fun `the label is the first ten characters of the SHA`() {
assertEquals("2acfecffeb", VersionInfo(commitSha = sha).commitLabel)
}

@Test
fun `a dirty build appends an asterisk`() {
assertEquals("2acfecffeb*", VersionInfo(commitSha = sha, isDirty = true).commitLabel)
}

@Test
fun `a SHA shorter than ten characters is shown whole`() {
assertEquals("2acfecf", VersionInfo(commitSha = "2acfecf").commitLabel)
}

@Test
fun `surrounding whitespace is not counted toward the ten characters`() {
assertEquals("2acfecffeb", VersionInfo(commitSha = " $sha\n").commitLabel)
}

@Test
fun `an empty SHA has no label`() {
assertNull(VersionInfo().commitLabel)
}

@Test
fun `a blank SHA has no label, even when dirty`() {
assertNull(VersionInfo(commitSha = " ", isDirty = true).commitLabel)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -930,7 +930,10 @@ private fun ShareTile(
}
}

/** The "Version … • Build …" footer; its repeated tap toggles beta access (see the ViewModel). */
/**
* The two-line version footer, "Version … • Build …" over "<commit> • <track>". Its repeated tap
* toggles beta access (see the ViewModel).
*/
@Composable
private fun VersionFooter(
viewModel: MenuScreenViewModel,
Expand All @@ -946,8 +949,16 @@ private fun VersionFooter(
.noRippleClickable(enabled = enabled) {
viewModel.dispatchEvent(Event.OnVersionInfoClicked)
},
text = stringResource(
R.string.subtitle_appVersionInfoFooter,
text = state.appVersionInfo.commitLabel?.let { commit ->
stringResource(
R.string.subtitle_appVersionInfoFooter,
state.appVersionInfo.versionName,
state.appVersionInfo.versionCode,
commit,
state.releaseTrack,
)
} ?: stringResource(
R.string.subtitle_appVersionInfoFooterNoCommit,
state.appVersionInfo.versionName,
state.appVersionInfo.versionCode,
state.releaseTrack,
Expand Down
Loading