Skip to content

chore!: posthog-android 4.0 (integration PR), remove deprecated APIs - #871

Draft
turnipdabeets wants to merge 5 commits into
mainfrom
chore/v4-remove-deprecated
Draft

turnipdabeets wants to merge 5 commits into
mainfrom
chore/v4-remove-deprecated

Conversation

@turnipdabeets

@turnipdabeets turnipdabeets commented Oct 22, 2026 •

Copy link
Copy Markdown
Contributor

Important

This is the posthog-android 4.0 integration PR. Don't merge it until 4.0 is ready. Every other 4.0 change is a PR stacked on this branch (chore/v4-remove-deprecated) and merges into it. This PR then merges everything into main at once. The branch carries one changeset, .changeset/android-v4-major.md, and each stacked PR adds one line to it.

Stacked PRs (merge into this branch):

💡 Motivation and Context

Starts the next major: posthog-android 4.0 and core posthog 7.0, following the iOS 4.0 plan (PostHog/posthog-ios#557, PostHog/posthog-ios#873).

This first change removes APIs that are already deprecated on main:

Removed Use instead
PostHogConfig.apiKey, PostHogConfig(apiKey = …), PostHogAndroidConfig(apiKey = …) projectToken
PostHogConfig.propertiesSanitizer, PostHogPropertiesSanitizer addBeforeSend
PostHogConfig.evaluationEnvironments evaluationContexts
getFeatureFlagPayload() (instance and static) getFeatureFlagResult(key)?.payload
PostHogSessionReplayConfig.debouncerDelayMs throttleDelayMs

posthog-server keeps its own deprecated apiKey and getFeatureFlagPayload; the server SDK gets its own major separately. The React Native and Flutter Android code calls none of the removed APIs.

remoteConfig is also deprecated, but removing it changes behavior (setup always fetches /config), so it gets its own stacked PR (#874).

No sdk-specs contract is affected; this only removes deprecated aliases.

💚 How did you test it?

  • ./gradlew :posthog:test :posthog-android:testReleaseUnitTest pass (1064 core and 762 Android tests).
  • apiDump regenerated; apiCheck passes.
  • Tests that only covered the removed APIs are deleted; the payload test now goes through getFeatureFlagResult.

📝 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

🤖 Agent context

Autonomy: Human-driven (agent-assisted)

Claude Code (Claude Opus 5.5) found the deprecated APIs, removed them, updated the tests and API dumps, and checked the Flutter and React Native Android code for callers. remoteConfig was split out after it turned out to be a real behavior switch, not a no-op.

🤖 Generated with Claude Code

@turnipdabeets turnipdabeets self-assigned this Oct 22, 2026
@turnipdabeets
turnipdabeets marked this pull request as ready for review October 22, 2026 19:43
@turnipdabeets
turnipdabeets requested a review from a team as a code owner October 22, 2026 19:43
@github-actions

github-actions Bot commented Oct 22, 2026 •

Copy link
Copy Markdown
Contributor

posthog-android Compliance Report

Date: 2026-10-28 20:46:24 UTC
Duration: 118479ms

✅ All Tests Passed!

46/46 tests passed


Capture Tests

✅ 29/29 tests passed

View Details
Test Status Duration
Format Validation.Event Has Required Fields ✅ 400ms
Format Validation.Event Has Uuid ✅ 39ms
Format Validation.Event Has Lib Properties ✅ 30ms
Format Validation.Distinct Id Is String ✅ 26ms
Format Validation.Token Is Present ✅ 27ms
Format Validation.Custom Properties Preserved ✅ 30ms
Format Validation.Event Has Timestamp ✅ 26ms
Retry Behavior.Retries On 503 ✅ 7029ms
Retry Behavior.Does Not Retry On 400 ✅ 4028ms
Retry Behavior.Does Not Retry On 401 ✅ 4030ms
Retry Behavior.Respects Retry After Header ✅ 7031ms
Retry Behavior.Implements Backoff ✅ 17038ms
Retry Behavior.Retries On 500 ✅ 7017ms
Retry Behavior.Retries On 502 ✅ 7019ms
Retry Behavior.Retries On 504 ✅ 7019ms
Retry Behavior.Max Retries Respected ✅ 17040ms
Deduplication.Generates Unique Uuids ✅ 47ms
Deduplication.Preserves Uuid On Retry ✅ 7020ms
Deduplication.Preserves Uuid And Timestamp On Retry ✅ 12031ms
Deduplication.Preserves Uuid And Timestamp On Batch Retry ✅ 7018ms
Deduplication.No Duplicate Events In Batch ✅ 43ms
Deduplication.Different Events Have Different Uuids ✅ 29ms
Compression.Sends Gzip When Enabled ✅ 20ms
Batch Format.Uses Proper Batch Structure ✅ 20ms
Batch Format.Flush With No Events Sends Nothing ✅ 15ms
Batch Format.Multiple Events Batched Together ✅ 40ms
Error Handling.Does Not Retry On 403 ✅ 4021ms
Error Handling.Does Not Retry On 413 ✅ 4023ms
Error Handling.Retries On 408 ✅ 5033ms

Feature_Flags Tests

✅ 17/17 tests passed

View Details
Test Status Duration
Request Payload.Request With Person Properties Device Id ✅ 41ms
Request Payload.Flags Request Uses V2 Query Param ✅ 27ms
Request Payload.Flags Request Hits Flags Path Not Decide ✅ 27ms
Request Payload.Flags Request Omits Authorization Header ✅ 39ms
Request Payload.Token In Flags Body Matches Init ✅ 23ms
Request Payload.Groups Round Trip ✅ 24ms
Request Payload.Groups Default To Empty Object ✅ 25ms
Request Payload.Disable Geoip False Propagates As Geoip Disable False ✅ 23ms
Request Payload.Disable Geoip Omitted Defaults To False ✅ 25ms
Request Payload.Flag Keys To Evaluate Contains Only Requested Key ✅ 21ms
Request Lifecycle.No Flags Request On Init Alone ✅ 11ms
Request Lifecycle.No Flags Request On Normal Capture ✅ 22ms
Request Lifecycle.Two Flag Calls Produce Two Remote Requests ✅ 38ms
Request Lifecycle.Mock Response Value Is Returned To Caller ✅ 22ms
Retry Behavior.Retries Flags On 502 ✅ 327ms
Retry Behavior.Retries Flags On 504 ✅ 326ms
Side Effect Events.Get Feature Flag Captures Feature Flag Called Event ✅ 29ms

@marandaneto
marandaneto marked this pull request as draft October 23, 2026 08:55
@marandaneto

Copy link
Copy Markdown
Member

moved to draft since its not mergeable yet

@turnipdabeets

turnipdabeets commented Oct 24, 2026 •

Copy link
Copy Markdown
Contributor Author

moved to draft since its not mergeable yet

Was hoping to get a review on these changes in particular first so I can merge all the other PRs into this one. Then we can mark this as draft if we want. Just because there are changes in here, but it's just removing deprecated APIs so I'll can keep this in draft and and merge into it.

Remove the public APIs already marked deprecated: apiKey and the
apiKey factories, propertiesSanitizer and PostHogPropertiesSanitizer,
evaluationEnvironments, getFeatureFlagPayload, and the replay
debouncerDelayMs. remoteConfig moves to its own change because
setting it to false still changes setup behavior.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@turnipdabeets
turnipdabeets force-pushed the chore/v4-remove-deprecated branch from a41d9b9 to caf64bd Compare October 26, 2026 18:47
@turnipdabeets
turnipdabeets marked this pull request as draft October 26, 2026 22:43
turnipdabeets and others added 3 commits October 26, 2026 19:09
Matches posthog-ios 4.0 and the sdk-specs payload decoding contract.
* chore!: make SDK-internal helpers non-public for posthog-android 4.0

Make internal the public declarations that no other module in this repo
and no wrapper (Flutter, React Native, KMP) uses. LogLine and LogcatParser
are Java, so they become package-private.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* fix: keep GzipRequestInterceptor public for the compliance adapter

sdk_compliance_adapter is a separate Gradle module, only included by its
Dockerfile, and constructs GzipRequestInterceptor directly.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Setup now always loads /config. With remoteConfig = false, setup used to skip
/config, which left remote settings unloaded since /flags stopped returning
config.

Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@github-actions

github-actions Bot commented Oct 27, 2026 •

Copy link
Copy Markdown
Contributor
⚠️ `posthog-android-surveys-compose` is modified but not declared in any changeset

This is informational — the PR is not blocked. Click the triangle above to collapse, or push a fix and this comment will auto-delete.

Modified in this PR but not in any changeset:

  • posthog-android-surveys-compose

If this package should ship the change, add it to the changeset frontmatter:

---
"posthog-android-surveys-compose": patch
---

Changesets in this PR:

  • posthog — major
  • posthog-android — major
  • posthog-server — minor

* chore!: pass the load result to the feature flags callback

PostHogConfig.onFeatureFlags and reloadFeatureFlags() now take a PostHogFeatureFlagsCallback, whose loaded() receives a PostHogFeatureFlagsLoaded with the enabled flags, their values, and errorsLoading, matching posthog-ios 4.0. Every path that invoked the callback passes an accurate result, including failures, a disabled SDK, and bootstrap.

PostHogOnFeatureFlags moves to posthog-server under the same name, so the server's API is unchanged and it can drop the type in its own major.

* chore: drop the unused server callback wrapper

posthog-server calls its own PostHogOnFeatureFlags directly, and the core stateless client never calls config.onFeatureFlags. Bump posthog-server to minor since it now depends on core 7.0, and document that a bootstrapped onFeatureFlags runs on the setup() thread.

* fix: report persisted flags when the first flags load fails

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix: isolate the bootstrap internal flags callback from setup

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix: keep loaded flags when a flags reload fails

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix: retry flag cache hydration while storage is unreadable

A failed load now hydrates the flag cache before the callback. Under Direct
Boot that read returned empty values and latched, so persisted flags stayed
hidden after unlock. Only latch once the preferences are readable.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix: skip flag cache reads while storage is unreadable

Every flag getter retried hydration under Direct Boot and re-read each cached
key, each read failing against locked preferences. Check availability once and
skip the reads until storage is readable.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix: don't let cache hydration undo a concurrent reset

Hydration reads the cache off the flags lock, so a reset() landing between the
read and the commit had the previous identity's flags restored. clear() now
bumps a generation and hydration drops a commit from an older one.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>

This branch has not been deployed

No deployments
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