Files
LibreMediaConverter/gradle/libs.versions.toml
T
JMR-devandClaude Opus 5 93b1fbd5a9 Give this project the lint and formatting setup LibreMail already has
There was none: no .editorconfig, no static analysis, and CI ran only tests.
Style was whatever the IDE happened to do, which is fine until two of them
disagree.

The split is LibreMail's, because it is the one that avoids arguments between
tools: ktlint owns formatting, detekt owns static analysis with its formatting
ruleset left off. Neither can contradict the other about the same line.

Adapted rather than copied. LibreMail is Gradle 9.6 / JDK 21 with the
configuration cache off; this is Gradle 9.5 / JDK 17 with it on, and Kotlin
lives under src/main/java rather than src/main/kotlin -- so its plugin versions
were evidence, not proof. Verified here before committing: both plugins
resolve, ktlint reads src/main/java, and the run stores a configuration cache
entry rather than tripping over it.

detekt.yml carries only what applies. The Compose relaxations transfer intact
-- a @Composable function is legitimately long, PascalCase, and full of dp
literals no matter which app it is in. LibreMail's ForbiddenImport guard and
its LargeClass exclusions do not: they name an AppLog facade and two test
files that exist over there and nowhere here, and config that guards nothing
is worse than no config, because the next reader has to work out that it is
dead.

detekt 2.0 is an alpha. That is not a preference: stable 1.23.x stops at
Gradle 8.12 and this project is on 9.5, so there is no other line to be on.

Coverage is reported, not gated. A floor needs a measured baseline, and the
JVM test stack here is still junit-only -- a number picked before measuring
would either fail on day one or mean nothing.

Android lint gets warningsAsErrors because the other two tools fail on any
finding, and a gate that stays green while its report fills up is not a gate.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-22 14:09:31 -05:00

94 lines
5.3 KiB
TOML

