Skip to content

chore!: raise minimum iOS deployment target to 15 - #876

Merged
turnipdabeets merged 1 commit into
chore/v4-remove-deprecatedfrom
chore/v4-min-ios-15
Oct 5, 2026
Merged

turnipdabeets merged 1 commit into
chore/v4-remove-deprecatedfrom
chore/v4-min-ios-15

Conversation

@turnipdabeets

@turnipdabeets turnipdabeets commented Sep 30, 2026 •

Copy link
Copy Markdown
Contributor

💡 Motivation and Context

Part of the 4.0 stack, on top of #873. It raises the minimum iOS deployment target from 13.0 to 15.0 and removes the availability checks and fallbacks that the new floor makes dead. Mac Catalyst follows iOS.

The macOS (10.15), tvOS (13.0), watchOS (6.0) and visionOS (1.0) minimums are unchanged.

Wrapper SDKs

Wrappers can't adopt posthog-ios 4.0 until their own iOS minimum is at least 15. Raising it is a breaking change for each wrapper, so each one does it in its own major.

Wrapper iOS 15 minimum
posthog-flutter PostHog/posthog-flutter#637 (draft, open): base PR for posthog_flutter 6.0.0. Podspec, plugin Package.swift and example go to 15.0, plus Xcode 26.
posthog-kmp PostHog/posthog-kmp#89 (merged 2026-10-03)
React Native plugin, CocoaPods PostHog/posthog-js#5194 (draft, open): requires iOS 15 and React Native 0.71
React Native plugin, SPM Already .iOS(.v15) in ios/Package.swift

What changed

  • Deployment targets: Package.swift, Package@swift-5.9.swift, PostHog.podspec, PostHog.xcodeproj, PostHogExampleAutocapture.xcodeproj, and the -target in scripts/check-public-api.sh.
  • Availability cleanup: 97 checks touched in the SDK and tests, plus 2 in examples.
Kind Count
iOS-only @available(iOS 13–15, *) annotations removed 64
iOS-only #available conditions removed, with their dead else branches 29
Multi-platform checks narrowed to their non-iOS part 24
  • Fallbacks removed with them:
    • The setSurveys / setSurveysConfig guards in PostHogConfig; the setters now assign directly.
    • The "Surveys can be rendered only on iOS 15+" early return.
    • The optional taskResume in the network swizzler.
    • The UIToolbar fallback to .primaryActionTriggered in autocapture.
    • The UISwitch.title guards in replay.
  • Two checks main added later (UIViewController.swift split-view style and its traversal test) are narrowed to tvOS 14.0. The survey-translation tests now use the public surveysConfig instead of the backing property.
  • Not touched: about 40 iOS 15 checks in the PostHogExampleAutocapture app, which are now always true. They're harmless, and that app mirrors Apple's UIKit catalog sample.
  • Left in place: 77 version checks. 48 are for iOS 16 and later, and 29 protect macOS, tvOS or watchOS.

Public API change: nothing is removed or renamed, and the API snapshot has no diff because it does not record availability. The 7 URLSession.postHog* async methods, surveys, surveysConfig, the two push-open methods and captureDeepLink(openURLContexts:) lose their iOS availability annotations.

Docs to update on posthog.com

  • iOS minimum stated as 13: contents/docs/session-replay/_snippets/ios-installation.mdx
  • Surveys "iOS 15.0 or later" wording and an #available sample: contents/docs/surveys/_snippets/ios-surveys-installation.mdx, contents/docs/surveys/installation/ios.mdx
  • Push "iOS 14 or newer / on iOS 13" wording: contents/docs/workflows/push-notifications/ios.mdx, contents/docs/workflows/push-notifications/react-native.mdx
  • Flutter and KMP pages that state iOS 13, to change when those wrappers raise their minimum.

💚 How did you test it?

