Skip to content

fix(experiments): freeze clock in metricQueryUtils getQuery tests - #70244

Merged
pauldambra merged 1 commit into
masterfrom
posthog-code/experiment-metric-query-clock-flake
Jul 11, 2026
Merged

fix(experiments): freeze clock in metricQueryUtils getQuery tests#70244
pauldambra merged 1 commit into
masterfrom
posthog-code/experiment-metric-query-clock-flake

Conversation

@pauldambra

Copy link
Copy Markdown
Member

Problem

metricQueryUtils.test.ts is auto-quarantined as flaky by Trunk (e.g. getQuery returns the correct query for a mean metric with sum math type). The getQuery tests compare a query object whose date_from/date_to are built from dayjs().

Changes

getQuery (in metricQueryUtils.ts) computes the default date range at call time:

date_from: dayjs().subtract(EXPERIMENT_DEFAULT_DURATION, 'day').format('YYYY-MM-DDTHH:mm'),
date_to: dayjs().endOf('d').format('YYYY-MM-DDTHH:mm'),

Each getQuery test recomputes the identical dayjs() expressions independently in its expected value. Both are formatted to the minute. When a minute rollover falls between getQuery's internal dayjs() read and the test's read, the two minute strings differ (e.g. 12:34 vs 12:35) and toEqual fails. Seven tests in the file share this pattern — a rare (~ms-per-minute) timing race, exactly the profile of an auto-quarantined flake.

Freeze the system clock file-wide with fake timers at a fixed midday instant so both reads resolve to the same time. Deliberately not using advanceTimers — the clock must not move, or the race persists. The freeze is harmless to the file's other (pure, date-independent) describe blocks.

