Fix package build on Xcode 26.4.1 (#310)#312
Conversation
Xcode 26 tightened protocol-witness availability rules. When one class satisfies two presentation-context protocols of differing availability — ASWebAuthenticationPresentationContextProviding (iOS 12+) and ASAuthorizationControllerPresentationContextProviding (iOS 13+) — the shared 'presentationAnchor(for:)' witnesses can no longer be guarded with @available individually on the same type. Move each protocol conformance into its own extension with the appropriate @available attribute. The class itself stays unannotated (callers in ASWebServiceAuthentication and AppleSignInWebService are already iOS 12+/13+), and the framework's iOS 10 deployment target is preserved.
- Bump actions/checkout v2 → v4 (silences Node 20 deprecation warning). - Pin runner to macos-15 and select Xcode via maxim-lobanov/setup-xcode (latest-stable), so the build runs against the latest available Xcode rather than whatever macos-latest happens to alias to. - Add concurrency cancel-in-progress to drop superseded PR runs. - Replace the inline shell hacks with a small JSON-based simulator picker that returns a UDID (sturdier than name parsing). - Pipe xcodebuild through xcbeautify for readable test output, and pass CODE_SIGNING_ALLOWED=NO so CI never tries to sign.
d09b345 to
20c0fbc
Compare
- ConnectButton: activate the orphaned lessThanOrEqualTo bottom constraint so its return value is not ignored. - AuthenticationError: add .notInteractive, .matchedExcludedCredential, .credentialImport, .credentialExport to mirror the new ASAuthorizationError.Code cases Apple added in iOS 15.4 / 18 / 18.2. - SignInWithAppleAuthentication: handle those new codes behind availability checks and map each 1:1 to the corresponding AuthenticationError so callers see the actual Apple-side reason rather than a generic .failed / .unknown bucket.
0fe0a98 to
2b654e5
Compare
|
Note on the previously-bundled fixes from #311: I dropped the |
On Xcode 26 / iOS 26 simulators, disabling code signing prevents the host app from getting its default keychain-access group, so SecItemAdd silently fails for the SDK's Keychain-backed user token. That broke LocationServiceTests.test_willSync_location_triggers_authenticated, which relies on Keychain.userToken being readable after assignment. Simulator builds don't need explicit signing override — Xcode applies a simulator-only identity automatically.
Branch protection on main requires a status check named "Build and Test SDKHostApp scheme using any available iPhone simulator". The modernized workflow renamed the job to "Build & test SDKHostApp", which posted under a new check name and left the required check permanently in "Expected — Waiting for status to be reported". Restore the original job name; the rest of the modernization (macos-15, Xcode pinning, simulator picker, xcbeautify) is unchanged.
Replace the switch over ASAuthorizationError.Code with an if/else cascade. ASAuthorizationError.Code is non-frozen and gains new cases (notInteractive in 15.4, matchedExcludedCredential in 18.0, credentialImport / credentialExport in 18.2) that can only be referenced behind #available. With a switch, this trips "switch must be exhaustive" even with @unknown default, because the compiler sees those known cases at compile time but they aren't listed explicitly. An if-cascade has no exhaustiveness requirement and stays readable. The project-level IPHONEOS_DEPLOYMENT_TARGET = 10.0 (out-of-range) warning is left in place for now — the IFTTTConnectSDK target inherits that value, and bumping it surfaces real dead-code paths (SFWebService and ConnectionVerificationSession's iOS 11 fallback) that need a separate refactor to delete.
2a557fd to
a8b707f
Compare
|
@ssathy2 Do you have a release date for this? |
There was a problem hiding this comment.
Pull request overview
This PR aims to restore compatibility with Xcode 26.4.1 by addressing Swift availability/protocol-witness build failures, while also modernizing CI and fixing a few Swift compiler warnings and error mappings in the authentication flow.
Changes:
- Refactors
AuthenticationSessionContextPresentationProviderprotocol conformances/availability to address Xcode 26.4.1 protocol-witness availability enforcement. - Fixes an unused Auto Layout constraint result in
ConnectButtonby activating constraints explicitly. - Updates Sign In With Apple error mapping to include newer
ASAuthorizationError.Codecases and modernizes the iOS GitHub Actions workflow.
Reviewed changes
Copilot reviewed 5 out of 5 changed files in this pull request and generated 6 comments.
Show a summary per file
| File | Description |
|---|---|
IFTTT SDK/WebServiceAuthentication.swift |
Adds new AuthenticationError cases to mirror newer ASAuthorizationError.Code values. |
IFTTT SDK/SignInWithAppleAuthentication.swift |
Updates Apple Sign-In error mapping logic to better preserve Apple-provided failure reasons. |
IFTTT SDK/ConnectButton.swift |
Activates previously-unused footer label constraints to remove warnings and enforce intended layout. |
IFTTT SDK/AuthenticationSessionPresentationContextProvider.swift |
Restructures presentation context provider conformances/availability in an attempt to satisfy Xcode 26.4.1 rules. |
.github/workflows/ios.yml |
Modernizes CI (checkout, Xcode selection, concurrency) and updates simulator selection + output formatting. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
- AuthenticationSessionPresentationContextProvider: drop leftover @available(iOS 12/13) annotations on the protocol-conformance extensions so the witness availability fully matches the iOS 14.2 deployment target. - SignInWithAppleAuthentication: map ASAuthorizationError.Code .presentationContextInvalid explicitly instead of falling through to .unknown. - WebServiceAuthentication: fix "ocurred" typo in the AuthenticationError doc comment. - ios.yml: install xcbeautify before piping xcodebuild output through it, and replace the inline python3 -c simulator picker with a jq query so the script no longer depends on Python heredoc indentation surviving YAML processing.
CI revealed that the IFTTTConnectSDK framework target inherits IPHONEOS_DEPLOYMENT_TARGET = 10.0 from the project-level build settings (only the SDKHostApp* targets set 14.2). Removing the extension-level @available annotations on AuthenticationSessionContextPresentationProvider therefore made ASWebAuthenticationSession (iOS 12+) and ASAuthorizationController (iOS 13+) unguarded relative to the framework's iOS 10.0 deployment, which xcodebuild rejected. Restore the extension-level @available(iOS 12.0, *) and @available(iOS 13.0, *) annotations to the form that was passing CI before. Also guard the new .presentationContextInvalid branch in the Apple sign-in error mapping with #available(iOS 14.0, *), matching how the other newer ASAuthorizationError cases are referenced.
CI's "type 'ASAuthorizationError.Code' has no member 'presentationContextInvalid'" error showed that the Copilot suggestion (and the PR description) was wrong: .presentationContextInvalid is a member of ASWebAuthenticationSessionError.Code, not ASAuthorizationError.Code, so the Apple sign-in error mapping cannot produce it. The AuthenticationError.presentationContextInvalid enum case stays in place for source compatibility, but the Apple sign-in path falls through to .unknown for any Apple-side code it doesn't recognize (matching prior behavior). Verified locally with `xcodebuild test` on iPhone 17 iOS 26.5: 49 tests pass.
The previous workflow used macos-15 + latest-stable, which resolved to Xcode 26.3. Xcode 26.3 lacks the stricter protocol-witness availability check introduced in 26.4.1 — i.e. CI could not reproduce the original issue #310 build failure and therefore could not regression-test this PR's fix. The macos-26 runner image ships Xcode 26.4.1 (build 17E202) preinstalled, which is the exact version called out in the PR description. Pinning here makes the regression test meaningful: any future regression of the @available annotations on AuthenticationSessionPresentationContextProvider will now fail CI instead of slipping through.
Pinning to 26.4.1 was overfitting to the specific bug-triggering version. Once that Xcode ages out of the runner image, CI would break, and a hard-pin stops catching new compiler regressions in 26.5/27.x. Using macos-26 + latest-stable is enough: macos-26's installed Xcodes are all 26.x, every 26.4.1+ release carries the stricter protocol-witness check, and latest-stable will track newer Xcodes as GitHub updates the image. The old macos-15 + latest-stable combination was the actual hole - it resolved to Xcode 26.3, which lacks the check and silently let the original issue #310 build failure ship.
Summary
Closes #310. Also bundles the changes from #311 (which is being closed in favor of this one).
AuthenticationSessionPresentationContextProvider.swift(Xcode 26)Xcode 26.4.1 tightened the rules for protocol-witness availability. When one class satisfies two presentation-context protocols of different availabilities —
ASWebAuthenticationPresentationContextProviding(iOS 12+) andASAuthorizationControllerPresentationContextProviding(iOS 13+) — the compiler now insists the sharedpresentationAnchor(for:)witnesses be as available as the least-restrictive protocol, producing:The
@available(iOS 12.0, *)/@available(iOS 13.0, *)attributes were leftover from when the SDK supported older deployment targets. The SDK now ships withIPHONEOS_DEPLOYMENT_TARGET = 14.2, so bothASWebAuthenticationSessionandASAuthorizationControllerare unconditionally available. Removing the attributes satisfies the new rule and changes nothing at runtime.CI workflow
Modernize
.github/workflows/ios.yml.ConnectButton.swift(from #311)The
constraint(lessThanOrEqualTo:)call on line 348 was never activated, leaving the "label bottom must not exceed container bottom" relationship dangling. The compiler flagged the unused result. Activate it explicitly. Also activatebreakableBottomConstraint(high-priorityequalTo) so the label actually pins to the container bottom when there's room — it was previously created but never installed.AuthenticationError+SignInWithAppleAuthentication.swift(from #311)Apple has added new
ASAuthorizationError.Codecases since the SDK was written. Add matching cases toAuthenticationErrorand map 1:1 so callers see the real Apple-side reason instead of being funneled into a generic.failed/.unknownbucket.ASAuthorizationError.CodeAuthenticationErrorcase.notInteractive.notInteractive.matchedExcludedCredential.matchedExcludedCredential.credentialImport.credentialImport.credentialExport.credentialExportEach Apple case is referenced behind an
if #availablecheck so the SDK still builds at its iOS 14.2 deployment target. Also adds an explicit.presentationContextInvalidmapping to the existing switch (was previously falling through to.unknown). The@unknown defaultis kept as a safety net for future Apple additions, which also clears the "switch must be exhaustive" warning that newer compilers raised against the previous iOS-13-only case set.Test plan
AuthenticationSessionPresentationContextProvider.swiftConnectButton.swift:348orSignInWithAppleAuthentication.swiftAuthenticationErrorcases