diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..3f7257b --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,92 @@ +name: CI + +on: + push: + pull_request: + +permissions: + contents: read + +jobs: + linux: + name: Linux (Swift ${{ matrix.swift }}, ${{ matrix.configuration }}) + runs-on: ubuntu-24.04 + container: swift:${{ matrix.swift }}-noble + timeout-minutes: 30 + strategy: + fail-fast: false + matrix: + # The oldest supported Swift (swift-tools-version 6.2) and the newest. + swift: ["6.2", "6.4"] + configuration: [debug, release] + steps: + - uses: actions/checkout@v7 + + - name: Install SQLite + run: | + apt-get update + apt-get install -y --no-install-recommends pkg-config libsqlite3-dev + + - name: Toolchain + run: swift --version + + - name: Build (warnings are errors) + run: | + flags="-c ${{ matrix.configuration }} -Xswiftc -warnings-as-errors" + # @testable imports need testing enabled in an optimized build. + [ "${{ matrix.configuration }}" = release ] && flags="$flags -Xswiftc -enable-testing" + echo "FLAGS=$flags" >> "$GITHUB_ENV" + swift build --build-tests $flags + + - name: Test + run: swift test $FLAGS + + macos: + name: macOS (Xcode ${{ matrix.xcode }}, ${{ matrix.configuration }}) + runs-on: macos-26 + timeout-minutes: 30 + strategy: + fail-fast: false + matrix: + # The oldest Xcode with Swift 6.2, and the runner's default. + xcode: ["26.0.1", "26.6"] + configuration: [debug, release] + steps: + - uses: actions/checkout@v7 + + - name: Select Xcode + run: | + sudo xcode-select -s /Applications/Xcode_${{ matrix.xcode }}.app + swift --version + + - name: Build (warnings are errors) + run: | + flags="-c ${{ matrix.configuration }} -Xswiftc -warnings-as-errors" + # @testable imports need testing enabled in an optimized build. + [ "${{ matrix.configuration }}" = release ] && flags="$flags -Xswiftc -enable-testing" + echo "FLAGS=$flags" >> "$GITHUB_ENV" + swift build --build-tests $flags + + - name: Test + run: swift test $FLAGS + + ios: + name: iOS Simulator + runs-on: macos-26 + timeout-minutes: 30 + steps: + - uses: actions/checkout@v7 + + - name: Select Xcode + run: | + sudo xcode-select -s /Applications/Xcode_26.6.app + xcodebuild -version + + # The test target builds at the package's iOS 15 deployment target, so this also + # catches APIs that need a newer iOS. No SWIFT_TREAT_WARNINGS_AS_ERRORS: Xcode builds the + # Perfect-CRUD dependency with warnings suppressed, and the two flags conflict. The macOS + # and Linux jobs check warnings. + - name: Test + run: | + xcodebuild test -scheme PerfectSQLite \ + -destination 'platform=iOS Simulator,name=iPhone 17,OS=latest' diff --git a/Package.swift b/Package.swift index 93b1298..f52f24e 100644 --- a/Package.swift +++ b/Package.swift @@ -3,7 +3,7 @@ import PackageDescription let package = Package( name: "PerfectSQLite", - platforms: [.macOS(.v12)], + platforms: [.macOS(.v12), .iOS(.v15)], products: [ .library(name: "PerfectSQLite", targets: ["PerfectSQLite"]), ], diff --git a/README.md b/README.md index 11ce8aa..c32d5be 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,7 @@ Swift 6.2 - Platforms macOS 12+ | Linux + Platforms macOS 12+ | iOS 15+ | Linux License Apache @@ -14,7 +14,7 @@ This project provides a Swift wrapper around the SQLite 3 C library, plus a [Perfect-CRUD](https://github.com/PerfectlySoft/Perfect-CRUD) database driver built on top of it. -**Modernized for Swift 6.** Requires **swift-tools-version 6.2** and builds under full **Swift 6 language mode** (strict concurrency checking on for both the library and test targets). Supports **macOS 12+** (`platforms: [.macOS(.v12)]`) and **Linux** (tested with Swift 6.2.4, 6.3.2 and 6.4 on Ubuntu 24.04). iOS/tvOS/watchOS aren't declared or tested. +**Modernized for Swift 6.** Requires **swift-tools-version 6.2** and builds under full **Swift 6 language mode** (strict concurrency checking on for both the library and test targets). Supports **macOS 12+** and **iOS 15+** (`platforms: [.macOS(.v12), .iOS(.v15)]`) and **Linux** (tested with Swift 6.2.4, 6.3.2 and 6.4 on Ubuntu 24.04). CI runs the tests on Linux (Swift 6.2 and 6.4), macOS (Xcode 26.0.1 and 26.6) and the iOS Simulator. tvOS/watchOS/visionOS aren't declared or tested. The pre-Swift-6 version of this package is preserved on the [`legacy`](../../tree/legacy) branch. @@ -57,7 +57,7 @@ dependencies: [ and add `"PerfectSQLite"` to your target's `dependencies` array. You need the Swift 6.2 toolchain (or newer). -- **macOS:** SQLite ships with the macOS 12+ SDK; nothing else to install. If the build fails on `PerfectCSQLite` (`no such module 'PerfectCSQLite'` or `unable to resolve module dependency: 'PerfectCSQLite'`), the SDK's `SQLite3` module wasn't found: check the selected toolchain and SDK (`xcode-select -p`, `xcrun --show-sdk-path`). +- **macOS / iOS:** SQLite ships with the macOS 12+ and iOS 15+ SDKs; nothing else to install. If the build fails on `PerfectCSQLite` (`no such module 'PerfectCSQLite'` or `unable to resolve module dependency: 'PerfectCSQLite'`), the SDK's `SQLite3` module wasn't found: check the selected toolchain and SDK (`xcode-select -p`, `xcrun --show-sdk-path`). - **Linux:** install the SQLite development package (`sqlite-devel` on Fedora/RHEL), e.g. on Debian/Ubuntu: ```bash diff --git a/Tests/PerfectSQLiteTests/PerfectSQLiteTests.swift b/Tests/PerfectSQLiteTests/PerfectSQLiteTests.swift index 505888e..66edfa2 100644 --- a/Tests/PerfectSQLiteTests/PerfectSQLiteTests.swift +++ b/Tests/PerfectSQLiteTests/PerfectSQLiteTests.swift @@ -52,14 +52,14 @@ func getDB(reset: Bool = true) throws -> Database { func getTestDB() throws -> Database { let db = try getDB() try db.create(TestTable1.self, policy: .dropTable) - try db.transaction { + _ = try db.transaction { try db.table(TestTable1.self).insert((1...5).map { num -> TestTable1 in let n = UInt8(num) let blob: [UInt8]? = (num % 2 != 0) ? nil : [UInt8](arrayLiteral: n+1, n+2, n+3, n+4, n+5) return TestTable1(id: num, name: "This is name bind \(num)", integer: num, double: Double(num), blob: blob) }) } - try db.transaction { + _ = try db.transaction { try db.table(TestTable2.self).insert((1...5).flatMap { parentId -> [TestTable2] in (1...5).map { num -> TestTable2 in let n = UInt8(num) @@ -326,7 +326,7 @@ func getDB(reset: Bool = true) throws -> Database { @Test func selfJoin() throws { struct Me: Codable { let id: Int; let parentId: Int; let mes: [Me]?; init(id i: Int, parentId p: Int) { id = i; parentId = p; mes = nil } } let db = try getTestDB() - try db.transaction { + _ = try db.transaction { try db.create(Me.self, policy: .dropTable) .insert([Me(id: 1, parentId: 0), Me(id: 2, parentId: 1), Me(id: 3, parentId: 1), Me(id: 4, parentId: 1), Me(id: 5, parentId: 1)]) diff --git a/Tests/PerfectSQLiteTests/ReconcileTableTests.swift b/Tests/PerfectSQLiteTests/ReconcileTableTests.swift index 6b2647b..d33cda1 100644 --- a/Tests/PerfectSQLiteTests/ReconcileTableTests.swift +++ b/Tests/PerfectSQLiteTests/ReconcileTableTests.swift @@ -181,7 +181,7 @@ extension PerfectSQLiteTests { #expect(try columnNames(db, of: TestTable1.tableName).contains("int")) #expect(try db.table(TestTable2.self).count() == 25) // A table nothing references can still be rebuilt in one. - try db.transaction { + _ = try db.transaction { try db.create(ReducedTestTable2.self, policy: [.reconcileTable, .shallow]) } let childTable = TestTable2.CRUDTableName @@ -206,7 +206,7 @@ extension PerfectSQLiteTests { foreignKeysOn = stmt.columnInt(position: 0) } #expect(foreignKeysOn == 1) - try db.transaction { + _ = try db.transaction { try db.table(TestTable1.self).where(\TestTable1.id == 3).delete() } #expect(try db.table(TestTable2.self).count() == 20)