feat(data-warehouse): implement runpod import source - #70710
Conversation
|
Hey @Gilbert09! 👋 It looks like your git author email on this PR isn't your
You can fix it for this repo with: git config user.email "you@posthog.com"Or set it globally with |
🦔 Hogbox preview · ✅ ready▶ Open the preview
commit |
Adds the user-facing doc for the new RunPod warehouse source (PostHog/posthog#70710), following the canonical source-doc template. Generated-By: PostHog Code Task-Id: 87af3114-851f-4c28-b114-3b075d0a0ff4
🤖 CI report✅ Bundle size — no changeUncompressed size of every built Total: 64.77 MiB · no change No file changed by more than 1000 B. Posted automatically by build-bundle-size-report · uncompressed bytes from dist-report ✅ Eager graph — within budgetHow much code each root ships on the eager path — downloaded and parsed before the surface is interactive. Measured from the esbuild output chunks (post-tree-shake, static imports only); lazy
🟢 Largest files eagerly shipped from
|
| Size | File |
|---|---|
| 126.8 KiB | ../node_modules/.pnpm/react-dom@18.3.1_react@18.3.1/node_modules/react-dom/cjs/react-dom.production.min.js |
| 24.6 KiB | ../node_modules/.pnpm/buffer@6.0.3/node_modules/buffer/index.js |
| 6.3 KiB | ../node_modules/.pnpm/react@18.3.1/node_modules/react/cjs/react.production.min.js |
| 4.5 KiB | ../node_modules/.pnpm/@jspm+core@2.1.0/node_modules/@jspm/core/nodelibs/browser/process.js |
| 3.9 KiB | ../node_modules/.pnpm/scheduler@0.23.2/node_modules/scheduler/cjs/scheduler.production.min.js |
| 1.4 KiB | ../node_modules/.pnpm/base64-js@1.5.1/node_modules/base64-js/index.js |
| 1.3 KiB | src/RootErrorBoundary.tsx |
| 912 B | ../node_modules/.pnpm/ieee754@1.2.1/node_modules/ieee754/index.js |
| 789 B | src/scenes/ChunkLoadErrorBoundary.tsx |
| 762 B | src/index.tsx |
Largest files eagerly shipped from src/scenes/AuthenticatedShell.tsx
| Size | File |
|---|---|
| 281.3 KiB | ../node_modules/.pnpm/posthog-js@1.402.3/node_modules/posthog-js/dist/rrweb.js |
| 267.7 KiB | ../node_modules/.pnpm/@posthog+icons@0.38.0_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/@posthog/icons/dist/posthog-icons.es.js |
| 235.5 KiB | src/taxonomy/core-filter-definitions-by-group.json |
| 222.9 KiB | ../node_modules/.pnpm/posthog-js@1.402.3/node_modules/posthog-js/dist/module.js |
| 164.0 KiB | src/queries/validators.js |
| 154.3 KiB | ../node_modules/.pnpm/re2js@0.4.1/node_modules/re2js/build/index.esm.js |
| 126.8 KiB | ../node_modules/.pnpm/react-dom@18.3.1_react@18.3.1/node_modules/react-dom/cjs/react-dom.production.min.js |
| 105.8 KiB | src/lib/api.ts |
| 93.3 KiB | ../node_modules/.pnpm/prosemirror-view@1.40.1/node_modules/prosemirror-view/dist/index.js |
| 92.7 KiB | ../packages/quill/packages/quill/dist/index.js |
Posted automatically by check-eager-graph · sizes are eager output bytes (shipped, post-tree-shake) from the esbuild metafile · part of #32479
✅ Dist folder size — 🔺 +3.0 KiB (+0.0%)
Total size of the built frontend/dist folder (all assets), compared against the base branch.
Total: 1312.62 MiB · 🔺 +3.0 KiB (+0.0%)
⚠️ Backend coverage — 98.0% of changed backend lines covered — 7 uncovered
🧪 Backend test coverage
Patch coverage — changed backend lines (products + core): ████████████████████ 98.0% (378 / 385)
| File | Patch | Uncovered changed lines |
|---|---|---|
products/warehouse_sources/backend/temporal/data_imports/sources/runpod/source.py |
90.6% | 114–115, 117 |
products/warehouse_sources/backend/temporal/data_imports/sources/runpod/runpod.py |
96.6% | 63, 104, 107, 224 |
🤖 Agents: add a test covering the lines above, or note why under "How did you test this code?". Machine-readable gap list: the patch-coverage artifact on this run (gh run download 29463697062 -n patch-coverage), or the coverage-data block at the end of this comment.
Per-product line coverage (touched products)
| Product | Coverage | Lines |
|---|---|---|
demo |
███████████░░░░░░░░░ 56.2% |
1,497 / 2,663 |
tasks |
█████████████░░░░░░░ 67.4% |
25,560 / 37,895 |
signals |
████████████████░░░░ 79.1% |
19,035 / 24,073 |
data_modeling |
████████████████░░░░ 80.0% |
4,834 / 6,045 |
cdp |
████████████████░░░░ 80.7% |
3,118 / 3,864 |
notebooks |
█████████████████░░░ 84.3% |
6,343 / 7,520 |
agent_platform |
█████████████████░░░ 84.7% |
3,273 / 3,862 |
cohorts |
█████████████████░░░ 86.1% |
4,022 / 4,671 |
actions |
█████████████████░░░ 86.6% |
717 / 828 |
product_tours |
█████████████████░░░ 87.5% |
1,266 / 1,447 |
exports |
██████████████████░░ 88.3% |
6,891 / 7,800 |
conversations |
██████████████████░░ 88.9% |
16,129 / 18,133 |
dashboards |
██████████████████░░ 89.1% |
5,719 / 6,418 |
mcp_analytics |
██████████████████░░ 89.1% |
2,502 / 2,807 |
error_tracking |
██████████████████░░ 89.6% |
9,718 / 10,852 |
alerts |
██████████████████░░ 89.9% |
3,638 / 4,046 |
engineering_analytics |
██████████████████░░ 90.1% |
5,105 / 5,665 |
streamlit_apps |
██████████████████░░ 90.4% |
2,499 / 2,764 |
slack_app |
██████████████████░░ 90.6% |
9,511 / 10,503 |
marketing_analytics |
██████████████████░░ 90.8% |
11,514 / 12,684 |
product_analytics |
██████████████████░░ 91.1% |
5,599 / 6,143 |
data_warehouse |
██████████████████░░ 92.1% |
18,133 / 19,683 |
workflows |
██████████████████░░ 92.4% |
5,148 / 5,574 |
web_analytics |
███████████████████░ 92.7% |
13,624 / 14,691 |
ai_observability |
███████████████████░ 92.8% |
14,868 / 16,019 |
surveys |
███████████████████░ 92.9% |
5,687 / 6,120 |
posthog_ai |
███████████████████░ 93.2% |
1,322 / 1,418 |
approvals |
███████████████████░ 93.3% |
3,395 / 3,640 |
reminders |
███████████████████░ 93.4% |
468 / 501 |
early_access_features |
███████████████████░ 93.8% |
848 / 904 |
endpoints |
███████████████████░ 94.1% |
8,606 / 9,143 |
skills |
███████████████████░ 94.4% |
2,827 / 2,995 |
revenue_analytics |
███████████████████░ 94.5% |
3,598 / 3,809 |
review_hog |
███████████████████░ 94.6% |
6,532 / 6,905 |
logs |
███████████████████░ 95.3% |
9,528 / 9,994 |
experiments |
███████████████████░ 95.6% |
24,171 / 25,288 |
replay_vision |
███████████████████░ 95.7% |
13,354 / 13,952 |
annotations |
███████████████████░ 96.2% |
732 / 761 |
warehouse_sources |
███████████████████░ 96.2% |
232,919 / 241,997 |
feature_flags |
███████████████████░ 96.3% |
16,038 / 16,661 |
user_interviews |
███████████████████░ 96.4% |
2,242 / 2,325 |
data_catalog |
███████████████████░ 97.1% |
2,035 / 2,095 |
customer_analytics |
███████████████████░ 97.2% |
7,480 / 7,698 |
Report-only. Patch coverage = changed backend lines covered vs origin/master. Sorted lowest first.
Known gaps: lines covered only by Temporal tests show as uncovered; core line numbers may drift if master changed the same file.
|
The only red check is deploy preview (Hogbox preview environment), and it's an infrastructure failure unrelated to this change — not a code or test failure. The provisioning backend fails before any of this PR's code runs, with errors like This is a backend-only data-warehouse source change with no frontend or deploy impact, so there's nothing to fix here in code. The preview job retries on each push and should recover once the preview infra is healthy. All 168 required checks pass, including the warehouse-sources product tests and the Temporal Django tests that exercise this source. 🦉 via talyn.dev |
PR overviewAll previously flagged issues have been addressed. No open security concerns remain on this pull request. Security reviewNo open security issues remain on this pull request. Fixed/addressed: 1 · PR risk: 0/10 |
|
Addressed the startup-command finding in f930932: The failing |
|
👋 Visual changes detected for this PR. Review and approve in PostHog Visual Review If these changes are unexpected, they may be caused by a flaky test or a broken snapshot on master. Don't approve — rerun the job or wait for a fix. |
Adds the user-facing doc for the new RunPod warehouse source (PostHog/posthog#70710), following the canonical source-doc template. Generated-By: PostHog Code Task-Id: 87af3114-851f-4c28-b114-3b075d0a0ff4
Implements the RunPod warehouse source: daily billing history for pods, serverless endpoints, and network volumes (incremental via server-side startTime windows), plus full-refresh snapshots of pods, endpoints, templates, and network volumes. Resumable via 90-day window checkpoints, tracked HTTP transport, canonical table descriptions, and an official brand icon. Generated-By: PostHog Code Task-Id: 87af3114-851f-4c28-b114-3b075d0a0ff4
RunPod Pods, endpoints, and templates carry a user-configured `env` map that can hold cloud access keys and other credentials. Those objects were yielded unchanged, materializing the secrets in the warehouse where any project member with warehouse access could read them, and their raw response bodies were eligible for HTTP sample capture. Strip `env` recursively from inventory records before yielding, and disable HTTP sample capture for the endpoints that carry it (the env values have arbitrary user-chosen names the name-based sample scrubbers can't recognise). Generated-By: PostHog Code Task-Id: 7779dbe7-46f5-404b-a4a3-847a70c8db51
Remove unreleasedSource=True so the finished source is visible in the connector catalog, and drop any test asserting the hidden state.
RunPod Pods, endpoints, and templates also carry user-controlled dockerStartCmd and dockerEntrypoint command arrays, which can embed credentials as CLI arguments just like the env map. Add both to the endpoints' sensitive_keys so the existing recursive strip removes them before rows reach the warehouse, and extend the stripping test to guard the full key set. Generated-By: PostHog Code Task-Id: 87af3114-851f-4c28-b114-3b075d0a0ff4
648a93c to
bf07bd1
Compare
Generated-By: PostHog Code Task-Id: 4f3080d3-dcd3-4379-8bbc-a24aaf889472
Problem
RunPod is a fast-growing GPU cloud used heavily by AI startups for on-demand GPU capacity and autoscaling serverless inference. Teams running workloads there want their compute inventory and, above all, their billing history queryable next to product data in the PostHog data warehouse. The
runpodsource existed only as a scaffolded stub (unreleasedSource=True, no sync logic).Why
Requested implementation of the scaffolded RunPod source so warehouse users can analyze GPU spend and infrastructure alongside their product data.
Changes
Implements the RunPod source end-to-end following the standard
source.py/settings.py/runpod.pysplit, as aResumableSource:billing_pods,billing_endpoints,billing_network_volumes) and four inventory snapshots (pods,endpoints,templates,network_volumes), verified against RunPod's live OpenAPI spec atrest.runpod.io/v1.startTimefilter, so they support incremental syncs on the buckettimefield with a 48h lookback re-read (open day buckets keep accumulating charges; merge dedupes on a surrogate id hashed from the bucket start + grouping dimensions, never the amounts). Inventory lists have no updated-since filter and ship full refresh only.sort_mode="asc"), with resume state saved after each yielded window.make_tracked_session(), tenacity retries for 429/5xx, non-retryable 401/403 mapping,validate_credentialsprobe (403 accepted at create time for scoped keys), canonical table/column descriptions from the official API docs,lists_tables_without_credentials = Truefor public docs, and the official RunPod brand icon (SVG from their docs site).unreleasedSource=TruewithreleaseStatus=ReleaseStatus.ALPHA; regeneratedRunPodSourceConfig; movedrunpodinto the Implemented table inSOURCES.md. Enum + migration already landed with the scaffold, so no new migration.Note
I could not curl-verify the billing endpoints' filtering behavior with real credentials (no RunPod account available), so the time-window semantics follow the live OpenAPI spec conservatively:
startTimeis floored to UTC midnight to stay aligned with day-bucket boundaries, and merge-on-surrogate-id absorbs any boundary overlap. Noted in code comments.The user-facing doc (
contents/docs/cdp/sources/runpod.md) is written per the docs template and needs to land in the posthog.com repo;audit_source_docsreports no runpod issues against it.How did you test this code?
pytest products/warehouse_sources/backend/temporal/data_imports/sources/runpod/tests/(41 passed). New coverage, per group:endTimeomitted on the final window, resumes from saved state, and sorts rows ascending. Catches unbounded walks and watermark corruption.pytest products/warehouse_sources/backend/temporal/data_imports/sources/tests/+ config generator tests (1566 passed) — registry-wide guards.ruff check --fix,ruff format, andhogli ci:preflight --fix(0 failures).Automatic notifications
Docs update
Doc written for the posthog.com repo at
contents/docs/cdp/sources/runpod.md(canonical template,<SourceParameters />+<SourceTables />, alpha callout); it needs to land there since it lives outside this repo.🤖 Agent context
Autonomy: Human-driven (agent-assisted)
Built with PostHog Code following the
/implementing-warehouse-sources,/documenting-warehouse-sources, and/writing-testsskills. Key decisions: modeled on the anthropic source (closest shape: API key + bucketed billing reports + entity snapshots); chose day buckets (API default, stable surrogate keys) with a 48h lookback over hour buckets; chose 90-day request windows to bound memory since the API doesn't paginate; skipped thecontainerregistryauthendpoint (id/name only, low warehouse value); kept the source unreleased/alpha as directed. The Stripe config drift the generator produced in this env (missing OAuth env vars) was reverted, keeping only the RunPod hunk ingenerated_configs.py.Created with PostHog Code