Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Configure release signing for conference app #1124

Merged
merged 25 commits into from
Aug 28, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
6fdd581
Configure release signing for conference app
ashdavies Aug 18, 2024
2cfb104
Adjust string properties for better call site usage
ashdavies Aug 18, 2024
c8ec19e
Create new workflow
ashdavies Aug 24, 2024
8e7ab06
Use nullable signing configuration
ashdavies Aug 24, 2024
0fc2e1d
Migrate Google Services json to 1Password
ashdavies Aug 24, 2024
2b53d7f
Bump version of 1Password secrets
ashdavies Aug 24, 2024
e0117b5
Debug key storage with hello world
ashdavies Aug 24, 2024
7aa7f8f
Is this case sensitive?
ashdavies Aug 24, 2024
4fdbcfc
CLI is not case sensitive
ashdavies Aug 24, 2024
eaf4502
Adjust vault structure for simpler naming
ashdavies Aug 24, 2024
88ee94b
Move hello world to release workflow
ashdavies Aug 24, 2024
9b05a67
Quotes maybe?
ashdavies Aug 24, 2024
921c8ff
Merge branch 'main' into feature/release-signing
ashdavies Aug 26, 2024
360164f
Remove hello world
ashdavies Aug 26, 2024
e38ab02
Default application credentials required
ashdavies Aug 26, 2024
e181bfe
Include token permissions
ashdavies Aug 26, 2024
5485273
Use step outputs
ashdavies Aug 26, 2024
3e7a64e
Create boolean property with tag function
ashdavies Aug 26, 2024
8470abf
Include proguard rules for slf4j
ashdavies Aug 26, 2024
4545d7b
Archive APK artifact
ashdavies Aug 27, 2024
dcbe44f
Merge branch 'main' into feature/release-signing
ashdavies Aug 27, 2024
ce2e11b
Init release from debug
ashdavies Aug 28, 2024
053dd0a
Merge branch 'main' into feature/release-signing
ashdavies Aug 28, 2024
3e7ddf1
Adjust upload artifact path wildcard
ashdavies Aug 28, 2024
5ddd5ae
Android release on merge
ashdavies Aug 28, 2024
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
86 changes: 86 additions & 0 deletions .github/workflows/android-release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
name: Android Release

on:
push:
branches:
- main

workflow_dispatch:
inputs:
log_level:
type: choice
description: Log Level
required: false
default: info
options:
- error
- quiet
- warning
- lifecycle
- info
- debug

concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number }}
cancel-in-progress: true

jobs:
build:
name: Assemble Release
runs-on: ubuntu-latest

permissions:
pull-requests: 'write'
id-token: 'write'

steps:
- uses: actions/checkout@v3

- uses: ./.github/actions/setup-cloud
with:
workload_identity_provider: ${{ secrets.GOOGLE_WORKLOAD_IDENTITY }}
service_account: ${{ secrets.GOOGLE_SERVICE_ACCOUNT_ID }}
setup_gcloud: false

- uses: ./.github/actions/setup-gradle

- uses: 1password/load-secrets-action/configure@v2
with:
service-account-token: ${{ secrets.OP_SERVICE_ACCOUNT_TOKEN }}

- id: op-secrets
uses: 1password/load-secrets-action@v2
with:
export-env: false
env:
GOOGLE_SERVICES: op://development/google services/playground release/base64
KEYSTORE_BASE64: op://development/playground keystore/keystore base64
KEYSTORE_PASSWORD: op://development/playground keystore/keystore password
KEY_ALIAS: op://development/playground keystore/key alias
KEY_PASSWORD: op://development/playground keystore/key password

- env:
GOOGLE_SERVICES: ${{ steps.op-secrets.outputs.GOOGLE_SERVICES }}
KEYSTORE_BASE64: ${{ steps.op-secrets.outputs.KEYSTORE_BASE64 }}
run: |
echo $GOOGLE_SERVICES | base64 --decode > app-launcher/android/google-services.json
echo $GOOGLE_SERVICES | base64 --decode > conferences-app/google-services.json
echo $KEYSTORE_BASE64 | base64 --decode > keystore.jks

