Skip to content

Update CI to run on macOS 11#63

Merged
dfed merged 9 commits into
mainfrom
dfed--update-ci
Sep 3, 2022
Merged

Update CI to run on macOS 11#63
dfed merged 9 commits into
mainfrom
dfed--update-ci

Conversation

@dfed

@dfed dfed commented Sep 2, 2022

Copy link
Copy Markdown
Owner

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

Comment thread Scripts/build.swift
Comment on lines +198 to +200
// Set the configuration to be release – this configuration is not supported when running xcodebuild without a xcodeproj file.
xcodeBuildArguments.append("-configuration")
xcodeBuildArguments.append("Release")

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Comment thread Scripts/build.swift
.tvOS_15,
.macOS_12,
.watchOS_8:
// Xcode 13 does not require xcodeproj generation

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fun fact: we can run xcodebuild without an xcodeproj on Xcode 13!

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Interesting!

Comment thread .github/workflows/ci.yml Outdated
Comment on lines +109 to +120
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

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These new lines resolve #44

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Comment thread .github/workflows/ci.yml
'iOS_12,tvOS_12',
'iOS_13,tvOS_13,watchOS_6',
'macOS_10_15'
'macOS_10_15',

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Comment thread .github/workflows/ci.yml
matrix:
platforms: [
'iOS_14,tvOS_14,watchOS_7',
'macOS_11',

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Now that we're running on macOS 11 and targeting Xcode 12 we can run tests against the macOS 11 SDK!

Comment thread .github/workflows/ci.yml
strategy:
matrix:
platforms: [
'iOS_12,tvOS_12',

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Comment thread Scripts/build.swift
case tvOS_14
case tvOS_15
case macOS_10_15
case watchOS_5

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't know why watchOS_5 was here: we weren't running tests on it!

Comment thread .github/workflows/ci.yml Outdated
- name: Bundle Install
run: bundle install
- name: Select Xcode Version
run: sudo xcode-select --switch /Applications/Xcode_13.4.1.app/Contents/Developer

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice! de95961

Comment thread .github/workflows/ci.yml Outdated
@dfed dfed requested a review from fdiaz September 2, 2022 21:06
@dfed dfed marked this pull request as ready for review September 2, 2022 21:06
@dfed dfed requested a review from bachand September 2, 2022 21:07
Comment on lines -34 to +37
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)

@dfed dfed Sep 2, 2022

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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) {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't have enough context to review these changes but everything else LGTM!

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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:

  1. Get a pointer to the underlying data (withUnsafePointer(to: data) { ... })
  2. 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))
  3. Using that buffer pointer to load the underlying BigEndianHostSwappable, i.e. read the pointer buffer from memory and cast it as the current type. (decodedSize.load(as: Self.self))
  4. 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:

  1. Get the underlying buffer pointer for the underlying data (withUnsafeBytes { ... })
  2. Using that buffer pointer (i.e. a pointer range) to load the underlying BigEndianHostSwappable, i.e. read the pointer buffer from memory and cast it as the current type. ($0.load(as: Self.self))
  3. 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.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To make sure I follow, the issue was that we were violating this requirement?
Screen Shot 2022-09-02 at 6 47 19 PM

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Exactly!

@dfed

dfed commented Sep 3, 2022

Copy link
Copy Markdown
Owner Author

I have made all the new CI checks required. Merging!

@dfed dfed merged commit 944702f into main Sep 3, 2022
@dfed dfed deleted the dfed--update-ci branch September 3, 2022 00:01

@bachand bachand left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I reviewed the changes to BigEndianHostSwappable. Thanks for the explanation Dan!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Build and test in CI using swift (in addition to xcodebuild)

3 participants