0
0
mirror of https://github.com/ankidroid/Anki-Android.git synced 2024-09-19 19:42:17 +02:00

Implement release mode instrumentation with better proguard rules

This commit is contained in:
Voczi 2024-06-25 20:43:02 +02:00 committed by Mike Hardy
parent 9951decf36
commit a4f0d8f511
8 changed files with 109 additions and 27 deletions

View File

@ -20,6 +20,13 @@ jobs:
timeout-minutes: 75
env:
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
TEST_RELEASE_BUILD: true
# could be better, '/home/runner' should be '~/' but neither that nor '$HOME' worked
STOREFILEDIR: /home/runner/src
STOREFILE: android-keystore
STOREPASS: testpass
KEYPASS: testpass
KEYALIAS: nrkeystorealias
strategy:
fail-fast: false
matrix:
@ -33,6 +40,15 @@ jobs:
# This is useful for benchmarking, do 0, 1, 2, etc (up to 256 max job-per-matrix limit) for averages
iteration: [0]
steps:
- name: Test Credential Prep
run: |
echo "KSTOREPWD=$STOREPASS" >> $GITHUB_ENV
echo "KEYPWD=$KEYPASS" >> $GITHUB_ENV
mkdir $STOREFILEDIR
cd $STOREFILEDIR
echo y | keytool -genkeypair -dname "cn=AnkiDroid, ou=ankidroid, o=AnkiDroid, c=US" -alias $KEYALIAS -keypass $KEYPASS -keystore "$STOREFILE" -storepass $STOREPASS -keyalg RSA -validity 20000
shell: bash
- uses: actions/checkout@v4
with:
fetch-depth: 50
@ -80,7 +96,7 @@ jobs:
timeout_minutes: 15
retry_wait_seconds: 60
max_attempts: 3
command: ./gradlew packagePlayDebug packagePlayDebugAndroidTest --daemon
command: ./gradlew packagePlayRelease packagePlayReleaseAndroidTest --daemon
- name: AVD Boot and Snapshot Creation
# Only generate a snapshot for saving if we are on main branch with a cache miss
@ -147,6 +163,13 @@ jobs:
sleep 5
./gradlew uninstallAll jacocoAndroidTestReport --daemon
- name: Upload Test Report
uses: actions/upload-artifact@v4
if: always()
with:
name: ${{ matrix.api-level }}-${{ matrix.arch }}-${{matrix.target}}-${{matrix.first-boot-delay}}-${{matrix.iteration}}-jacocoAndroidTestReport
path: ~/work/Anki-Android/Anki-Android/AnkiDroid/build/reports/jacoco/
- name: Upload Emulator Log
uses: actions/upload-artifact@v4
if: always()

View File

@ -6,6 +6,7 @@ plugins {
alias(libs.plugins.kotlin.android)
alias(libs.plugins.kotlin.parcelize)
alias(libs.plugins.kotlin.serialization)
alias(libs.plugins.keeper)
id 'idea'
}
@ -15,6 +16,12 @@ repositories {
maven { url "https://jitpack.io" }
}
keeper {
traceReferences {
// Silence missing definitions
arguments.set(["--map-diagnostics:MissingDefinitionsDiagnostic", "error", "none"])
}
}
idea {
module {
@ -42,6 +49,12 @@ android {
aidl = true
}
if (rootProject.testReleaseBuild) {
testBuildType "release"
} else {
testBuildType "debug"
}
defaultConfig {
applicationId "com.ichi2.anki"
buildConfigField "Boolean", "CI", (System.getenv("CI") == "true").toString()
@ -77,6 +90,12 @@ android {
versionCode=21900107
versionName="2.19alpha7"
minSdk libs.versions.minSdk.get().toInteger()
// Stays until this is in a release: https://github.com/google/desugar_jdk_libs/commit/c01a5446ca13586b801dbba4d83c6821337b3cc2
if (testReleaseBuild && minSdk < 24) {
minSdk 24
}
// After #13695: change .tests_emulator.yml
targetSdk libs.versions.targetSdk.get().toInteger()
testApplicationId "com.ichi2.anki.tests"
@ -129,9 +148,11 @@ android {
resValue "string", "applicationId", "${defaultConfig.applicationId}${applicationIdSuffix}"
}
named('release') {
testCoverageEnabled = testReleaseBuild
minifyEnabled true
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
testProguardFile 'proguard-test-rules.pro'
splits.abi.universalApk = universalApkEnabled // Build universal APK for release with `-Duniversal-apk=true`
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
signingConfig signingConfigs.release
// syntax: assembleRelease -PcustomSuffix="suffix" -PcustomName="New name"
@ -293,7 +314,7 @@ tasks.register('assertNonzeroAndroidTests') {
}
}
afterEvaluate {
tasks.named('connectedPlayDebugAndroidTest').configure { finalizedBy('assertNonzeroAndroidTests') }
tasks.named(androidTestName).configure { finalizedBy('assertNonzeroAndroidTests') }
}
apply from: "./robolectricDownloader.gradle"

View File

@ -92,6 +92,12 @@ def fileFilter = [
'**/*$Result$*.*'
]
def classDir = 'tmp/kotlin-classes/play'
if (rootProject.testReleaseBuild)
classDir += "Release"
else
classDir += "Debug"
// Our merge report task
def testReport = tasks.register('jacocoTestReport', JacocoReport) {
def htmlOutDir = project.layout.buildDirectory.dir("reports/jacoco/$name/html").get().asFile
@ -105,7 +111,7 @@ def testReport = tasks.register('jacocoTestReport', JacocoReport) {
html.destination htmlOutDir
}
def kotlinClasses = fileTree(dir: project.layout.buildDirectory.dir('tmp/kotlin-classes/playDebug'), excludes: fileFilter)
def kotlinClasses = fileTree(dir: project.layout.buildDirectory.dir(classDir), excludes: fileFilter)
def mainSrc = "$project.projectDir/src/main/java"
sourceDirectories.from = files([mainSrc])
@ -117,7 +123,7 @@ def testReport = tasks.register('jacocoTestReport', JacocoReport) {
}
testReport.configure {
dependsOn('testPlayDebugUnitTest')
dependsOn('connectedPlayDebugAndroidTest')
dependsOn(rootProject.androidTestName)
}
// A unit-test only report task
@ -133,7 +139,7 @@ def unitTestReport = tasks.register('jacocoUnitTestReport', JacocoReport) {
html.destination htmlOutDir
}
def kotlinClasses = fileTree(dir: project.layout.buildDirectory.dir('tmp/kotlin-classes/playDebug'), excludes: fileFilter)
def kotlinClasses = fileTree(dir: project.layout.buildDirectory.dir(classDir), excludes: fileFilter)
def mainSrc = "$project.projectDir/src/main/java"
sourceDirectories.from = files([mainSrc])
@ -158,7 +164,7 @@ def androidTestReport = tasks.register('jacocoAndroidTestReport', JacocoReport)
html.destination htmlOutDir
}
def kotlinClasses = fileTree(dir: project.layout.buildDirectory.dir('tmp/kotlin-classes/playDebug'), excludes: fileFilter)
def kotlinClasses = fileTree(dir: project.layout.buildDirectory.dir(classDir), excludes: fileFilter)
def mainSrc = "$project.projectDir/src/main/java"
sourceDirectories.from = files([mainSrc])
@ -167,7 +173,8 @@ def androidTestReport = tasks.register('jacocoAndroidTestReport', JacocoReport)
'**/*.ec'
])
}
androidTestReport.configure { dependsOn('connectedPlayDebugAndroidTest') }
androidTestReport.configure { dependsOn(rootProject.androidTestName) }
// Issue 16640 - some emulators run, but register zero coverage
tasks.register('assertNonzeroAndroidTestCoverage') {

View File

@ -1,14 +1,10 @@
# Add project specific ProGuard rules here.
# By default, the flags in this file are appended to flags specified
# in C:\Program Files (x86)\Android\android-sdk/tools/proguard/proguard-android.txt
# You can edit the include path and order by changing the proguardFiles
# directive in build.gradle.kts.
# You can control the set of applied configuration files using the
# proguardFiles setting in build.gradle.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html
# Add any project specific keep options here:
# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
@ -16,16 +12,16 @@
# public *;
#}
# FIXME remove this entire Android 4.2 workaround from 12/3/15 timrae commit for 2.15.x+
# Samsung Android 4.2 bug workaround
# https://code.google.com/p/android/issues/detail?id=78377
-keepattributes **
-keep class !android.support.v7.view.menu.**,!android.support.design.internal.NavigationMenu,!android.support.design.internal.NavigationMenuPresenter,!android.support.design.internal.NavigationSubMenu,** {*;}
#5806 - Class: ActionBarOverflow
-keep public class android.support.v7.internal.view.menu.** { *; }
-keep public class androidx.appcompat.view.menu.** { *; }
-dontpreverify
-dontoptimize
-dontshrink
-dontwarn **
-dontnote **
# Uncomment this to preserve the line number information for
# debugging stack traces.
-keepattributes SourceFile,LineNumberTable
# Used through Reflection
-keep class com.ichi2.anki.**.*Fragment { *; }
-keep class * extends com.google.protobuf.GeneratedMessageLite { *; }
-keep class androidx.core.app.ActivityCompat$* { *; }
-keep class androidx.concurrent.futures.** { *; }
# Ignore unused packages
-dontwarn javax.naming.**
-dontwarn org.ietf.jgss.**

View File

@ -0,0 +1,11 @@
# These proguard rules are only needed when building
# for the combination of testing and release mode
# Certain androidx frameworks that are test-only have
# issues with proguard / minimization in release mode
# Used for testing
-keep class kotlin.test.** { *; }
-keep class **.R$layout { <init> (...); <fields>; }
# Ignore unused packages
-dontwarn com.google.protobuf.GeneratedMessageLite$*

View File

@ -1,4 +1,6 @@
import com.android.build.api.dsl.CommonExtension
import com.android.build.api.extension.impl.AndroidComponentsExtensionImpl
import com.slack.keeper.optInToKeeper
import org.gradle.api.tasks.testing.logging.TestExceptionFormat
import org.gradle.internal.jvm.Jvm
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
@ -18,6 +20,11 @@ buildscript {
}
}
}
dependencies {
// Stays until this is merged: https://github.com/slackhq/keeper/pull/147
classpath(files("${rootDir.path}/tools/keeper-gradle-plugin.jar"))
}
}
plugins {
@ -29,6 +36,7 @@ plugins {
alias(libs.plugins.kotlin.serialization) apply false
alias(libs.plugins.ktlint) apply false
alias(libs.plugins.dokka) apply false
alias(libs.plugins.keeper) apply false
}
val localProperties = java.util.Properties()
@ -64,6 +72,15 @@ subprojects {
it.systemProperties["junit.jupiter.execution.parallel.enabled"] = true
it.systemProperties["junit.jupiter.execution.parallel.mode.default"] = "concurrent"
}
val androidComponentsExtension =
extensions.findByName("androidComponents") as AndroidComponentsExtensionImpl<*, *, *>
androidComponentsExtension.beforeVariants { builder ->
if (testReleaseBuild && builder.name == "playRelease")
{
builder.optInToKeeper()
}
}
}
/**
@ -118,6 +135,11 @@ val preDexEnabled by extra("true" == System.getProperty("pre-dex", "true"))
// allows for universal APKs to be generated
val universalApkEnabled by extra("true" == System.getProperty("universal-apk", "false"))
val testReleaseBuild by extra(System.getenv("TEST_RELEASE_BUILD") == "true")
var androidTestName by extra(
if (testReleaseBuild) "connectedPlayReleaseAndroidTest" else "connectedPlayDebugAndroidTest"
)
val gradleTestMaxParallelForks by extra(
if (System.getProperty("os.name") == "Mac OS X") {
// macOS reports hardware cores. This is accurate for CI, Intel (halved due to SMT) and Apple Silicon

View File

@ -67,6 +67,7 @@ robolectric = "4.12.2"
searchpreference = "2.5.1"
seismic = "1.0.3"
sharedPreferencesMock = "1.2.4"
slackKeeper = "0.16.0"
slf4jTimber = "3.1"
timber = "5.0.1"
triplet = "3.10.0"
@ -177,3 +178,4 @@ dokka = { id = "org.jetbrains.dokka", version.ref = "dokka" }
ktlint = { id = "org.jlleitschuh.gradle.ktlint", version.ref = "ktlint" }
keeper = { id = "com.slack.keeper", version.ref = "slackKeeper" }

Binary file not shown.