The SwiftNIO project is engaged in a substantial refactor of our internal codebase to make it easier to build applications that use SwiftNIO but that do not require our POSIX-based event loops (such as iOS applications).
As part of this work we stumbled over an interesting issue. In our most recent step we changed our Package.swift so that two of our products, NIOHTTP1
and NIOWebSocket
no longer import NIO
or depend on it. This triggered a breakage in swift-aws-lambda-runtime.
The cause of this breakage was a mismatch between the Package.swift
file and the actual imports of the module. The AWSLambdaRuntimeCore
target was defined like this in Package.swift
:
.target(name: "AWSLambdaRuntimeCore", dependencies: [
.product(name: "Logging", package: "swift-log"),
.product(name: "Backtrace", package: "swift-backtrace"),
.product(name: "NIOHTTP1", package: "swift-nio"),
.product(name: "_NIOConcurrency", package: "swift-nio"),
]),
However, in a couple of the files the code also included an import NIO
. Previously, when NIO was a dependency of NIOHTTP1
and _NIOConcurrency
, this import worked. However, when we removed the NIO dependency this import started to fail.
My question for the community is: how should we consider the semantic versioning impact of this? For my part, I see two major arguments.
The first is that this is a straightforward SemVer Major. Code that previously built, now does not. This change risks breaking adopter code and so we should delay it until a 3.0 release.
The second argument is that the adopter code was not correct, and could have been broken at any time. Most notably, it's easy to imagine a world where the Swift package manager changed its compilation model such that it broke this import. More broadly, it is also likely to be surprising to most framework developers that removing a dependency may trigger a SemVer major, but adding one won't.
I'd like to get the opinion of the community here: what do we, as a community, believe is acceptable?