Skip to content

Commit

Permalink
Improve CI time and restore apk functionality (#160)
Browse files Browse the repository at this point in the history
* fix(jacoco): Fix line 65535 issue with jacoco

Fix line 65535 by updating jacoco to a newer version and implementing
workaround to prevent jacoco report from being corrupted by this issue.
Taken from EPFLSWENT2024G1/partagix#78 suggested
coaches.

* ci(parallel): Improve CI runtime by parallelizing

Split up tasks that can be run concurrently and merge their results for
sonar cloud.
Remove minify and shrinking operations to speed up assembly at the cost
of bigger APKs

* ci(runtime): Integrate firebase emulator

Integrate firebase emulator inside the new CI to pass tests correctly.

* ci(runtime): Move linting to unit test checks

Move linting operation to unit test to offload and parallelize
ui test job.
  • Loading branch information
RemIsMyWaifuu authored Nov 13, 2024
1 parent 26f46a8 commit 21cba83
Show file tree
Hide file tree
Showing 2 changed files with 157 additions and 50 deletions.
181 changes: 137 additions & 44 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -1,60 +1,95 @@
name: CI - Test Runner

# Run the workflow when commits are pushed on main or when a PR is modified
on:
push:
branches:
- main

pull_request:
types:
- opened
- synchronize
- reopened

jobs:
ci:
name: CI
# Execute the CI on the course's runners
unit_tests:
name: Run Unit Tests
runs-on: ubuntu-latest

steps:
# First step : Checkout the repository on the runner
- name: Checkout
- name: Checkout repository
uses: actions/checkout@v4
with:
submodules: recursive
fetch-depth: 0 # Shallow clones should be disabled for a better relevancy of Sonar analysis (if we use Sonar Later)
fetch-depth: 0

- name: Enable KVM permissions
run: |
echo 'KERNEL=="kvm", GROUP="kvm", MODE="0666", OPTIONS+="static_node=kvm"' | sudo tee /etc/udev/rules.d/99-kvm4all.rules
sudo udevadm control --reload-rules
sudo udevadm trigger --name-match=kvm
- name: Setup JDK 17
uses: actions/setup-java@v4
with:
distribution: "temurin"
java-version: "17"

- name: Gradle cache
uses: gradle/actions/setup-gradle@v3

# Kernel-based Virtual Machine (KVM) is an open source virtualization technology built into Linux. Enabling it allows the Android emulator to run faster.
- name: Enable KVM group perms
- name: Decode secrets for Google services
env:
GOOGLE_SERVICES: ${{ secrets.GOOGLE_SERVICES }}
run: |
echo "$GOOGLE_SERVICES" | base64 --decode > ./app/google-services.json
- name: Set execute permissions for gradlew
run: chmod +x ./gradlew

- name: Run Unit Tests
run: ./gradlew check lint --parallel --build-cache

- name: Save Unit Test Results
if: success() # Only save if the tests were successful
uses: actions/upload-artifact@v3
with:
name: unit-test-results
path: |
app/build/test-results/
app/build/reports/
app/build/outputs/
ui_tests:
name: Run UI Tests
runs-on: ubuntu-latest

steps:
- name: Checkout repository
uses: actions/checkout@v4
with:
submodules: recursive
fetch-depth: 0

- name: Enable KVM permissions
run: |
echo 'KERNEL=="kvm", GROUP="kvm", MODE="0666", OPTIONS+="static_node=kvm"' | sudo tee /etc/udev/rules.d/99-kvm4all.rules
sudo udevadm control --reload-rules
sudo udevadm trigger --name-match=kvm
- name: Setup JDK
- name: Setup JDK 17
uses: actions/setup-java@v4
with:
distribution: "temurin"
java-version: "17"

# Caching is a very useful part of a CI, as a workflow is executed in a clean environment every time,
# this means that one would need to re-download and re-process gradle files for every run. Which is very time consuming.
#
# To avoid that, we cache the the gradle folder to reuse it later.
- name: Gradle cache
uses: gradle/actions/setup-gradle@v3

# Load google-services.json and local.properties from the secrets
- name: Decode secrets
- name: Decode secrets for Google services
env:
GOOGLE_SERVICES: ${{ secrets.GOOGLE_SERVICES }}
# LOCAL_PROPERTIES: ${{ secrets.LOCAL_PROPERTIES }}
run: |
echo "$GOOGLE_SERVICES" | base64 --decode > ./app/google-services.json
# echo "$LOCAL_PROPERTIES" | base64 --decode > ./local.properties
# Cache the Emulator, if the cache does not hit, create the emulator
- name: AVD cache
Expand All @@ -75,24 +110,9 @@ jobs:
arch: x86_64
force-avd-creation: false
emulator-options: -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none
disable-animations: false
disable-animations: true
script: echo "Generated AVD snapshot for caching."

- name: Grant execute permission for gradlew
run: |
chmod +x ./gradlew
# Check formatting
- name: KTFmt Check
run: |
./gradlew ktfmtCheck
# This step runs gradle commands to build the application
- name: Assemble
run: |
# To run the CI with debug information, add --info
./gradlew assemble lint --parallel --build-cache

- name: Cache firebase emulators
uses: actions/cache@v4
with:
Expand All @@ -105,11 +125,14 @@ jobs:
run: |
curl -sL https://firebase.tools | bash
# Run Unit tests
- name: Run tests
- name: Set execute permissions for gradlew
run: chmod +x ./gradlew

# This step runs gradle commands to build the application
- name: Assemble
run: |
# To run the CI with debug information, add --info
./gradlew check --parallel --build-cache
./gradlew assemble --parallel --build-cache
# Run connected tests on the emulator
- name: run tests
Expand All @@ -123,13 +146,83 @@ jobs:
disable-animations: true
script: firebase emulators:exec "./gradlew connectedCheck --parallel --build-cache"

# This step generates the coverage report which will be uploaded to sonar
- name: Generate Coverage Report
- name: Save UI Test Results
if: success() # Only save if the tests were successful
uses: actions/upload-artifact@v3
with:
name: ui-test-results
path: |
app/build/androidTests/connected/
app/build/reports/
app/build/outputs/
app/build/test-results/
coverage:
name: Generate and Upload Coverage Report
runs-on: ubuntu-latest
needs: [unit_tests, ui_tests] # Ensure both test jobs complete first

steps:
- name: Checkout repository
uses: actions/checkout@v4
with:
submodules: recursive
fetch-depth: 0

- name: Download Unit Test Results
uses: actions/download-artifact@v3
with:
name: unit-test-results
path: unit-test-results/

- name: Download UI Test Results
uses: actions/download-artifact@v3
with:
name: ui-test-results
path: ui-test-results/

- name: Setup JDK 17
uses: actions/setup-java@v4
with:
distribution: "temurin"
java-version: "17"
java-package: jdk

- name: Decode secrets for Google services
env:
GOOGLE_SERVICES: ${{ secrets.GOOGLE_SERVICES }}
run: |
./gradlew jacocoTestReport
echo "$GOOGLE_SERVICES" | base64 --decode > ./app/google-services.json
- name: Copy downloaded unit test results to build folder
run: |
echo "Listing downloaded unit-test-results:"
ls -R unit-test-results/
echo "Copying unit-test-results to ./app/build..."
cp -r unit-test-results/. ./app/build/ || true # Overwrite if needed, create directories as necessary
- name: Copy downloaded UI test results to build folder
run: |
echo "Listing downloaded ui-test-results:"
ls -R ui-test-results/
echo "Copying ui-test-results to ./app/build..."
cp -r ui-test-results/. ./app/build/ || true # Overwrite if needed, create directories as necessary
- name: List contents of ./app/build folder after copying
run: |
echo "Listing contents of ./app/build after copying:"
ls -R ./app/build/ # Ensure everything is copied correctly
- name: Gradle cache
uses: gradle/actions/setup-gradle@v3


- name: Generate Jacoco Coverage Report
run: ./gradlew jacocoTestReport

# Upload the various reports to sonar
- name: Upload report to SonarCloud
- name: Upload Coverage to SonarCloud
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
Expand Down
26 changes: 20 additions & 6 deletions app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ android {
val keyAlias = System.getenv("KEY_ALIAS") ?: localProperties.getProperty("KEY_ALIAS")
val keyPassword = System.getenv("KEY_PASSWORD") ?: localProperties.getProperty("KEY_PASSWORD")
val mapsApiKey: String = System.getenv("MAPS_API_KEY") ?: (localProperties.getProperty("MAPS_API_KEY") ?: "")
var chosenConfig: Boolean = false // this is to avoid issues with the signing config when building apk

defaultConfig {
manifestPlaceholders["MAPS_API_KEY"] = mapsApiKey
Expand All @@ -45,15 +46,16 @@ android {

buildTypes {
release {
isMinifyEnabled = true
isShrinkResources = true
proguardFiles(
getDefaultProguardFile("proguard-android-optimize.txt"),
"proguard-rules.pro"
)
//isMinifyEnabled = true
//isShrinkResources = true
//proguardFiles(
// getDefaultProguardFile("proguard-android-optimize.txt"),
// "proguard-rules.pro"
//)
// Only assign signing config if it exists
if (keystoreFile != null && keystorePassword != null && keyAlias != null && keyPassword != null) {
println("creating a release config")
chosenConfig = true // prevent debug signingConfig from getting created
signingConfig = signingConfigs.create("release") {
storeFile(file(keystoreFile))
storePassword(keystorePassword)
Expand All @@ -67,6 +69,18 @@ android {
}

debug {
if (keystoreFile != null && keystorePassword != null && keyAlias != null && keyPassword != null && !chosenConfig) {
println("creating a debug config")
signingConfig = signingConfigs.create("debug") {
storeFile(file(keystoreFile))
storePassword(keystorePassword)
keyAlias(keyAlias)
keyPassword(keyPassword)
}
}
else {
println("No debug signing config set.")
}
enableUnitTestCoverage = true
enableAndroidTestCoverage = true
}
Expand Down

0 comments on commit 21cba83

Please sign in to comment.