Skip to content

ci: run the interaction proofs in WebKit for gesture, motion and touch changes - #9138

Merged
cixzhang merged 3 commits into
mainfrom
ci/interaction-webkit-lane
Oct 31, 2026
Merged

cixzhang merged 3 commits into
mainfrom
ci/interaction-webkit-lane

Conversation

@cixzhang

@cixzhang cixzhang commented Oct 31, 2026 •

Copy link
Copy Markdown
Contributor

Maintainer impact

The touch interaction proofs run in Chromium only (pr-interaction --project chromium), so a correction that exists only for WebKit, the engine of every iOS browser, has no CI guard. #8360's tap-on-moving-content correction (presentedHitTesting.interaction.browser.spec.ts) is one example: the WebKit project in playwright.interaction.config.ts exists but never runs on a pull request, so a regression in WebKit-specific gesture or motion code can land green.

Intended invariant

  • Every existing check keeps its current behavior.
  • The test join stays the one required context for test owners, and every owner it waits on reports success whether it ran or skipped (spec:AST-030 FR7, FR11).
  • Pull-request jobs stay within the 15-minute budget on standard runners.
  • The scope step and the heavy-suite caps are the shared ones.

Change

  • New pr-interaction-webkit job in ci.yml. It mirrors pr-interaction step for step but runs --project webkit, after npx playwright install --with-deps webkit on ubuntu-latest, with a 15-minute timeout.
  • Scope (.github/actions/test-scope paths): the code where WebKit and Chromium differ on touch — packages/core/src/gestures/, packages/core/src/motion/, packages/core/src/internal/touch*, packages/core/src/utils/{press*,touch*,primaryClick*,isApplePlatform*}, packages/core/src/hooks/{useMenuPress*,menuPress*,useLongPress*,usePressFeedback*}, internal/interaction-harness/ — plus the shared setup pr-interaction keeps (spec:AST-030 FR13): playwright.interaction.config.ts, package.json, pnpm-lock.yaml, apps/storybook/, packages/themes/*/src/, internal/a11y-spec/, and its own definition (.github/workflows/ci.yml, the scope action).
    • The presented-hit-testing specs live under packages/core/src/gestures/__tests__/browser/, so the gestures path covers them.
  • Run: only the specs whose bundles reach that code: the gestures spec, animatedLayout and animator (motion), and the harness spec (177 tests). The motion adopters spec renders Storybook components (Collapsible, TreeList, ScrollableArea), and the component specs (DateInput, TabList, TreeList, SideNav) stay with the Chromium proofs, so a WebKit break there never turns an unrelated pull request red. A contract test builds each WebKit bundle and requires every source file it reaches to be in scope.
  • Out of scope: a visible "Skip the WebKit proofs outside their scope" step, and the job reports success.
  • Heavy-suite caps: the merge-ref heavy-suite caps step plus the counted "Heavy suite runs" step, in the same positions as pr-interaction.
  • Join: test now needs pr-interaction-webkit, and ci-test-join.mjs requires its success. No new required context.
  • Specs that need Chromium-only evidence (CDP tracing, scripted touch timestamps) already skip themselves in WebKit (harness README).

Evidence

Scope

  • No intended public API, product behavior, visual direction, or policy change.
  • Product changes discovered during the work were removed or split.
  • Public text and artifacts contain no internal Meta context.

Testing

pnpm vitest run --project node .github/scripts/; actionlint .github/workflows/ci.yml; replay of PR file lists through the scope pattern.

…h changes

pr-interaction runs the touch interaction proofs in Chromium only, so a
WebKit- or iOS-only correction had no CI guard. pr-interaction-webkit runs the
same proofs in WebKit (Playwright on ubuntu-latest, 15-minute budget), scoped
to the gesture host and recognizers, the motion runtime, the touch helpers,
press feedback, the menu press model, and the harness and config that drive
them (plus its own definition). Out of scope it skips visibly and reports
success; the existing test join requires it, so it adds no required context.
It uses the shared scope action and the merge-ref heavy-suite caps.
@vercel

vercel Bot commented Oct 31, 2026 •

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated
astryx Ready Ready Preview Oct 31, 2026 4:08pm UTC

Request Review

@astracat-bot

astracat-bot Bot commented Oct 31, 2026 •

Copy link
Copy Markdown

AI review status for this pull request.

Review status Updated
🟢 Reviewed (for maintainers only) Oct 31, 2026, 4:20 PM UTC

@meta-cla meta-cla Bot added the CLA Signed This label is managed by the Meta Open Source bot. label Oct 31, 2026
@github-actions

github-actions Bot commented Oct 31, 2026 •

Copy link
Copy Markdown
Contributor

PR Analysis Report

Preview: the links below open this branch's latest Vercel deployment, which can trail a new push until that push's deployment is ready.

📚 Storybook Preview

View Storybook for this PR

🧪 Sandbox Preview

View Sandbox for this PR

No new or modified components detected.

Bundle Size Summary

No component packages changed.

Accessibility Audit

Status: The accessibility audit did not run on this pull request. It runs after merges to main and before each release; pull requests that touch components run it with the ci:heavy-lanes label.


Generated by PR Enrichment workflow | Storybook | Sandbox | View full report

@astracat-bot astracat-bot 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.

Requesting changes: the WebKit job is wired into test correctly and passed on this head, but its scope needs to match what it runs and what spec:AST-030 FR13 requires before it can guard what it claims.

  • The run executes every interaction spec, DateInput, TabList and TreeList included, while the scope covers only gestures, motion and the harness, so a WebKit break in those specs lands green and fails test on the next unrelated in-scope pull request; filter the run to the in-scope spec directories or widen the scope to match.
  • package.json, pnpm-lock.yaml, Storybook config, theme sources and internal/a11y-spec/ skip the job, although FR13 runs shared infrastructure in full and pr-interaction already keeps them in scope; a Playwright upgrade is the clearest case.
  • Smaller: pressGesture.ts, menuPressGesture.ts, useLongPress.ts, usePressFeedback.ts and touchPresentation.ts fall outside the regex, so the skip message is wrong for them.

[Automated review]

Comment thread .github/workflows/ci.yml Outdated
id: scope
uses: ./.test-scope/.github/actions/test-scope
with:
paths: '^(packages/core/src/gestures/|packages/core/src/motion/|packages/core/src/internal/touch|packages/core/src/utils/pressFeedback|packages/core/src/hooks/useMenuPress|internal/interaction-harness/|playwright\.interaction\.config\.ts$|\.github/workflows/ci\.yml$|\.github/actions/test-scope/)'

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

This regex leaves out package.json, pnpm-lock.yaml, apps/storybook/, packages/themes/[^/]+/src/ and internal/a11y-spec/, which pr-interaction keeps (line 1785) and spec:AST-030 FR13 treats as shared infrastructure that runs the full suite. A Playwright upgrade swaps the WebKit build these proofs run on and would skip them. It also misses the press and menu-press state machines (utils/pressGesture.ts, hooks/menuPressGesture.ts, hooks/menuPressOnItems.ts, hooks/usePressFeedback.ts, hooks/useLongPress.ts) and the touch gate (utils/touchPresentation.ts, utils/touchQueries.ts), so the skip message on line 1911 is wrong for them.

Comment thread .github/workflows/ci.yml
Comment on lines +1966 to +1970
run: |
pnpm exec playwright test \
--config playwright.interaction.config.ts \
--project webkit \
--output interaction-proof-output-webkit

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

With no spec filter this runs every interaction spec, including DateInput/MonthScrollerSteps, TabList/TabListOverflow and TreeList/TreeListGuideAlignment (nine tests that pass in WebKit today), but the scope above never gates on those components or specs. A pull request that breaks one in WebKit lands green, and the next in-scope pull request gets the red test. Either pass the in-scope spec directories here (internal/interaction-harness packages/core/src/gestures packages/core/src/motion) or widen the scope to every directory with an interaction spec.

Comment on lines +146 to +150
'packages/themes/neutral/src/neutralTheme.ts',
'apps/storybook/.storybook/preview.tsx',
'docs/specs/AST-030/spec.md',
'package.json',
'pnpm-lock.yaml',

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

These assertions pin theme sources, Storybook config, package.json and pnpm-lock.yaml as skipping the WebKit proofs, the opposite of FR13's shared-infrastructure rule and of the Chromium contract in ci-interaction.test.mjs. They should flip with the scope fix.

Run only the gesture, motion and harness specs, so a WebKit break in a
component spec never turns an unrelated pull request red. Bring the shared
setup pr-interaction already keeps into scope (spec:AST-030 FR13: root
manifests and lockfile, Storybook config, theme sources, the a11y spec
helpers), and widen the press and touch helpers the regex missed.

@astracat-bot astracat-bot 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.

Requesting changes: the shared-setup scope and the run filter now match spec:AST-030 FR13's shared-infrastructure clause, and the WebKit job passed on this head, but the scope still misses code the run loads. animatedLayoutAdopters renders Collapsible, TreeList, ScrollableArea and useAnimatedLayout, and the gesture fixture bundles utils/primaryClick.ts and utils/isApplePlatform.ts; none matches the regex at ci.yml:1902, so a WebKit break there lands green and fails test on the next in-scope pull request. Add those paths to the scope with test cases (or leave the adopters spec to the Chromium job), then refresh the description's Scope list.

[Automated review]

Comment thread .github/workflows/ci.yml Outdated
id: scope
uses: ./.test-scope/.github/actions/test-scope
with:
paths: '^(packages/core/src/gestures/|packages/core/src/motion/|packages/core/src/internal/touch|packages/core/src/utils/(press|touch)|packages/core/src/hooks/(useMenuPress|menuPress|useLongPress|usePressFeedback)|internal/interaction-harness/|internal/a11y-spec/|playwright\.interaction\.config\.ts$|packages/themes/[^/]+/src/|apps/storybook/|\.github/workflows/ci\.yml$|package\.json$|pnpm-lock\.yaml$|\.github/actions/test-scope/)'

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

This regex misses code the WebKit run loads: animatedLayoutAdopters renders Collapsible, TreeList, ScrollableArea and hooks/useAnimatedLayout.ts (apps/storybook/stories/AnimatedLayout.stories.tsx:5-9), and the gesture fixture bundles utils/primaryClick.ts and utils/isApplePlatform.ts. A WebKit break through any of them skips this job and fails test on the next in-scope pull request. Add packages/core/src/(Collapsible|TreeList|ScrollableArea)/, packages/core/src/hooks/useAnimatedLayout and packages/core/src/utils/(primaryClick|isApplePlatform), or drop the adopters spec from the run.

];
for (const target of targets) {
expect(run).toContain(target);
// Each spec directory it runs is one its scope covers.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

This checks that each run directory is in scope, not that the code those specs load is; the adopters story and the gesture fixture both reach paths the regex skips. An in-scope case per reached path (for example packages/core/src/TreeList/TreeListItem.tsx) would pin it.

The gesture fixture bundles utils/primaryClick and utils/isApplePlatform, so
both join the scope. The motion adopters spec renders Storybook components
(Collapsible, TreeList, ScrollableArea), so it stays with the Chromium proofs.
A contract test builds each WebKit bundle and requires every source it reaches
to be in scope.

@astracat-bot astracat-bot 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.

Approving: the WebKit lane now matches what it runs. The scope covers every source the four specs load — an esbuild pass over fixture.ts, animatedLayoutBundle.ts and motionBundle.ts puts all 41 inputs in scope, and the run resolves to 177 tests in the four intended files — and test picks the job up through ci-test-join.mjs without a new required context, so spec:AST-030 FR7, FR11, FR13, FR16 and FR17 all hold.

One thing worth a follow-up, not a blocker: the reach test lists its bundle entries by hand (ci-interaction-webkit.test.mjs:143-147), while the run's gestures/ and internal/interaction-harness/ filters pick up any new spec or fixture. #8360 adds bareFixture.ts, which imports utils/selectionLock.ts — outside the scope regex — so the guard would stay green there; building every non-spec file under the run's directories would keep it true by construction.

[Automated review]

Comment on lines +143 to +147
it.each([
'packages/core/src/gestures/__tests__/browser/fixture.ts',
'packages/core/src/motion/__tests__/animatedLayoutBundle.ts',
'packages/core/src/motion/__tests__/motionBundle.ts',
])('keeps everything %s bundles in scope', async entry => {

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Non-blocking: this list is hand-kept, while the run's gestures/ and internal/interaction-harness/ filters pick up any new spec or fixture on their own. #8360 adds bareFixture.ts beside fixture.ts, and it imports utils/selectionLock.ts, which the scope regex does not cover — the guard would stay green there. Discovering the entries (every non-spec file under the run's test directories) would keep this true by construction.

@cixzhang
cixzhang merged commit 26143a4 into main Oct 31, 2026
51 checks passed
@github-actions
github-actions Bot deleted the ci/interaction-webkit-lane branch November 1, 2026 06:05

This branch was successfully deployed

1 active deployment
Preview — 83540eec Deployed Oct 31, 2026 by vercel[bot]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

CLA Signed This label is managed by the Meta Open Source bot.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant