build(ios): pin SQLCipher and make Swift Package Manager the verified iOS path - #696
Open
kklem0 wants to merge 7 commits into
Open
build(ios): pin SQLCipher and make Swift Package Manager the verified iOS path#696kklem0 wants to merge 7 commits into
kklem0 wants to merge 7 commits into
Conversation
SQLCipher 4.11.0 removed CocoaPods support ("Removes CocoaPods support
(SQLCipher.podspec.json)" in its CHANGELOG), so 4.10.0 is the last version
published to the CocoaPods trunk and this pod cannot advance past it. Pin it
there rather than leaving the dependency open, so CocoaPods resolution is
deterministic and the ceiling is visible in the podspec.
Pin the Swift package to SQLCipher.swift 4.17.0 exactly. That is the same
SQLCipher release Android uses after net.zetetic:sqlcipher-android was updated
to 4.17.0, so both native platforms sit on one SQLite baseline (3.53.3).
…spec verify:ios built the CocoaPods development workspace, whose Podfile pinned SQLCipher to ~>4.5.6. CI was therefore validating the plugin against a SQLCipher that no consumer resolves. Build the Swift package instead, which is the integration Capacitor 8 gives a new iOS project by default. build-for-testing rather than build, so the XCTest target is compiled on every run, and a generic iOS Simulator destination rather than a named simulator, so the gate does not depend on which simulators a machine happens to have. Running the tests needs a concrete device and stays a local command, documented in CONTRIBUTING.md. Compiling that target showed it has never built under Swift Package Manager: Package.swift has declared it since SPM support was added, but the source imported the Xcode workspace's module name rather than the package module, and its call to CapacitorSQLite() predates the config: parameter. Nothing built it, because the previous command used the Plugin scheme, which excludes tests. Both errors are fixed here. Add verify:ios:pod so the CocoaPods path that existing consumers depend on cannot break unnoticed. It needs --allow-warnings for six warnings that predate this change: one on the repository URL scheme, five from the plugin sources.
Nothing references ios/Podfile, ios/Plugin.xcodeproj or ios/Plugin.xcworkspace now that verify:ios builds the Swift package. Podfile.lock and Pods/ were never tracked, and the npm files whitelist only ever shipped ios/Plugin/, so none of this reached a consumer. pod lib lint covers what building the workspace covered, and covers it better: it builds the pod from the podspec in a clean-room project against the SQLCipher version consumers actually resolve, rather than against the Podfile's ~>4.5.6. Contributors open Package.swift in Xcode instead of generating a workspace first. The XCTest target is unaffected and stays at ios/PluginTests, now built by verify:ios.
Both integrations are supported and they link different SQLCipher versions, which a consumer cannot infer from anything currently written down. State the difference plainly: SQLCipher 4.17.0 and a SQLite 3.53.3 baseline on Swift Package Manager, 4.10.0 and 3.50.4 on CocoaPods, with the reason the latter cannot move and a pointer to npx cap spm-migration-assistant for projects that want to cross over. CONTRIBUTING gains the two iOS gates, the fact that the unit tests are compiled but not run by verify:ios, and the command to run them locally.
Five warnings, each fixed without changing behaviour. BiometricIDAuthentication: @unknown default does not cover a case the SDK declares, so LABiometryType.opticID made the switch non-exhaustive. It is handled explicitly and throws the same message it already produced through the default arm. It is unreachable in any case, since the package and the podspec are iOS only. UtilsDownloadFromHTTP and UtilsFile: ZIPFoundation's Archive(url:accessMode: preferredEncoding:) is deprecated in favour of a throwing initialiser. The two overloads differ only in a defaulted third label, so the call had to name pathEncoding to select the replacement; try? then yields the optional the surrounding guard already expects. The deprecated initialiser's body is try? self.init(url:accessMode:pathEncoding:), so this is the same call. UtilsSQLCipher and UtilsSQLStatement: two immutables that are computed and never read, from pure functions, so the lines are removed.
The gate was added with --allow-warnings because pod lib lint failed validation on six warnings that all predate it. Five were compiler warnings in the plugin sources and are fixed in the preceding commit. The sixth is here: package.json carries the npm form of the repository URL, git+https://..., which CocoaPods parses as a git+https scheme and reports as not being an https link. Strip the prefix once and use the result for both homepage and source, leaving package.json alone. With that, pod lib lint passes clean, so the flag comes off and the CocoaPods gate is strict.
@ionic/swiftlint-config excludes node_modules and ios/Pods but not .build, where Swift Package Manager checks its dependencies out, so npm run lint also linted ZIPFoundation and capacitor-swift-pm: 79 Swift files instead of 31, and 51 violations instead of 21. None of it is error severity today, but a dependency shipping one would fail the lint script for reasons unrelated to this repository. node-swiftlint reads its configuration through cosmiconfig, whose search order puts the package.json swiftlint key ahead of any config file, and the key is a bare module name with no way to extend it. So the key gives way to swiftlint.config.js, which spreads the same Ionic config and adds the one exclusion.
kklem0
added a commit
to kklem0/sqlite
that referenced
this pull request
Aug 1, 2026
The banner promised native tracks upstream exactly. That was right while the only divergence was the web engine, and it is too strict now: it would have the consumer app ship a known-worse iOS build for as long as an upstream review takes, to keep a rule that exists only to make rebases cheap. Native now tracks upstream and may additionally carry commits from pull requests this fork already has open upstream, and nothing else. Those retire by themselves: once upstream merges, the next rebase drops them as patch-equivalent. Currently that is capacitor-community#696.
kklem0
added a commit
to kklem0/sqlite
that referenced
this pull request
Aug 1, 2026
Native only. Android SQLCipher 4.17.0 arrives in the base from the upstream merge of capacitor-community#695. iOS is carried from capacitor-community#696, this fork's open follow-up, under the amended native policy: SQLCipher pinned on both dependency managers, Swift Package Manager as the built and verified path, the XCTest target compiling again, the unused CocoaPods development workspace removed, and the plugin's compiler warnings cleared.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Follow-up to #695, where you asked for a PR pinning the iOS version. Investigating that turned up something larger than a pin.
The finding
SQLCipher discontinued CocoaPods. From its
CHANGELOG.md,[4.11.0] - (October 2025):pod trunk info SQLCipherstops at 4.10.0 (2025-08-04); SQLCipher itself is at 4.17.0 (2026-07-08). The pod is not neglected, it is discontinued. Zetetic's replacement is SQLCipher.swift, whose earliest tag is 4.10.0, so it begins exactly where the pod stops.After #695 brought Android to 4.17.0, only the SPM path can follow it.
iOS was in fact a three-way split, with this repo's own CI on the oldest branch of it:
ios/Podfile(build and CI)~>4.5.6Package.swift(SPM consumers)from: "4.14.0"4.17.0What this PR does
SQLCipher 4.10.0, the ceiling, with a comment so the number is not read as a preference;Package.swiftatexact: "4.17.0"to match Android.verify:iosfrompod installplus theios/Plugin.xcworkspacebuild toxcodebuild build-for-testing -scheme CapacitorCommunitySqlite -destination 'generic/platform=iOS Simulator'.verify:ios:pod(pod lib lint) to the same CI job, so the CocoaPods path stays gated rather than merely surviving.ios/Podfile,ios/Plugin.xcodeprojandios/Plugin.xcworkspace, which nothing references after (2) and (3).pod lib lint: thegit+https://repository URL that CocoaPods reads as a non-httpsscheme, and five Swift compiler warnings inios/Plugin/. The gate runs with no warnings allowed..build, sonpm run lintstops linting the SPM checkouts of ZIPFoundation and capacitor-swift-pm.npx cap spm-migration-assistant.The podspec stays and is unchanged in behaviour, so CocoaPods apps are unaffected. SPM becoming the maintained path here only follows Capacitor 8, where
cap add iosalready defaults to it.A defect this surfaced, which is the point of (2) and (3)
The SPM test target has never compiled, since SPM support landed in #686.
Package.swiftdeclares.testTarget(path: "ios/PluginTests"), but the source said@testable import Plugin, the Xcode workspace's module name; under SPM the module isCapacitorSQLitePlugin:Fixing that exposed a second break underneath: the test calls
CapacitorSQLite()against an initialiser that has beeninit(config: SqliteConfig)for some time.Nothing ever built this target, which is how both survived: the old CI command used the
Pluginscheme, which excludes tests.build-for-testingcompiles it on every run, so it cannot rot again.Review map
build(ios): pin SQLCipher for both dependency managersbuild(ios): verify iOS through Swift Package Manager and lint the podspecpackage.json, CI, and the two-line test-target fixchore(ios): remove the unused CocoaPods development workspacedocs(ios): document the Swift Package Manager and CocoaPods pathsfix(ios): clear the compiler warnings in the plugin sourcesbuild(ios): lint the podspec with no warnings allowed--allow-warningsdroppedbuild: keep SwiftLint out of the Swift Package Manager checkoutsswiftlint.config.jsThe test fix rides in commit 2 so that no commit leaves the workspace's
PluginTeststarget broken.Verified locally (Xcode 26.6, CocoaPods 1.17.0)
verify:iosgreen for library and test target with no compiler warnings,xcodebuild teston a simulator passestestEcho,verify:ios:podpasses against SQLCipher 4.10.0 with no warnings allowed,swift package resolvepins 4.17.0. SwiftLint goes from 79 files to 31 and 51 violations to 21, all remaining ones pre-existing. Android, web and Electron untouched.One packaging check worth naming, because it could have bitten silently:
Package.swiftpoints a test target atios/PluginTests, which the npmfileswhitelist does not ship. I packed the tarball, pointed a throwaway SPM package at it with.package(path:)and a real import, and built for iOS Simulator. Fine: SwiftPM excludes a dependency's test targets from the graph and never resolves their paths.