- id: gradle
env:
ANDROID_API_KEY: ${{ secrets.ANDROID_API_KEY }}
BROWSER_API_KEY: ${{ secrets.BROWSER_API_KEY }}
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
KEY_STORE_FILE: keystore.jks
KEY_STORE_PASSWORD: ${{ steps.op-secrets.outputs.KEYSTORE_PASSWORD }}
RELEASE_KEY_ALIAS: ${{ steps.op-secrets.outputs.KEY_ALIAS }}
RELEASE_KEY_PASSWORD: ${{ steps.op-secrets.outputs.KEY_PASSWORD }}
SERVER_CLIENT_ID: ${{ secrets.SERVER_CLIENT_ID }}
run: ./gradlew assembleRelease --console=plain

- uses: actions/upload-artifact@v2
with:
if-no-files-found: error
name: apk-release
path: "**/*-release.apk"
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
name: Pre Merge Checks
name: Pull Request
on: [ pull_request ]

concurrency:
Expand All @@ -7,7 +7,7 @@ concurrency:

jobs:
build:
name: Pre Merge Checks
name: Build
runs-on: ubuntu-latest

permissions:
Expand All @@ -17,8 +17,7 @@ jobs:
steps:
- uses: actions/checkout@v3

- id: setup-cloud
uses: ./.github/actions/setup-cloud
- uses: ./.github/actions/setup-cloud
with:
workload_identity_provider: ${{ secrets.GOOGLE_WORKLOAD_IDENTITY }}
service_account: ${{ secrets.GOOGLE_SERVICE_ACCOUNT_ID }}
Expand Down
11 changes: 8 additions & 3 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,10 @@
/.idea

# Android
/gradle.properties
**/local.properties
/captures
*.hprof
*.apk
*.ap_

# Database
*.db
Expand All @@ -22,9 +22,14 @@
**/*.log

# Gradle
/gradle.properties
**/local.properties
.gradle
build
/reports

# Keystore Files
*.jks
*.keystore

# Kotlin
.kotlin/sessions
Expand Down
Binary file removed app-launcher/android/google-services.aes
Binary file not shown.
1 change: 0 additions & 1 deletion asg-service/src/.gitignore

This file was deleted.

51 changes: 44 additions & 7 deletions conferences-app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,48 @@ android {
res.srcDirs("src/androidMain/res")
}

val release by signingConfigs.creating {
val debug by signingConfigs.getting
initWith(debug)

enableV3Signing = true
enableV4Signing = true

val keyStoreFile by stringPropertyOrNull {
if (it != null) storeFile = rootProject.file(it)
}

val keyStorePassword by stringPropertyOrNull {
if (it != null) storePassword = it
}

val releaseKeyAlias by stringPropertyOrNull {
if (it != null) keyAlias = it
}

val releaseKeyPassword by stringPropertyOrNull {
if (it != null) keyPassword = it
}
}

buildTypes {
debug {
applicationIdSuffix = ".debug"
}

release {
isMinifyEnabled = true
isShrinkResources = true

signingConfig = release

proguardFiles(
getDefaultProguardFile("proguard-android-optimize.txt"),
"proguard-rules.pro",
)
}
}

defaultConfig {
versionName = "1.0"
versionCode = 1
Expand All @@ -26,13 +68,8 @@ android {
}

buildConfig {
val androidApiKey by stringProperty { value ->
buildConfigField("ANDROID_API_KEY", value)
}

val androidStrictMode by booleanProperty { value ->
buildConfigField("ANDROID_STRICT_MODE", value)
}
val androidApiKey by stringPropertyWithTag(::buildConfigField)
val androidStrictMode by booleanPropertyWithTag(::buildConfigField)

packageName.set(android.namespace)
}
Expand Down
Binary file removed conferences-app/google-services.aes
Binary file not shown.
1 change: 1 addition & 0 deletions conferences-app/proguard-rules.pro
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
-dontwarn org.slf4j.impl.StaticLoggerBinder
Original file line number Diff line number Diff line change
Expand Up @@ -46,13 +46,13 @@ internal class MainActivity : ComponentActivity() {
}

setContent {
LauncherApp { intent.getStringExtra(it) }
LauncherApp()
}
}
}

@Composable
private fun LauncherApp(context: Context = LocalContext.current, extra: (String) -> String?) {
private fun LauncherApp(context: Context = LocalContext.current) {
ProvideHttpClient(
config = {
install(DefaultRequest) {
Expand Down
57 changes: 39 additions & 18 deletions fused-properties/src/main/kotlin/StringProperty.kt
Original file line number Diff line number Diff line change
Expand Up @@ -6,39 +6,60 @@ import kotlin.properties.ReadOnlyProperty

public fun interface ReadOnlyDelegateProvider<T> : PropertyDelegateProvider<Any?, ReadOnlyProperty<Any?, T>>

private fun Project.stringPropertyProvider(propertyName: String): Provider<String> {
private interface PropertyDefinition {
val gradlePropertyName: String
val envPropertyName: String
}

private fun PropertyDefinition(propertyName: String) = object : PropertyDefinition {
private val propertyNameParts = propertyName.split(Regex("(?=[A-Z])"))
override val gradlePropertyName = propertyNameParts.joinToString(".") { it.lowercase() }
override val envPropertyName = propertyNameParts.joinToString("_") { it.uppercase() }
}

private fun Project.stringPropertyProvider(definition: PropertyDefinition): Provider<String> {
val rootPropertiesProvider = rootProject.cachedLocalPropertiesProvider()
val localPropertiesProvider = cachedLocalPropertiesProvider()
val startPropertiesProvider = startParameterProvider()

val propertyNameParts = propertyName.split(Regex("(?=[A-Z])"))
val gradlePropertyName = propertyNameParts.joinToString(".") { it.lowercase() }
val envPropertyName = propertyNameParts.joinToString("_") { it.uppercase() }

return startPropertiesProvider.mapOrNull { it[gradlePropertyName] }
.orElse(localPropertiesProvider.map { it.getProperty(gradlePropertyName) })
.orElse(rootPropertiesProvider.map { it.getProperty(gradlePropertyName) })
.orElse(providers.gradleProperty(gradlePropertyName))
.orElse(providers.environmentVariable(envPropertyName))
return startPropertiesProvider.mapOrNull { it[definition.gradlePropertyName] }
.orElse(localPropertiesProvider.map { it.getProperty(definition.gradlePropertyName) })
.orElse(rootPropertiesProvider.map { it.getProperty(definition.gradlePropertyName) })
.orElse(providers.gradleProperty(definition.gradlePropertyName))
.orElse(providers.environmentVariable(definition.envPropertyName))
}

public fun Project.booleanProperty(block: (Boolean) -> Unit = { }): ReadOnlyDelegateProvider<Boolean> {
return readOnlyDelegateProvider { it.get().toBoolean().also(block) }
return readOnlyDelegateProvider { provider, _ -> provider.get().toBoolean().also(block) }
}

public fun Project.booleanPropertyWithTag(action: (String, Boolean) -> Unit): ReadOnlyDelegateProvider<Boolean> {
return readOnlyDelegateProvider { provider, tag -> provider.get().toBoolean().also { action(tag, it) } }
}

public fun Project.stringProperty(block: (String) -> Unit = { }): ReadOnlyDelegateProvider<String> {
return readOnlyDelegateProvider { it.get().also(block) }
return readOnlyDelegateProvider { provider, _ -> provider.get().also(block) }
}

public fun Project.stringPropertyWithTag(action: (String, String) -> Unit): ReadOnlyDelegateProvider<String> {
return readOnlyDelegateProvider { provider, tag -> provider.get().also { action(tag, it) } }
}

public fun Project.stringPropertyOrNull(block: (String?) -> Unit = { }): ReadOnlyDelegateProvider<String?> {
return readOnlyDelegateProvider { it.orNull.also(block) }
return readOnlyDelegateProvider { provider, _ -> provider.orNull.also(block) }
}

private fun <T> Project.readOnlyDelegateProvider(transform: (Provider<String>) -> T): ReadOnlyDelegateProvider<T> {
return ReadOnlyDelegateProvider { _, property ->
val value = transform(stringPropertyProvider(property.name))
ReadOnlyProperty { _, _ -> value }
}
private fun <T> Project.readOnlyDelegateProvider(
transform: (provider: Provider<String>, tag: String) -> T,
): ReadOnlyDelegateProvider<T> = ReadOnlyDelegateProvider { _, property ->
val definition = PropertyDefinition(property.name)

val value = transform(
stringPropertyProvider(definition),
definition.envPropertyName,
)

ReadOnlyProperty { _, _ -> value }
}

private fun <S : Any, T> Provider<S>.mapOrNull(block: (S) -> T?): Provider<T> {
Expand Down
Empty file added keystore.properties
Empty file.
Loading