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
39 changes: 36 additions & 3 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,35 @@ jobs:
- name: Test
run: swift test

# Compile-only gate for the four non-macOS platforms declared in Package.swift. Tests stay macOS-only
# because they need the CoreBluetoothMock harness, not a real radio — but without this leg a change
# could silently break a declared platform.
platform-build:
name: Build (${{ matrix.platform }})
runs-on: macos-15
timeout-minutes: 30
strategy:
fail-fast: false
matrix:
platform: [iOS, tvOS, watchOS, visionOS]
steps:
- uses: actions/checkout@v4

- name: Select Xcode
run: |
if [ ! -d /Applications/Xcode_16.4.app ]; then
echo "Xcode 16.4 not found. Installed Xcode versions:"
ls /Applications | grep Xcode || true
exit 1
fi
sudo xcode-select -s /Applications/Xcode_16.4.app/Contents/Developer

- name: Build
run: |
xcodebuild build \
-scheme ReliaBLE \
-destination 'generic/platform=${{ matrix.platform }}'

docc:
name: DocC catalog
runs-on: macos-15
Expand All @@ -61,22 +90,26 @@ jobs:
# Builds the static-hosting site AND acts as the DocC validation gate on
# every PR via --warnings-as-errors. The extra static-hosting flags don't
# affect validation; they just shape the output for GitHub Pages.
#
# Output goes to ./user-docs, NOT ./docs. Publishing is by Pages artifact (below), so the
# directory name is arbitrary — and ./docs holds hand-written plans, designs, and reviews that
# generate-documentation would wipe out when this command is run locally.
- name: Build DocC catalog
run: |
swift package --allow-writing-to-directory ./docs \
swift package --allow-writing-to-directory ./user-docs \
generate-documentation --target ReliaBLE \
--disable-indexing \
--transform-for-static-hosting \
--hosting-base-path ReliaBLE \
--output-path ./docs \
--output-path ./user-docs \
--warnings-as-errors

# Only publish from master; PRs validate but do not deploy.
- name: Upload Pages artifact
if: github.ref == 'refs/heads/master'
uses: actions/upload-pages-artifact@v3
with:
path: ./docs
path: ./user-docs

deploy-docs:
name: Deploy documentation
Expand Down
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,9 @@ Packages/
docc-output/
DerivedData/

# Generated DocC static-hosting site (see the docc job in .github/workflows/ci.yml).
user-docs/

# CocoaPods
#
# We recommend against adding the Pods directory to your .gitignore. However
Expand Down
1 change: 1 addition & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -57,3 +57,4 @@ The library is built with Swift 6 and **complete concurrency checking**. The `Re
- Public API on `ReliaBLEManager` is the supported surface for external consumers. Adding/removing methods there is a breaking change.
- `forceMock: true` is currently passed to `CBCentralManagerFactory.instance(...)` in `BluetoothActor`. The production factory ignores this parameter; the mock factory honors it. Don't "clean it up" — it's load-bearing for the test target.
- DocC catalog lives at `Sources/ReliaBLE/Documentation.docc/`. The `swift-docc-plugin` is a package dep so `swift package generate-documentation` works. This documentation **must** be kept up to date with the public API on `ReliaBLEManager` and the overall architecture and usage patterns.
- **Generated DocC output goes to `./user-docs` (gitignored), never `./docs`.** `./docs` is AI agent managed plans, designs, investigations, and reviews.
10 changes: 3 additions & 7 deletions Demo/ReliaBLE Demo/ReliaBLE Demo/Central/CentralView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -278,15 +278,11 @@ private struct DeviceDetailView: View {
}

Button(action: {
let handle = reliaBLE.peripheral(id: device.id)
if isActive {
Task { try? await reliaBLE.disconnect(from: Peripheral(id: device.id)) }
Task { try? await handle.disconnect() }
} else {
Task {
try? await reliaBLE.connect(
to: Peripheral(id: device.id),
autoReconnect: autoReconnect
)
}
Task { try? await handle.connect(autoReconnect: autoReconnect) }
}
}) {
Text(isActive ? "Disconnect" : "Connect")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ actor DeviceStoreActor: ModelActor {
try? modelContext.save()
}

func syncDevices(_ peripherals: [Peripheral]) {
func syncDevices(_ peripherals: [DiscoveredPeripheral]) {
assertWritesOffMainThread()

do {
Expand Down
Loading
Loading