Update CI to run on macOS 11#63
Conversation
| // Set the configuration to be release – this configuration is not supported when running xcodebuild without a xcodeproj file. | ||
| xcodeBuildArguments.append("-configuration") | ||
| xcodeBuildArguments.append("Release") |
There was a problem hiding this comment.
This configuration only existing when we have an xcodeproj file sucks. I managed to continue testing in Release in CI by using swift test -c release -Xswiftc -enable-testing. We're still running via xcodebuild for test coverage on Xcode 13, but that run is in debug rather than Release.
| .tvOS_15, | ||
| .macOS_12, | ||
| .watchOS_8: | ||
| // Xcode 13 does not require xcodeproj generation |
There was a problem hiding this comment.
fun fact: we can run xcodebuild without an xcodeproj on Xcode 13!
| spm-13-swift: | ||
| name: Swift Build Xcode 13 | ||
| runs-on: macOS-12 | ||
| steps: | ||
| - name: Checkout Repo | ||
| uses: actions/checkout@v2 | ||
| - name: Bundle Install | ||
| run: bundle install | ||
| - name: Select Xcode Version | ||
| run: sudo xcode-select --switch /Applications/Xcode_13.4.1.app/Contents/Developer | ||
| - name: Build and Test Framework | ||
| run: swift test -c release -Xswiftc -enable-testing |
There was a problem hiding this comment.
Qing has told me to always use xcrun swift for these things which IIRC it's so we use the swift version from Xcode rather than the one installed in the system.
| 'iOS_12,tvOS_12', | ||
| 'iOS_13,tvOS_13,watchOS_6', | ||
| 'macOS_10_15' | ||
| 'macOS_10_15', |
There was a problem hiding this comment.
Fun fact, we can still run tests against the macOS 10.15 SDK even while running on macOS 11. We can only do this while running on Xcode 11.
| matrix: | ||
| platforms: [ | ||
| 'iOS_14,tvOS_14,watchOS_7', | ||
| 'macOS_11', |
There was a problem hiding this comment.
Now that we're running on macOS 11 and targeting Xcode 12 we can run tests against the macOS 11 SDK!
| strategy: | ||
| matrix: | ||
| platforms: [ | ||
| 'iOS_12,tvOS_12', |
There was a problem hiding this comment.
| case tvOS_14 | ||
| case tvOS_15 | ||
| case macOS_10_15 | ||
| case watchOS_5 |
There was a problem hiding this comment.
I don't know why watchOS_5 was here: we weren't running tests on it!
| - name: Bundle Install | ||
| run: bundle install | ||
| - name: Select Xcode Version | ||
| run: sudo xcode-select --switch /Applications/Xcode_13.4.1.app/Contents/Developer |
There was a problem hiding this comment.
JFYI xcversion comes installed in these machines, which would make selecting an Xcode much easier than this https://github.com/actions/runner-images/blob/main/images/macos/macos-11-Readme.md#xcode-support-tools
e366e6e to
aaab74d
Compare
| let decodedSize = withUnsafePointer(to: data) { | ||
| return UnsafeRawBufferPointer(start: $0, count: Self.storageLength) | ||
| let decodedSize = data.withUnsafeBytes { | ||
| return $0.load(as: Self.self) | ||
| } | ||
| self = Self.swapToHost(decodedSize.load(as: Self.self)) | ||
| self = Self.swapToHost(decodedSize) |
There was a problem hiding this comment.
Woof. I don't understand why this change was necessary to get CI passing in Release on Xcode 13 – Debug worked fine.
The good news is the only tests that were failing were:
-[CacheAdvanceTests.BigEndianHostSwappableTests test_init_canBeInitializedFromEncodedData]
-[CacheAdvanceTests.EncodableMessageTests test_encodedData_encodesCorrectSize]
These tests are effectively testing implementation details – the integration tests where we persist messages and de-persist them were still succeeding.
So, what does this change do? Instead of creating a buffer pointer from the data's pointer, I instead access the underlying data's bytes directly. Skipping the translation to a buffer pointer simplifies what's happening here, which fixed the underlying issue. Skipping the translation buffer likely also gave us a very small performance win.
Edit: I DO understand why this changed worked. See explanation above.
| /// | ||
| /// - Parameter data: A data blob representing encodable data. Must be of length `Self.storageLength`. | ||
| init(_ data: Data) { | ||
| let decodedSize = withUnsafePointer(to: data) { |
There was a problem hiding this comment.
I don't have enough context to review these changes but everything else LGTM!
There was a problem hiding this comment.
I am confident in these changes (we have excellent test coverage), so I'm okay merging this in.
What's happening in this method is we're instantiating a BigEndianHostSwappable (i.e. a UInt64, UInt32, or UInt8) from a Data blob.
The way we did that was:
- Get a pointer to the underlying data (
withUnsafePointer(to: data) { ... }) - Turn that pointer into a buffer pointer (i.e. a pointer range) starting at the pointer and ending at the length of storage required to store this type (
UnsafeRawBufferPointer(start: $0, count: Self.storageLength)) - Using that buffer pointer to
loadthe underlyingBigEndianHostSwappable, i.e. read the pointer buffer from memory and cast it as the current type. (decodedSize.load(as: Self.self)) - Swap the read-in value to have the same Endian-ness as the current machine – this is only necessary if the file has been transferred between machines of different Endian-ness. (
Self.swapToHost(...))
The way we're doing it now is:
- Get the underlying buffer pointer for the underlying data (
withUnsafeBytes { ... }) - Using that buffer pointer (i.e. a pointer range) to
loadthe underlyingBigEndianHostSwappable, i.e. read the pointer buffer from memory and cast it as the current type. ($0.load(as: Self.self)) - Swap the read-in value to have the same Endian-ness as the current machine – this is only necessary if the file has been transferred between machines of different Endian-ness. (
Self.swapToHost(...))
The issue with the old code (which of course I figured out by typing all of this out) was that we were working over the unsafe buffer pointer range outside of the withUnsafePointer call. If I change this code to read:
let decodedSize = withUnsafePointer(to: data) {
return UnsafeRawBufferPointer(start: $0, count: Self.storageLength).load(as: Self.self)
}
The tests pass in Release! So changing from withUnsafePointer to withUnsafeBytes wasn't the issue. Instead, it was where we were interacting with the buffer! That said, I do like the semantics of withUnsafeBytes better.
|
I have made all the new CI checks required. Merging! |
bachand
left a comment
There was a problem hiding this comment.
I reviewed the changes to BigEndianHostSwappable. Thanks for the explanation Dan!

macOS 10.15 is no longer supported by Github Actions. So instead let's run CI on macOS 11 and macOS 12.
While I was here, I also added Xcode 13 CI runs, and resolved #44