[versions]
# Build tooling.
# NOTE: AGP 9 has BUILT-IN Kotlin support. Applying org.jetbrains.kotlin.android
# FAILS the build. AGP 9.3.1 brings kotlin-gradle-plugin 2.2.10 transitively, so the
# Compose compiler plugin below must match that version, not the newest Kotlin release.
agp = "9.3.1"
kotlin = "2.2.10"
ksp = "2.3.11"
# AndroidX / Compose
composeBom = "2026.08.00"
coreKtx = "1.19.0"
activityCompose = "1.13.0"
lifecycle = "2.11.0"
navigation = "2.9.8"
work = "2.11.2"
datastore = "1.2.1"
media3 = "1.11.0"
room = "2.8.4"
documentfile = "1.1.0"
annotation = "1.10.0"
# Test
junit = "4.13.2"
androidxJunit = "1.3.0"
espressoCore = "3.7.0"
smartException = "0.2.1"
# Lint/format. ktlint owns formatting; detekt owns static analysis (its formatting
# ruleset stays off, so the two can never disagree about the same line).
# detekt 2.0 is the only line with Gradle 9 support -- stable 1.23.x tops out at
# Gradle 8.12, and this project is on 9.5.
ktlint = "14.2.0"
detekt = "2.0.0-alpha.5"
# JaCoCo coverage agent. Pinned rather than inheriting whatever Gradle 9.5 bundles,
# so the agent version that reads Kotlin 2.2.10 bytecode is stated, not implied.
jacoco = "0.8.13"
[libraries]
androidx-core-ktx = { group = "androidx.core", name = "core-ktx", version.ref = "coreKtx" }
androidx-activity-compose = { group = "androidx.activity", name = "activity-compose", version.ref = "activityCompose" }
androidx-lifecycle-runtime-ktx = { group = "androidx.lifecycle", name = "lifecycle-runtime-ktx", version.ref = "lifecycle" }
androidx-lifecycle-runtime-compose = { group = "androidx.lifecycle", name = "lifecycle-runtime-compose", version.ref = "lifecycle" }
androidx-lifecycle-viewmodel-compose = { group = "androidx.lifecycle", name = "lifecycle-viewmodel-compose", version.ref = "lifecycle" }
# Compose — versions come from the BOM, so no version.ref here.
compose-bom = { group = "androidx.compose", name = "compose-bom", version.ref = "composeBom" }
compose-material3 = { group = "androidx.compose.material3", name = "material3" }
compose-material3-windowsize = { group = "androidx.compose.material3", name = "material3-window-size-class" }
compose-material-icons-extended = { group = "androidx.compose.material", name = "material-icons-extended" }
compose-ui = { group = "androidx.compose.ui", name = "ui" }
compose-ui-graphics = { group = "androidx.compose.ui", name = "ui-graphics" }
compose-ui-tooling = { group = "androidx.compose.ui", name = "ui-tooling" }
compose-ui-tooling-preview = { group = "androidx.compose.ui", name = "ui-tooling-preview" }
compose-ui-test-junit4 = { group = "androidx.compose.ui", name = "ui-test-junit4" }
compose-ui-test-manifest = { group = "androidx.compose.ui", name = "ui-test-manifest" }
androidx-navigation-compose = { group = "androidx.navigation", name = "navigation-compose", version.ref = "navigation" }
androidx-work-runtime-ktx = { group = "androidx.work", name = "work-runtime-ktx", version.ref = "work" }
androidx-work-testing = { group = "androidx.work", name = "work-testing", version.ref = "work" }
androidx-datastore-preferences = { group = "androidx.datastore", name = "datastore-preferences", version.ref = "datastore" }
androidx-documentfile = { group = "androidx.documentfile", name = "documentfile", version.ref = "documentfile" }
androidx-annotation = { group = "androidx.annotation", name = "annotation", version.ref = "annotation" }
# Media3 — the hardware fast path (Apache-2.0).
media3-transformer = { group = "androidx.media3", name = "media3-transformer", version.ref = "media3" }
media3-effect = { group = "androidx.media3", name = "media3-effect", version.ref = "media3" }
media3-common = { group = "androidx.media3", name = "media3-common", version.ref = "media3" }
media3-exoplayer = { group = "androidx.media3", name = "media3-exoplayer", version.ref = "media3" }
media3-muxer = { group = "androidx.media3", name = "media3-muxer", version.ref = "media3" }
# Room — job history. Added in a later phase; KSP plugin stays unapplied until then.
androidx-room-runtime = { group = "androidx.room", name = "room-runtime", version.ref = "room" }
androidx-room-ktx = { group = "androidx.room", name = "room-ktx", version.ref = "room" }
androidx-room-compiler = { group = "androidx.room", name = "room-compiler", version.ref = "room" }
# Required at runtime by the ffmpeg-kit-next wrapper: AbstractSession.fail()
# references smartexception.java.Exceptions. Debug builds tolerate its absence through
# lazy class loading, so this only surfaces as a crash on the first FFmpeg error --
# or, as it did here, as an R8 missing-class error.
smart-exception-java = { group = "com.arthenica", name = "smart-exception-java", version.ref = "smartException" }
junit = { group = "junit", name = "junit", version.ref = "junit" }
androidx-junit = { group = "androidx.test.ext", name = "junit", version.ref = "androidxJunit" }
androidx-espresso-core = { group = "androidx.test.espresso", name = "espresso-core", version.ref = "espressoCore" }
[plugins]
android-application = { id = "com.android.application", version.ref = "agp" }
kotlin-compose = { id = "org.jetbrains.kotlin.plugin.compose", version.ref = "kotlin" }
ksp = { id = "com.google.devtools.ksp", version.ref = "ksp" }
ktlint = { id = "org.jlleitschuh.gradle.ktlint", version.ref = "ktlint" }
detekt = { id = "dev.detekt", version.ref = "detekt" }
# DO NOT add org.jetbrains.kotlin.android — AGP 9 built-in Kotlin makes it a build failure.