chore: template public API snapshot versions#238
Conversation
Prompt To Fix All With AIFix the following 1 code review issue. Work through them one at a time, proposing concise fixes.
---
### Issue 1 of 1
Directory.Build.targets:30-40
**Backslash path separators break the task on Linux**
`_PublicApiSnapshotOutputDir` ends with `\`, and all task parameters (`SourceFile`, `OutputFile`) are typed as `System.String`. MSBuild does not normalize path separators for `System.String` parameters — unlike `ITaskItem` parameters or `Exists()` calls — so the raw string is passed to the C# `File.ReadAllText`/`File.WriteAllText` calls. On Linux `\` is not a path separator, meaning `File.ReadAllText("$(MSBuildProjectDirectory)\PublicAPI.Shipped.txt")` looks for a file named `PostHog\PublicAPI.Shipped.txt` inside the parent directory, which doesn't exist. The release CI runs on `ubuntu-latest`, so this path would throw a `FileNotFoundException` there. Replacing all `\` separators in property values and task attribute strings with `/` (which Windows also accepts) would fix this portably.
Reviews (1): Last reviewed commit: "chore: support package-specific API vers..." | Re-trigger Greptile |
posthog-dotnet Compliance ReportDate: 2026-06-22 06:52:09 UTC
|
| Test | Status | Duration |
|---|---|---|
| Request Payload.Request With Person Properties Device Id | ❌ | 45ms |
| Request Payload.Flags Request Uses V2 Query Param | ❌ | 24ms |
| Request Payload.Flags Request Hits Flags Path Not Decide | ❌ | 6ms |
| Request Payload.Flags Request Omits Authorization Header | ❌ | 5ms |
| Request Payload.Token In Flags Body Matches Init | ❌ | 5ms |
| Request Payload.Groups Round Trip | ❌ | 6ms |
| Request Payload.Groups Default To Empty Object | ❌ | 5ms |
| Request Payload.Person Properties Distinct Id Auto Populated When Caller Omits It | ❌ | 6ms |
| Request Payload.Disable Geoip False Propagates As Geoip Disable False | ❌ | 5ms |
| Request Payload.Disable Geoip Omitted Defaults To False | ❌ | 5ms |
| Request Payload.Flag Keys To Evaluate Contains Only Requested Key | ❌ | 5ms |
| Request Lifecycle.No Flags Request On Init Alone | ✅ | 4ms |
| Request Lifecycle.No Flags Request On Normal Capture | ✅ | 188ms |
| Request Lifecycle.Two Flag Calls Produce Two Remote Requests | ❌ | 8ms |
| Request Lifecycle.Mock Response Value Is Returned To Caller | ❌ | 6ms |
| Side Effect Events.Get Feature Flag Captures Feature Flag Called Event | ❌ | 5ms |
Failures
request_payload.request_with_person_properties_device_id
404, message='Not Found', url='http://sdk-adapter:8080/get_feature_flag'
request_payload.flags_request_uses_v2_query_param
404, message='Not Found', url='http://sdk-adapter:8080/get_feature_flag'
request_payload.flags_request_hits_flags_path_not_decide
404, message='Not Found', url='http://sdk-adapter:8080/get_feature_flag'
request_payload.flags_request_omits_authorization_header
404, message='Not Found', url='http://sdk-adapter:8080/get_feature_flag'
request_payload.token_in_flags_body_matches_init
404, message='Not Found', url='http://sdk-adapter:8080/get_feature_flag'
request_payload.groups_round_trip
404, message='Not Found', url='http://sdk-adapter:8080/get_feature_flag'
request_payload.groups_default_to_empty_object
404, message='Not Found', url='http://sdk-adapter:8080/get_feature_flag'
request_payload.person_properties_distinct_id_auto_populated_when_caller_omits_it
404, message='Not Found', url='http://sdk-adapter:8080/get_feature_flag'
request_payload.disable_geoip_false_propagates_as_geoip_disable_false
404, message='Not Found', url='http://sdk-adapter:8080/get_feature_flag'
request_payload.disable_geoip_omitted_defaults_to_false
404, message='Not Found', url='http://sdk-adapter:8080/get_feature_flag'
request_payload.flag_keys_to_evaluate_contains_only_requested_key
404, message='Not Found', url='http://sdk-adapter:8080/get_feature_flag'
request_lifecycle.two_flag_calls_produce_two_remote_requests
404, message='Not Found', url='http://sdk-adapter:8080/get_feature_flag'
request_lifecycle.mock_response_value_is_returned_to_caller
404, message='Not Found', url='http://sdk-adapter:8080/get_feature_flag'
side_effect_events.get_feature_flag_captures_feature_flag_called_event
404, message='Not Found', url='http://sdk-adapter:8080/get_feature_flag'
|
Reviews (2): Last reviewed commit: "fix: make public API template rendering ..." | Re-trigger Greptile |
💡 Motivation and Context
The release workflow bumps package versions before running
dotnet build. ThePostHogproject generates a publicVersionConstants.Versionconstant from its package version, and PublicApiAnalyzers treat the literal value of a public const as part of the API snapshot. This caused the release build to fail whenPostHogmoved from2.7.1to2.8.0whilePublicAPI.Shipped.txtstill contained the old literal version.This PR fixes the CI failure by making public API snapshots render
<version>placeholders before PublicApiAnalyzers run, and updates thePostHogshipped API snapshot to use that placeholder forPostHog.Versioning.VersionConstants.Version.It also ensures the rendering target is available in the SDK compliance Docker build and uses portable
/path separators for Linux CI.PostHog.AspNetCoreandPostHog.AIdo not currently expose or use their own runtime version constants, so this PR does not add new version APIs for those packages.💚 How did you test it?
dotnet build --configuration Release --no-restoredotnet test --configuration Release --no-builddotnet publish sdk_compliance_adapter/SdkComplianceAdapter.csproj -c Release -o /tmp/posthog-dotnet-sdk-compliance-publishdotnet build --configuration Release --no-restoresucceeds with:PostHog=2.8.0PostHog.AspNetCore=2.7.0PostHog.AI=0.1.3Note: attempted a local Docker build for the SDK compliance adapter, but Docker was not available in the local environment.
📝 Checklist
If releasing new changes
pnpm changesetto generate a changeset file🤖 Agent context
Autonomy: Human-driven (agent-assisted)
Implemented with pi. The chosen approach is intentionally scoped to the runtime API that caused the release failure: the existing
PostHog.Versioning.VersionConstants.Versionpublic const. A root MSBuild target renders public API snapshots from templates before Roslyn PublicApiAnalyzers run, while committed snapshots remain stable across package version bumps. Review feedback about Linux path handling and SDK compliance Docker inputs was addressed in a follow-up commit.