diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 21df66e..b6cab19 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -11,6 +11,10 @@ on: # Always run on PRs pull_request: +concurrency: + group: 'ci-${{ github.event.merge_group.head_ref || github.head_ref }}-${{ github.workflow }}' + cancel-in-progress: true + env: # Test on API 30 because that's the first version with ATDs API_LEVEL: '30' @@ -18,13 +22,14 @@ env: jobs: build: - name: ${{ matrix.job }} / AGP ${{ matrix.agp }} + name: ${{ matrix.job }} / AGP ${{ matrix.agp }} / OS ${{ matrix.os }} # Use macOS for emulator hardware acceleration - runs-on: 'ubuntu-latest' + runs-on: ${{ matrix.os }} timeout-minutes: 30 strategy: fail-fast: false # We want to see all results matrix: + os: [ 'ubuntu-latest', 'windows-latest', 'macos-latest'] agp: ['8.4.0', '8.5.0-alpha08'] job: ['instrumentation', 'plugin'] env: @@ -58,11 +63,18 @@ jobs: if: matrix.job == 'instrumentation' run: ./gradlew :sample:minifyExternalStagingWithR8 validateL8 --stacktrace + - name: Enable KVM group perms + if: matrix.job == 'instrumentation' && matrix.os == 'ubuntu-latest' + 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 + # TODO AVD caching disabled due to https://github.com/ReactiveCircus/android-emulator-runner/issues/278 # - name: AVD cache # uses: actions/cache@v3 # id: avd-cache -# if: matrix.job == 'instrumentation' +# if: matrix.job == 'instrumentation' && matrix.os == 'ubuntu-latest' # with: # path: | # ~/.android/avd/* @@ -71,7 +83,7 @@ jobs: # key: avd-${{ env.API_LEVEL }}-${{ env.AVD_TARGET }} # # - name: Create AVD and generate snapshot for caching -# if: matrix.job == 'instrumentation' && steps.avd-cache.outputs.cache-hit != 'true' +# if: matrix.job == 'instrumentation' && matrix.os == 'ubuntu-latest' && steps.avd-cache.outputs.cache-hit != 'true' # uses: reactivecircus/android-emulator-runner@v2 # with: # api-level: ${{ env.API_LEVEL }} @@ -84,7 +96,7 @@ jobs: # script: echo "Generated AVD snapshot for caching." - name: Run instrumentation tests - if: matrix.job == 'instrumentation' + if: matrix.job == 'instrumentation' && matrix.os == 'ubuntu-latest' uses: reactivecircus/android-emulator-runner@v2 with: api-level: ${{ env.API_LEVEL }} @@ -105,16 +117,14 @@ jobs: adb uninstall com.slack.keeper.sample || true adb uninstall com.slack.keeper.sample.androidTest || true - - name: (Fail-only) Bundle the build report - if: failure() - run: find . -type d -name 'reports' | zip -@ -r build-reports.zip - - - name: (Fail-only) Upload the build report + - name: (Fail-only) Upload the build reports if: failure() uses: actions/upload-artifact@v3 with: - name: error-report-${{ matrix.job }}-${{ matrix.agp }} - path: build-reports.zip + name: error-report-${{ matrix.job }}-${{ matrix.agp }}-${{ matrix.os }} + path: | + keeper-gradle-plugin/build/reports + sample/build/reports publish-snapshots: name: Publish Snapshots diff --git a/keeper-gradle-plugin/src/main/java/com/slack/keeper/ZipFlingerExt.kt b/keeper-gradle-plugin/src/main/java/com/slack/keeper/ZipFlingerExt.kt index 1b1c4a2..672b4ce 100644 --- a/keeper-gradle-plugin/src/main/java/com/slack/keeper/ZipFlingerExt.kt +++ b/keeper-gradle-plugin/src/main/java/com/slack/keeper/ZipFlingerExt.kt @@ -30,7 +30,18 @@ internal fun File.classesSequence(): Sequence> { .filter { it.extension == "class" } .filterNot { "META-INF" in it.name } .sortedBy { it.invariantSeparatorsPath } - .map { it.absolutePath.removePrefix(prefix).removePrefix("/") to it } + .map { + // zip specification "4.4.17.1 file name: (Variable)" items: + it.absolutePath + // "The name of the file, with optional relative path. + // The path stored MUST NOT contain a drive or + // device letter, or a leading slash" + .removePrefix(prefix) + .removePrefix(File.separator) + // "All slashes MUST be forward slashes '/' as opposed + // to backwards slashes '\' for compatibility" + .replace(File.separator, "/") to it + } } /** Extracts classes from the target [jar] into this archive. */ diff --git a/keeper-gradle-plugin/src/test/kotlin/com/slack/keeper/KeeperFunctionalTest.kt b/keeper-gradle-plugin/src/test/kotlin/com/slack/keeper/KeeperFunctionalTest.kt index 92521a0..d2bdbb8 100644 --- a/keeper-gradle-plugin/src/test/kotlin/com/slack/keeper/KeeperFunctionalTest.kt +++ b/keeper-gradle-plugin/src/test/kotlin/com/slack/keeper/KeeperFunctionalTest.kt @@ -118,7 +118,8 @@ internal class KeeperFunctionalTest { projectDir.generatedChild("ExternalStagingAndroidTest/inferredKeepRules.pro") assertThat(generatedRules.readText().trim()) .isEqualTo( - EXPECTED_TRACE_REFERENCES_CONFIG.map { indentRules(it.key, it.value) }.joinToString("\n") + EXPECTED_TRACE_REFERENCES_CONFIG.map { indentRules(it.key, it.value) } + .joinToString(System.lineSeparator()) ) // Finally - verify our rules were included in the final minification execution. @@ -292,7 +293,11 @@ private val EXPECTED_TRACE_REFERENCES_CONFIG: Map?> = private fun indentRules(header: String, content: List?) = if (content == null) header else { - "$header {\n${content.joinToString("\n") { " $it" }}\n}" + "$header {" + + System.lineSeparator() + + content.joinToString(System.lineSeparator()) { " $it" } + + System.lineSeparator() + + "}" } @Language("PROGUARD") @@ -399,7 +404,10 @@ private fun buildGradleFile( id 'com.slack.keeper' } - java { toolchain { languageVersion.set(JavaLanguageVersion.of(21)) } } + // Ideally we use toolchains for a known version; this fails on windows w/WindowsRegistry access issues + // See: https://github.com/gradle/native-platform/issues/274 + // So we will just rely on environment JDK + //java { toolchain { languageVersion.set(JavaLanguageVersion.of(21)) } } tasks.withType(KotlinCompile).configureEach { compilerOptions { jvmTarget.set(JvmTarget.JVM_11) } } @@ -480,7 +488,7 @@ private fun buildGradleFile( } dependencies { - ${extraDependencies.entries.joinToString("\n") { " ${it.key} ${it.value}" }} + ${extraDependencies.entries.joinToString(System.lineSeparator()) { " ${it.key} ${it.value}" }} } """ .trimIndent()