Skip to content

Commit 91d3578

Browse files
authored
V2: Add support for Android (#217)
* Add support for Android * Update CI for swift 6.2 * Update CI * Add Android to CI * swift format * Remove dodgy test * Update mosquitto config * Use mosquitto 2.0.22 * os(macOS) || os(Linux) || os(Android)
1 parent 90f1f64 commit 91d3578

File tree

11 files changed

+68
-64
lines changed

11 files changed

+68
-64
lines changed

.github/workflows/ci.yml

Lines changed: 48 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,11 @@ on:
44
push:
55
branches:
66
- main
7+
- v3
78
pull_request:
89
branches:
910
- main
11+
- v3
1012
release:
1113
types: [published]
1214
workflow_dispatch:
@@ -15,10 +17,19 @@ concurrency:
1517
cancel-in-progress: true
1618

1719
jobs:
18-
macos:
19-
runs-on: macOS-latest
20+
macos-unit:
21+
strategy:
22+
matrix:
23+
macos-version:
24+
- macos-15
25+
- macos-26
26+
runs-on: ${{ matrix.macos-version }}
2027
timeout-minutes: 15
2128
steps:
29+
- name: Select appropriate Xcode version
30+
uses: maxim-lobanov/setup-xcode@v1
31+
with:
32+
xcode-version: latest-stable
2233
- name: Checkout
2334
uses: actions/checkout@v6
2435
- name: Install and run Mosquitto
@@ -27,42 +38,40 @@ jobs:
2738
mosquitto -d -c mosquitto/config/mosquitto.conf
2839
- name: SPM tests
2940
run: swift test --enable-code-coverage
30-
- name: Convert coverage files
31-
run: |
32-
xcrun llvm-cov export -format "lcov" \
33-
.build/debug/mqtt-nioPackageTests.xctest/Contents/MacOs/mqtt-nioPackageTests \
34-
-ignore-filename-regex="\/Tests\/" \
35-
-instr-profile=.build/debug/codecov/default.profdata > info.lcov
36-
- name: Upload to codecov.io
37-
uses: codecov/codecov-action@v4
41+
- name: Upload coverage data
42+
uses: vapor/swift-codecov-action@v0.3
3843
with:
39-
files: info.lcov
40-
token: ${{ secrets.CODECOV_TOKEN }}
44+
codecov_token: ${{ secrets.CODECOV_TOKEN }}
4145

42-
ios:
43-
runs-on: macOS-latest
46+
ios-build:
47+
runs-on: macos-latest
4448
timeout-minutes: 15
4549
steps:
50+
- name: Select appropriate Xcode version
51+
uses: maxim-lobanov/setup-xcode@v1
52+
with:
53+
xcode-version: latest-stable
4654
- name: Checkout
4755
uses: actions/checkout@v6
4856
- name: Xcodebuild
4957
run: |
50-
xcodebuild build -scheme mqtt-nio -destination 'platform=iOS Simulator,name=iPhone 16'
58+
xcodebuild build -scheme mqtt-nio -destination 'platform=iOS Simulator,name=iPhone 17'
5159
52-
linux:
60+
linux-unit:
5361
runs-on: ubuntu-latest
5462
timeout-minutes: 15
5563
strategy:
5664
matrix:
5765
tag:
58-
- swift:5.10
5966
- swift:6.0
6067
- swift:6.1
68+
- swift:6.2
6169
container:
6270
image: ${{ matrix.tag }}
6371
services:
6472
mosquitto:
65-
image: eclipse-mosquitto
73+
# Use mosquitto 2.0.22 because we can't get 2.1.0 to work inside a GH action
74+
image: eclipse-mosquitto:2.0.22
6675
options: --name mosquitto
6776
ports:
6877
- 1883:1883
@@ -74,8 +83,9 @@ jobs:
7483
- ${{ github.workspace }}/mosquitto/config:/mosquitto/config
7584
- ${{ github.workspace }}/mosquitto/certs:/mosquitto/certs
7685
- ${{ github.workspace }}/mosquitto/socket:/mosquitto/socket
77-
7886
steps:
87+
- name: Install curl
88+
run: apt-get update -yq && apt-get install -y curl
7989
- name: Checkout
8090
uses: actions/checkout@v6
8191
- name: Restart Mosquitto
@@ -89,15 +99,23 @@ jobs:
8999
env:
90100
MOSQUITTO_SERVER: mosquitto
91101
run: |
92-
swift test --enable-test-discovery --enable-code-coverage
93-
- name: Convert coverage files
94-
run: |
95-
llvm-cov export -format="lcov" \
96-
.build/debug/mqtt-nioPackageTests.xctest \
97-
-ignore-filename-regex="\/Tests\/" \
98-
-instr-profile .build/debug/codecov/default.profdata > info.lcov
99-
- name: Upload to codecov.io
100-
uses: codecov/codecov-action@v4
102+
swift test --enable-code-coverage
103+
- name: Upload coverage data
104+
uses: vapor/swift-codecov-action@v0.3
101105
with:
102-
files: info.lcov
103-
token: ${{ secrets.CODECOV_TOKEN }}
106+
codecov_token: ${{ secrets.CODECOV_TOKEN }}
107+
108+
android-build:
109+
name: Android Build
110+
runs-on: ubuntu-latest
111+
timeout-minutes: 15
112+
strategy:
113+
fail-fast: false
114+
steps:
115+
- name: "Checkout"
116+
uses: actions/checkout@v6
117+
- name: "Build for Android"
118+
uses: skiptools/swift-android-action@v2
119+
with:
120+
build-tests: true
121+
run-tests: false

Package.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ let package = Package(
2626
.product(name: "NIOConcurrencyHelpers", package: "swift-nio"),
2727
.product(name: "NIOHTTP1", package: "swift-nio"),
2828
.product(name: "NIOWebSocket", package: "swift-nio"),
29-
.product(name: "NIOSSL", package: "swift-nio-ssl", condition: .when(platforms: [.linux, .macOS])),
29+
.product(name: "NIOSSL", package: "swift-nio-ssl", condition: .when(platforms: [.linux, .macOS, .android])),
3030
.product(name: "NIOTransportServices", package: "swift-nio-transport-services"),
3131
]
3232
),