How did you test this code?

  • Deterministically demonstrated the mechanism: a scratch test froze the clock at :59.999, read the date_from expression (as getQuery does), advanced ~2ms across the minute boundary, and read it again (as the test's expected value does) — the two minute strings differed, which is precisely what makes toEqual fail. (Scratch test removed; not part of this PR.)
  • Ran the full metricQueryUtils.test.ts file 10x with the freeze: 10/10 green, no impact on the non-date describe blocks.

The natural flake rate is far too low to catch in a practical repro loop, so validation is the deterministic mechanism demonstration above plus the frozen-clock fix that removes the nondeterminism at its source.

🤖 Agent context

Autonomy: Human-driven (agent-assisted)

Authored by PostHog Code (Opus) working a flaky-test backlog. Pulled the quarantined-test list from Trunk's list-quarantined-tests REST API (998 auto-quarantined tests), filtered to frontend, and picked this one because a pure-function test flaking points to a definite nondeterminism (here: unfrozen dayjs()) rather than an environment race. Invoked the repo /fixing-flaky-tests skill. Fix follows the existing LemonCalendarSelect.test.tsx fake-timers idiom, adjusted to a frozen (non-advancing) clock so the minute-precision reads can't diverge.


Created with PostHog Code

getQuery builds date_from/date_to from dayjs() at call time formatted to
the minute (YYYY-MM-DDTHH:mm). The getQuery tests recompute the same
dayjs() expressions independently in their expected values, so when a
minute rollover falls between getQuery's internal read and the test's
read, the two minute strings differ and toEqual fails. Seven tests share
this pattern; it is why the file is auto-quarantined as flaky.

Freeze the system clock file-wide (fake timers without advanceTimers, so
it cannot move) at a fixed midday instant, making both reads resolve to
the same time. Verified the mechanism deterministically (two dayjs reads
straddling :59.999 -> :00.001 produce different minute strings) and ran
the full file 10x green with the freeze.

Generated-By: PostHog Code
Task-Id: 579aeefd-dccd-4225-9813-79f735ee0c3f
@github-actions

github-actions Bot commented Jul 11, 2026

Copy link
Copy Markdown
Contributor

🦔 Hogbox preview · ✅ ready

▶ Open the preview

🔑 Login test@posthog.com / 12345678 (demo data)
🧩 Running this PR's backend and frontend, on the PostHog :master base
🔗 Link stable across rebuilds — a re-push swaps the box underneath, the URL stays
🔒 Access tailnet only (PostHog VPN)
🛠️ Admin inspect & debug state in hogland
💤 Idle sleeps after ~30 min idle (snapshot to S3, zero node cost) and wakes on your next visit in ~30s, behind a brief "waking up" screen

commit 05104b8 · box box-ee2892699174 · ready in 503s (push → usable) · build log · rebuilds on every push, torn down on close

@pr-assigner-resolver-posthog
pr-assigner-resolver-posthog Bot requested a review from a team July 11, 2026 17:33
@github-actions

github-actions Bot commented Jul 11, 2026

Copy link
Copy Markdown
Contributor

🤖 CI report

Bundle size — no change

Uncompressed size of every built .js bundle, compared against the base branch.

Total: 68.08 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 budget

How 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 import() / React.lazy chunks are not counted.

Root Eager (shipped) Δ vs base Budget
entry (logged-out pages, app bootstrap)
src/index.tsx
1.21 MiB · 22 files no change ███░░░░░░░ 28.2% of 4.29 MiB
authenticated shell (every logged-in page)
src/scenes/AuthenticatedShell.tsx
8.10 MiB · 2,974 files no change █████████░ 87.5% of 9.25 MiB

🟢 node_modules/monaco-editor/ stays out of src/index.tsx
🟢 src/lib/components/ActivityLog/describers stays out of src/index.tsx
🟢 [object Object] stays out of src/index.tsx
🟢 [object Object] stays out of src/index.tsx
🟢 node_modules/monaco-editor/ stays out of src/scenes/AuthenticatedShell.tsx
🟢 src/lib/components/ActivityLog/describers stays out of src/scenes/AuthenticatedShell.tsx
🟢 [object Object] stays out of src/scenes/AuthenticatedShell.tsx
🟢 [object Object] stays out of src/scenes/AuthenticatedShell.tsx

Largest files eagerly shipped from src/index.tsx
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
668 B src/index.tsx
Largest files eagerly shipped from src/scenes/AuthenticatedShell.tsx
Size File
278.2 KiB ../node_modules/.pnpm/posthog-js@1.399.2/node_modules/posthog-js/dist/rrweb.js
266.9 KiB ../node_modules/.pnpm/@posthog+icons@0.37.4_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/@posthog/icons/dist/posthog-icons.es.js
234.9 KiB src/taxonomy/core-filter-definitions-by-group.json
221.5 KiB ../node_modules/.pnpm/posthog-js@1.399.2/node_modules/posthog-js/dist/module.js
164.0 KiB src/queries/validators.js
154.2 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.9 KiB src/lib/api.ts
93.3 KiB ../node_modules/.pnpm/prosemirror-view@1.40.1/node_modules/prosemirror-view/dist/index.js
90.6 KiB ../node_modules/.pnpm/@tiptap+core@3.20.6_@tiptap+pm@3.20.6/node_modules/@tiptap/core/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 — no change

Total size of the built frontend/dist folder (all assets), compared against the base branch.

Total: 1283.90 MiB · no change

⚠️ Playwright — 1 failed

🎭 Playwright report · View test results →

1 failed test:

  • Retention calculations, period, breakdown, and chart (chromium)

These issues are not necessarily caused by your changes.
Annoyed by this section? Help fix flakies and failures and it will go green!

@trunk-io

trunk-io Bot commented Jul 11, 2026

Copy link
Copy Markdown

Static BadgeStatic BadgeStatic BadgeStatic Badge

View Full Report ↗︎Docs

@pauldambra pauldambra added the stamphog Request AI approval (no full review) label Jul 11, 2026

@stamphog stamphog Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Test-only change freezing fake timers to fix a flaky date-comparison test; diff matches the description exactly, no risky territory touched, no outstanding concerns.

  • 👍 on the PR from chatgpt-codex-connector[bot], hex-security-app[bot].
Gate mechanics and policy version
Gate Result
prerequisites all clear
deny-list no deny categories matched
size 0L, 0F substantive, 12L/1F incl. docs/generated/snapshots — within ceiling
tier T0 auto-approve: T0-deterministic (12L, 1F, single-area, fix)
stamphog 2.0.0b3 .stamphog/policy.yml @ b7847a3 · reviewed head 05104b8

@pauldambra
pauldambra enabled auto-merge (squash) July 11, 2026 18:36
@pauldambra
pauldambra merged commit dd4eae1 into master Jul 11, 2026
283 checks passed
@pauldambra
pauldambra deleted the posthog-code/experiment-metric-query-clock-flake branch July 11, 2026 18:41
@deployment-status-posthog

deployment-status-posthog Bot commented Jul 11, 2026

Copy link
Copy Markdown

Deploy status

Environment Status Deployed At Workflow
dev ✅ Deployed 2026-07-11 19:03 UTC Run
prod-us ✅ Deployed 2026-07-11 19:15 UTC Run
prod-eu ✅ Deployed 2026-07-11 19:15 UTC Run

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

Labels

stamphog Request AI approval (no full review)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant