From 66b1a862cc5ec07de02d0274a2f73a90c494ffbd Mon Sep 17 00:00:00 2001 From: charlie mangano Date: Mon, 11 Nov 2024 09:30:36 +0100 Subject: [PATCH 1/7] feat: add Secrets Gradle plugin dependencies Added the [Secrets Gradle plugin](https://github.com/google/secrets-gradle-plugin) to the project. This plugin securely provides our secrets to our project, including during CI build. --- app/build.gradle.kts | 10 ++++------ build.gradle.kts | 12 +++++++----- gradle/libs.versions.toml | 2 ++ 3 files changed, 13 insertions(+), 11 deletions(-) diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 927aacf6c..c64a6c486 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -1,18 +1,16 @@ -import java.io.FileInputStream -import java.util.Properties - plugins { // supabase setup kotlin("plugin.serialization") version "2.0.0-RC1" - - alias(libs.plugins.androidApplication) alias(libs.plugins.jetbrainsKotlinAndroid) alias(libs.plugins.ktfmt) // alias(libs.plugins.sonar) alias(libs.plugins.compose.compiler) - id("jacoco") + id("com.android.application") + id("kotlin-android") + id("jacoco") id("org.sonarqube") version "5.1.0.4882" + id("com.google.android.libraries.mapsplatform.secrets-gradle-plugin") } android { diff --git a/build.gradle.kts b/build.gradle.kts index 2aa71de65..1462cebba 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -1,8 +1,10 @@ // Top-level build file where you can add configuration options common to all sub-projects/modules. plugins { - alias(libs.plugins.androidApplication) apply false - alias(libs.plugins.jetbrainsKotlinAndroid) apply false - alias(libs.plugins.ktfmt) apply false - kotlin("plugin.serialization") version "2.0.0-RC1" apply false - alias(libs.plugins.compose.compiler) apply false + alias(libs.plugins.androidApplication) apply false + alias(libs.plugins.jetbrainsKotlinAndroid) apply false + alias(libs.plugins.ktfmt) apply false + kotlin("plugin.serialization") version "2.0.0-RC1" apply false + alias(libs.plugins.compose.compiler) apply false } + +buildscript { dependencies { classpath(libs.secrets.gradle.plugin) } } diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 1bc07b910..7a60ec553 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -24,6 +24,7 @@ mockkVersion = "1.12.0" mockitoMockitoCore = "5.4.0" navigationComposeVersion = "2.8.2" runner = "1.6.2" +secretsGradlePlugin = "2.0.1" ui = "1.6.8" uiTestJunit4 = "1.6.8" uiTestJunit4Version = "1.0.5" @@ -131,6 +132,7 @@ mockk-android = { module = "io.mockk:mockk-android", version.ref = "mockkAndroid mockk-v1120 = { module = "io.mockk:mockk", version.ref = "mockkVersion" } okhttp = { module = "com.squareup.okhttp3:okhttp", version.ref = "okhttp" } robolectric = { module = "org.robolectric:robolectric", version.ref = "robolectric" } +secrets-gradle-plugin = { module = "com.google.android.libraries.mapsplatform.secrets-gradle-plugin:secrets-gradle-plugin", version.ref = "secretsGradlePlugin" } test-core-ktx = { group = "androidx.test", name = "core-ktx", version.ref = "androidxCoreKtx" } androidx-junit-ktx = { group = "androidx.test.ext", name = "junit-ktx", version.ref = "junitKtx" } androidx-ui-test-junit4-android = { group = "androidx.compose.ui", name = "ui-test-junit4-android", version.ref = "uiTestJunit4Android" } From 0bbb4c46b5dc496e265d484287bac1aedd2c787f Mon Sep 17 00:00:00 2001 From: charlie mangano Date: Mon, 11 Nov 2024 09:32:32 +0100 Subject: [PATCH 2/7] chore: update `.gitignore` to include `secrets.properties` This file is stored locally on everyone's computer and contains our API keys and client URLs and should never be checked to VCS --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index a636c5981..1dea50d91 100644 --- a/.gitignore +++ b/.gitignore @@ -2,6 +2,7 @@ .DS_Store .gradle /local.properties +/secrets.properties /build /captures .externalNativeBuild From 3d75fadb30a2d213dadcf3eaf89cea66300aaec6 Mon Sep 17 00:00:00 2001 From: charlie mangano Date: Mon, 11 Nov 2024 09:35:59 +0100 Subject: [PATCH 3/7] build: initialise plugin in `build.gradle.kts` (app) with proper values The `secrets.default.properties` provides a template for `secrets.properties` for the CI pipeline. The plugin will fill it with our secrets during build. --- app/build.gradle.kts | 5 +++++ secrets.defaults.properties | 7 +++++++ 2 files changed, 12 insertions(+) create mode 100644 secrets.defaults.properties diff --git a/app/build.gradle.kts b/app/build.gradle.kts index c64a6c486..5015e306b 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -244,6 +244,11 @@ dependencies { implementation("androidx.compose.material3:material3-window-size-class:1.3.0") } +secrets { + propertiesFileName = "secrets.properties" + defaultPropertiesFileName = "secrets.defaults.properties" +} + tasks.withType { // Configure Jacoco for each tests configure { diff --git a/secrets.defaults.properties b/secrets.defaults.properties new file mode 100644 index 000000000..0ffa5733a --- /dev/null +++ b/secrets.defaults.properties @@ -0,0 +1,7 @@ +# This file serves as a template for the secrets.properties file. +# It should be checked into Version Control Systems to provide a structure for the required API keys and client URLs. +# The actual values should be filled in by the CI pipeline using the Secrets Gradle plugin and GitHub Secrets. +POWERSYNC_URL=SAFE_DEFAULT_VALUE_POWERSYNC_URL +SUPABASE_KEY=SAFE_DEFAULT_VALUE_SUPABASE_KEY +SERVICE_KEY=SAFE_DEFAULT_VALUE_SERVICE_KEY +SUPABASE_URL=SAFE_DEFAULT_VALUE_SUPABASE_URL From 83997004bc12334d86723c4342ac109ca190b60f Mon Sep 17 00:00:00 2001 From: charlie mangano Date: Mon, 11 Nov 2024 09:37:59 +0100 Subject: [PATCH 4/7] build: remove redundant creation of `BuildConfig` fields for our secrets This is now handled by the plugin. --- app/build.gradle.kts | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 5015e306b..6f7952ec9 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -17,15 +17,6 @@ android { namespace = "com.android.periodpals" compileSdk = 34 - // Load the API key from local.properties - val localProperties = Properties() - val localPropertiesFile = rootProject.file("local.properties") - if (localPropertiesFile.exists()) { - localProperties.load(FileInputStream(localPropertiesFile)) - } - val supabaseUrl = localProperties.getProperty("SUPABASE_URL") - val supabaseKey = localProperties.getProperty("SUPABASE_KEY") - defaultConfig { applicationId = "com.android.periodpals" minSdk = 28 @@ -35,9 +26,6 @@ android { testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" vectorDrawables { useSupportLibrary = true } - - buildConfigField("String", "SUPABASE_URL", "\"${supabaseUrl}\"") - buildConfigField("String", "SUPABASE_KEY", "\"${supabaseKey}\"") } buildFeatures { buildConfig = true } From 9ed1804e00be64f8dbbfd68c4a8cc8caaa9fe612 Mon Sep 17 00:00:00 2001 From: charlie mangano Date: Mon, 11 Nov 2024 09:47:19 +0100 Subject: [PATCH 5/7] ci: add `secret.properties` setup to handle secrets in `AndroidBuild` workflow This fetches the secrets from GitHub Secrets and pastes them into the template file `secrets.defaults.properties`. This file is then copied over to a `secrets.properties` created in the CI. This ensures proper and secure secrets handling. --- .github/workflows/AndroidBuild.yml | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/.github/workflows/AndroidBuild.yml b/.github/workflows/AndroidBuild.yml index e85869c64..afa2f6576 100644 --- a/.github/workflows/AndroidBuild.yml +++ b/.github/workflows/AndroidBuild.yml @@ -23,6 +23,19 @@ jobs: run: | chmod +x ./gradlew + - name: Setup secrets.properties + env: + SUPABASE_KEY: ${{ secrets.SUPABASE_KEY }} + SERVICE_KEY: ${{ secrets.SERVICE_KEY }} + SUPABASE_URL: ${{ secrets.SUPABASE_URL }} + POWERSYNC_URL: ${{ secrets.POWERSYNC_URL }} + run: | + sed -e "s|SAFE_DEFAULT_VALUE_SERVICE_KEY|$SERVICE_KEY|g;" \ + -e "s|SAFE_DEFAULT_VALUE_SUPABASE_KEY|$SUPABASE_KEY|g;" \ + -e "s|SAFE_DEFAULT_VALUE_SUPABASE_URL|$SUPABASE_URL|g;" \ + -e "s|SAFE_DEFAULT_VALUE_POWERSYNC_URL|$POWERSYNC_URL|g;" \ + + - name: Build with Gradle run: ./gradlew build From 126ee654dc39e99c94e291b2e164c9cd8189b3a9 Mon Sep 17 00:00:00 2001 From: charlie mangano Date: Mon, 11 Nov 2024 10:27:53 +0100 Subject: [PATCH 6/7] fix: correctly pipe secrets in `sed` --- .github/workflows/AndroidBuild.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/AndroidBuild.yml b/.github/workflows/AndroidBuild.yml index afa2f6576..62fc6665e 100644 --- a/.github/workflows/AndroidBuild.yml +++ b/.github/workflows/AndroidBuild.yml @@ -33,7 +33,7 @@ jobs: sed -e "s|SAFE_DEFAULT_VALUE_SERVICE_KEY|$SERVICE_KEY|g;" \ -e "s|SAFE_DEFAULT_VALUE_SUPABASE_KEY|$SUPABASE_KEY|g;" \ -e "s|SAFE_DEFAULT_VALUE_SUPABASE_URL|$SUPABASE_URL|g;" \ - -e "s|SAFE_DEFAULT_VALUE_POWERSYNC_URL|$POWERSYNC_URL|g;" \ + -e "s|SAFE_DEFAULT_VALUE_POWERSYNC_URL|$POWERSYNC_URL|g;" secrets.defaults.properties > secrets.properties - name: Build with Gradle From 516b1b2bac98d85d2db1d6fae5c856f673ef39e1 Mon Sep 17 00:00:00 2001 From: charlie mangano Date: Mon, 11 Nov 2024 11:47:44 +0100 Subject: [PATCH 7/7] ci: add secret.properties setup to handle secrets in `ci` workflow This fetches the secrets from GitHub Secrets and pastes them into the template file `secrets.defaults.properties`. This file is then copied over to a `secrets.properties` created in the CI. This ensures proper and secure secrets handling. --- .github/workflows/ci.yml | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 4f34d8ee2..d2c8d5d16 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -87,6 +87,19 @@ jobs: run: | chmod +x ./gradlew + - name: Setup secrets.properties + env: + SUPABASE_KEY: ${{ secrets.SUPABASE_KEY }} + SERVICE_KEY: ${{ secrets.SERVICE_KEY }} + SUPABASE_URL: ${{ secrets.SUPABASE_URL }} + POWERSYNC_URL: ${{ secrets.POWERSYNC_URL }} + run: | + sed -e "s|SAFE_DEFAULT_VALUE_SERVICE_KEY|$SERVICE_KEY|g;" \ + -e "s|SAFE_DEFAULT_VALUE_SUPABASE_KEY|$SUPABASE_KEY|g;" \ + -e "s|SAFE_DEFAULT_VALUE_SUPABASE_URL|$SUPABASE_URL|g;" \ + -e "s|SAFE_DEFAULT_VALUE_POWERSYNC_URL|$POWERSYNC_URL|g;" secrets.defaults.properties > secrets.properties + + # Check formatting - name: KTFmt Check run: |