Skip to content

Fix package build on Xcode 26.4.1 (#310)#312

Open
ssathy2 wants to merge 6 commits into
mainfrom
fix/xcode-26-protocol-witness-availability
Open

Fix package build on Xcode 26.4.1 (#310)#312
ssathy2 wants to merge 6 commits into
mainfrom
fix/xcode-26-protocol-witness-availability

Conversation

@ssathy2
Copy link
Copy Markdown
Contributor

@ssathy2 ssathy2 commented Apr 24, 2026

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+) and ASAuthorizationControllerPresentationContextProviding (iOS 13+) — the compiler now insists the shared presentationAnchor(for:) witnesses be as available as the least-restrictive protocol, producing:

Protocol 'ASAuthorizationControllerPresentationContextProviding' requires
'presentationAnchor(for:)' to be available in iOS 12.0 and newer
AuthenticationSessionPresentationContextProvider.swift:30

The @available(iOS 12.0, *) / @available(iOS 13.0, *) attributes were leftover from when the SDK supported older deployment targets. The SDK now ships with IPHONEOS_DEPLOYMENT_TARGET = 14.2, so both ASWebAuthenticationSession and ASAuthorizationController are 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 activate breakableBottomConstraint (high-priority equalTo) 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.Code cases since the SDK was written. Add matching cases to AuthenticationError and map 1:1 so callers see the real Apple-side reason instead of being funneled into a generic .failed / .unknown bucket.

ASAuthorizationError.Code New AuthenticationError case Since
.notInteractive .notInteractive iOS 15.4
.matchedExcludedCredential .matchedExcludedCredential iOS 18.0
.credentialImport .credentialImport iOS 18.2
.credentialExport .credentialExport iOS 18.2

Each Apple case is referenced behind an if #available check so the SDK still builds at its iOS 14.2 deployment target. Also adds an explicit .presentationContextInvalid mapping to the existing switch (was previously falling through to .unknown). The @unknown default is 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

  • Package builds on Xcode 26.4.1 (17E202) with no errors on AuthenticationSessionPresentationContextProvider.swift
  • No warnings on ConnectButton.swift:348 or SignInWithAppleAuthentication.swift
  • Host app's connect flow (web-auth redirect, Sign In With Apple) still presents correctly
  • Connect button footer layout visually unchanged in the host app
  • Sign-in-with-Apple: canceled / failed / invalidResponse / notHandled / presentationContextInvalid / unknown flows surface expected errors
  • Sign-in-with-Apple on iOS 18.2+: passkey exclude-list and credential-import/export error paths surface their new dedicated AuthenticationError cases

ssathy2 added 2 commits April 26, 2026 21:29
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.
@ssathy2 ssathy2 force-pushed the fix/xcode-26-protocol-witness-availability branch from d09b345 to 20c0fbc Compare April 27, 2026 02:30
@ssathy2 ssathy2 mentioned this pull request Apr 27, 2026
4 tasks
- 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.
@ssathy2 ssathy2 force-pushed the fix/xcode-26-protocol-witness-availability branch from 0fe0a98 to 2b654e5 Compare April 27, 2026 17:15
@ssathy2
Copy link
Copy Markdown
Contributor Author

ssathy2 commented Apr 27, 2026

Note on the previously-bundled fixes from #311: I dropped the .presentationContextInvalid mapping that the Copilot reviewer suggested on #311 (comment r3139960316). The suggestion is incorrect — ASAuthorizationError.Code does not have a .presentationContextInvalid case (that case lives on this SDK's own AuthenticationError enum). Adding it broke the build. The other two #311 review fixes (ASAuthorizationError.Code doc references in WebServiceAuthentication.swift, and activating breakableBottomConstraint) are kept.

ssathy2 added 3 commits April 27, 2026 12:28
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.
@ssathy2 ssathy2 force-pushed the fix/xcode-26-protocol-witness-availability branch from 2a557fd to a8b707f Compare April 27, 2026 18:01
@rockarts
Copy link
Copy Markdown

@ssathy2 Do you have a release date for this?

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.

Package fails to build in Xcode 26.4.1 (17E202)

2 participants