feat(data-warehouse): implement clickhouse_cloud import source - #71233
Conversation
Fill in the scaffolded ClickHouse Cloud source: endpoint catalog, tracked HTTP transport with 31-day usageCost date windowing and resumable state, schemas, credential validation, canonical descriptions, and tests. Ships visible with releaseStatus=ALPHA. Generated-By: PostHog Code Task-Id: 4605404a-b4c7-41a0-ad05-8410ffd7248a
|
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 |
🤖 CI report
|
| File | Patch | Uncovered changed lines |
|---|---|---|
products/warehouse_sources/backend/temporal/data_imports/sources/clickhouse_cloud/clickhouse_cloud.py |
96.4% | 46–47, 108, 140–141, 143 |
products/warehouse_sources/backend/temporal/data_imports/sources/clickhouse_cloud/tests/test_clickhouse_cloud.py |
97.9% | 140–142, 238 |
🤖 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 29435165022 -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,473 / 37,804 |
signals |
████████████████░░░░ 79.1% |
19,072 / 24,111 |
data_modeling |
████████████████░░░░ 80.0% |
4,834 / 6,045 |
cdp |
████████████████░░░░ 80.7% |
3,118 / 3,864 |
agent_platform |
█████████████████░░░ 84.2% |
3,112 / 3,695 |
notebooks |
█████████████████░░░ 84.3% |
6,343 / 7,520 |
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.0% |
5,647 / 6,345 |
mcp_analytics |
██████████████████░░ 89.1% |
2,502 / 2,807 |
error_tracking |
██████████████████░░ 89.6% |
9,724 / 10,852 |
alerts |
██████████████████░░ 89.9% |
3,638 / 4,046 |
engineering_analytics |
██████████████████░░ 90.1% |
5,105 / 5,665 |
streamlit_apps |
██████████████████░░ 90.5% |
2,502 / 2,764 |
slack_app |
██████████████████░░ 90.6% |
9,511 / 10,503 |
marketing_analytics |
██████████████████░░ 90.8% |
11,514 / 12,684 |
product_analytics |
██████████████████░░ 91.1% |
5,527 / 6,068 |
data_warehouse |
██████████████████░░ 92.4% |
18,005 / 19,489 |
workflows |
██████████████████░░ 92.4% |
5,150 / 5,574 |
web_analytics |
███████████████████░ 92.7% |
13,624 / 14,691 |
ai_observability |
███████████████████░ 92.8% |
14,863 / 16,014 |
surveys |
███████████████████░ 92.9% |
5,660 / 6,094 |
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 |
skills |
███████████████████░ 94.4% |
2,827 / 2,995 |
revenue_analytics |
███████████████████░ 94.5% |
3,598 / 3,809 |
review_hog |
███████████████████░ 94.6% |
6,500 / 6,873 |
endpoints |
███████████████████░ 94.6% |
8,647 / 9,143 |
logs |
███████████████████░ 95.3% |
9,528 / 9,994 |
replay_vision |
███████████████████░ 95.7% |
13,300 / 13,896 |
experiments |
███████████████████░ 95.7% |
24,171 / 25,248 |
feature_flags |
███████████████████░ 96.1% |
14,757 / 15,354 |
annotations |
███████████████████░ 96.2% |
732 / 761 |
warehouse_sources |
███████████████████░ 96.2% |
224,038 / 232,910 |
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.
✅ Django migration risk — no migrations to analyze
No Django migrations need risk analysis.
The scaffold base branch's regeneration of generated_configs.py made StripeAuthMethodConfig's option sub-fields required, which breaks mypy and Stripe test collection (only the selected auth option's fields are present in a config dict, so they must be optional). Restore the exact class shape checked in on master. Generated-By: PostHog Code Task-Id: 4605404a-b4c7-41a0-ad05-8410ffd7248a
|
CI triage: the failing Pushed 0176148 restoring the exact class shape master has. Note for the base branch (#71137): anyone re-running |
6a0420e
into
tom/scaffold-100-eng-support-sources
Problem
The
clickhouse_cloudwarehouse source was scaffolded in #71137 withunreleasedSource=Trueand no sync logic. FinOps and platform teams want ClickHouse Cloud cost and service data in the warehouse for chargeback, cost-trend, and capacity dashboards.Changes
Implements the source end-to-end and ships it visible with
releaseStatus=ALPHA(theunreleasedSourceflag is removed).Architecture (per the
source.py/settings.py/ transport split):settings.py– declarative endpoint catalog:organizations,services,usage_cost,api_keys,members,activities,backups, with per-endpoint primary keys, stable partition keys (date,createdAt,startedAt), and incremental fields.clickhouse_cloud.py– transport overmake_tracked_session()with HTTP Basic auth (API key ID/secret). The API returns complete unpaginatedresultarrays, and scopes each key to exactly one organization.usage_costis the flagship stream: the API capsfrom_date/to_dateat 31 days per request, so the source walks contiguous non-overlapping windows forward from the org'screatedAt(full refresh) or the watermark (incremental), yielding rows sorted ascending so per-batch watermark checkpointing stays correct. Nestedmetrics(storageCHC, computeCHC, ...) are flattened into columns. Recent records are restated until ClickHouse locks them, so the schema declares a 31-day incremental lookback and is merge-only.ResumableSource: the usage cost walk bookmarks the next window start in Redis after each yielded window, so Temporal retries resume mid-backfill instead of restarting.Retry-After(the API allows 10 requests per 10s); 401/403 are registered as non-retryable with actionable user messages.canonical_descriptions.pydocuments every table/column from the official OpenAPI spec, andlists_tables_without_credentials=Truepublishes the catalog to the public docs.Note
Endpoint shapes were verified against the live public OpenAPI spec at
api.clickhouse.cloud(fetched during implementation) plus unauthenticated probes for error shapes. I couldn't run authenticated calls (no ClickHouse Cloud credentials), so two behaviors are spec-verified but not live-verified: theactivitiesfrom_datefilter (kept merge-only so a silently-ignored filter can't duplicate rows) and the exact lock cadence of usage cost records (covered by the 31-day re-pull window).Docs: PostHog/posthog.com#18554 adds
contents/docs/cdp/sources/clickhouse-cloud.md;docsUrlmatches the slug andaudit_source_docsreports no issues for this source.How did you test this code?
pytest products/warehouse_sources/backend/temporal/data_imports/sources/clickhouse_cloud/tests/– 52 tests pass.from_date > to_date, resume state saved before yield (data loss on crash), missingorganizationId/serviceIdstamping (breaks composite primary keys), activities arriving unsorted (corrupts the ascending watermark), credential-status mapping, and retry/non-retryable error classification.unreleasedSource).sources/tests/,common/test/) pass except pre-existing MinIO-dependent failures that also fail on the base branch.ruff check/ruff formatclean.generate:source-configsregeneratedClickhouseCloudSourceConfig.Automatic notifications
Docs update
PostHog/posthog.com#18554 adds the source doc.
🤖 Agent context
Autonomy: Human-driven (agent-assisted)
/implementing-warehouse-sources,/documenting-warehouse-sources, and/writing-testsskills.list[dict]batches instead of a source-levelBatcherper current skill guidance.rest_source.RESTClientbecause the API has no pagination and needs date-window chunking; skipped the Prometheus metrics endpoint (point-in-time text-format scrapes don't fit warehouse tables well) – can be added later if requested.Created with PostHog Code