android: run ktlint and detekt from the image, not as Gradle plugins
Android / Kotlin + Rust (debug APK) (push) Failing after 1m47s
Desktop (Tauri) / Windows installer (cross-compiled) (push) Successful in 2m6s
Desktop (Tauri) / Tauri desktop (Linux) (push) Successful in 4m2s
Desktop (Tauri) / Update manifest (push) Successful in 5s

First Android run failed at plugin resolution:

  Plugin [id: 'io.gitlab.arturbosch.detekt', version: '2.0.0-alpha.3'] was not
  found in any of the following sources

That version is published to neither Maven Central nor the plugin portal — the
latest detekt anywhere is 1.23.8. It was copied from Minstrel's catalog, where it
presumably resolves from a cached artifact; copying a pin without checking it
exists is what made it my problem.

Rather than chase a working plugin version, the analyzers now run from the CLIs
ci-rust-android already ships. That was the point of putting them in the image in
step 3, and going through Gradle plugins would have meant a SECOND pinned version
of each tool, resolved at build time, kept in lockstep with the image's by hand.
One less resolution step, and step 3's decision finally earns its keep.

Also replaces the source-ordering hack while here. Kotlin has to compile after
the bindings are generated, and the usual `tasks.withType<KotlinCompile>` cannot
be written in this build at all — AGP 9's built-in Kotlin means that class is not
on the buildscript classpath. Passing the TASK PROVIDERS to srcDir instead lets
Gradle read their @OutputDirectory and infer the ordering itself, which is the
idiomatic form and removes the dependsOn entirely.

Good news from the failed run: the Gradle wrapper check passed, so Gradle 9.1.0
on the image's JDK 25 works — the toolchain decision from step 3 holds.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-08-18 15:35:17 -04:00
co-authored by Claude Opus 5
parent 20907abf6e
commit f179928c57
4 changed files with 25 additions and 33 deletions
+8 -23
View File
@@ -3,8 +3,6 @@ import javax.inject.Inject
plugins {
alias(libs.plugins.android.application)
alias(libs.plugins.compose.compiler)
alias(libs.plugins.ktlint)
alias(libs.plugins.detekt)
}
// The Cargo workspace root — two levels up from android/app.
@@ -192,8 +190,14 @@ android {
sourceSets {
getByName("main") {
// The .so and the bindings are build outputs, not checked-in sources.
jniLibs.srcDir(jniLibsOut)
java.srcDir(bindingsOut)
// Passing the TASK PROVIDERS, not plain paths: Gradle reads each
// task's @OutputDirectory and infers the build ordering itself. A
// bare path would compile Kotlin before the bindings exist, and the
// usual fix — depending on KotlinCompile by type — cannot be written
// here, because AGP 9's built-in Kotlin means that class is not on
// the buildscript classpath.
jniLibs.srcDir(cargoNdkDebug)
java.srcDir(generateBindings)
}
}
@@ -202,25 +206,6 @@ android {
}
}
// Kotlin compilation needs the generated bindings to exist first.
tasks.withType<org.jetbrains.kotlin.gradle.tasks.KotlinCompile>().configureEach {
dependsOn(generateBindings)
}
tasks.named("preBuild") { dependsOn(generateBindings) }
// ktlint must not police generated code — it is uniffi's output, not ours, and
// there is no edit that would fix a complaint about it.
ktlint {
filter {
exclude { it.file.path.contains("generated") }
}
}
detekt {
buildUponDefaultConfig = true
config.setFrom(files("$rootDir/config/detekt.yml"))
}
dependencies {
implementation(libs.androidx.core.ktx)
implementation(libs.androidx.activity.compose)