Sources/MQTTNIO/MQTTClient.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ import NIOConcurrencyHelpers
2121
import Network
2222
import NIOTransportServices
2323
#endif
24-
#if os(macOS) || os(Linux)
24+
#if os(macOS) || os(Linux) || os(Android)
2525
import NIOSSL
2626
#endif
2727

@@ -125,7 +125,7 @@ public final class MQTTClient {
125125
case .createNew:
126126
#if canImport(Network)
127127
switch configuration.tlsConfiguration {
128-
#if os(macOS) || os(Linux)
128+
#if os(macOS) || os(Linux) || os(Android)
129129
case .niossl:
130130
self.eventLoopGroup = MultiThreadedEventLoopGroup(numberOfThreads: 1)
131131
#endif

Sources/MQTTNIO/MQTTConfiguration.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
import NIO
1515
import NIOHTTP1
1616

17-
#if os(macOS) || os(Linux)
17+
#if os(macOS) || os(Linux) || os(Android)
1818
import NIOSSL
1919
#endif
2020

@@ -32,7 +32,7 @@ extension MQTTClient {
3232
/// by this variable. It is recommended on iOS you use NIO Transport Services.
3333
public enum TLSConfigurationType {
3434
/// NIOSSL TLS configuration
35-
#if os(macOS) || os(Linux)
35+
#if os(macOS) || os(Linux) || os(Android)
3636
case niossl(TLSConfiguration)
3737
#endif
3838
#if canImport(Network)

Sources/MQTTNIO/MQTTConnection.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ import Foundation
2424
import Network
2525
import NIOTransportServices
2626
#endif
27-
#if os(macOS) || os(Linux)
27+
#if os(macOS) || os(Linux) || os(Android)
2828
import NIOSSL
2929
#endif
3030

@@ -116,7 +116,7 @@ final class MQTTConnection {
116116
switch client.configuration.tlsConfiguration {
117117
case .ts(let config):
118118
options = try config.getNWProtocolTLSOptions()
119-
#if os(macOS) || os(Linux)
119+
#if os(macOS) || os(Linux) || os(Android)
120120
case .niossl:
121121
throw MQTTError.wrongTLSConfig
122122
#endif
@@ -133,7 +133,7 @@ final class MQTTConnection {
133133
}
134134
#endif
135135

136-
#if os(macOS) || os(Linux) // canImport(Network)
136+
#if os(macOS) || os(Linux) || os(Android)
137137
if let clientBootstrap = ClientBootstrap(validatingGroup: client.eventLoopGroup) {
138138
let tlsConfiguration: TLSConfiguration
139139
switch client.configuration.tlsConfiguration {

Sources/MQTTNIO/MQTTListeners.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ final class MQTTListeners<ReturnType> {
1919

2020
func notify(_ result: ReturnType) {
2121
let listeners = self.lock.withLock {
22-
return self.listeners
22+
self.listeners
2323
}
2424
for listener in listeners.values {
2525
listener(result)

Sources/MQTTNIO/TSTLSConfiguration.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515

1616
import Foundation
1717
import Network
18-
#if os(macOS) || os(Linux)
18+
#if os(macOS) || os(Linux) || os(Android)
1919
import NIOSSL
2020
#endif
2121

@@ -98,7 +98,7 @@ public struct TSTLSConfiguration {
9898
/// Create certificate array from already loaded SecCertificate array
9999
public static func certificates(_ secCertificates: [SecCertificate]) -> Self { .init(certificates: secCertificates) }
100100

101-
#if os(macOS) || os(Linux)
101+
#if os(macOS) || os(Linux) || os(Android)
102102
/// Create certificate array from PEM file
103103
public static func pem(_ filename: String) throws -> Self {
104104
let certificates = try NIOSSLCertificate.fromPEMFile(filename)

Tests/MQTTNIOTests/MQTTNIOTests+async.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ import XCTest
2020

2121
@testable import MQTTNIO
2222

23-
#if os(macOS) || os(Linux)
23+
#if os(macOS) || os(Linux) || os(Android)
2424
import NIOSSL
2525
#endif
2626

Tests/MQTTNIOTests/MQTTNIOTests.swift

Lines changed: 4 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ import XCTest
2323
#if canImport(Network)
2424
import NIOTransportServices
2525
#endif
26-
#if os(macOS) || os(Linux)
26+
#if os(macOS) || os(Linux) || os(Android)
2727
import NIOSSL
2828
#endif
2929

@@ -568,20 +568,6 @@ final class MQTTNIOTests: XCTestCase {
568568
try client2.disconnect().wait()
569569
}
570570

571-
/// Check listeners don't create a reference cycle if they reference the client
572-
func testListenerReferenceCycle() throws {
573-
func createClient() throws -> MQTTClient? {
574-
let client = self.createClient(identifier: "testListenerReferenceCycle")
575-
client.addPublishListener(named: "refcycle") { _ in
576-
print(client)
577-
}
578-
try client.syncShutdownGracefully()
579-
return client
580-
}
581-
weak var client = try createClient()
582-
XCTAssertNil(client)
583-
}
584-
585571
func testSubscribeAll() throws {
586572
if ProcessInfo.processInfo.environment["CI"] != nil {
587573
return
@@ -756,7 +742,7 @@ final class MQTTNIOTests: XCTestCase {
756742
.joined(separator: "/")
757743

758744
static var eventLoopGroupSingleton: EventLoopGroup {
759-
#if os(Linux)
745+
#if os(Linux) || os(Android)
760746
MultiThreadedEventLoopGroup.singleton
761747
#else
762748
// Return TS Eventloop for non-Linux builds, as we use TS TLS
@@ -766,7 +752,7 @@ final class MQTTNIOTests: XCTestCase {
766752

767753
static var _tlsConfiguration: Result<MQTTClient.TLSConfigurationType, Error> = {
768754
do {
769-
#if os(Linux)
755+
#if os(Linux) || os(Android)
770756

771757
let rootCertificate = try NIOSSLCertificate.fromPEMFile(MQTTNIOTests.rootPath + "/mosquitto/certs/ca.pem")
772758
let certificate = try NIOSSLCertificate.fromPEMFile(MQTTNIOTests.rootPath + "/mosquitto/certs/client.pem")
@@ -805,7 +791,7 @@ final class MQTTNIOTests: XCTestCase {
805791
switch self._tlsConfiguration {
806792
case .success(let config):
807793
switch config {
808-
#if os(macOS) || os(Linux)
794+
#if os(macOS) || os(Linux) || os(Android)
809795
case .niossl(let config):
810796
var tlsConfig = TLSConfiguration.makeClientConfiguration()
811797
tlsConfig.trustRoots = withTrustRoots == true ? (config.trustRoots ?? .default) : .default

Tests/MQTTNIOTests/MQTTNIOv5Tests.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ import XCTest
2020

2121
@testable import MQTTNIO
2222

23-
#if os(macOS) || os(Linux)
23+
#if os(macOS) || os(Linux) || os(Android)
2424
import NIOSSL
2525
#endif
2626

@@ -417,7 +417,7 @@ final class MQTTNIOv5Tests: XCTestCase {
417417

418418
_ = try client.v5.connect().wait()
419419
let authFuture = client.v5.auth(properties: []) { _, eventLoop in
420-
return eventLoop.makeSucceededFuture(.init(reason: .continueAuthentication, properties: []))
420+
eventLoop.makeSucceededFuture(.init(reason: .continueAuthentication, properties: []))
421421
}
422422
XCTAssertThrowsError(try authFuture.wait()) { error in
423423
switch error {

0 commit comments

Comments
 (0)