From aeffbc8c915080f0137a2d4e6b1ef29cbd99e4b8 Mon Sep 17 00:00:00 2001 From: Philipp Grosswiler Date: Tue, 16 Jun 2026 11:55:41 +0200 Subject: [PATCH 01/10] feat(ios): add SwiftPM package support --- RELEASING.md | 2 +- docs/how-to/add-meshlink-to-your-app.md | 9 ++++++- docs/how-to/use-meshlink-from-swift.md | 4 +-- docs/reference/release-status.md | 7 +++--- docs/reference/repository-layout.md | 1 + meshlink-spm/Package.release.swift | 19 +++++++++++++++ meshlink-spm/Package.swift | 18 ++++++++++++++ meshlink-spm/README.md | 24 ++++++++++++++++++ meshlink/build.gradle.kts | 3 +++ scripts/spm/package-meshlink-xcframework.sh | 27 +++++++++++++++++++++ 10 files changed, 107 insertions(+), 7 deletions(-) create mode 100644 meshlink-spm/Package.release.swift create mode 100644 meshlink-spm/Package.swift create mode 100644 meshlink-spm/README.md create mode 100755 scripts/spm/package-meshlink-xcframework.sh diff --git a/RELEASING.md b/RELEASING.md index 31997175..86c62768 100644 --- a/RELEASING.md +++ b/RELEASING.md @@ -14,7 +14,7 @@ The intended first public release shape is: - a published `:meshlink` artifact for Gradle consumers - the existing generated Apple framework path for iOS Xcode hosts -- no Swift Package Manager package yet +- Swift Package Manager support for both checkout and release binary targets - no CocoaPods pod yet Artifact publication is not yet wired into this repository. That means the diff --git a/docs/how-to/add-meshlink-to-your-app.md b/docs/how-to/add-meshlink-to-your-app.md index 40b09b40..a858fb18 100644 --- a/docs/how-to/add-meshlink-to-your-app.md +++ b/docs/how-to/add-meshlink-to-your-app.md @@ -19,6 +19,7 @@ Use it when you need to: | already shares the MeshLink Gradle build | depend on `project(":meshlink")` directly | | lives in a separate Gradle repo | use a composite build with dependency substitution | | is a native iOS Xcode app | call `:meshlink:embedAndSignAppleFrameworkForXcode` from an Xcode pre-build script | +| wants SwiftPM integration | use `meshlink-spm/Package.swift` for local checkout development or `meshlink-spm/Package.release.swift` for the release binary target | ## Installation flow at a glance @@ -53,13 +54,19 @@ blockers. This repository does **not** yet publish: - a Maven Central artifact -- a Swift Package Manager package - a CocoaPods pod +Swift Package Manager support is available from this checkout via the +`meshlink-spm/` package manifests: + +- `Package.swift` for local checkout integration +- `Package.release.swift` as the release binary-target template + The supported installation paths today are: - Gradle source integration for Android or shared Kotlin code - a Gradle-built Apple framework linked by Xcode for iOS +- a SwiftPM binary target prepared from the repository checkout ## 2. Confirm the host requirements first diff --git a/docs/how-to/use-meshlink-from-swift.md b/docs/how-to/use-meshlink-from-swift.md index f5471c99..821a062d 100644 --- a/docs/how-to/use-meshlink-from-swift.md +++ b/docs/how-to/use-meshlink-from-swift.md @@ -1,12 +1,12 @@ # How to use MeshLink from Swift This guide shows you how to call MeshLink from Swift through the generated -`MeshLink` Apple framework. +`MeshLink` Apple framework or the SwiftPM binary package. Use it when: - your app code is Swift, not shared Kotlin UI or business logic -- your Xcode target already links the generated `MeshLink` framework +- your Xcode target already links the generated `MeshLink` framework or the SwiftPM package - you want the Swift-facing startup, lifecycle, flow-collection, and send patterns diff --git a/docs/reference/release-status.md b/docs/reference/release-status.md index ae757730..86c9bf3c 100644 --- a/docs/reference/release-status.md +++ b/docs/reference/release-status.md @@ -52,9 +52,10 @@ Today, supported integration paths are: - direct Gradle source integration for Android or shared Kotlin code - composite-build substitution for a separate Gradle host app - a Gradle-built Apple framework linked by Xcode for iOS +- a SwiftPM local checkout package under `meshlink-spm/` +- a SwiftPM binary-target release template under `meshlink-spm/` -There is not yet a published Maven Central artifact, Swift Package Manager -package, or CocoaPods pod. +There is not yet a published Maven Central artifact or CocoaPods pod. ## Intended first public release shape @@ -62,7 +63,7 @@ The planned first public release shape is: - publish `:meshlink` for Gradle consumers - keep the generated Apple framework path for iOS Xcode hosts -- continue without Swift Package Manager for the first release +- ship Swift Package Manager support alongside the iOS framework path - continue without CocoaPods for the first release ## Release-readiness work already in place diff --git a/docs/reference/repository-layout.md b/docs/reference/repository-layout.md index 161ca69a..cc438526 100644 --- a/docs/reference/repository-layout.md +++ b/docs/reference/repository-layout.md @@ -78,6 +78,7 @@ flowchart LR | `:meshlink-reference` | Kotlin Multiplatform library | `:meshlink` | Shared reference-app shell, screens, session model, export logic, and automation support | | `:meshlink-reference:android` | Android application module | `:meshlink-reference` | Android host application for the shared reference-app shell | | `meshlink-reference/ios` | Native Xcode project | exported `MeshLinkReference` framework from `:meshlink-reference` | iOS host application, signing, simulator, device, and UI-test workflows | +| `meshlink-spm/` | Swift Package manifests | `:meshlink` XCFramework artifacts staged under `meshlink/build/swiftpm/` | SwiftPM local checkout and release binary-target packaging | | `:meshlink-proof:android` | Android application module | `:meshlink` | Android proof and benchmark surface for physical validation | | `meshlink-proof/ios` | Native Xcode project | exported `MeshLink` framework from `:meshlink` | iOS proof and benchmark surface for physical validation | | `:benchmarks` | JVM benchmark module | `:meshlink` | Retained JVM performance baselines and benchmark tasks | diff --git a/meshlink-spm/Package.release.swift b/meshlink-spm/Package.release.swift new file mode 100644 index 00000000..64f0b2a3 --- /dev/null +++ b/meshlink-spm/Package.release.swift @@ -0,0 +1,19 @@ +// swift-tools-version: 5.9 +import PackageDescription + +let package = Package( + name: "MeshLink", + platforms: [ + .iOS(.v14), + ], + products: [ + .library(name: "MeshLink", targets: ["MeshLink"]), + ], + targets: [ + .binaryTarget( + name: "MeshLink", + url: "https://example.invalid/releases/MeshLink.xcframework.zip", + checksum: "REPLACE_WITH_SWIFT_PACKAGE_CHECKSUM" + ), + ] +) diff --git a/meshlink-spm/Package.swift b/meshlink-spm/Package.swift new file mode 100644 index 00000000..cdca187b --- /dev/null +++ b/meshlink-spm/Package.swift @@ -0,0 +1,18 @@ +// swift-tools-version: 5.9 +import PackageDescription + +let package = Package( + name: "MeshLink", + platforms: [ + .iOS(.v14), + ], + products: [ + .library(name: "MeshLink", targets: ["MeshLink"]), + ], + targets: [ + .binaryTarget( + name: "MeshLink", + path: "../meshlink/build/swiftpm/MeshLink.xcframework" + ), + ] +) diff --git a/meshlink-spm/README.md b/meshlink-spm/README.md new file mode 100644 index 00000000..9b084dd2 --- /dev/null +++ b/meshlink-spm/README.md @@ -0,0 +1,24 @@ +# MeshLink SwiftPM support + +This directory holds the Swift Package Manager manifests for MeshLink. + +## Local checkout package + +Use `Package.swift` when you are working from this repository checkout. +It points at the XCFramework staged by the packaging helper: + +```bash +./scripts/spm/package-meshlink-xcframework.sh +``` + +That helper: + +1. builds the MeshLink XCFramework from the Gradle module +2. stages it at `meshlink/build/swiftpm/MeshLink.xcframework` +3. zips the artifact for release distribution +4. prints the Swift Package checksum for the zip + +## Release package template + +Use `Package.release.swift` when preparing a release binary target. +Replace the placeholder URL and checksum with the published artifact values. diff --git a/meshlink/build.gradle.kts b/meshlink/build.gradle.kts index 0bcc52b1..7cea1ff5 100644 --- a/meshlink/build.gradle.kts +++ b/meshlink/build.gradle.kts @@ -2,6 +2,7 @@ import io.gitlab.arturbosch.detekt.Detekt import org.gradle.api.tasks.testing.Test import org.jetbrains.kotlin.gradle.ExperimentalKotlinGradlePluginApi import org.jetbrains.kotlin.gradle.dsl.JvmTarget +import org.jetbrains.kotlin.gradle.plugin.mpp.apple.XCFramework plugins { alias(libs.plugins.kotlin.multiplatform) @@ -16,6 +17,7 @@ plugins { kotlin { explicitApi() + val meshLinkXCFramework = XCFramework() jvm { compilerOptions { jvmTarget.set(JvmTarget.JVM_21) } } android { namespace = "ch.trancee.meshlink" @@ -30,6 +32,7 @@ kotlin { baseName = "MeshLink" isStatic = true binaryOption("bundleId", "ch.trancee.meshlink") + meshLinkXCFramework.add(this) } } applyDefaultHierarchyTemplate() diff --git a/scripts/spm/package-meshlink-xcframework.sh b/scripts/spm/package-meshlink-xcframework.sh new file mode 100755 index 00000000..f48183e7 --- /dev/null +++ b/scripts/spm/package-meshlink-xcframework.sh @@ -0,0 +1,27 @@ +#!/usr/bin/env bash +set -euo pipefail + +repo_root="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)" +artifact_dir="$repo_root/meshlink/build/swiftpm" +xcframework_name="MeshLink.xcframework" +xcframework_source="$repo_root/meshlink/build/XCFrameworks/release/$xcframework_name" +xcframework_staging="$artifact_dir/$xcframework_name" +zip_path="$artifact_dir/$xcframework_name.zip" +checksum_path="$artifact_dir/$xcframework_name.checksum" + +cd "$repo_root" +./gradlew :meshlink:assembleXCFramework + +rm -rf "$artifact_dir" +mkdir -p "$artifact_dir" +cp -R "$xcframework_source" "$xcframework_staging" +rm -f "$zip_path" "$checksum_path" + +cd "$artifact_dir" +zip -qry "$xcframework_name.zip" "$xcframework_name" +checksum="$(swift package compute-checksum "$xcframework_name.zip")" +printf '%s\n' "$checksum" > "$checksum_path" + +printf 'XCFramework staged at: %s\n' "$xcframework_staging" +printf 'Archive written to: %s\n' "$zip_path" +printf 'SwiftPM checksum: %s\n' "$checksum" From 3e45837cd56944318266ba6d93ba0f0fa63169df Mon Sep 17 00:00:00 2001 From: Philipp Grosswiler Date: Tue, 16 Jun 2026 12:05:16 +0200 Subject: [PATCH 02/10] feat(ios): move SwiftPM package to repo root --- ...age.release.swift => Package.release.swift | 0 meshlink-spm/Package.swift => Package.swift | 2 +- README.md | 4 ++-- RELEASING.md | 2 +- docs/how-to/add-meshlink-to-your-app.md | 8 +++---- docs/how-to/use-meshlink-from-swift.md | 4 ++-- docs/reference/release-status.md | 7 +++--- docs/reference/repository-layout.md | 3 ++- meshlink-spm/README.md | 22 ++++++------------- 9 files changed, 21 insertions(+), 31 deletions(-) rename meshlink-spm/Package.release.swift => Package.release.swift (100%) rename meshlink-spm/Package.swift => Package.swift (82%) diff --git a/meshlink-spm/Package.release.swift b/Package.release.swift similarity index 100% rename from meshlink-spm/Package.release.swift rename to Package.release.swift diff --git a/meshlink-spm/Package.swift b/Package.swift similarity index 82% rename from meshlink-spm/Package.swift rename to Package.swift index cdca187b..9e0e0398 100644 --- a/meshlink-spm/Package.swift +++ b/Package.swift @@ -12,7 +12,7 @@ let package = Package( targets: [ .binaryTarget( name: "MeshLink", - path: "../meshlink/build/swiftpm/MeshLink.xcframework" + path: "meshlink/build/swiftpm/MeshLink.xcframework" ), ] ) diff --git a/README.md b/README.md index 6e7ff482..7742743b 100644 --- a/README.md +++ b/README.md @@ -16,8 +16,8 @@ MeshLink has not cut a public stable release yet. Today, the repository is still source-distributed from a local checkout. The intended first public release shape is a published `:meshlink` artifact for -Gradle consumers while iOS continues to use the generated Apple framework path. -Swift Package Manager and CocoaPods are not part of that first-release target. +Gradle consumers while iOS can use the generated Apple framework path or the +SwiftPM package at the repository root. For the current distribution shape and remaining release blockers, use the [release status reference](docs/reference/release-status.md). diff --git a/RELEASING.md b/RELEASING.md index 86c62768..efd6a2ad 100644 --- a/RELEASING.md +++ b/RELEASING.md @@ -15,7 +15,7 @@ The intended first public release shape is: - a published `:meshlink` artifact for Gradle consumers - the existing generated Apple framework path for iOS Xcode hosts - Swift Package Manager support for both checkout and release binary targets -- no CocoaPods pod yet +- SwiftPM support at the repository root for checkout and release binary targets Artifact publication is not yet wired into this repository. That means the repository can now automate release PRs, tags, GitHub releases, and next- diff --git a/docs/how-to/add-meshlink-to-your-app.md b/docs/how-to/add-meshlink-to-your-app.md index a858fb18..f6c62dd3 100644 --- a/docs/how-to/add-meshlink-to-your-app.md +++ b/docs/how-to/add-meshlink-to-your-app.md @@ -19,7 +19,7 @@ Use it when you need to: | already shares the MeshLink Gradle build | depend on `project(":meshlink")` directly | | lives in a separate Gradle repo | use a composite build with dependency substitution | | is a native iOS Xcode app | call `:meshlink:embedAndSignAppleFrameworkForXcode` from an Xcode pre-build script | -| wants SwiftPM integration | use `meshlink-spm/Package.swift` for local checkout development or `meshlink-spm/Package.release.swift` for the release binary target | +| wants SwiftPM integration | use the root-level `Package.swift` for local checkout development or `Package.release.swift` for the release binary target | ## Installation flow at a glance @@ -54,10 +54,8 @@ blockers. This repository does **not** yet publish: - a Maven Central artifact -- a CocoaPods pod -Swift Package Manager support is available from this checkout via the -`meshlink-spm/` package manifests: +Swift Package Manager support is available from the repository root via: - `Package.swift` for local checkout integration - `Package.release.swift` as the release binary-target template @@ -66,7 +64,7 @@ The supported installation paths today are: - Gradle source integration for Android or shared Kotlin code - a Gradle-built Apple framework linked by Xcode for iOS -- a SwiftPM binary target prepared from the repository checkout +- a SwiftPM package at the repository root for local checkout or binary-target use ## 2. Confirm the host requirements first diff --git a/docs/how-to/use-meshlink-from-swift.md b/docs/how-to/use-meshlink-from-swift.md index 821a062d..74c90786 100644 --- a/docs/how-to/use-meshlink-from-swift.md +++ b/docs/how-to/use-meshlink-from-swift.md @@ -1,12 +1,12 @@ # How to use MeshLink from Swift This guide shows you how to call MeshLink from Swift through the generated -`MeshLink` Apple framework or the SwiftPM binary package. +`MeshLink` Apple framework or the root-level SwiftPM package. Use it when: - your app code is Swift, not shared Kotlin UI or business logic -- your Xcode target already links the generated `MeshLink` framework or the SwiftPM package +- your Xcode target already links the generated `MeshLink` framework or the root-level SwiftPM package - you want the Swift-facing startup, lifecycle, flow-collection, and send patterns diff --git a/docs/reference/release-status.md b/docs/reference/release-status.md index 86c9bf3c..84df80df 100644 --- a/docs/reference/release-status.md +++ b/docs/reference/release-status.md @@ -52,10 +52,10 @@ Today, supported integration paths are: - direct Gradle source integration for Android or shared Kotlin code - composite-build substitution for a separate Gradle host app - a Gradle-built Apple framework linked by Xcode for iOS -- a SwiftPM local checkout package under `meshlink-spm/` -- a SwiftPM binary-target release template under `meshlink-spm/` +- a root-level SwiftPM local checkout package (`Package.swift`) +- a root-level SwiftPM binary-target release template (`Package.release.swift`) -There is not yet a published Maven Central artifact or CocoaPods pod. +There is not yet a published Maven Central artifact. ## Intended first public release shape @@ -64,7 +64,6 @@ The planned first public release shape is: - publish `:meshlink` for Gradle consumers - keep the generated Apple framework path for iOS Xcode hosts - ship Swift Package Manager support alongside the iOS framework path -- continue without CocoaPods for the first release ## Release-readiness work already in place diff --git a/docs/reference/repository-layout.md b/docs/reference/repository-layout.md index cc438526..db2a4cbf 100644 --- a/docs/reference/repository-layout.md +++ b/docs/reference/repository-layout.md @@ -78,7 +78,8 @@ flowchart LR | `:meshlink-reference` | Kotlin Multiplatform library | `:meshlink` | Shared reference-app shell, screens, session model, export logic, and automation support | | `:meshlink-reference:android` | Android application module | `:meshlink-reference` | Android host application for the shared reference-app shell | | `meshlink-reference/ios` | Native Xcode project | exported `MeshLinkReference` framework from `:meshlink-reference` | iOS host application, signing, simulator, device, and UI-test workflows | -| `meshlink-spm/` | Swift Package manifests | `:meshlink` XCFramework artifacts staged under `meshlink/build/swiftpm/` | SwiftPM local checkout and release binary-target packaging | +| `Package.swift` | Swift Package manifest | `meshlink/build/swiftpm/MeshLink.xcframework` | SwiftPM local checkout package for Xcode and `swift package` consumers | +| `Package.release.swift` | Swift Package manifest template | published XCFramework ZIP artifact | SwiftPM release binary-target packaging | | `:meshlink-proof:android` | Android application module | `:meshlink` | Android proof and benchmark surface for physical validation | | `meshlink-proof/ios` | Native Xcode project | exported `MeshLink` framework from `:meshlink` | iOS proof and benchmark surface for physical validation | | `:benchmarks` | JVM benchmark module | `:meshlink` | Retained JVM performance baselines and benchmark tasks | diff --git a/meshlink-spm/README.md b/meshlink-spm/README.md index 9b084dd2..73407f6b 100644 --- a/meshlink-spm/README.md +++ b/meshlink-spm/README.md @@ -1,24 +1,16 @@ # MeshLink SwiftPM support -This directory holds the Swift Package Manager manifests for MeshLink. +Swift Package Manager support lives at the repository root: -## Local checkout package +- `Package.swift` for local checkout integration +- `Package.release.swift` for the release binary-target template -Use `Package.swift` when you are working from this repository checkout. -It points at the XCFramework staged by the packaging helper: +Use the packaging helper to stage the XCFramework and print the checksum: ```bash ./scripts/spm/package-meshlink-xcframework.sh ``` -That helper: - -1. builds the MeshLink XCFramework from the Gradle module -2. stages it at `meshlink/build/swiftpm/MeshLink.xcframework` -3. zips the artifact for release distribution -4. prints the Swift Package checksum for the zip - -## Release package template - -Use `Package.release.swift` when preparing a release binary target. -Replace the placeholder URL and checksum with the published artifact values. +The helper builds the MeshLink XCFramework from the Gradle module, stages it at +`meshlink/build/swiftpm/MeshLink.xcframework`, zips the artifact, and prints +the Swift Package checksum. From 4c56d22555ee41e18c5d6e1f75d5ec559db8142b Mon Sep 17 00:00:00 2001 From: Philipp Grosswiler Date: Tue, 16 Jun 2026 12:09:52 +0200 Subject: [PATCH 03/10] chore(ci): validate SwiftPM packaging --- .github/workflows/ci.yml | 28 ++++++++++++++++++++++++++++ meshlink-spm/README.md | 10 ++++++---- 2 files changed, 34 insertions(+), 4 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 04a605c0..9a0d45ae 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -100,3 +100,31 @@ jobs: build/reports/** meshlink/build/reports/** **/test-results/** + + meshlink-swiftpm-macos: + runs-on: macos-latest + timeout-minutes: 45 + + steps: + - name: Checkout + uses: actions/checkout@v6.0.2 + + - name: Set up Java + uses: actions/setup-java@v5.2.0 + with: + distribution: temurin + java-version: '21' + cache: gradle + + - name: Build SwiftPM packaging artifact + run: ./scripts/spm/package-meshlink-xcframework.sh + + - name: Upload SwiftPM packaging outputs + if: failure() + uses: actions/upload-artifact@v7.0.1 + with: + name: meshlink-swiftpm-reports + if-no-files-found: ignore + path: | + meshlink/build/swiftpm/** + meshlink/build/XCFrameworks/** diff --git a/meshlink-spm/README.md b/meshlink-spm/README.md index 73407f6b..f7ddb3c4 100644 --- a/meshlink-spm/README.md +++ b/meshlink-spm/README.md @@ -1,16 +1,18 @@ # MeshLink SwiftPM support -Swift Package Manager support lives at the repository root: +Swift Package Manager support now lives at the repository root. + +Use: - `Package.swift` for local checkout integration - `Package.release.swift` for the release binary-target template -Use the packaging helper to stage the XCFramework and print the checksum: +For packaging, run: ```bash ./scripts/spm/package-meshlink-xcframework.sh ``` -The helper builds the MeshLink XCFramework from the Gradle module, stages it at -`meshlink/build/swiftpm/MeshLink.xcframework`, zips the artifact, and prints +That helper builds the MeshLink XCFramework from the Gradle module, stages it +at `meshlink/build/swiftpm/MeshLink.xcframework`, zips the artifact, and prints the Swift Package checksum. From 3e97e689e22911d1cc1b13054ae2484bf7cfccff Mon Sep 17 00:00:00 2001 From: Philipp Grosswiler Date: Tue, 16 Jun 2026 12:28:54 +0200 Subject: [PATCH 04/10] chore(release): automate SwiftPM release assets --- .github/workflows/swiftpm-release.yml | 42 +++++++++++++++++++++++++++ RELEASING.md | 10 +++---- docs/reference/release-status.md | 1 + 3 files changed, 48 insertions(+), 5 deletions(-) create mode 100644 .github/workflows/swiftpm-release.yml diff --git a/.github/workflows/swiftpm-release.yml b/.github/workflows/swiftpm-release.yml new file mode 100644 index 00000000..671c2f55 --- /dev/null +++ b/.github/workflows/swiftpm-release.yml @@ -0,0 +1,42 @@ +name: swiftpm-release + +on: + release: + types: + - published + +permissions: + contents: write + +concurrency: + group: swiftpm-release-${{ github.event.release.tag_name }} + cancel-in-progress: false + +jobs: + package-swiftpm-release: + runs-on: macos-latest + timeout-minutes: 60 + + steps: + - name: Checkout release tag + uses: actions/checkout@v6.0.2 + with: + ref: ${{ github.event.release.tag_name }} + + - name: Set up Java + uses: actions/setup-java@v5.2.0 + with: + distribution: temurin + java-version: '21' + cache: gradle + + - name: Build SwiftPM release artifacts + run: ./scripts/spm/package-meshlink-xcframework.sh + + - name: Upload SwiftPM release assets + uses: softprops/action-gh-release@v2.2.1 + with: + tag_name: ${{ github.event.release.tag_name }} + files: | + meshlink/build/swiftpm/MeshLink.xcframework.zip + meshlink/build/swiftpm/MeshLink.xcframework.checksum diff --git a/RELEASING.md b/RELEASING.md index efd6a2ad..29e1d5d5 100644 --- a/RELEASING.md +++ b/RELEASING.md @@ -14,12 +14,12 @@ The intended first public release shape is: - a published `:meshlink` artifact for Gradle consumers - the existing generated Apple framework path for iOS Xcode hosts -- Swift Package Manager support for both checkout and release binary targets -- SwiftPM support at the repository root for checkout and release binary targets +- Swift Package Manager support at the repository root for checkout and release binary targets -Artifact publication is not yet wired into this repository. That means the -repository can now automate release PRs, tags, GitHub releases, and next- -snapshot bumps, but publishing the SDK artifact remains a separate follow-up. +Artifact publication is partially wired into this repository. The release +workflow now packages the SwiftPM XCFramework zip and checksum on published +GitHub releases, while the Maven/Gradle SDK publication and signing steps remain +separate follow-up work. ## Release automation diff --git a/docs/reference/release-status.md b/docs/reference/release-status.md index 84df80df..89f9cb99 100644 --- a/docs/reference/release-status.md +++ b/docs/reference/release-status.md @@ -71,6 +71,7 @@ The repository now has: - a maintained CI workflow for the core MeshLink SDK verification bundle - a `release-please` workflow and manifest configuration for cumulative release PRs, tags, and next-snapshot bumps +- a SwiftPM release workflow that packages the XCFramework zip and checksum for published GitHub releases - a changelog for release-facing notes - a security policy for private vulnerability reporting - a maintainer release runbook From d2a54bbc87cd0acbee34d92e714e55045d28376a Mon Sep 17 00:00:00 2001 From: Philipp Grosswiler Date: Tue, 16 Jun 2026 12:31:05 +0200 Subject: [PATCH 05/10] chore(ios): remove legacy swiftpm redirect folder --- meshlink-spm/README.md | 18 ------------------ 1 file changed, 18 deletions(-) delete mode 100644 meshlink-spm/README.md diff --git a/meshlink-spm/README.md b/meshlink-spm/README.md deleted file mode 100644 index f7ddb3c4..00000000 --- a/meshlink-spm/README.md +++ /dev/null @@ -1,18 +0,0 @@ -# MeshLink SwiftPM support - -Swift Package Manager support now lives at the repository root. - -Use: - -- `Package.swift` for local checkout integration -- `Package.release.swift` for the release binary-target template - -For packaging, run: - -```bash -./scripts/spm/package-meshlink-xcframework.sh -``` - -That helper builds the MeshLink XCFramework from the Gradle module, stages it -at `meshlink/build/swiftpm/MeshLink.xcframework`, zips the artifact, and prints -the Swift Package checksum. From 7864ac1eca07716bbf90de0280261367a6a4db58 Mon Sep 17 00:00:00 2001 From: Philipp Grosswiler Date: Tue, 16 Jun 2026 12:31:59 +0200 Subject: [PATCH 06/10] docs(release): tighten SwiftPM wording --- README.md | 2 +- RELEASING.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 7742743b..b3644c21 100644 --- a/README.md +++ b/README.md @@ -17,7 +17,7 @@ MeshLink has not cut a public stable release yet. Today, the repository is still source-distributed from a local checkout. The intended first public release shape is a published `:meshlink` artifact for Gradle consumers while iOS can use the generated Apple framework path or the -SwiftPM package at the repository root. +root-level SwiftPM package. For the current distribution shape and remaining release blockers, use the [release status reference](docs/reference/release-status.md). diff --git a/RELEASING.md b/RELEASING.md index 29e1d5d5..647e63b7 100644 --- a/RELEASING.md +++ b/RELEASING.md @@ -14,7 +14,7 @@ The intended first public release shape is: - a published `:meshlink` artifact for Gradle consumers - the existing generated Apple framework path for iOS Xcode hosts -- Swift Package Manager support at the repository root for checkout and release binary targets +- root-level Swift Package Manager support for both checkout and release binary targets Artifact publication is partially wired into this repository. The release workflow now packages the SwiftPM XCFramework zip and checksum on published From 9b58ef2e8480605f35f6051711a163a46f303491 Mon Sep 17 00:00:00 2001 From: Philipp Grosswiler Date: Tue, 16 Jun 2026 12:37:53 +0200 Subject: [PATCH 07/10] docs(release): clarify SwiftPM package root --- docs/reference/release-status.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/reference/release-status.md b/docs/reference/release-status.md index 89f9cb99..06a4ee25 100644 --- a/docs/reference/release-status.md +++ b/docs/reference/release-status.md @@ -52,8 +52,8 @@ Today, supported integration paths are: - direct Gradle source integration for Android or shared Kotlin code - composite-build substitution for a separate Gradle host app - a Gradle-built Apple framework linked by Xcode for iOS -- a root-level SwiftPM local checkout package (`Package.swift`) -- a root-level SwiftPM binary-target release template (`Package.release.swift`) +- a root-level SwiftPM local checkout package (`Package.swift` at the repository root) +- a root-level SwiftPM binary-target release template (`Package.release.swift` at the repository root) There is not yet a published Maven Central artifact. From 7a30d95f238d9f2217f1afa7d17a478789049487 Mon Sep 17 00:00:00 2001 From: Philipp Grosswiler Date: Tue, 16 Jun 2026 12:43:45 +0200 Subject: [PATCH 08/10] fix(ios): align xcframework name with framework --- meshlink/build.gradle.kts | 2 +- scripts/spm/package-meshlink-xcframework.sh | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/meshlink/build.gradle.kts b/meshlink/build.gradle.kts index 7cea1ff5..65666df6 100644 --- a/meshlink/build.gradle.kts +++ b/meshlink/build.gradle.kts @@ -17,7 +17,7 @@ plugins { kotlin { explicitApi() - val meshLinkXCFramework = XCFramework() + val meshLinkXCFramework = XCFramework("MeshLink") jvm { compilerOptions { jvmTarget.set(JvmTarget.JVM_21) } } android { namespace = "ch.trancee.meshlink" diff --git a/scripts/spm/package-meshlink-xcframework.sh b/scripts/spm/package-meshlink-xcframework.sh index f48183e7..53134b2c 100755 --- a/scripts/spm/package-meshlink-xcframework.sh +++ b/scripts/spm/package-meshlink-xcframework.sh @@ -10,7 +10,7 @@ zip_path="$artifact_dir/$xcframework_name.zip" checksum_path="$artifact_dir/$xcframework_name.checksum" cd "$repo_root" -./gradlew :meshlink:assembleXCFramework +./gradlew :meshlink:assembleMeshLinkReleaseXCFramework rm -rf "$artifact_dir" mkdir -p "$artifact_dir" From 771ff3ca68239821865c23ff2b458ed866674cb4 Mon Sep 17 00:00:00 2001 From: Philipp Grosswiler Date: Tue, 16 Jun 2026 14:19:10 +0200 Subject: [PATCH 09/10] fix(build): add slf4j nop binder --- build.gradle.kts | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/build.gradle.kts b/build.gradle.kts index aae16cbf..6fc14eeb 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -5,6 +5,12 @@ import org.gradle.api.Project import org.gradle.api.tasks.Delete import org.gradle.api.tasks.wrapper.Wrapper +buildscript { + dependencies { + classpath("org.slf4j:slf4j-nop:1.7.30") + } +} + private fun isAgpDependencyResolutionWarningListener(listener: Any): Boolean { if (listener::class.java.name.startsWith("com.android.build.gradle.internal.DependencyResolutionChecksKt$")) { return true From 3074b4ae5d738dc0c2b4570ed1eeff41e1faa771 Mon Sep 17 00:00:00 2001 From: Philipp Grosswiler Date: Tue, 16 Jun 2026 14:21:09 +0200 Subject: [PATCH 10/10] fix(test): wait for route expiry before send --- .../meshlink/integration/MeshRoutingIntegrationTest.kt | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/meshlink/src/commonTest/kotlin/ch/trancee/meshlink/integration/MeshRoutingIntegrationTest.kt b/meshlink/src/commonTest/kotlin/ch/trancee/meshlink/integration/MeshRoutingIntegrationTest.kt index bb78d698..571c72f2 100644 --- a/meshlink/src/commonTest/kotlin/ch/trancee/meshlink/integration/MeshRoutingIntegrationTest.kt +++ b/meshlink/src/commonTest/kotlin/ch/trancee/meshlink/integration/MeshRoutingIntegrationTest.kt @@ -471,6 +471,12 @@ class MeshRoutingIntegrationTest { prewarmRoute(sender = sender, recipient = recipient) harness.unlinkPeers(sender, recipient) testDelay(100) + awaitDiagnosticForPeer( + diagnostics = sender.diagnosticSink::events, + code = DiagnosticCode.ROUTE_EXPIRED, + peerIdValue = recipient.peerId.value, + routeAvailable = false, + ) // Act val sendResult = sender.meshLink.send(recipient.peerId, payload)