From b15ad605a8e2698ce5f78673fd42debc87ebdb44 Mon Sep 17 00:00:00 2001 From: Connor Tumbleson Date: Sun, 19 Jul 2026 13:12:09 -0400 Subject: [PATCH 1/8] feat: move to v0.37.0 --- INTERNAL.md | 7 +++++-- gradle/libs.versions.toml | 2 +- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/INTERNAL.md b/INTERNAL.md index a9f47e2f3f..c63e24892e 100644 --- a/INTERNAL.md +++ b/INTERNAL.md @@ -42,12 +42,15 @@ signing.keyId={gpgKeyId} signing.password={gpgPassphrase} signing.secretKeyRingFile={gpgSecretKingRingLocation} -ossrhUsername={sonatypeUsername} -ossrhPassword={sonatypePassword} +mavenCentralUsername={sonatypeUsername} +mavenCentralPassword={sonatypePassword} ``` Release with maven with `./gradlew build shadowJar release publish`. +* Generate secret key ring - `gpg --export-secret-keys -o ~/.gnupg/secring.gpg` +* Generate Maven password - `https://central.sonatype.com/usertoken` + ### Building the binary. > [!IMPORTANT] diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 32361cf83f..881745a4ae 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -9,7 +9,7 @@ r8 = "9.1.31" smali = "b6365a84f4" # https://github.com/google/smali/issues/100 xmlpull = "1.1.3.1" xmlunit = "2.12.0" -maven-publish = "0.33.0" +maven-publish = "0.37.0" [libraries] baksmali = { module = "com.github.iBotPeaches.smali:smali-baksmali", version.ref = "baksmali" } From 4b720ef1dcfcd11a20399a7a02ba5c4e486a9de1 Mon Sep 17 00:00:00 2001 From: Connor Tumbleson Date: Sun, 19 Jul 2026 13:12:58 -0400 Subject: [PATCH 2/8] chore: maven publish is jdk 17+ --- INTERNAL.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/INTERNAL.md b/INTERNAL.md index c63e24892e..fbfb9bd0b8 100644 --- a/INTERNAL.md +++ b/INTERNAL.md @@ -54,7 +54,7 @@ Release with maven with `./gradlew build shadowJar release publish`. ### Building the binary. > [!IMPORTANT] -> In order to publish Maven artifacts you need JDK 11+. +> In order to publish Maven artifacts you need JDK 17+. In order to maintain a clean slate. Run `gradlew clean` to start from a clean slate. Now lets build the new binary version. We should not have any new commits since the tagged commit. From 7f5aa79abad6ccbc77e9832a3997ebb7d2ba2337 Mon Sep 17 00:00:00 2001 From: Connor Tumbleson Date: Mon, 20 Jul 2026 19:07:31 -0400 Subject: [PATCH 3/8] wip --- .github/workflows/build.yml | 10 +++---- brut.apktool/apktool-cli/build.gradle.kts | 4 --- build.gradle.kts | 36 +++++++++++++++++++---- settings.gradle.kts | 5 ++++ 4 files changed, 40 insertions(+), 15 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index a8d25853d7..4df3c2fcd1 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -64,18 +64,18 @@ jobs: - analyze-mac-aapt - analyze-linux-aapt - analyze-windows-aapt - name: Build/Test (JDK ${{ matrix.java }}, ${{ matrix.os }}) + name: Build (JDK 17) / Test (JDK ${{ matrix.test-java }}, ${{ matrix.os }}) strategy: fail-fast: true matrix: os: [ ubuntu-latest, macOS-latest, windows-latest ] - java: [ 8, 11, 17, 21 ] + test-java: [ 8, 11, 17, 21 ] steps: - uses: actions/checkout@v7 - uses: actions/setup-java@v5 with: distribution: 'zulu' - java-version: ${{ matrix.java }} + java-version: 17 - uses: gradle/actions/setup-gradle@v6.2.0 with: @@ -83,11 +83,11 @@ jobs: - name: Build (Linux/Mac) if: runner.os != 'Windows' - run: ./gradlew build shadowJar proguard + run: ./gradlew build shadowJar proguard -PtestJdkVersion=${{ matrix.test-java }} - name: Build (Windows) if: runner.os == 'Windows' - run: ./gradlew.bat build shadowJar proguard + run: ./gradlew.bat build shadowJar proguard -PtestJdkVersion=${{ matrix.test-java }} upload-artifact: runs-on: ubuntu-latest diff --git a/brut.apktool/apktool-cli/build.gradle.kts b/brut.apktool/apktool-cli/build.gradle.kts index 0c8f192331..45f41649e5 100644 --- a/brut.apktool/apktool-cli/build.gradle.kts +++ b/brut.apktool/apktool-cli/build.gradle.kts @@ -63,10 +63,6 @@ val shadowJar = tasks.register("shadowJar", Jar::class) { tasks.register("proguard") { dependsOn("shadowJar") - onlyIf { - JavaVersion.current().isJava11Compatible - } - val proguardRules = file("proguard-rules.pro") val originalJar = shadowJar.map { it.outputs.files.singleFile } diff --git a/build.gradle.kts b/build.gradle.kts index 88c385ee00..731cd02819 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -9,6 +9,10 @@ var apktoolVersion by extra("") defaultTasks("build", "shadowJar", "proguard") +require(JavaVersion.current().isCompatibleWith(JavaVersion.VERSION_17)) { + "Building Apktool requires JDK 17 or newer, but Gradle is running on JDK ${JavaVersion.current()}." +} + // Functions val gitDescribe: String? by lazy { try { @@ -52,9 +56,7 @@ if ("release" !in gradle.startParameter.taskNames) { plugins { `java-library` - if (JavaVersion.current().isJava11Compatible) { - alias(libs.plugins.vanniktech.maven.publish) apply false - } + alias(libs.plugins.vanniktech.maven.publish) apply false } allprojects { @@ -77,8 +79,30 @@ subprojects { apply(plugin = "java-library") java { - sourceCompatibility = JavaVersion.VERSION_1_8 - targetCompatibility = JavaVersion.VERSION_1_8 + toolchain { + languageVersion = JavaLanguageVersion.of(17) + } + } + + tasks.withType { + // Built with JDK 17, but emit Java 8 compatible bytecode against the Java 8 API. + options.release = 8 + options.compilerArgs.add("-Xlint:-options") + + options.encoding = "UTF-8" + } + + // CI passes -PtestJdkVersion to run the test suite on an older JVM (8/11) + // while the build itself stays on JDK 17. + (findProperty("testJdkVersion") as String?)?.toIntOrNull()?.let { testJdkVersion -> + val toolchains = extensions.getByType() + tasks.withType { + javaLauncher = toolchains.launcherFor { + languageVersion = JavaLanguageVersion.of(testJdkVersion) + // Zulu ships JDK 8 builds for every OS/arch we test on, including mac arm64. + vendor = JvmVendorSpec.AZUL + } + } } tasks.withType().configureEach { @@ -94,7 +118,7 @@ subprojects { "apktool-lib", "apktool-cli" ) - if (project.name in mavenProjects && JavaVersion.current().isJava11Compatible) { + if (project.name in mavenProjects) { apply(from = "${rootProject.projectDir}/gradle/scripts/publishing.gradle") } } diff --git a/settings.gradle.kts b/settings.gradle.kts index 8ef80b9f7e..8ba5092483 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -1,3 +1,8 @@ +plugins { + // Allows Gradle to auto-download the JDK requested via -PtestJdkVersion. + id("org.gradle.toolchains.foojay-resolver-convention") version "1.0.0" +} + rootProject.name = "apktool-cli" include( "brut.j.common", "brut.j.util", "brut.j.dir", "brut.j.xml", "brut.j.yaml", From 44547f81b5fae740e6699ebb07ff04413ff9cedd Mon Sep 17 00:00:00 2001 From: Connor Tumbleson Date: Wed, 22 Jul 2026 06:38:13 -0400 Subject: [PATCH 4/8] build: test on Java 25 as well --- .github/workflows/build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 4df3c2fcd1..11cd6fb1b6 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -69,7 +69,7 @@ jobs: fail-fast: true matrix: os: [ ubuntu-latest, macOS-latest, windows-latest ] - test-java: [ 8, 11, 17, 21 ] + test-java: [ 8, 11, 17, 21, 25 ] steps: - uses: actions/checkout@v7 - uses: actions/setup-java@v5 From bf5c47ece6bc01a56b03fb95467ba88f25e79a19 Mon Sep 17 00:00:00 2001 From: Connor Tumbleson Date: Wed, 22 Jul 2026 11:56:28 -0400 Subject: [PATCH 5/8] chore: fix feedback from Copilot Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> --- INTERNAL.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/INTERNAL.md b/INTERNAL.md index fbfb9bd0b8..13463700c2 100644 --- a/INTERNAL.md +++ b/INTERNAL.md @@ -40,13 +40,13 @@ need a `gradle.properties` file in root with the structure: ``` signing.keyId={gpgKeyId} signing.password={gpgPassphrase} -signing.secretKeyRingFile={gpgSecretKingRingLocation} +signing.secretKeyRingFile={gpgSecretKeyRingLocation} mavenCentralUsername={sonatypeUsername} mavenCentralPassword={sonatypePassword} ``` -Release with maven with `./gradlew build shadowJar release publish`. +Release to Maven with `./gradlew build shadowJar release publish`. * Generate secret key ring - `gpg --export-secret-keys -o ~/.gnupg/secring.gpg` * Generate Maven password - `https://central.sonatype.com/usertoken` @@ -54,7 +54,7 @@ Release with maven with `./gradlew build shadowJar release publish`. ### Building the binary. > [!IMPORTANT] -> In order to publish Maven artifacts you need JDK 17+. +> Building Apktool (and publishing Maven artifacts) requires JDK 17+. In order to maintain a clean slate. Run `gradlew clean` to start from a clean slate. Now lets build the new binary version. We should not have any new commits since the tagged commit. From 2c682a6de8b55e0db5e6be785f8602ce3f1e011e Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 23 Jul 2026 14:39:24 +0000 Subject: [PATCH 6/8] build: log test JVM path and version in doFirst to confirm toolchain selection --- build.gradle.kts | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/build.gradle.kts b/build.gradle.kts index 731cd02819..5892e276f1 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -102,6 +102,15 @@ subprojects { // Zulu ships JDK 8 builds for every OS/arch we test on, including mac arm64. vendor = JvmVendorSpec.AZUL } + doFirst { + val launcher = javaLauncher.get() + logger.lifecycle( + "[{}] Test JVM: {} (runtime: {})", + project.name, + launcher.executablePath, + launcher.metadata.javaRuntimeVersion + ) + } } } From b0fd80bdd218d5c8b6d6b685ed455caca54a68aa Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 23 Jul 2026 15:22:33 +0000 Subject: [PATCH 7/8] build: add test summary and failed/skipped event logging to all Test tasks --- build.gradle.kts | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/build.gradle.kts b/build.gradle.kts index 5892e276f1..3d1fd6472f 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -92,6 +92,25 @@ subprojects { options.encoding = "UTF-8" } + tasks.withType { + testLogging { + events("failed", "skipped") + } + afterSuite(KotlinClosure2({ descriptor, result -> + // Only print the summary for the top-level suite (the task itself, not individual classes). + if (descriptor.parent == null) { + logger.lifecycle( + "[{}] Tests: {} passed, {} failed, {} skipped (total: {})", + project.name, + result.successfulTestCount, + result.failedTestCount, + result.skippedTestCount, + result.testCount + ) + } + })) + } + // CI passes -PtestJdkVersion to run the test suite on an older JVM (8/11) // while the build itself stays on JDK 17. (findProperty("testJdkVersion") as String?)?.toIntOrNull()?.let { testJdkVersion -> From f3b36e0ae8a3bac6c7ce87ab778209c40608be57 Mon Sep 17 00:00:00 2001 From: IgorEisberg Date: Fri, 24 Jul 2026 01:16:37 +0300 Subject: [PATCH 8/8] Some cleanup --- build.gradle.kts | 22 ++++++---------------- gradlew.bat | 2 +- 2 files changed, 7 insertions(+), 17 deletions(-) diff --git a/build.gradle.kts b/build.gradle.kts index 3d1fd6472f..477145bd98 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -84,15 +84,13 @@ subprojects { } } - tasks.withType { - // Built with JDK 17, but emit Java 8 compatible bytecode against the Java 8 API. - options.release = 8 - options.compilerArgs.add("-Xlint:-options") - + tasks.withType().configureEach { options.encoding = "UTF-8" + // Build with JDK 17, but emit Java 8 compatible bytecode against the Java 8 API. + options.release.set(8) } - tasks.withType { + tasks.withType().configureEach { testLogging { events("failed", "skipped") } @@ -113,9 +111,9 @@ subprojects { // CI passes -PtestJdkVersion to run the test suite on an older JVM (8/11) // while the build itself stays on JDK 17. - (findProperty("testJdkVersion") as String?)?.toIntOrNull()?.let { testJdkVersion -> + providers.gradleProperty("testJdkVersion").orNull?.toIntOrNull()?.let { testJdkVersion -> val toolchains = extensions.getByType() - tasks.withType { + tasks.withType().configureEach { javaLauncher = toolchains.launcherFor { languageVersion = JavaLanguageVersion.of(testJdkVersion) // Zulu ships JDK 8 builds for every OS/arch we test on, including mac arm64. @@ -133,14 +131,6 @@ subprojects { } } - tasks.withType().configureEach { - options.encoding = "UTF-8" - - if (JavaVersion.current().isJava9Compatible) { - options.release.set(8) - } - } - val mavenProjects = arrayOf( "brut.j.common", "brut.j.util", "brut.j.dir", "brut.j.xml", "brut.j.yaml", "apktool-lib", "apktool-cli" diff --git a/gradlew.bat b/gradlew.bat index 25da30dbde..45667ee4cf 100644 --- a/gradlew.bat +++ b/gradlew.bat @@ -53,7 +53,7 @@ goto fail :findJavaFromJavaHome set JAVA_HOME=%JAVA_HOME:"=% -set JAVA_EXE=%JAVA_HOME%/bin/java.exe +set JAVA_EXE=%JAVA_HOME%\bin\java.exe if exist "%JAVA_EXE%" goto execute