Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
28 changes: 28 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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/**
42 changes: 42 additions & 0 deletions .github/workflows/swiftpm-release.yml
Original file line number Diff line number Diff line change
@@ -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
19 changes: 19 additions & 0 deletions Package.release.swift
Original file line number Diff line number Diff line change
@@ -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"
),
]
)
18 changes: 18 additions & 0 deletions Package.swift
Original file line number Diff line number Diff line change
@@ -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"
),
]
)
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
root-level SwiftPM package.

For the current distribution shape and remaining release blockers, use the
[release status reference](docs/reference/release-status.md).
Expand Down
10 changes: 5 additions & 5 deletions RELEASING.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
- no Swift Package Manager package yet
- no CocoaPods pod yet
- root-level Swift Package Manager support for both 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

Expand Down
6 changes: 6 additions & 0 deletions build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
9 changes: 7 additions & 2 deletions docs/how-to/add-meshlink-to-your-app.md
Original file line number Diff line number Diff line change
Expand Up @@ -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 the root-level `Package.swift` for local checkout development or `Package.release.swift` for the release binary target |

## Installation flow at a glance

Expand Down Expand Up @@ -53,13 +54,17 @@ 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 the repository root via:

- `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 package at the repository root for local checkout or binary-target use

## 2. Confirm the host requirements first

Expand Down
4 changes: 2 additions & 2 deletions docs/how-to/use-meshlink-from-swift.md
Original file line number Diff line number Diff line change
@@ -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 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
- 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

Expand Down
9 changes: 5 additions & 4 deletions docs/reference/release-status.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,25 +52,26 @@ 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` 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, Swift Package Manager
package, or CocoaPods pod.
There is not yet a published Maven Central artifact.

## Intended first public release shape

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
- continue without CocoaPods for the first release
- ship Swift Package Manager support alongside the iOS framework path

## Release-readiness work already in place

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
Expand Down
2 changes: 2 additions & 0 deletions docs/reference/repository-layout.md
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +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 |
| `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 |
Expand Down
3 changes: 3 additions & 0 deletions meshlink/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -16,6 +17,7 @@ plugins {

kotlin {
explicitApi()
val meshLinkXCFramework = XCFramework("MeshLink")
jvm { compilerOptions { jvmTarget.set(JvmTarget.JVM_21) } }
android {
namespace = "ch.trancee.meshlink"
Expand All @@ -30,6 +32,7 @@ kotlin {
baseName = "MeshLink"
isStatic = true
binaryOption("bundleId", "ch.trancee.meshlink")
meshLinkXCFramework.add(this)
}
}
applyDefaultHierarchyTemplate()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
27 changes: 27 additions & 0 deletions scripts/spm/package-meshlink-xcframework.sh
Original file line number Diff line number Diff line change
@@ -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:assembleMeshLinkReleaseXCFramework

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"
Loading