After rebasing onto #873 (no conflicts):

  • make test (macOS): 909 tests pass.
  • make apiCheck: snapshot up to date.
  • iOS simulator (iPhone 17 Pro, iOS 26.4): all 1282 Swift Testing tests pass. One XCTest case failed once, does not capture event if opt out (PostHogSDKTest.swift:581, expected 0 events, got 1). This PR doesn't touch that test, and PostHogSDKTest then passed 3 of 3 reruns, so it looks timing-dependent.

Before the rebase, on top of #874:

  • make test (macOS): 909 tests pass.
  • iOS simulator (iPhone 17 Pro, iOS 26.4): 1282 tests pass on the rerun. The first run ended when the test process exited unexpectedly mid-suite, with no assertion failure, while other builds were running on the machine. It was not reproduced against the base branch, so it is unexplained.
  • make apiCheck: snapshot up to date.
  • make buildSdk: all seven builds succeed (iOS, SwiftPM macOS, macOS, Mac Catalyst, tvOS, watchOS, visionOS).
  • Simulator builds of PostHogExample, PostHogObjCExample, PostHogExampleStoryboard and PostHogExampleAutocapture succeed.
  • Not run: CocoaPods and XCFramework example builds, pod lib lint, and the macOS, tvOS, watchOS and visionOS example apps.

📝 Checklist

  • I reviewed the submitted code.
  • I added tests to verify the changes.
  • I updated the docs if needed.
  • No breaking change or entry added to the changelog.

If releasing new changes

  • Ran pnpm changeset to generate a changeset file

The changeset is major and was written by hand in the changeset format.

🤖 Agent context

Autonomy: Human-driven (agent-assisted)

  • Written with Claude Code (Opus 5.5).
  • Only the iOS floor moves. A check was removed only where iOS was the sole platform it protected; checks that also gate macOS, tvOS or watchOS were narrowed, not removed.
  • Raising the other floors would unlock little more: 22 checks for macOS 12, 3 for tvOS 15, 6 for watchOS 8.
  • _surveys / _surveysConfig backing properties stay, because PostHogSurveyIntegration compiles on macOS under TESTING, where the public properties are unavailable.

🤖 Generated with Claude Code

@turnipdabeets turnipdabeets self-assigned this Sep 30, 2026
@github-actions

github-actions Bot commented Sep 30, 2026 •

Copy link
Copy Markdown
Contributor

posthog-ios Compliance Report

Date: 2026-10-05 17:01:01 UTC
Duration: 245311ms

⚠️ Some Tests Failed

44/45 tests passed, 1 failed


Capture Tests

⚠️ 28/29 tests passed, 1 failed

View Details
Test Status Duration
Format Validation.Event Has Required Fields ✅ 6782ms
Format Validation.Event Has Uuid ✅ 3300ms
Format Validation.Event Has Lib Properties ✅ 2897ms
Format Validation.Distinct Id Is String ✅ 2809ms
Format Validation.Token Is Present ✅ 2892ms
Format Validation.Custom Properties Preserved ✅ 2838ms
Format Validation.Event Has Timestamp ✅ 3300ms
Retry Behavior.Retries On 503 ✅ 11714ms
Retry Behavior.Does Not Retry On 400 ✅ 4854ms
Retry Behavior.Does Not Retry On 401 ✅ 4801ms
Retry Behavior.Respects Retry After Header ✅ 7728ms
Retry Behavior.Implements Backoff ✅ 21324ms
Retry Behavior.Retries On 500 ✅ 9309ms
Retry Behavior.Retries On 502 ✅ 9311ms
Retry Behavior.Retries On 504 ✅ 9295ms
Retry Behavior.Max Retries Respected ❌ 21778ms
Deduplication.Generates Unique Uuids ✅ 3009ms
Deduplication.Preserves Uuid On Retry ✅ 9342ms
Deduplication.Preserves Uuid And Timestamp On Retry ✅ 16684ms
Deduplication.Preserves Uuid And Timestamp On Batch Retry ✅ 7958ms
Deduplication.No Duplicate Events In Batch ✅ 3163ms
Deduplication.Different Events Have Different Uuids ✅ 3072ms
Compression.Sends Gzip When Enabled ✅ 2784ms
Batch Format.Uses Proper Batch Structure ✅ 2866ms
Batch Format.Flush With No Events Sends Nothing ✅ 365ms
Batch Format.Multiple Events Batched Together ✅ 2995ms
Error Handling.Does Not Retry On 403 ✅ 4854ms
Error Handling.Does Not Retry On 413 ✅ 5005ms
Error Handling.Retries On 408 ✅ 9350ms

