From 32c1e3a7716065dcea141ce45404389134291110 Mon Sep 17 00:00:00 2001 From: James Rich <2199651+jamesarich@users.noreply.github.com> Date: Fri, 17 Jul 2026 00:16:25 -0500 Subject: [PATCH] fix(build): repair main after the Kotlin 2.4 dependency merge storm MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The rapid-fire Renovate automerges each passed CI individually but broke main in combination — three separate semantic conflicts: 1. build-logic: KGP 2.4 removed the old per-flavor ABI-validation DSL (AbiValidationMultiplatformExtension, its enabled property, and filters on the MPP variant spec). Migrate to the unified abiValidation { } function on the Kotlin extension, which both enables and configures validation. 2. Kotlin 2.4.10 -> 2.4.0: SKIE 0.10.13 (latest, 2026-06-24) hard-fails on 2.4.10 — its ceiling is 2.4.0 — killing every Apple-target build. The renovate PR went green because only ubuntu jobs ran it. Pin Kotlin to 2.4.0 and bump both together once SKIE adds support. kable 0.44.x klibs (built with Kotlin 2.4.0) resolve fine. 3. kable 0.44.1 renamed ExperimentalApi -> ExperimentalKableApi; transport-ble's FakePeripheral opt-in updated. Also regenerates the ABI reference dumps under the 2.4 toolchain: internal-member mangling changed ($core -> $org_meshtastic_core), default constructors are now dumped, and transport-tcp's READ_CHUNK_BYTES / READ_TIMEOUT_MS constants left the public dump — reviewers should eyeball that last one. No published release exists yet, so dump churn has no consumer impact. Verified locally (macOS, arm64): ./gradlew :build-logic:convention:compileKotlin ./gradlew checkKotlinAbi jvmTest ./gradlew :core:iosSimulatorArm64Test \ :samples:parity-app:linkReleaseFrameworkIosSimulatorArm64 # SKIE gate ./gradlew spotlessCheck detekt Co-Authored-By: Claude Fable 5 Signed-off-by: James Rich <2199651+jamesarich@users.noreply.github.com> --- .../main/kotlin/PublishingConventionPlugin.kt | 37 +++++++------------ core/api/jvm/core.api | 5 ++- gradle/libs.versions.toml | 2 +- .../sdk/transport/ble/BleTransportHookTest.kt | 4 +- transport-tcp/api/jvm/transport-tcp.api | 2 - 5 files changed, 21 insertions(+), 29 deletions(-) diff --git a/build-logic/convention/src/main/kotlin/PublishingConventionPlugin.kt b/build-logic/convention/src/main/kotlin/PublishingConventionPlugin.kt index 514d6e1..e101fa9 100644 --- a/build-logic/convention/src/main/kotlin/PublishingConventionPlugin.kt +++ b/build-logic/convention/src/main/kotlin/PublishingConventionPlugin.kt @@ -8,12 +8,9 @@ import com.vanniktech.maven.publish.MavenPublishBaseExtension import org.gradle.api.Plugin import org.gradle.api.Project -import org.gradle.api.plugins.ExtensionAware import org.gradle.kotlin.dsl.configure import org.gradle.kotlin.dsl.getByType import org.jetbrains.kotlin.gradle.dsl.KotlinProjectExtension -import org.jetbrains.kotlin.gradle.dsl.abi.AbiValidationExtension -import org.jetbrains.kotlin.gradle.dsl.abi.AbiValidationMultiplatformExtension import org.jetbrains.kotlin.gradle.dsl.abi.ExperimentalAbiValidation class PublishingConventionPlugin : Plugin { @@ -21,28 +18,22 @@ class PublishingConventionPlugin : Plugin { override fun apply(target: Project) = with(target) { pluginManager.apply("com.vanniktech.maven.publish") - // Enable Kotlin Gradle Plugin's built-in ABI validation (Kotlin 2.2+), - // the JetBrains-supported successor to kotlinx-binary-compatibility-validator. + // Enable Kotlin Gradle Plugin's built-in ABI validation, the + // JetBrains-supported successor to kotlinx-binary-compatibility-validator. // Tasks: ./gradlew checkKotlinAbi (verify, auto-bound to check) // ./gradlew updateKotlinAbi (refresh reference dump). - // The `abiValidation` accessor is a dynamic Gradle extension on the - // KotlinProjectExtension; lookup is by name+type for plugin-id agnosticism. - plugins.withId("org.jetbrains.kotlin.multiplatform") { - val kotlin = extensions.getByType(KotlinProjectExtension::class) - val abi = (kotlin as ExtensionAware).extensions - .getByName("abiValidation") as AbiValidationMultiplatformExtension - abi.enabled.set(true) - // Hide implementation packages from the public ABI surface - // (e.g. SQLDelight-generated row classes / queries / database in - // `…internal.**`). See ADR-005 and API-P0-2. - abi.filters.exclude.byNames.add("**.internal.**") - } - plugins.withId("org.jetbrains.kotlin.jvm") { - val kotlin = extensions.getByType(KotlinProjectExtension::class) - val abi = (kotlin as ExtensionAware).extensions - .getByName("abiValidation") as AbiValidationExtension - abi.enabled.set(true) - abi.filters.exclude.byNames.add("**.internal.**") + // KGP 2.4 unified the DSL: `abiValidation { }` on the Kotlin extension + // both enables validation and configures it (the old per-flavor + // extensions and their `enabled` property were removed). + listOf("org.jetbrains.kotlin.multiplatform", "org.jetbrains.kotlin.jvm").forEach { id -> + plugins.withId(id) { + extensions.getByType(KotlinProjectExtension::class).abiValidation { + // Hide implementation packages from the public ABI surface + // (e.g. SQLDelight-generated row classes / queries / database + // in `…internal.**`). See ADR-005 and API-P0-2. + filters.exclude.byNames.add("**.internal.**") + } + } } extensions.configure { diff --git a/core/api/jvm/core.api b/core/api/jvm/core.api index 6991edb..1616526 100644 --- a/core/api/jvm/core.api +++ b/core/api/jvm/core.api @@ -174,6 +174,7 @@ public final class org/meshtastic/sdk/AdminResultException$Unauthorized : org/me public final class org/meshtastic/sdk/AutoReconnectConfig { public static final field Companion Lorg/meshtastic/sdk/AutoReconnectConfig$Companion; + public fun ()V public synthetic fun (ZJJLjava/lang/Integer;DDILkotlin/jvm/internal/DefaultConstructorMarker;)V public synthetic fun (ZJJLjava/lang/Integer;DDLkotlin/jvm/internal/DefaultConstructorMarker;)V public fun (ZLkotlin/time/Duration;Lkotlin/time/Duration;Ljava/lang/Integer;DD)V @@ -919,7 +920,7 @@ public abstract class org/meshtastic/sdk/MeshtasticException : java/lang/Excepti public final fun getOperation ()Ljava/lang/String; public final fun getTransportIdentity ()Lorg/meshtastic/sdk/TransportIdentity; public final fun getTransportIdentity-qAME2vk ()Ljava/lang/String; - public final fun setTransportIdentity$core (Lorg/meshtastic/sdk/TransportIdentity;)V + public final fun setTransportIdentity$org_meshtastic_core (Lorg/meshtastic/sdk/TransportIdentity;)V public final fun withContext (Lorg/meshtastic/sdk/MeshtasticException;Lorg/meshtastic/sdk/TransportIdentity;Ljava/lang/String;)Lorg/meshtastic/sdk/MeshtasticException; public final fun withContext-V_XA3as (Lorg/meshtastic/sdk/MeshtasticException;Ljava/lang/String;Ljava/lang/String;)Lorg/meshtastic/sdk/MeshtasticException; public static synthetic fun withContext-V_XA3as$default (Lorg/meshtastic/sdk/MeshtasticException;Lorg/meshtastic/sdk/MeshtasticException;Ljava/lang/String;Ljava/lang/String;ILjava/lang/Object;)Lorg/meshtastic/sdk/MeshtasticException; @@ -1385,6 +1386,7 @@ public abstract class org/meshtastic/sdk/RetryPolicy { } public final class org/meshtastic/sdk/RetryPolicy$ExponentialBackoff : org/meshtastic/sdk/RetryPolicy { + public fun ()V public synthetic fun (IJJDDILkotlin/jvm/internal/DefaultConstructorMarker;)V public synthetic fun (IJJDDLkotlin/jvm/internal/DefaultConstructorMarker;)V public fun (ILkotlin/time/Duration;Lkotlin/time/Duration;DD)V @@ -1411,6 +1413,7 @@ public final class org/meshtastic/sdk/RetryPolicy$ExponentialBackoff : org/mesht } public final class org/meshtastic/sdk/RetryPolicy$Fixed : org/meshtastic/sdk/RetryPolicy { + public fun ()V public synthetic fun (IJILkotlin/jvm/internal/DefaultConstructorMarker;)V public synthetic fun (IJLkotlin/jvm/internal/DefaultConstructorMarker;)V public fun (ILkotlin/time/Duration;)V diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 95c570e..19a2fe8 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -2,7 +2,7 @@ [versions] # --- Kotlin & build --- -kotlin = "2.4.10" # SKIE 0.10.12 supports up to 2.3.21 (build-logic ABI DSL + SKIE both break on 2.4.0) +kotlin = "2.4.0" # SKIE 0.10.13 ceiling — it rejects 2.4.10 outright; bump both together when SKIE releases support agp = "9.3.0" gradle = "9.5.1" javaVersion = "21" diff --git a/transport-ble/src/commonTest/kotlin/org/meshtastic/sdk/transport/ble/BleTransportHookTest.kt b/transport-ble/src/commonTest/kotlin/org/meshtastic/sdk/transport/ble/BleTransportHookTest.kt index 6c28b03..fefe985 100644 --- a/transport-ble/src/commonTest/kotlin/org/meshtastic/sdk/transport/ble/BleTransportHookTest.kt +++ b/transport-ble/src/commonTest/kotlin/org/meshtastic/sdk/transport/ble/BleTransportHookTest.kt @@ -10,7 +10,7 @@ package org.meshtastic.sdk.transport.ble import com.juul.kable.Characteristic import com.juul.kable.Descriptor import com.juul.kable.DiscoveredService -import com.juul.kable.ExperimentalApi +import com.juul.kable.ExperimentalKableApi import com.juul.kable.Identifier import com.juul.kable.Peripheral import com.juul.kable.State @@ -130,7 +130,7 @@ class BleTransportHookTest { */ // ExperimentalUuidApi: on iOS targets Kable's `Identifier` is kotlin.uuid.Uuid (experimental); // the override below trips the opt-in only when compiled for those targets. -@OptIn(ExperimentalApi::class, kotlin.uuid.ExperimentalUuidApi::class) +@OptIn(ExperimentalKableApi::class, kotlin.uuid.ExperimentalUuidApi::class) private class FakePeripheral : Peripheral { private val stateFlow = MutableStateFlow(State.Disconnected()) diff --git a/transport-tcp/api/jvm/transport-tcp.api b/transport-tcp/api/jvm/transport-tcp.api index d9fd789..cab915e 100644 --- a/transport-tcp/api/jvm/transport-tcp.api +++ b/transport-tcp/api/jvm/transport-tcp.api @@ -1,6 +1,4 @@ public final class org/meshtastic/sdk/transport/tcp/TcpTransport : org/meshtastic/sdk/RadioTransport { - public static final field READ_CHUNK_BYTES I - public static final field READ_TIMEOUT_MS J public fun (Ljava/lang/String;I)V public synthetic fun (Ljava/lang/String;IILkotlin/jvm/internal/DefaultConstructorMarker;)V public fun connect (Lkotlin/coroutines/Continuation;)Ljava/lang/Object;