Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
416e806
Update Gradle wrapper to 8.14.4 and foojay-resolver-convention plugin…
solcott May 21, 2026
f7d757b
Update GitHub Actions in CI workflow
solcott May 21, 2026
9fd9dfc
Remove redundant explicit nativeMain dependency on commonMain
solcott May 21, 2026
b5e3f2d
Remove deprecated kotlin.js.compiler=ir from gradle.properties
solcott May 21, 2026
2400595
Move ktlint import-ordering rule to .editorconfig
solcott May 21, 2026
68cc08c
Update Kotlin compiler options and multiplatform configuration
solcott May 21, 2026
92b875c
Configure Gradle Daemon JVM toolchain to Azul JDK 17
solcott May 21, 2026
7f4ee8d
Modernize build configuration and centralize version management
solcott May 22, 2026
df89a2f
Migrate to Android Kotlin Multiplatform Library plugin and update dep…
solcott May 22, 2026
1047128
Configure KMMBridge for Swift Package Manager publishing
solcott May 26, 2026
3b7d333
Modernize Gradle configuration and migrate plugins to Version Catalog
solcott May 29, 2026
b8b97be
Update atomicFu to 0.33.0 in libs.versions.toml
solcott Jun 1, 2026
6caf3c6
Update CI workflow to include test reporting and conditional Codecov …
solcott Jun 1, 2026
46828f9
Configure JS test tasks in KotlinMultiplatformConventionPlugin
solcott Jun 1, 2026
9382830
Add write permissions to KMMBridge workflows
solcott Jun 1, 2026
08ac065
Enable KMM publishing and configure GitHub release artifacts
solcott Jun 1, 2026
578956b
Remove JUnit report publishing from CI workflow
solcott Jun 2, 2026
82d8c57
Consolidate KMMBridge publishing into one release-only workflow
solcott Jun 2, 2026
89e395b
Update Gradle wrapper to 9.6.1
solcott Jul 13, 2026
82b13b3
Update Gradle plugin versions for Maven Publish and Spotless
solcott Jul 13, 2026
1d9383d
Remove `kotlinx-atomicfu` dependency from `KotlinMultiplatformConvent…
solcott Jul 18, 2026
a1f2ec3
Update Android Gradle Plugin and Kover versions
solcott Jul 18, 2026
5cdb72b
Remove permissions from build-and-test job in CI workflow
solcott Jul 18, 2026
1faf0d2
Rename KMMBridge-Publish workflow and update local build instructions
solcott Jul 19, 2026
6b18ec7
Consolidate project version into the version catalog
solcott Jul 19, 2026
b671403
Remove stale Android BCV api dumps
solcott Jul 20, 2026
9805deb
Extract formatting setup into a convention plugin
solcott Jul 20, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
root = true

[*.{kt,kts}]
ktlint_standard_import-ordering = disabled
12 changes: 12 additions & 0 deletions .github/workflows/KMMBridge-Release.yml

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is there not a KMMBridge-Debug.yml / KMMBridge-Release.yml?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good call on the naming — I've renamed KMMBridge-Publish.ymlKMMBridge-Release.yml to make the intent explicit. It's now based on KMMBridge's new recommended flow ([Base-Publish.yml](https://github.com/touchlab/KMMBridgeSPMQuickStart/blob/main/.github/workflows/Base-Publish.yml)), since a lot changed since the version we previously used.

There's no KMMBridge-Debug.yml because only release is something we distribute:

  • The SPM Package.swift binary target can point at one XCFramework URL per tag, so a separate debug variant isn't independently consumable — a second publish would just overwrite the manifest.
  • Debug XCFrameworks are a local dev concern. When you need to step through Kotlin from Xcode, KMMBridge builds one on demand via ./gradlew store:spmDevBuild, which rewrites Package.swift to a local path — no CI or Release upload. So a debug workflow would have nothing to publish.

I've also fixed the stale line-1 comment that claimed it published "both debug and release."

Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# Publish the release XCFramework to a GitHub Release.
# Debug XCFrameworks are built locally on demand via `./gradlew <module>:spmDevBuild`.
name: KMMBridge-Publish
on:
workflow_dispatch:

jobs:
call-publish:
permissions:
contents: write
packages: write
uses: ./.github/workflows/create_swift_package.yml
18 changes: 9 additions & 9 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ jobs:
api-level: [ 29 ]
steps:
- name: Checkout
uses: actions/checkout@v4
uses: actions/checkout@v6
with:
# PR builds (including forks) check out the PR head from its source repo;
# push builds fall back to the pushed ref on this repo. Without the
Expand All @@ -31,26 +31,26 @@ jobs:
persist-credentials: false

- name: Set up JDK 17
uses: actions/setup-java@v4
uses: actions/setup-java@v5
with:
distribution: 'zulu'
java-version: '17'

- name: Setup Gradle
uses: gradle/gradle-build-action@v3
uses: gradle/actions/setup-gradle@v6

- name: Grant execute permission for Gradlew
run: chmod +x gradlew

- name: Build and Test with Coverage
run: ./gradlew clean build koverXmlReport --stacktrace
run: ./gradlew clean build koverXmlReport --stacktrace --continue

- name: Upload Coverage to Codecov
# Secrets (including CODECOV_TOKEN) are not exposed to fork PRs, so the
# upload would fail under fail_ci_if_error. Skip it for forks; coverage is
# still uploaded and enforced for same-repo PRs and pushes to main.
if: ${{ github.event.pull_request.head.repo.full_name == github.repository || github.event_name != 'pull_request' }}
uses: codecov/codecov-action@v4
uses: codecov/codecov-action@v6
with:
token: ${{ secrets.CODECOV_TOKEN }}
files: build/reports/kover/coverage.xml
Expand All @@ -65,23 +65,23 @@ jobs:
needs: build-and-test
steps:
- name: Checkout
uses: actions/checkout@v4
uses: actions/checkout@v6

- name: Set up JDK 17
uses: actions/setup-java@v4
uses: actions/setup-java@v5
with:
distribution: 'zulu'
java-version: '17'

- name: Setup Gradle
uses: gradle/gradle-build-action@v3
uses: gradle/actions/setup-gradle@v6

- name: Grant execute permission for Gradlew
run: chmod +x gradlew

- name: Retrieve Version
run: |
echo "VERSION_NAME=$(grep -w 'VERSION_NAME' gradle.properties | cut -d'=' -f2)" >> $GITHUB_ENV
echo "VERSION_NAME=$(grep -E '^store[[:space:]]*=' gradle/libs.versions.toml | head -1 | cut -d'"' -f2)" >> $GITHUB_ENV

- name: Publish to Maven Central (Central Portal)
env:
Expand Down
68 changes: 64 additions & 4 deletions .github/workflows/create_swift_package.yml
Original file line number Diff line number Diff line change
@@ -1,7 +1,67 @@
name: Create Swift Package
# Based on: https://github.com/touchlab/KMMBridgeSPMQuickStart/blob/main/.github/workflows/Base-Publish.yml
# Publishes the release XCFrameworks to a GitHub Release.
# For debugging Kotlin from Xcode, build a debug XCFramework locally with
# `./gradlew <module>:spmDevBuild` instead.
name: Base-Publish

on:
workflow_dispatch:
workflow_call:

permissions:
contents: write
packages: write

jobs:
publish:
uses: touchlab/KMMBridgeGithubWorkflow/.github/workflows/faktorybuildbranches.yml@v0.6
kmmbridgepublish:
concurrency: "kmmbridgepublish-${{ github.repository }}"
runs-on: macos-latest
steps:
- name: Checkout the repo with tags
uses: actions/checkout@v6
with:
fetch-depth: 0
fetch-tags: true

- name: Retrieve Version
id: versionPropertyValue
run: |
VERSION=$(grep -E '^store[[:space:]]*=' gradle/libs.versions.toml | head -1 | cut -d'"' -f2)
echo "propVal=$VERSION" >> $GITHUB_OUTPUT

- name: Set up JDK 17
uses: actions/setup-java@v5
with:
distribution: 'zulu'
java-version: '17'

- name: Setup Gradle
uses: gradle/actions/setup-gradle@v6

- name: Grant execute permission for Gradlew
run: chmod +x gradlew

- name: Create or Find Artifact Release
id: devrelease
uses: softprops/action-gh-release@v2
with:
token: ${{ secrets.GITHUB_TOKEN }}
tag_name: "${{ steps.versionPropertyValue.outputs.propVal }}"

- name: Build and Publish
run: |
./gradlew kmmBridgePublish \
-PNATIVE_BUILD_TYPE=RELEASE \
-PGITHUB_ARTIFACT_RELEASE_ID=${{ steps.devrelease.outputs.id }} \
-PGITHUB_PUBLISH_TOKEN=${{ secrets.GITHUB_TOKEN }} \
-PGITHUB_REPO=${{ github.repository }} \
-PENABLE_PUBLISHING=true \
--no-daemon --info --stacktrace
env:
GRADLE_OPTS: -Dkotlin.incremental=false -Dorg.gradle.jvmargs="-Xmx3g -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8 -XX:MaxMetaspaceSize=512m"

- uses: touchlab/ga-update-release-tag@v1
id: update-release-tag
with:
commitMessage: "KMP SPM package release for ${{ steps.versionPropertyValue.outputs.propVal }}"
tagMessage: "KMP release version ${{ steps.versionPropertyValue.outputs.propVal }}"
tagVersion: ${{ steps.versionPropertyValue.outputs.propVal }}
74 changes: 25 additions & 49 deletions build.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,63 +1,39 @@
import org.jetbrains.kotlin.gradle.dsl.JvmTarget
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile

plugins {
alias(libs.plugins.android.kotlin.multiplatform) apply false
alias(libs.plugins.android.library) apply false
alias(libs.plugins.kotlin.multiplatform) apply false
alias(libs.plugins.kotlin.serialization) apply false
alias(libs.plugins.dokka) apply false
alias(libs.plugins.vanniktech.maven.publish) apply false
alias(libs.plugins.atomicfu) apply false
alias(libs.plugins.kotlin.cocoapods) apply false
alias(libs.plugins.ktlint)
id("com.diffplug.spotless") version "6.4.1"
}

buildscript {
repositories {
mavenCentral()
gradlePluginPortal()
google()
}

dependencies {
classpath(libs.android.gradle.plugin)
classpath(libs.kotlin.gradle.plugin)
classpath(libs.kotlin.serialization.plugin)
classpath(libs.dokka.gradle.plugin)
classpath(libs.ktlint.gradle.plugin)
classpath(libs.jacoco.gradle.plugin)
classpath(libs.maven.publish.plugin)
classpath(libs.atomic.fu.gradle.plugin)
classpath(libs.kmmBridge.gradle.plugin)
classpath(libs.binary.compatibility.validator)
}
}

allprojects {
repositories {
mavenCentral()
google()
}
}

subprojects {
apply(plugin = "org.jlleitschuh.gradle.ktlint")
apply(plugin = "com.diffplug.spotless")

ktlint {
disabledRules.add("import-ordering")
}

spotless {
kotlin {
target("src/**/*.kt")
}
}
alias(libs.plugins.spotless)
alias(libs.plugins.binary.compatibility.validator) apply false
alias(libs.plugins.kmmbridge.github) apply false
}

tasks {
withType<org.jetbrains.kotlin.gradle.tasks.KotlinCompile> {
kotlinOptions {
jvmTarget = "11"
withType<KotlinCompile> {
compilerOptions {
jvmTarget = JvmTarget.fromTarget(libs.versions.jvmCompat.get())
}
}

withType<JavaCompile>().configureEach {
sourceCompatibility = JavaVersion.VERSION_11.name
targetCompatibility = JavaVersion.VERSION_11.name
sourceCompatibility = libs.versions.jvmCompat.get()
targetCompatibility = libs.versions.jvmCompat.get()
}
}

// Workaround for https://youtrack.jetbrains.com/issue/KT-62040
tasks.getByName("wrapper")

tasks.named<UpdateDaemonJvm>("updateDaemonJvm") {
// JDK 17 is the minimum version supported by the org.gradle.toolchains.foojay-resolver-convention plugin
languageVersion = JavaLanguageVersion.of(17)
vendor.set(JvmVendorSpec.AZUL)
}
69 changes: 0 additions & 69 deletions cache/api/android/cache.api

This file was deleted.

2 changes: 1 addition & 1 deletion cache/api/jvm/cache.api

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you re-run apiDump - I would have expected the Android dumps to regenerate too

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The jvm() and android targets use different compilation backends with different -jvm-default modes.

Kotlin 2.2 changed the default -jvm-default from disable to enable. Under enable, an interface method with a default body (getAllPresent()) is emitted as a real JVM default method — non-abstract in the dump, with DefaultImpls kept for compat. The jvm() target picked this up on the Kotlin bump; the android target (compiled by AGP) pins its own mode and stayed on the old abstract + DefaultImpls shape.

Three ways to reconcile, your call:

  • disable on JVM → both revert to abstract + DefaultImpls.
  • enable on Android → both match the new JVM shape (real default method + DefaultImpls).
  • no-compatibility on both → both drop DefaultImpls, real default method only.

The last two emit real interface default methods, which Android supports at API 24+ — safe since minSdk = 24.

Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
public abstract interface class org/mobilenativefoundation/store/cache5/Cache {
public abstract fun getAllPresent ()Ljava/util/Map;
public fun getAllPresent ()Ljava/util/Map;
public abstract fun getAllPresent (Ljava/util/List;)Ljava/util/Map;
public abstract fun getIfPresent (Ljava/lang/Object;)Ljava/lang/Object;
public abstract fun getOrPut (Ljava/lang/Object;Lkotlin/jvm/functions/Function0;)Ljava/lang/Object;
Expand Down
8 changes: 2 additions & 6 deletions cache/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -5,22 +5,18 @@ plugins {
kotlin {

sourceSets {
val commonMain by getting {
commonMain {
dependencies {
api(libs.kotlinx.atomic.fu)
api(projects.core)
implementation(libs.kotlinx.coroutines.core)
}
}
val commonTest by getting {
commonTest {
dependencies {
implementation(libs.junit)
implementation(libs.kotlinx.coroutines.test)
}
}
}
}

android {
namespace = "org.mobilenativefoundation.store.cache"
}
2 changes: 0 additions & 2 deletions cache/src/androidMain/AndroidManifest.xml

This file was deleted.

Loading