Failures

retry_behavior.max_retries_respected

Expected 4 requests, got 6

Feature_Flags Tests

✅ 16/16 tests passed

View Details
Test Status Duration
Request Payload.Request With Person Properties Device Id ✅ 2945ms
Request Payload.Flags Request Uses V2 Query Param ✅ 3188ms
Request Payload.Flags Request Hits Flags Path Not Decide ✅ 2901ms
Request Payload.Flags Request Omits Authorization Header ✅ 2856ms
Request Payload.Token In Flags Body Matches Init ✅ 2922ms
Request Payload.Groups Round Trip ✅ 2887ms
Request Payload.Groups Default To Empty Object ✅ 2893ms
Request Payload.Person Properties Distinct Id Auto Populated When Caller Omits It ✅ 2903ms
Request Payload.Disable Geoip False Propagates As Geoip Disable False ✅ 2774ms
Request Payload.Disable Geoip Omitted Defaults To False ✅ 2875ms
Request Payload.Flag Keys To Evaluate Contains Only Requested Key ✅ 2965ms
Request Lifecycle.No Flags Request On Init Alone ✅ 81ms
Request Lifecycle.No Flags Request On Normal Capture ✅ 2700ms
Request Lifecycle.Two Flag Calls Produce Two Remote Requests ✅ 5381ms
Request Lifecycle.Mock Response Value Is Returned To Caller ✅ 2870ms
Side Effect Events.Get Feature Flag Captures Feature Flag Called Event ✅ 3127ms

Raise the iOS floor from 13 to 15 (Mac Catalyst follows) and remove the
availability checks and fallbacks that only protected iOS 13/14.
macOS, tvOS, watchOS and visionOS minimums are unchanged, so checks that
also gate those platforms keep their non-iOS clauses.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@turnipdabeets
turnipdabeets marked this pull request as ready for review October 5, 2026 17:02
@turnipdabeets
turnipdabeets requested a review from a team as a code owner October 5, 2026 17:02
@greptile-apps

greptile-apps Bot commented Oct 5, 2026 •

Copy link
Copy Markdown
Contributor

Retrigger

[High risk] Raises minimum iOS version requirement from 13 to 15.

The PR appears safe to merge; no actionable regression was identified.

Reviews (1) · Last reviewed commit: "chore!: raise minimum iOS deployment tar..."

@turnipdabeets
turnipdabeets merged commit bbb48c2 into chore/v4-remove-deprecated Oct 5, 2026
54 of 55 checks passed
@turnipdabeets
turnipdabeets deleted the chore/v4-min-ios-15 branch October 5, 2026 22:47
turnipdabeets added a commit that referenced this pull request Oct 7, 2026
Raise the iOS floor from 13 to 15 (Mac Catalyst follows) and remove the
availability checks and fallbacks that only protected iOS 13/14.
macOS, tvOS, watchOS and visionOS minimums are unchanged, so checks that
also gate those platforms keep their non-iOS clauses.

Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
turnipdabeets added a commit that referenced this pull request Oct 9, 2026
Raise the iOS floor from 13 to 15 (Mac Catalyst follows) and remove the
availability checks and fallbacks that only protected iOS 13/14.
macOS, tvOS, watchOS and visionOS minimums are unchanged, so checks that
also gate those platforms keep their non-iOS clauses.

Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
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.

2 participants