From 208a7d96421c5fa3c84f4b4be669fdbb4d240b3f Mon Sep 17 00:00:00 2001 From: Ali Kabiri Date: Thu, 2 Mar 2023 08:48:36 +0100 Subject: [PATCH 01/37] apply sonar gradle plugin Signed-off-by: Ali Kabiri --- app/build.gradle.kts | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 23b09bd3..dbc6dd0e 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -9,6 +9,7 @@ plugins { id("kotlin-kapt") id("dagger.hilt.android.plugin") id("jacoco") + id ("org.sonarqube") version "3.5.0.2730" } repositories { @@ -103,6 +104,14 @@ tasks.register("jacocoTestReport") { ))}) } +sonarqube { + properties { + property("sonar.projectKey", System.getenv("SONAR_PROJECT_KEY")) + property("sonar.organization", System.getenv("SONAR_ORGANIZATION")) + property("sonar.host.url", System.getenv("SONAR_HOST_URL")) + } +} + fun loadKeyStore(ksProp: Properties) { val ksPropFile = file("keystore.properties") if (ksPropFile.exists()) { From 2af25c11a72b1395dfbf597a33dfac72b2822e9a Mon Sep 17 00:00:00 2001 From: Ali Kabiri Date: Thu, 2 Mar 2023 08:55:35 +0100 Subject: [PATCH 02/37] set usesCleartextTraffic to false Signed-off-by: Ali Kabiri --- app/src/main/AndroidManifest.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index c87c749d..521743c2 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -8,6 +8,7 @@ Date: Thu, 2 Mar 2023 09:02:25 +0100 Subject: [PATCH 03/37] add a CircleCI step to analyze on SonarCloud Signed-off-by: Ali Kabiri --- .circleci/config.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.circleci/config.yml b/.circleci/config.yml index aca01a1e..8503a425 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -41,6 +41,9 @@ jobs: - run: ./gradlew pixel2api30DebugAndroidTest --stacktrace - run: ./gradlew testDebugUnitTest --stacktrace - run: ./gradlew jacocoTestReport --stacktrace + - run: + name: Analyze on SonarCloud + command: ./gradlew assembleDebug lint sonar - codecov/upload: file: app/build/mergedReportDir/jacocoTestReport/jacocoTestReport.xml - store_test_results: From 7b0d13c19a00c6f96adc8f00b31fcda1ca6c309a Mon Sep 17 00:00:00 2001 From: Ali Kabiri Date: Thu, 2 Mar 2023 09:16:19 +0100 Subject: [PATCH 04/37] apply SonarCloud context to build Signed-off-by: Ali Kabiri --- .circleci/config.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 8503a425..cf0cac16 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -54,4 +54,5 @@ jobs: workflows: workflow: jobs: - - android-test + - android-test: + context: SonarCloud From 9484f1a006e9b281892da1b7191f2a42a91a769f Mon Sep 17 00:00:00 2001 From: Ali Kabiri Date: Thu, 2 Mar 2023 09:27:22 +0100 Subject: [PATCH 05/37] use lintDebug instead of lint Signed-off-by: Ali Kabiri --- .circleci/config.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index cf0cac16..966735b4 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -43,7 +43,7 @@ jobs: - run: ./gradlew jacocoTestReport --stacktrace - run: name: Analyze on SonarCloud - command: ./gradlew assembleDebug lint sonar + command: ./gradlew assembleDebug lintDebug sonar - codecov/upload: file: app/build/mergedReportDir/jacocoTestReport/jacocoTestReport.xml - store_test_results: From 9da237367542da94ab3c82e464d0dae9c8e5db0a Mon Sep 17 00:00:00 2001 From: Ali Kabiri Date: Thu, 9 Mar 2023 16:58:53 +0100 Subject: [PATCH 06/37] Update config.yml --- .circleci/config.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 966735b4..904da6a1 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -43,7 +43,7 @@ jobs: - run: ./gradlew jacocoTestReport --stacktrace - run: name: Analyze on SonarCloud - command: ./gradlew assembleDebug lintDebug sonar + command: ./gradlew lintDebug sonar - codecov/upload: file: app/build/mergedReportDir/jacocoTestReport/jacocoTestReport.xml - store_test_results: From 8bc7e1c2432b5d8938a4b6c4982d85d7f2987f24 Mon Sep 17 00:00:00 2001 From: Ali Kabiri Date: Thu, 9 Mar 2023 16:59:11 +0100 Subject: [PATCH 07/37] cleanup; no changes --- app/build.gradle.kts | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/app/build.gradle.kts b/app/build.gradle.kts index dbc6dd0e..075e4633 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -9,14 +9,13 @@ plugins { id("kotlin-kapt") id("dagger.hilt.android.plugin") id("jacoco") - id ("org.sonarqube") version "3.5.0.2730" } repositories { } android { - compileSdkVersion(33) + compileSdk = 33 compileOptions { sourceCompatibility = JavaVersion.VERSION_1_8 @@ -25,8 +24,8 @@ android { defaultConfig { applicationId = "org.kabiri.android.usbterminal" - minSdkVersion(23) - targetSdkVersion(33) + minSdk = 23 + targetSdk = 33 versionCode = 13 versionName = "0.9.12" testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" @@ -125,7 +124,6 @@ val firebase_bom_version: String by project val hilt_version: String by project dependencies { -// implementation fileTree("libs") { include(setOf("*.jar")) } implementation("androidx.appcompat:appcompat:1.6.0") implementation("androidx.core:core-ktx:1.9.0") implementation("androidx.constraintlayout:constraintlayout:2.1.4") From e22c184726728abf2a9744678697db34ad3e5c4c Mon Sep 17 00:00:00 2001 From: Ali Kabiri Date: Thu, 9 Mar 2023 17:00:07 +0100 Subject: [PATCH 08/37] update structure; add sonarqube config --- build.gradle | 34 ++++++++++++++++------------------ settings.gradle | 17 ++++++++++++++++- 2 files changed, 32 insertions(+), 19 deletions(-) diff --git a/build.gradle b/build.gradle index 2e395f32..4b609460 100644 --- a/build.gradle +++ b/build.gradle @@ -1,5 +1,3 @@ -// Top-level build file where you can add configuration options common to all sub-projects/modules. - buildscript { ext { kotlin_version = '1.7.10' @@ -7,29 +5,29 @@ buildscript { firebase_bom_version = '30.5.0' jacoco_version = '0.8.8' } - repositories { - google() - mavenCentral() - } dependencies { - classpath 'com.android.tools.build:gradle:7.4.1' - classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" classpath "com.google.dagger:hilt-android-gradle-plugin:$hilt_version" - classpath 'com.google.gms:google-services:4.3.14' - classpath 'com.google.firebase:firebase-crashlytics-gradle:2.9.2' - // NOTE: Do not place your application dependencies here; they belong - // in the individual module build.gradle files + classpath "com.google.gms:google-services:4.3.15" + classpath "com.google.firebase:firebase-crashlytics-gradle:2.9.4" } } -allprojects { - repositories { - google() - mavenCentral() - maven { url "https://jitpack.io" } - } +plugins { + id("com.android.application") version "7.4.2" apply false + id("org.jetbrains.kotlin.android") version "1.7.0" apply false + id("org.sonarqube") version "3.5.0.2730" } task clean(type: Delete) { delete rootProject.buildDir } + +sonarqube { + properties { + property "sonar.organization", "superus8r" + property "sonar.projectKey", "superus8r_arduino-usb-terminal" + property "sonar.projectName", "arduino-usb-terminal" + property "sonar.sourceEncoding", "UTF-8" + property "sonar.host.url", "https://sonarcloud.io" + } +} \ No newline at end of file diff --git a/settings.gradle b/settings.gradle index 8a5a18d2..19a3c784 100644 --- a/settings.gradle +++ b/settings.gradle @@ -1,2 +1,17 @@ +pluginManagement { + repositories { + google() + mavenCentral() + gradlePluginPortal() + } +} +dependencyResolutionManagement { + repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS) + repositories { + google() + mavenCentral() + maven { url "https://jitpack.io" } + } +} rootProject.name='USBTerminal' -include ':app' +include ':app' \ No newline at end of file From ef84962254c94167aff53ac67d6373795f849aaa Mon Sep 17 00:00:00 2001 From: Ali Kabiri Date: Thu, 9 Mar 2023 17:16:09 +0100 Subject: [PATCH 09/37] remove extra steps, save gradle cache after generating jacoco reports Signed-off-by: Ali Kabiri --- .circleci/config.yml | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 904da6a1..3999805a 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -27,13 +27,10 @@ jobs: image: android:2022.12.1 resource_class: large steps: - - run: lsb_release -a - checkout - run: python3 scripts/generateKsPropFile.py - run: python3 scripts/generateGoogleServicesJson.py - restore_gradle_cache - - run: ./gradlew tasks - - save_gradle_cache - run: sdkmanager --list - run: (yes || true) | sdkmanager "tools" "platform-tools" "build-tools;33.0.2" "platforms;android-33" "system-images;android-30;google_atd;x86" - run: (yes || true) | sdkmanager --licenses @@ -41,6 +38,7 @@ jobs: - run: ./gradlew pixel2api30DebugAndroidTest --stacktrace - run: ./gradlew testDebugUnitTest --stacktrace - run: ./gradlew jacocoTestReport --stacktrace + - save_gradle_cache - run: name: Analyze on SonarCloud command: ./gradlew lintDebug sonar From bef16324c4c2f197f5a7f95300b917196b26b43c Mon Sep 17 00:00:00 2001 From: Ali Kabiri Date: Thu, 9 Mar 2023 18:00:20 +0100 Subject: [PATCH 10/37] add info about testing using gradle managed devices, firebase crashlytics, and overview text Signed-off-by: Ali Kabiri --- README.md | 64 ++++++++++++++++++++++++++++++++++++------------------- 1 file changed, 42 insertions(+), 22 deletions(-) diff --git a/README.md b/README.md index e0102fa7..1fabb76f 100644 --- a/README.md +++ b/README.md @@ -1,15 +1,22 @@ # arduino-usb-terminal - Terminal-like app to send commands to Arduino through USB +Simplify testing your IoT projects by using your Android device to send commands to Arduino through USB. ![Android CI](https://github.com/k4biri/arduino-usb-terminal/workflows/Android%20CI/badge.svg) [![superus8r](https://circleci.com/gh/superus8r/arduino-usb-terminal.svg?style=shield)](https://circleci.com/gh/superus8r/arduino-usb-terminal) [![codecov](https://codecov.io/gh/superus8r/arduino-usb-terminal/branch/develop/graph/badge.svg?token=RYIUU345QG)](https://codecov.io/gh/superus8r/arduino-usb-terminal) +[![Reliability Rating](https://sonarcloud.io/api/project_badges/measure?project=superus8r_arduino-usb-terminal&metric=reliability_rating)](https://sonarcloud.io/summary/new_code?id=superus8r_arduino-usb-terminal) +[![Security Rating](https://sonarcloud.io/api/project_badges/measure?project=superus8r_arduino-usb-terminal&metric=security_rating)](https://sonarcloud.io/summary/new_code?id=superus8r_arduino-usb-terminal) +[![Maintainability Rating](https://sonarcloud.io/api/project_badges/measure?project=superus8r_arduino-usb-terminal&metric=sqale_rating)](https://sonarcloud.io/summary/new_code?id=superus8r_arduino-usb-terminal) + + Ever thought of testing your Arduino project on the go without using a LapTop? + + Sometimes, you just want to send simple commands to an Arduino through USB without getting that 1.4 kilogram laptop out of the bag! 😉 - This app simplifies testing your Arduino components that work with direct usb commands by giving you the ability to send custom commands and view the returned message from your Arduino device. + Especially if the Android phone in your pocket has enough resources to do that! - This is being done as a hobby, and for experimenting, so probably there might be some flaws; As an example, the vendor ID of Arduino is hardcoded to only work with Arduino devices, but this is my use case and please feel free to change it to match your needs. + This is being done as a hobby, and for experimenting, so probably there might be some flaws; As an example, the vendor ID of Arduino is set to only work with Arduino devices, but this is my use case and please feel free to change it to match your needs. Or if you have a great idea to make this dynamic wile keeping the app simple, please feel free to open a pull request! # Build and Run The app is available for free on Google Play Store (Arduino USB Terminal). @@ -17,32 +24,45 @@ Please read the **Sentry Reports** part on this page before running the project to avoid build failures. Get it on Google Play + + + # Tests + You can run all the instrumented tests using a Gradle Managed Device in one line: +``` +./gradlew pixel2api30DebugAndroidTest +``` +This command will run an Android emulator on the background and run all the tests. +After a successful run, the test coverage file will be available in your build folder: +``` +app/build/outputs/managed_device_code_coverage/pixel2api30/coverage.ec +``` +To create a unified coverage report you can use the Jacoco task: +``` +./gradlew jacocoTestReport +// Jacoco HTML and XML output will be under the following path: +app/build/mergedReportDir/jacocoTestReport +``` +More info about Gradle managed devices in official Android testing docs: [Scale your tests with Gradle Managed Devices](https://developer.android.com/studio/test/gradle-managed-devices) + + - ## Terminal - A Simple terminal page which does what it is supposed to do interacting with an Arduino manually through the USB cable. + ## Firebase Crashlytics Reports + The project uses Firebase Crashlytics for the crash reports, therefore you will need to create a free Firebase project to use it. + - Once you create a Firebase project, Firebase will provide you with a config file (`google-services.json`). + - Place your `google-services.json` file under the `app/` directory and build the project to activate it. - ## Joystick - The Joystick is removed for the first release. + More info on [Firebase official docs for getting started with Firebase Crashlytics](https://firebase.google.com/docs/crashlytics/get-started?platform=android) - ## Tests - Currently, there are some basic tests to run on the CI, but needs improvements. - UI tests will be completed once the project is migrated to Jetpack Compose. + If this is not needed, you can remove the crashlytics dependency in project leve and app level build.gradle files. + - remove `classpath "com.google.firebase:firebase-crashlytics-gradle:2.9.4"` from `build.gradle` file + - remove `implementation("com.google.firebase:firebase-crashlytics-ktx")` from `app/build.gradle.kts` file - ## Sentry Reports - The project uses Sentry for the crash reports, if this is not needed, you can remove the following line in `AndroidManifest.xml`: - `` - But if it is needed, you need to [create a Sentry dsn value](https://docs.sentry.io/platforms/android/) to put under the following path: - `app/src/main/res/values/api_keys.xml` - The file contents might look like similar to this: - ` - - YOUR_SENTRY_SPECIFIC_VALUE - ` + ## Knows Issues +- Please feel free inform me about new issues - ### Knows Issues - _Still unknown! :) Suggestions and PRs are welcome! :) +--- ### More comes as the project evolves... \ No newline at end of file From 9b902c11f6bdd3e7ad9e2a147076cd72acfc290a Mon Sep 17 00:00:00 2001 From: Ali Kabiri Date: Thu, 9 Mar 2023 18:05:45 +0100 Subject: [PATCH 11/37] add info about testing using gradle managed devices Signed-off-by: Ali Kabiri --- README.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 1fabb76f..ed445f55 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,7 @@ Simplify testing your IoT projects by using your Android device to send commands [![Security Rating](https://sonarcloud.io/api/project_badges/measure?project=superus8r_arduino-usb-terminal&metric=security_rating)](https://sonarcloud.io/summary/new_code?id=superus8r_arduino-usb-terminal) [![Maintainability Rating](https://sonarcloud.io/api/project_badges/measure?project=superus8r_arduino-usb-terminal&metric=sqale_rating)](https://sonarcloud.io/summary/new_code?id=superus8r_arduino-usb-terminal) - Ever thought of testing your Arduino project on the go without using a LapTop? + Ever thought of testing your Arduino project on the go without using a lap top? Sometimes, you just want to send simple commands to an Arduino through USB without getting that 1.4 kilogram laptop out of the bag! 😉 @@ -42,6 +42,9 @@ To create a unified coverage report you can use the Jacoco task: // Jacoco HTML and XML output will be under the following path: app/build/mergedReportDir/jacocoTestReport ``` +Gradle automatically recognizes your environment and configures, runs, and closes the emulator in the background. +This has been tested on environments with Arm (Apple M1) and Intel CPUs. + More info about Gradle managed devices in official Android testing docs: [Scale your tests with Gradle Managed Devices](https://developer.android.com/studio/test/gradle-managed-devices) From 03e09104f90fde41d7223d15707f9e26bfa91c8a Mon Sep 17 00:00:00 2001 From: Ali Kabiri Date: Thu, 9 Mar 2023 18:19:17 +0100 Subject: [PATCH 12/37] specify jacoco custom output file path for sonar coverage Signed-off-by: Ali Kabiri --- build.gradle | 1 + 1 file changed, 1 insertion(+) diff --git a/build.gradle b/build.gradle index 4b609460..e1c4170a 100644 --- a/build.gradle +++ b/build.gradle @@ -29,5 +29,6 @@ sonarqube { property "sonar.projectName", "arduino-usb-terminal" property "sonar.sourceEncoding", "UTF-8" property "sonar.host.url", "https://sonarcloud.io" + property "sonar.coverage.jacoco.xmlReportPaths", "${project.rootDir}/app/build/mergedReportDir/jacocoTestReport/jacocoTestReport.xml" } } \ No newline at end of file From 45977ac4a1881ebed34f3dce3cfc6fa7bca67def Mon Sep 17 00:00:00 2001 From: Ali Kabiri Date: Fri, 10 Mar 2023 07:49:35 +0100 Subject: [PATCH 13/37] add sonar.java.binaries path Signed-off-by: Ali Kabiri --- build.gradle | 1 + 1 file changed, 1 insertion(+) diff --git a/build.gradle b/build.gradle index e1c4170a..ec2edbad 100644 --- a/build.gradle +++ b/build.gradle @@ -30,5 +30,6 @@ sonarqube { property "sonar.sourceEncoding", "UTF-8" property "sonar.host.url", "https://sonarcloud.io" property "sonar.coverage.jacoco.xmlReportPaths", "${project.rootDir}/app/build/mergedReportDir/jacocoTestReport/jacocoTestReport.xml" + property "sonar.java.binaries", "app/build/tmp/kotlin-classes/debug" } } \ No newline at end of file From 175528d8bfe1c8975c7991d9978d49702e48482c Mon Sep 17 00:00:00 2001 From: Ali Kabiri Date: Sat, 11 Mar 2023 12:35:37 +0100 Subject: [PATCH 14/37] update SonarScanner gradle properties; update README Signed-off-by: Ali Kabiri --- README.md | 12 ++++++++++++ build.gradle | 9 +++++++-- 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index ed445f55..01708181 100644 --- a/README.md +++ b/README.md @@ -59,6 +59,18 @@ More info about Gradle managed devices in official Android testing docs: [Scale If this is not needed, you can remove the crashlytics dependency in project leve and app level build.gradle files. - remove `classpath "com.google.firebase:firebase-crashlytics-gradle:2.9.4"` from `build.gradle` file - remove `implementation("com.google.firebase:firebase-crashlytics-ktx")` from `app/build.gradle.kts` file + + +## Sonar Cloud Analysis +The project uses Sonar Cloud manual analysis to detect code smells and potential bugs +To run the manual analysis locally, use the gradle `sonar` task: +``` +./gradlew sonar +``` +Since this uses the gradle scanner, the sonar properties are defined in root project's `build.gradle` file. +On one hand, the Sonar scanner requires local paths for `sonar.sources` and `sonar.binaries` properties, on the other hand it requires absolute path for `sonar.androidLint.reportPaths` and `sonar.coverage.jacoco.xmlReportPaths`. +More info on official Sonar docs: [SonarScanner for Gradle](https://docs.sonarcloud.io/advanced-setup/ci-based-analysis/sonarscanner-for-gradle/) + ## Knows Issues diff --git a/build.gradle b/build.gradle index ec2edbad..09ce2b2e 100644 --- a/build.gradle +++ b/build.gradle @@ -29,7 +29,12 @@ sonarqube { property "sonar.projectName", "arduino-usb-terminal" property "sonar.sourceEncoding", "UTF-8" property "sonar.host.url", "https://sonarcloud.io" - property "sonar.coverage.jacoco.xmlReportPaths", "${project.rootDir}/app/build/mergedReportDir/jacocoTestReport/jacocoTestReport.xml" - property "sonar.java.binaries", "app/build/tmp/kotlin-classes/debug" + + // sonar requires relative path for sources and binaries + property "sonar.sources", "/app/src/main/java" + property "sonar.binaries", "/app/build/tmp/kotlin-classes/debug" + // sonar requires absolute path for lint and jacoco reports! + property "sonar.androidLint.reportPaths", "$rootDir/app/build/reports/lint-results-debug.xml" + property "sonar.coverage.jacoco.xmlReportPaths", "$rootDir/app/build/mergedReportDir/jacocoTestReport/jacocoTestReport.xml" } } \ No newline at end of file From 5f8e09f5fff6276056a26a1226895a5a1fdd4ce3 Mon Sep 17 00:00:00 2001 From: Ali Kabiri Date: Sat, 11 Mar 2023 12:42:59 +0100 Subject: [PATCH 15/37] create a gradle task to generate google-services.json file from env vars Signed-off-by: Ali Kabiri --- .circleci/config.yml | 2 +- app/build.gradle.kts | 11 +++++++++++ 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 3999805a..d49905d2 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -29,11 +29,11 @@ jobs: steps: - checkout - run: python3 scripts/generateKsPropFile.py - - run: python3 scripts/generateGoogleServicesJson.py - restore_gradle_cache - run: sdkmanager --list - run: (yes || true) | sdkmanager "tools" "platform-tools" "build-tools;33.0.2" "platforms;android-33" "system-images;android-30;google_atd;x86" - run: (yes || true) | sdkmanager --licenses + - run: ./gradlew generateGoogleServicesJson - run: ./gradlew assembleDebug --stacktrace - run: ./gradlew pixel2api30DebugAndroidTest --stacktrace - run: ./gradlew testDebugUnitTest --stacktrace diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 075e4633..a3d78fb6 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -111,6 +111,17 @@ sonarqube { } } +tasks.register("generateGoogleServicesJson") { + doLast { + val jsonFileName = "google-services.json" + val fileContent = System.getenv("GOOGLE_SERVICES_JSON") + File(projectDir, jsonFileName).apply { + createNewFile(); writeText(fileContent) + println("generated google-services.json") + } + } +} + fun loadKeyStore(ksProp: Properties) { val ksPropFile = file("keystore.properties") if (ksPropFile.exists()) { From 3c9875a03ba4d9346e43dc104a000b153e4d7577 Mon Sep 17 00:00:00 2001 From: Ali Kabiri Date: Sat, 11 Mar 2023 12:56:50 +0100 Subject: [PATCH 16/37] create a gradle task to generate the ksProp file for signing Signed-off-by: Ali Kabiri --- .circleci/config.yml | 2 +- app/build.gradle.kts | 19 ++++++++++++++++++- 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index d49905d2..d144b6bb 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -28,11 +28,11 @@ jobs: resource_class: large steps: - checkout - - run: python3 scripts/generateKsPropFile.py - restore_gradle_cache - run: sdkmanager --list - run: (yes || true) | sdkmanager "tools" "platform-tools" "build-tools;33.0.2" "platforms;android-33" "system-images;android-30;google_atd;x86" - run: (yes || true) | sdkmanager --licenses + - run: ./gradlew generateKsPropFile - run: ./gradlew generateGoogleServicesJson - run: ./gradlew assembleDebug --stacktrace - run: ./gradlew pixel2api30DebugAndroidTest --stacktrace diff --git a/app/build.gradle.kts b/app/build.gradle.kts index a3d78fb6..2283d247 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -117,7 +117,24 @@ tasks.register("generateGoogleServicesJson") { val fileContent = System.getenv("GOOGLE_SERVICES_JSON") File(projectDir, jsonFileName).apply { createNewFile(); writeText(fileContent) - println("generated google-services.json") + println("generated $jsonFileName") + } + } +} + +tasks.register("generateKsPropFile") { + doLast { + val configFileName = "keystore.properties" + File("$projectDir, $configFileName").apply { + createNewFile() + writeText(""" + # Gradle signing properties for app module + release.file=${System.getenv("KS_PATH")} + release.storePassword=${System.getenv("KS_PASSWORD")} + release.keyAlias=${System.getenv("KS_KEY_ALIAS")} + release.keyPassword=${System.getenv("KS_KEY_PASSWORD")} + """.trimIndent()) + println("generated $configFileName") } } } From 190fa9d2b0e887c0c90c8d92029fdc163decad9c Mon Sep 17 00:00:00 2001 From: Ali Kabiri Date: Sat, 11 Mar 2023 13:05:54 +0100 Subject: [PATCH 17/37] update config.yml Signed-off-by: Ali Kabiri --- app/build.gradle.kts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 2283d247..7356bb65 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -129,10 +129,10 @@ tasks.register("generateKsPropFile") { createNewFile() writeText(""" # Gradle signing properties for app module - release.file=${System.getenv("KS_PATH")} - release.storePassword=${System.getenv("KS_PASSWORD")} - release.keyAlias=${System.getenv("KS_KEY_ALIAS")} - release.keyPassword=${System.getenv("KS_KEY_PASSWORD")} + release.file=${System.getenv("KS_PATH") ?: "empty"} + release.storePassword=${System.getenv("KS_PASSWORD") ?: "empty"} + release.keyAlias=${System.getenv("KS_KEY_ALIAS") ?: "empty"} + release.keyPassword=${System.getenv("KS_KEY_PASSWORD") ?: "empty"} """.trimIndent()) println("generated $configFileName") } From 79b933abaa961b9e1581538c122f3d41f346354a Mon Sep 17 00:00:00 2001 From: Ali Kabiri Date: Sat, 11 Mar 2023 13:12:34 +0100 Subject: [PATCH 18/37] fix an issue with keystore.properties path while using the gradle task to generate it Signed-off-by: Ali Kabiri --- app/build.gradle.kts | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 7356bb65..9b9c7aac 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -125,16 +125,16 @@ tasks.register("generateGoogleServicesJson") { tasks.register("generateKsPropFile") { doLast { val configFileName = "keystore.properties" - File("$projectDir, $configFileName").apply { + File(projectDir, configFileName).apply { createNewFile() writeText(""" # Gradle signing properties for app module - release.file=${System.getenv("KS_PATH") ?: "empty"} - release.storePassword=${System.getenv("KS_PASSWORD") ?: "empty"} - release.keyAlias=${System.getenv("KS_KEY_ALIAS") ?: "empty"} - release.keyPassword=${System.getenv("KS_KEY_PASSWORD") ?: "empty"} + release.file=${System.getenv("KS_PATH")} + release.storePassword=${System.getenv("KS_PASSWORD")} + release.keyAlias=${System.getenv("KS_KEY_ALIAS")} + release.keyPassword=${System.getenv("KS_KEY_PASSWORD")} """.trimIndent()) - println("generated $configFileName") + println("generated ${this.path}") } } } From 66265fb21f0028e946e10faf36db8cf48629de2d Mon Sep 17 00:00:00 2001 From: Ali Kabiri Date: Sat, 11 Mar 2023 13:17:12 +0100 Subject: [PATCH 19/37] update sonar --- app/build.gradle.kts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 9b9c7aac..db4b667d 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -129,10 +129,10 @@ tasks.register("generateKsPropFile") { createNewFile() writeText(""" # Gradle signing properties for app module - release.file=${System.getenv("KS_PATH")} - release.storePassword=${System.getenv("KS_PASSWORD")} - release.keyAlias=${System.getenv("KS_KEY_ALIAS")} - release.keyPassword=${System.getenv("KS_KEY_PASSWORD")} + release.file=${System.getenv("KS_PATH") ?: "empty"} + release.storePassword=${System.getenv("KS_PASSWORD") ?: "empty"} + release.keyAlias=${System.getenv("KS_KEY_ALIAS") ?: "empty"} + release.keyPassword=${System.getenv("KS_KEY_PASSWORD") ?: "empty"} """.trimIndent()) println("generated ${this.path}") } From 71425f895f41259dd0aff308106f25e442021558 Mon Sep 17 00:00:00 2001 From: Ali Kabiri Date: Sat, 11 Mar 2023 13:45:46 +0100 Subject: [PATCH 20/37] distribute the debug version to firebase appTester --- .circleci/config.yml | 31 +++++++++++++++++++++++++++++-- app/build.gradle.kts | 16 ++++++++++++++-- fastlane/Fastfile | 12 ++++++++++++ 3 files changed, 55 insertions(+), 4 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index d144b6bb..e794c12f 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -21,10 +21,17 @@ commands: - ~/.gradle/caches key: v1-gradle-cache-{{ arch }}-{{ checksum "build.gradle" }} -jobs: - android-test: +executors: + android-machine: machine: image: android:2022.12.1 + android-docker: + docker: + - image: cimg/android:2023.02 + +jobs: + android-test: + executor: android-machine resource_class: large steps: - checkout @@ -49,8 +56,28 @@ jobs: - store_artifacts: path: app/build/mergedReportDir + distribute-dev: + executor: android-docker + steps: + - checkout + - restore_gradle_cache + - run: + name: Prepare Fastlane + command: | + sudo bundle update + ./gradlew generateKsPropFile + ./gradlew generateGoogleServicesJson + ./gradlew assembleDebug + - run: + name: Distribute to Firebase AppTester + command: bundle exec fastlane distDev + - store_artifacts: + path: /home/circleci/project/app/build/outputs/apk/debug/app-debug.apk + destination: fastlane-output-debug + workflows: workflow: jobs: - android-test: context: SonarCloud + - distribute-dev diff --git a/app/build.gradle.kts b/app/build.gradle.kts index db4b667d..67e4eb06 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -26,8 +26,8 @@ android { applicationId = "org.kabiri.android.usbterminal" minSdk = 23 targetSdk = 33 - versionCode = 13 - versionName = "0.9.12" + versionCode = System.getenv("CIRCLE_BUILD_NUM")?.toIntOrNull() ?: 13 + versionName = "0.9.12${System.getenv("CIRCLE_BUILD_NUM") ?: ""}" testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" } @@ -139,6 +139,18 @@ tasks.register("generateKsPropFile") { } } +tasks.register("generateAppDistKey") { + doLast { + val jsonFileName = "app-dist-key.json" + val fileContent = System.getenv("GOOGLE_APP_DIST_FASTLANE_SERVICE_ACCOUNT") + File(rootDir, jsonFileName).apply { + createNewFile() + writeText(fileContent) + println("generated ${this.path}") + } + } +} + fun loadKeyStore(ksProp: Properties) { val ksPropFile = file("keystore.properties") if (ksPropFile.exists()) { diff --git a/fastlane/Fastfile b/fastlane/Fastfile index 1e03a189..a28e78d3 100644 --- a/fastlane/Fastfile +++ b/fastlane/Fastfile @@ -16,11 +16,23 @@ default_platform(:android) platform :android do + desc "Runs all the tests" lane :run_unit_tests do gradle(task: "testDebugUnitTest --stacktrace") end + desc "Deploy to Firebase AppTester channel" + lane :distDev do + gradle(task: "generateKsPropFile generateGoogleServicesJson generateAppDistKey clean assembleDebug") + firebase_app_distribution( + service_credentials_file: ENV['APP_DIST_SERVICE_ACCOUNT_PATH'], + app: "1:1032339097117:android:1e333da555ec74a71668f4", + groups: "testers", + release_notes: "", + ) + end + desc "Submit a new Beta Build to Crashlytics Beta" lane :beta do gradle(task: "clean assembleRelease") From c2b5ba1215493a649fe5770d4aebcf2bd29ead9a Mon Sep 17 00:00:00 2001 From: Ali Kabiri Date: Sat, 11 Mar 2023 13:58:29 +0100 Subject: [PATCH 21/37] check if keyStore properties are loaded before creating the default config --- app/build.gradle.kts | 36 ++++++++++++++++++++---------------- 1 file changed, 20 insertions(+), 16 deletions(-) diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 67e4eb06..55244f3d 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -32,15 +32,16 @@ android { } signingConfigs { - // read release credentials from keystore.properties file - val ksProp = Properties() - // load keys inside the ksProp file - loadKeyStore(ksProp) - create("release") { - keyAlias = ksProp.getProperty("release.keyAlias") - keyPassword = ksProp.getProperty("release.keyPassword") - storeFile = file(ksProp.getProperty("release.file")) - storePassword = ksProp.getProperty("release.storePassword") + + val ksName = "keystore.properties" + val ksProp = loadKeyStore(ksName) + ksProp?.let { + create("release") { + keyAlias = ksProp.getProperty("release.keyAlias") + keyPassword = ksProp.getProperty("release.keyPassword") + storeFile = file(ksProp.getProperty("release.file")) + storePassword = ksProp.getProperty("release.storePassword") + } } } @@ -129,10 +130,10 @@ tasks.register("generateKsPropFile") { createNewFile() writeText(""" # Gradle signing properties for app module - release.file=${System.getenv("KS_PATH") ?: "empty"} - release.storePassword=${System.getenv("KS_PASSWORD") ?: "empty"} - release.keyAlias=${System.getenv("KS_KEY_ALIAS") ?: "empty"} - release.keyPassword=${System.getenv("KS_KEY_PASSWORD") ?: "empty"} + release.file=${System.getenv("KS_PATH")} + release.storePassword=${System.getenv("KS_PASSWORD")} + release.keyAlias=${System.getenv("KS_KEY_ALIAS")} + release.keyPassword=${System.getenv("KS_KEY_PASSWORD")} """.trimIndent()) println("generated ${this.path}") } @@ -151,12 +152,15 @@ tasks.register("generateAppDistKey") { } } -fun loadKeyStore(ksProp: Properties) { - val ksPropFile = file("keystore.properties") - if (ksPropFile.exists()) { +fun loadKeyStore(name: String): Properties? { + val ksProp = Properties() + val ksPropFile = file(name) + return if (ksPropFile.exists()) { ksProp.load(FileInputStream(ksPropFile)) + ksProp } else { println("ERROR: local keystore file not found") + null } } From 33046e8ed0bc1b0e31b139892ddfb0a945005e6c Mon Sep 17 00:00:00 2001 From: Ali Kabiri Date: Sat, 11 Mar 2023 14:13:11 +0100 Subject: [PATCH 22/37] use findByName instead of getByName for release signing config Signed-off-by: Ali Kabiri --- app/build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 55244f3d..253fb968 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -47,7 +47,7 @@ android { buildTypes { named("release") { - signingConfig = signingConfigs.getByName("release") + signingConfig = signingConfigs.findByName("release") isMinifyEnabled = false proguardFiles(getDefaultProguardFile("proguard-android-optimize.txt"), "proguard-rules.pro") } From f306e4c4a0c17a92e6bb7e367a411519a88390af Mon Sep 17 00:00:00 2001 From: Ali Kabiri Date: Sat, 11 Mar 2023 14:21:15 +0100 Subject: [PATCH 23/37] add firebase_app_distribution plugin for fastlate --- .circleci/config.yml | 1 + Gemfile | 4 ++- Gemfile.lock | 64 +++++++++++++++++++++++--------------------- fastlane/Pluginfile | 5 ++++ 4 files changed, 42 insertions(+), 32 deletions(-) create mode 100644 fastlane/Pluginfile diff --git a/.circleci/config.yml b/.circleci/config.yml index e794c12f..46e202fb 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -58,6 +58,7 @@ jobs: distribute-dev: executor: android-docker + resource_class: large steps: - checkout - restore_gradle_cache diff --git a/Gemfile b/Gemfile index adc90d98..2ccf2ecb 100644 --- a/Gemfile +++ b/Gemfile @@ -1,3 +1,5 @@ source "https://rubygems.org" -gem "fastlane" \ No newline at end of file +gem "fastlane" +plugins_path = File.join(File.dirname(__FILE__), 'fastlane', 'Pluginfile') +eval_gemfile(plugins_path) if File.exist?(plugins_path) diff --git a/Gemfile.lock b/Gemfile.lock index 944b5730..7a0078bc 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,24 +1,24 @@ GEM remote: https://rubygems.org/ specs: - CFPropertyList (3.0.5) + CFPropertyList (3.0.6) rexml addressable (2.8.1) public_suffix (>= 2.0.2, < 6.0) artifactory (3.0.15) atomos (0.1.3) aws-eventstream (1.2.0) - aws-partitions (1.642.0) - aws-sdk-core (3.158.0) + aws-partitions (1.725.0) + aws-sdk-core (3.170.0) aws-eventstream (~> 1, >= 1.0.2) - aws-partitions (~> 1, >= 1.525.0) - aws-sigv4 (~> 1.1) + aws-partitions (~> 1, >= 1.651.0) + aws-sigv4 (~> 1.5) jmespath (~> 1, >= 1.6.1) - aws-sdk-kms (1.58.0) - aws-sdk-core (~> 3, >= 3.127.0) + aws-sdk-kms (1.63.0) + aws-sdk-core (~> 3, >= 3.165.0) aws-sigv4 (~> 1.1) - aws-sdk-s3 (1.114.0) - aws-sdk-core (~> 3, >= 3.127.0) + aws-sdk-s3 (1.119.1) + aws-sdk-core (~> 3, >= 3.165.0) aws-sdk-kms (~> 1) aws-sigv4 (~> 1.4) aws-sigv4 (1.5.2) @@ -36,8 +36,8 @@ GEM unf (>= 0.0.5, < 1.0.0) dotenv (2.8.1) emoji_regex (3.2.3) - excon (0.93.0) - faraday (1.10.2) + excon (0.99.0) + faraday (1.10.3) faraday-em_http (~> 1.0) faraday-em_synchrony (~> 1.0) faraday-excon (~> 1.1) @@ -66,7 +66,7 @@ GEM faraday_middleware (1.2.0) faraday (~> 1.0) fastimage (2.2.6) - fastlane (2.210.1) + fastlane (2.212.1) CFPropertyList (>= 2.3, < 4.0.0) addressable (>= 2.8, < 3.0.0) artifactory (~> 3.0) @@ -105,10 +105,11 @@ GEM xcodeproj (>= 1.13.0, < 2.0.0) xcpretty (~> 0.3.0) xcpretty-travis-formatter (>= 0.0.3) + fastlane-plugin-firebase_app_distribution (0.5.0) gh_inspector (1.1.3) - google-apis-androidpublisher_v3 (0.29.0) - google-apis-core (>= 0.9.0, < 2.a) - google-apis-core (0.9.0) + google-apis-androidpublisher_v3 (0.35.0) + google-apis-core (>= 0.11.0, < 2.a) + google-apis-core (0.11.0) addressable (~> 2.5, >= 2.5.1) googleauth (>= 0.16.2, < 2.a) httpclient (>= 2.8.1, < 3.a) @@ -117,10 +118,10 @@ GEM retriable (>= 2.0, < 4.a) rexml webrick - google-apis-iamcredentials_v1 (0.15.0) - google-apis-core (>= 0.9.0, < 2.a) - google-apis-playcustomapp_v1 (0.11.0) - google-apis-core (>= 0.9.0, < 2.a) + google-apis-iamcredentials_v1 (0.17.0) + google-apis-core (>= 0.11.0, < 2.a) + google-apis-playcustomapp_v1 (0.13.0) + google-apis-core (>= 0.11.0, < 2.a) google-apis-storage_v1 (0.19.0) google-apis-core (>= 0.9.0, < 2.a) google-cloud-core (1.6.0) @@ -128,8 +129,8 @@ GEM google-cloud-errors (~> 1.0) google-cloud-env (1.6.0) faraday (>= 0.17.3, < 3.0) - google-cloud-errors (1.3.0) - google-cloud-storage (1.43.0) + google-cloud-errors (1.3.1) + google-cloud-storage (1.44.0) addressable (~> 2.8) digest-crc (~> 0.4) google-apis-iamcredentials_v1 (~> 0.1) @@ -137,7 +138,7 @@ GEM google-cloud-core (~> 1.6) googleauth (>= 0.16.2, < 2.a) mini_mime (~> 1.0) - googleauth (1.2.0) + googleauth (1.3.0) faraday (>= 0.17.3, < 3.a) jwt (>= 1.4, < 3.0) memoist (~> 0.16) @@ -148,11 +149,11 @@ GEM http-cookie (1.0.5) domain_name (~> 0.5) httpclient (2.8.3) - jmespath (1.6.1) - json (2.6.2) - jwt (2.5.0) + jmespath (1.6.2) + json (2.6.3) + jwt (2.7.0) memoist (0.16.2) - mini_magick (4.11.0) + mini_magick (4.12.0) mini_mime (1.1.2) multi_json (1.15.0) multipart-post (2.0.0) @@ -160,8 +161,8 @@ GEM naturally (2.2.1) optparse (0.1.1) os (1.1.4) - plist (3.6.0) - public_suffix (5.0.0) + plist (3.7.0) + public_suffix (5.0.1) rake (13.0.6) representable (3.2.0) declarative (< 0.1.0) @@ -178,7 +179,7 @@ GEM faraday (>= 0.17.5, < 3.a) jwt (>= 1.5, < 3.0) multi_json (~> 1.10) - simctl (1.6.8) + simctl (1.6.10) CFPropertyList naturally terminal-notifier (2.0.0) @@ -195,7 +196,7 @@ GEM unf_ext (0.0.8.2) unf_ext (0.0.8.2-x64-mingw32) unicode-display_width (1.8.0) - webrick (1.7.0) + webrick (1.8.1) word_wrap (1.0.0) xcodeproj (1.22.0) CFPropertyList (>= 2.3.3, < 4.0) @@ -217,6 +218,7 @@ PLATFORMS DEPENDENCIES fastlane + fastlane-plugin-firebase_app_distribution BUNDLED WITH - 2.3.7 + 2.4.7 diff --git a/fastlane/Pluginfile b/fastlane/Pluginfile new file mode 100644 index 00000000..b18539bc --- /dev/null +++ b/fastlane/Pluginfile @@ -0,0 +1,5 @@ +# Autogenerated by fastlane +# +# Ensure this file is checked in to source control! + +gem 'fastlane-plugin-firebase_app_distribution' From a77ab32721bbbd034131f550e8eff6d7b0e65a20 Mon Sep 17 00:00:00 2001 From: Ali Kabiri Date: Sat, 11 Mar 2023 14:35:11 +0100 Subject: [PATCH 24/37] use gradle tasks to prepare the build on Github actions --- .github/workflows/android.yml | 45 ++++++++--------------------------- 1 file changed, 10 insertions(+), 35 deletions(-) diff --git a/.github/workflows/android.yml b/.github/workflows/android.yml index 86605917..e9188b06 100644 --- a/.github/workflows/android.yml +++ b/.github/workflows/android.yml @@ -12,24 +12,15 @@ jobs: with: ruby-version: '3.0' bundler-cache: true - - name: set up JDK 11 uses: actions/setup-java@v1 with: distribution: 'zulu' java-version: '11' - - name: set up Python - uses: actions/setup-python@v4 - with: - python-version: '3.10' - name: generate ksProp file - run: python scripts/generateKsPropFile.py - - name: create google-services.json file - run: cat app/google-services.json | base64 - - name: update google-services.json file - env: - DATA: ${{ secrets.GOOGLE_SERVICES_JSON }} - run: echo $DATA > app/google-services.json + run: ./gradlew generateKsPropFile + - name: generate google-services.json file + run: ./gradlew generateGoogleServicesJson - name: setup fastlane run: bundle install - name: run unit tests @@ -49,18 +40,10 @@ jobs: with: distribution: 'zulu' java-version: '11' - - name: set up Python - uses: actions/setup-python@v4 - with: - python-version: '3.10' - name: generate ksProp file - run: python scripts/generateKsPropFile.py - - name: create google-services.json file - run: cat app/google-services.json | base64 - - name: update google-services.json file - env: - DATA: ${{ secrets.GOOGLE_SERVICES_JSON }} - run: echo $DATA > app/google-services.json + run: ./gradlew generateKsPropFile + - name: generate google-services.json file + run: ./gradlew generateGoogleServicesJson - name: Lint run: bash ./gradlew lintDebug - name: Lint results @@ -70,7 +53,7 @@ jobs: path: app/build/reports/lint-results-debug.html ui-test: - runs-on: macOS-latest + runs-on: macos-latest steps: - name: checkout uses: actions/checkout@v2 @@ -79,18 +62,10 @@ jobs: with: distribution: 'zulu' java-version: '11' - - name: set up Python - uses: actions/setup-python@v4 - with: - python-version: '3.10' - name: generate ksProp file - run: python scripts/generateKsPropFile.py - - name: create google-services.json file - run: cat app/google-services.json | base64 - - name: update google-services.json file - env: - DATA: ${{ secrets.GOOGLE_SERVICES_JSON }} - run: echo $DATA > app/google-services.json + run: ./gradlew generateKsPropFile + - name: generate google-services.json file + run: ./gradlew generateGoogleServicesJson - name: run tests uses: reactivecircus/android-emulator-runner@v2 with: From 98140a1dbe52a3221738683099f33222be7b5ace Mon Sep 17 00:00:00 2001 From: Ali Kabiri Date: Sat, 11 Mar 2023 14:35:35 +0100 Subject: [PATCH 25/37] use fastlane to run all tests and generate coverage --- .circleci/config.yml | 4 +--- fastlane/Fastfile | 5 +++++ 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 46e202fb..981c275e 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -42,9 +42,7 @@ jobs: - run: ./gradlew generateKsPropFile - run: ./gradlew generateGoogleServicesJson - run: ./gradlew assembleDebug --stacktrace - - run: ./gradlew pixel2api30DebugAndroidTest --stacktrace - - run: ./gradlew testDebugUnitTest --stacktrace - - run: ./gradlew jacocoTestReport --stacktrace + - run: bundle exec fastlane testDev - save_gradle_cache - run: name: Analyze on SonarCloud diff --git a/fastlane/Fastfile b/fastlane/Fastfile index a28e78d3..debdf5e5 100644 --- a/fastlane/Fastfile +++ b/fastlane/Fastfile @@ -22,6 +22,11 @@ platform :android do gradle(task: "testDebugUnitTest --stacktrace") end + desc "Runs all the tests with coverage" + lane :testDev do + gradle(task: "pixel2api30DebugAndroidTest testDebugUnitTest jacocoTestReport --stacktrace") + end + desc "Deploy to Firebase AppTester channel" lane :distDev do gradle(task: "generateKsPropFile generateGoogleServicesJson generateAppDistKey clean assembleDebug") From 352e2524be11c878052641c33e2c34120d3cb4d2 Mon Sep 17 00:00:00 2001 From: Ali Kabiri Date: Sat, 11 Mar 2023 14:40:51 +0100 Subject: [PATCH 26/37] define env for google-servies.json file --- .github/workflows/android.yml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/.github/workflows/android.yml b/.github/workflows/android.yml index e9188b06..795e62ca 100644 --- a/.github/workflows/android.yml +++ b/.github/workflows/android.yml @@ -21,6 +21,8 @@ jobs: run: ./gradlew generateKsPropFile - name: generate google-services.json file run: ./gradlew generateGoogleServicesJson + env: + GOOGLE_SERVICES_JSON: ${{ secrets.GOOGLE_SERVICES_JSON }} - name: setup fastlane run: bundle install - name: run unit tests @@ -44,6 +46,8 @@ jobs: run: ./gradlew generateKsPropFile - name: generate google-services.json file run: ./gradlew generateGoogleServicesJson + env: + GOOGLE_SERVICES_JSON: ${{ secrets.GOOGLE_SERVICES_JSON }} - name: Lint run: bash ./gradlew lintDebug - name: Lint results @@ -66,6 +70,8 @@ jobs: run: ./gradlew generateKsPropFile - name: generate google-services.json file run: ./gradlew generateGoogleServicesJson + env: + GOOGLE_SERVICES_JSON: ${{ secrets.GOOGLE_SERVICES_JSON }} - name: run tests uses: reactivecircus/android-emulator-runner@v2 with: From 63a6fef1e4ddbd9d8df110c1511f59040ea28837 Mon Sep 17 00:00:00 2001 From: Ali Kabiri Date: Sat, 11 Mar 2023 14:41:08 +0100 Subject: [PATCH 27/37] remove unnecessary commands which is already handled by fastlane --- .circleci/config.yml | 2 -- 1 file changed, 2 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 981c275e..28870a96 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -64,8 +64,6 @@ jobs: name: Prepare Fastlane command: | sudo bundle update - ./gradlew generateKsPropFile - ./gradlew generateGoogleServicesJson ./gradlew assembleDebug - run: name: Distribute to Firebase AppTester From 5d9ea8438459fa2e8d9dc64dd005d68acc7e5601 Mon Sep 17 00:00:00 2001 From: Ali Kabiri Date: Sat, 11 Mar 2023 14:44:40 +0100 Subject: [PATCH 28/37] run bundle update before executing fastlane command Signed-off-by: Ali Kabiri --- .circleci/config.yml | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 28870a96..156cb678 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -42,7 +42,11 @@ jobs: - run: ./gradlew generateKsPropFile - run: ./gradlew generateGoogleServicesJson - run: ./gradlew assembleDebug --stacktrace - - run: bundle exec fastlane testDev + - run: + name: Fastlane - run all tests with coverage report + command: | + sudo bundle update + bundle exec fastlane testDev - save_gradle_cache - run: name: Analyze on SonarCloud From 1184ffccabb654c148131f9ed24b5e519dc4ffab Mon Sep 17 00:00:00 2001 From: Ali Kabiri Date: Sat, 11 Mar 2023 14:55:48 +0100 Subject: [PATCH 29/37] install ruby to run fastlane Signed-off-by: Ali Kabiri --- .circleci/config.yml | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 156cb678..59590bdd 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -1,6 +1,7 @@ version: 2.1 orbs: codecov: codecov/codecov@3.2.4 + ruby: circleci/ruby@2.0.0 commands: restore_gradle_cache: @@ -36,12 +37,11 @@ jobs: steps: - checkout - restore_gradle_cache - - run: sdkmanager --list - - run: (yes || true) | sdkmanager "tools" "platform-tools" "build-tools;33.0.2" "platforms;android-33" "system-images;android-30;google_atd;x86" - - run: (yes || true) | sdkmanager --licenses - run: ./gradlew generateKsPropFile - run: ./gradlew generateGoogleServicesJson - run: ./gradlew assembleDebug --stacktrace + - ruby/install: + version: '3.0' - run: name: Fastlane - run all tests with coverage report command: | @@ -66,9 +66,7 @@ jobs: - restore_gradle_cache - run: name: Prepare Fastlane - command: | - sudo bundle update - ./gradlew assembleDebug + command: sudo bundle update - run: name: Distribute to Firebase AppTester command: bundle exec fastlane distDev From 7a91b06609ee6f6d216ef6ed0f69888a113cdbed Mon Sep 17 00:00:00 2001 From: Ali Kabiri Date: Sat, 11 Mar 2023 15:07:07 +0100 Subject: [PATCH 30/37] install bundler using ruby gems --- .circleci/config.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.circleci/config.yml b/.circleci/config.yml index 59590bdd..b808917a 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -45,6 +45,7 @@ jobs: - run: name: Fastlane - run all tests with coverage report command: | + sudo gem install bundler sudo bundle update bundle exec fastlane testDev - save_gradle_cache From 036aa00075e95b9ee5ab9879c5e5d6b2fb5fa78a Mon Sep 17 00:00:00 2001 From: Ali Kabiri Date: Sat, 11 Mar 2023 15:07:19 +0100 Subject: [PATCH 31/37] hopefully setup github actions cache for gradle --- .github/workflows/android.yml | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/.github/workflows/android.yml b/.github/workflows/android.yml index 795e62ca..6a96ad37 100644 --- a/.github/workflows/android.yml +++ b/.github/workflows/android.yml @@ -17,6 +17,20 @@ jobs: with: distribution: 'zulu' java-version: '11' + - name: Cache Gradle wrapper + uses: actions/cache@v3 + with: + path: ~/.gradle/wrapper + key: ${{ runner.OS }}-gradle-wrapper-cache-${{ hashFiles('gradle/wrapper/gradle-wrapper.properties') }} + restore-keys: | + ${{ runner.OS }}-gradle-wrapper-cache- + - name: Cache Gradle caches + uses: actions/cache@v3 + with: + path: ~/.gradle/caches + key: ${{ runner.OS }}-gradle-caches-cache-${{ hashFiles('build.gradle') }} + restore-keys: | + ${{ runner.OS }}-gradle-caches-cache- - name: generate ksProp file run: ./gradlew generateKsPropFile - name: generate google-services.json file From 326ae8dacfb424ea2066415931b648ea08fb1ca4 Mon Sep 17 00:00:00 2001 From: Ali Kabiri Date: Sat, 11 Mar 2023 15:16:51 +0100 Subject: [PATCH 32/37] hopefully activate bundler cache on circleci Signed-off-by: Ali Kabiri --- .circleci/config.yml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index b808917a..5e9552e7 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -42,11 +42,13 @@ jobs: - run: ./gradlew assembleDebug --stacktrace - ruby/install: version: '3.0' + - ruby/install-deps: + with-cache: true - run: name: Fastlane - run all tests with coverage report command: | - sudo gem install bundler - sudo bundle update +# sudo gem install bundler +# sudo bundle update bundle exec fastlane testDev - save_gradle_cache - run: From 54127a410aed953897dedb1daaea6e924aedfb15 Mon Sep 17 00:00:00 2001 From: Ali Kabiri Date: Sat, 11 Mar 2023 15:17:20 +0100 Subject: [PATCH 33/37] hopefully activate bundler cache on circleci Signed-off-by: Ali Kabiri --- .circleci/config.yml | 2 -- 1 file changed, 2 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 5e9552e7..4630293a 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -47,8 +47,6 @@ jobs: - run: name: Fastlane - run all tests with coverage report command: | -# sudo gem install bundler -# sudo bundle update bundle exec fastlane testDev - save_gradle_cache - run: From 19ec385df46852a789ed62eb250d348d0806e469 Mon Sep 17 00:00:00 2001 From: Ali Kabiri Date: Sat, 11 Mar 2023 17:04:23 +0100 Subject: [PATCH 34/37] use fastlane to prepare the tests build Signed-off-by: Ali Kabiri --- .circleci/config.yml | 3 --- fastlane/Fastfile | 2 +- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 4630293a..a2a4a407 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -37,9 +37,6 @@ jobs: steps: - checkout - restore_gradle_cache - - run: ./gradlew generateKsPropFile - - run: ./gradlew generateGoogleServicesJson - - run: ./gradlew assembleDebug --stacktrace - ruby/install: version: '3.0' - ruby/install-deps: diff --git a/fastlane/Fastfile b/fastlane/Fastfile index debdf5e5..e8381099 100644 --- a/fastlane/Fastfile +++ b/fastlane/Fastfile @@ -24,7 +24,7 @@ platform :android do desc "Runs all the tests with coverage" lane :testDev do - gradle(task: "pixel2api30DebugAndroidTest testDebugUnitTest jacocoTestReport --stacktrace") + gradle(task: "generateKsPropFile generateGoogleServicesJson pixel2api30DebugAndroidTest testDebugUnitTest jacocoTestReport --stacktrace") end desc "Deploy to Firebase AppTester channel" From a1fc46388169a9ab82d9e481dedfae7332d9d575 Mon Sep 17 00:00:00 2001 From: Ali Kabiri Date: Sat, 11 Mar 2023 17:06:07 +0100 Subject: [PATCH 35/37] remove unnecessary python scrips which are already available as gradle tasks --- scripts/generateGoogleServicesJson.py | 9 --------- scripts/generateKsPropFile.py | 22 ---------------------- 2 files changed, 31 deletions(-) delete mode 100644 scripts/generateGoogleServicesJson.py delete mode 100644 scripts/generateKsPropFile.py diff --git a/scripts/generateGoogleServicesJson.py b/scripts/generateGoogleServicesJson.py deleted file mode 100644 index 3cd613ce..00000000 --- a/scripts/generateGoogleServicesJson.py +++ /dev/null @@ -1,9 +0,0 @@ -import os - -outputPath = "app/google-services.json" - -fileContent = os.getenv('GOOGLE_SERVICES_JSON') - -fhand = open(outputPath, 'w') -fhand.write(str(fileContent)) -fhand.close() \ No newline at end of file diff --git a/scripts/generateKsPropFile.py b/scripts/generateKsPropFile.py deleted file mode 100644 index 7731df9a..00000000 --- a/scripts/generateKsPropFile.py +++ /dev/null @@ -1,22 +0,0 @@ -# This script reads the keystore properties from environment variable -# and generates a keystore.properties file in app module. -# -# More info about gradle properties: -# https://ubuntudroid.medium.com/handling-environment-variables-in-gradle-fb1b8bb6c758 - -import os - -outputPath = "app/keystore.properties" - -keystoreFile = os.getenv('KS_PATH') -keystorePassword = os.getenv('KS_PASSWORD') -keyAlias = os.getenv('KS_KEY_ALIAS') -keyPassword = os.getenv('KS_KEY_PASSWORD') - -fhand = open(outputPath, 'w') -fhand.write("# Gradle properties for module app\n\n") -fhand.write("release.file=" + str(keystoreFile) + "\n") -fhand.write("release.storePassword=" + str(keystorePassword) + '\n') -fhand.write("release.keyAlias=" + str(keyAlias) + '\n') -fhand.write("release.keyPassword=" + str(keyPassword)) -fhand.close() \ No newline at end of file From 327376b747437762ab086b44063df191a131c872 Mon Sep 17 00:00:00 2001 From: Ali Kabiri Date: Sat, 11 Mar 2023 17:08:27 +0100 Subject: [PATCH 36/37] Update config.yml --- .circleci/config.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index a2a4a407..7f14bbc9 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -37,8 +37,8 @@ jobs: steps: - checkout - restore_gradle_cache - - ruby/install: - version: '3.0' +# - ruby/install: +# version: '3.0' - ruby/install-deps: with-cache: true - run: From 68ad67da6561ea570584e729dd2b34b99501b38c Mon Sep 17 00:00:00 2001 From: Ali Kabiri Date: Sat, 11 Mar 2023 17:10:42 +0100 Subject: [PATCH 37/37] Update config.yml --- .circleci/config.yml | 2 -- 1 file changed, 2 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 7f14bbc9..29704536 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -37,8 +37,6 @@ jobs: steps: - checkout - restore_gradle_cache -# - ruby/install: -# version: '3.0' - ruby/install-deps: with-cache: true - run: