Skip to content

Conversation

@slshults
Copy link
Contributor

This PR addresses SDK Doctor feedback related to some issues with versions, release dates, status badges, and an intermittent stale cache problem we've seen (e.g. what Robbie saw in this slack thread. I've seen it a lot as well when impersonating users while working on support tickets.)

Problem:

Intermittent stale cache problem slack thread

Changes

(some of these also relate to other changes mentioned further below):

  • Implemented auto-refresh logic to detect stale caches (>26 hours) and trigger background refresh
  • Fixed cachedAt timestamp accuracy: Store actual timestamp when writing to Redis instead of calculating from TTL
  • Added cachedAt field to GitHub SDK versions API response
  • Added cachedAt field to team SDK versions API response with backward compatibility for old cache format
  • Fixed outdated comments:
    • Changed "every 6-12 hours" to "daily at midnight UTC" in 3 locations
    • Changed "72 hours" to "7 days"

Problem:

Feedback from users confused by versions displayed, badges, lack of release date info, and versions less than a week old flagged as Outdated (ZD tickets 41473, 41482, and this slack thread)

Changes:

  • Removed redundant badges next to SDK name. Redundant and confusing because we're already Showing SDK health is good with a green box saying All caught up... etc, OR Time for an update! with a yellow or red (in dark mode) box saying An outdated SDK means... etc., as well as next to the version number. The badge I'm removing here looked as if it was referring to the latest available version, as mentioned in a feedback ticket cited above (more related changes below these first two screenshots):

    before:

CleanShot 2025-11-20 at 17 40 50@2x
**after:**
CleanShot 2025-11-20 at 17 47 43@2x
  • Restored streetlight color scheme (green/amber/red), now using amber for Recent (Related: fixed the problem with newer than github version cache so they are marked Current, details further below)
  • Add Web SDK-specific minor version threshold: 9+ minors behind to reduce false positives resulting from frequent minor version releases on the web SDK (other SDKs still using 3+ behind)
  • Fixed grace period off-by-one: versions ≤7 days old now marked Recent (was <7 days)
  • Added cache timestamp to "Current" badge tooltip, with a hint to click Releases link for versions released since cache time
  • Added a tooltip to the Latest available version with cached time, and a hint to check Releases for newer
  • Improved tooltips, including release date info for all versions of SDKs in the posthog-js monorepo, regardless of age, lazy-loaded to tooltips so it doesn't slow page load (see next problem/changes for details.) (may still need to do the same for some other SDKs which have also changed the formatting of version numbers since inception)

Problem:

For monorepo SDKs, versions less than a month old had no release date info (because they were already out of reach of the 100 we're caching from GitHub.)

Changes:

  • Added an endpoint for release dates for versions which aren't in the github version cache.
  • Now checks existing cache for the version's release date first, if not found it fetches the release date and caches it forever (past release dates will never change)

Problem:

After using Scan events, events can include releases newer than the github cache, so the newest version was incorrectly marked Recent.

Changes:

Check most recent version against cached Latest version available and mark it as Current (instead of Recent) if the semver of the team version is higher that then cached github version

Screenshots of the tooltips (because they make more sense when seen in the UI than when reading the code)...

Hovering over Latest version available (screenshot taken just after midnight UTC):
CleanShot 2025-11-20 at 19 20 09@2x

Hovering over a Current badge:
CleanShot 2025-11-20 at 19 07 31@2x

Hovering over a Recent badge:
CleanShot 2025-11-20 at 19 07 52@2x

Hovering over an Outdated badge of a legacy version format:
CleanShot 2025-11-20 at 19 08 03@2x

How did you test this code?

On my local.

Copy link
Contributor

@greptile-apps greptile-apps bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

8 files reviewed, no comments

Edit Code Review Agent Settings | Greptile

Copilot finished reviewing on behalf of slshults November 21, 2025 03:47
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR fixes intermittent stale cache issues in SDK Doctor and improves the user experience with better status badges, tooltips, and version detection. It addresses user confusion around version displays and adds auto-refresh logic to detect and handle stale caches.

Key changes:

  • Implemented auto-refresh logic to detect stale caches (>26 hours) and trigger background refresh
  • Fixed cachedAt timestamp accuracy by storing actual timestamp when writing to Redis
  • Added lazy-loading endpoint for release dates of SDK versions not in the main cache
  • Improved status badges with amber/green/red color scheme and comprehensive tooltips showing release dates

Reviewed Changes

Copilot reviewed 7 out of 7 changed files in this pull request and generated 6 comments.

Show a summary per file
File Description
posthog/urls.py Added new endpoint for lazy-loading individual SDK version dates
posthog/api/team_sdk_versions.py Updated cache format to include cachedAt timestamp with backward compatibility
posthog/api/github_sdk_versions.py Added SDK version date endpoint with fallback tag format support and SDK repo mapping
dags/sdk_doctor/team_sdk_versions.py Store actual timestamp when caching instead of calculating from TTL later
dags/sdk_doctor/github_sdk_versions.py Added cachedAt timestamp to GitHub SDK version cache data
frontend/src/layout/navigation-3000/sidepanel/sidePanelLogic.tsx Moved Status tab to appear earlier in the tab list
frontend/src/layout/navigation-3000/sidepanel/panels/sidePanelSdkDoctorLogic.tsx Added lazy-loading logic for missing release dates and auto-refresh for stale caches
frontend/src/layout/navigation-3000/sidepanel/panels/SidePanelSdkDoctor.tsx Updated UI with improved tooltips and removed redundant status badges

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines 176 to 233
const sdkVersion = sdkVersions[sdkType as SdkType]

// Merge lazy-loaded dates
const mergedReleaseDates = { ...sdkVersion.releaseDates }
Copy link

Copilot AI Nov 21, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Potential null reference error. sdkVersion could be undefined if the SDK type exists in teamSdkVersions but not in sdkVersions. Add a null check before accessing sdkVersion.releaseDates to prevent runtime errors.

Copilot uses AI. Check for mistakes.
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in 5th commit

Comment on lines 382 to 397
teamVersions.forEach((versionInfo) => {
if (typeof versionInfo !== 'object' || !('lib_version' in versionInfo)) {
return
}
const version = versionInfo.lib_version
// Avoid duplicate API calls for already-loaded dates
const hasReleaseDate =
sdkVersion.releaseDates[version] !== undefined ||
values.lazyLoadedDates[`${sdkType}:${version}`] !== undefined

if (!hasReleaseDate) {
// Background load updates state when ready
actions.loadVersionDate({ sdkType: sdkType as SdkType, version })
}
})
})
Copy link

Copilot AI Nov 21, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The teamVersions variable may not be an array when iterating over teamSdkVersions entries. The code needs to check if teamVersions is an array before calling forEach, similar to the filtering logic in the selector at line 223. This could cause a runtime error if metadata fields like cached or cachedAt are present.

Suggested change
teamVersions.forEach((versionInfo) => {
if (typeof versionInfo !== 'object' || !('lib_version' in versionInfo)) {
return
}
const version = versionInfo.lib_version
// Avoid duplicate API calls for already-loaded dates
const hasReleaseDate =
sdkVersion.releaseDates[version] !== undefined ||
values.lazyLoadedDates[`${sdkType}:${version}`] !== undefined
if (!hasReleaseDate) {
// Background load updates state when ready
actions.loadVersionDate({ sdkType: sdkType as SdkType, version })
}
})
})
if (Array.isArray(teamVersions)) {
teamVersions.forEach((versionInfo) => {
if (typeof versionInfo !== 'object' || !('lib_version' in versionInfo)) {
return
}
const version = versionInfo.lib_version
// Avoid duplicate API calls for already-loaded dates
const hasReleaseDate =
sdkVersion.releaseDates[version] !== undefined ||
values.lazyLoadedDates[`${sdkType}:${version}`] !== undefined
if (!hasReleaseDate) {
// Background load updates state when ready
actions.loadVersionDate({ sdkType: sdkType as SdkType, version })
}
})
}

Copilot uses AI. Check for mistakes.
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in 4th commit

Comment on lines +114 to +115
github_url = f"https://api.github.com/repos/{repo}/releases/tags/{tag_name}"
response = requests.get(github_url, timeout=10)
Copy link

Copilot AI Nov 21, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

GitHub API requests are made without authentication, which limits the rate to 60 requests per hour per IP. This could cause issues in production with multiple users triggering lazy-loads. Consider adding GitHub token authentication via headers to increase the rate limit to 5,000 requests per hour.

Copilot uses AI. Check for mistakes.
Copy link
Contributor Author

@slshults slshults Nov 22, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in 4th commit

Comment on lines 115 to 117
response = requests.get(github_url, timeout=10)

if response.status_code == 200:
Copy link

Copilot AI Nov 21, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing rate limit handling for GitHub API. When the rate limit is exceeded (status code 403), the endpoint returns a 404 error, which could be misleading. Consider checking for rate limit errors (status 403 with rate limit headers) and returning a more appropriate error message to help with debugging.

Copilot uses AI. Check for mistakes.
Copy link
Contributor Author

@slshults slshults Nov 22, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in 4th commit

Upgrading is a good idea, but it's not urgent yet.
</>
) : (
"Upgrading is a good idea, but it's not urgent yet"
Copy link

Copilot AI Nov 21, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[nitpick] Inconsistent quotation mark usage. This line uses double quotes while the surrounding JSX uses single quotes. Consider using single quotes for consistency with the rest of the codebase.

Suggested change
"Upgrading is a good idea, but it's not urgent yet"
'Upgrading is a good idea, but it\'s not urgent yet'

Copilot uses AI. Check for mistakes.
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in 4th commit

Comment on lines 91 to 92
except (json.JSONDecodeError, AttributeError):
pass
Copy link

Copilot AI Nov 21, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

'except' clause does nothing but pass and there is no explanatory comment.

Suggested change
except (json.JSONDecodeError, AttributeError):
pass
except (json.JSONDecodeError, AttributeError) as e:
logger.warning(f"[SDK Doctor] Failed to decode cachedAt for team {team_id}", error=str(e))
capture_exception(e)

Copilot uses AI. Check for mistakes.
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in 4th commit

@github-actions
Copy link
Contributor

github-actions bot commented Nov 21, 2025

Size Change: 0 B

Total Size: 3.4 MB

ℹ️ View Unchanged
Filename Size
frontend/dist/toolbar.js 3.4 MB

compressed-size-action

@slshults
Copy link
Contributor Author

Also added fallback for pre-monorepo release dates for node and react-native in the 4th commit.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants