Skip to content

ci(pr-a11y): skip contract specs an older PR head does not have - #8240

Merged
cixzhang merged 3 commits into
meta:mainfrom
vjeux:ci/pr-a11y-absent-specs
Oct 24, 2026
Merged

cixzhang merged 3 commits into
meta:mainfrom
vjeux:ci/pr-a11y-absent-specs

Conversation

@vjeux

@vjeux vjeux commented Oct 24, 2026 •

Copy link
Copy Markdown
Contributor

Maintainer impact

When a pull request that adds a pr-a11y contract step merges, pr-a11y breaks on every open pull request that branched before it. #8130 added "Run picker wheel pinch-zoom contract", and #8231's next run failed that step with Error: No tests found. Each open pull request hits it on its next push until it rebases, and again on the next such merge.

Intended invariant

A pr-a11y contract runs whenever its spec file exists in the checked-out PR head. Main's steps name only existing spec files. pr-a11y keeps checking out the exact PR head.

Change

Why: a pull request's run takes its workflow from the test merge with main, so it has main's newest steps, but pr-a11y checks out pull_request.head.sha (pinned by the provenance test). A contract step runs pnpm exec playwright test <spec> …, and a spec added on main after the branch point is not in that checkout. pr-scope-touches.sh is loaded from the base for the same reason.

  • .github/scripts/skip-absent-specs.sh defines a bash pnpm function. For pnpm exec playwright test, it drops spec files absent from the checkout and emits a ::notice naming each one ("…is not in this pull request's head; rebase onto main to run it"). A step left with no spec passes without running Playwright. Every other pnpm command runs unchanged, and Playwright's exit status still decides the step.
  • A new pr-a11y step, "Skip contract specs the PR head predates", loads the script from github.sha, the test merge commit the steps themselves come from (an older head lacks it, and pull_request.base.sha can lag main), and exports it as BASH_ENV, so every later bash step gets the wrapper.
    • The ~58 contract steps are unchanged, leaving open ci.yml edits nothing to conflict with.
    • If the merge commit cannot be read, the step warns and the contract steps run as before.
  • Pull requests only; a release check's exact head has every spec.

Not covered: a stale head that skips a new contract can merge without running it, as before the contract existed. A contract that main renames or moves after the branch point is skipped the same way.

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 exec vitest run --project node .github/scripts: 69 files, 1220 tests passed. New or changed:
    • skip-absent-specs.test.mjs (new) runs step scripts with bash -e and the wrapper in BASH_ENV, against a stand-in pnpm. It covers five cases:
      • every spec present: the command is unchanged;
      • one spec absent: it is dropped with a notice;
      • every spec absent: the step passes without Playwright;
      • Playwright fails: the step still fails;
      • other pnpm commands: untouched.
    • ci-test-routing.test.mjs:
      • every spec a pr-a11y step names exists, so main cannot point at a missing file, and a pull request that deletes a spec its steps still name fails here;
      • the wrapper step comes before every Playwright step, loads from github.sha (not the PR base) and sets BASH_ENV;
      • Playwright steps use bash and do not bypass the function.
    • release-check-workflow.test.mjs: the wrapper step runs on pull requests, not on release checks.
  • Failure injection: a typo'd spec path, the wrapper step moved after the contract steps, and a wrapper that keeps absent files each fail the matching test.
  • prettier, shellcheck, bash -n, check-executable-bits.

Maintainer note: two commits on top (c3a9cb4, cff15ae) fix the review's findings: the heading-links upload no longer expects evidence from a skipped spec, and the wrapper loads from the merge commit.

A pull request's run takes its workflow from the test merge with main,
but pr-a11y checks out the exact PR head. When a pull request that adds
a contract step merges, every open pull request that branched before it
fails that step with "No tests found" until it rebases.

pr-a11y now loads .github/scripts/skip-absent-specs.sh from the base and
exports it as BASH_ENV. Its pnpm function drops spec files absent from
the checkout from `pnpm exec playwright test`, with a notice naming
each, and passes a step left with none. Other pnpm commands and
Playwright's exit status are untouched, and none of the contract steps
change. A routing test keeps every spec a pr-a11y step names present on
main, so only an older head skips anything.
@vercel

vercel Bot commented Oct 24, 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 24, 2026 4:02pm UTC

Request Review

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

astracat-bot Bot commented Oct 24, 2026 •

Copy link
Copy Markdown

AI review status for this pull request.

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

@github-actions

github-actions Bot commented Oct 24, 2026 •

Copy link
Copy Markdown
Contributor

PR Analysis Report

📚 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: No accessibility violations detected.

Visual Regression

46 of 498 shot(s) changed.

A change here is a question, not a failure: check whether the after is the
picture you intended. Record that review on the PR. Baseline maintenance is an
explicit dispatch of CI; this report never rewrites the baseline or adds a release gate.

component story theme mode pixels
Selector Indicator Space Bottom Sheet Narrow End RTL neutral light 753,933
Selector Indicator Space Bottom Sheet Wide Start neutral light 740,072
Chat Full AI Chat probe light 230,823
Chat Full AI Chat probe dark 229,805
RichTextEditor Markdown parity: side by side probe dark 94,866
RichTextEditor Markdown parity: side by side probe light 89,762
Collapsible Dividers probe dark 66,445
Collapsible Dividers probe light 66,445
Chat Default neutral dark 36,304
Chat Default neutral light 35,767
Chat Empty State probe light 23,531
Chat Empty State probe dark 22,622
ChatAutoScroll Scroll Behavior Comparison neutral dark 15,378
ChatAutoScroll Scroll Behavior Comparison neutral light 14,107
Chat With Attachments probe light 13,406
Chat With Attachments probe dark 11,232
ProgressBar With Target Mark probe dark 7,895
ProgressBar With Target Mark probe light 7,895
Markdown Default neutral dark 7,573
Markdown Default neutral light 7,566

and 26 more.


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.

Recommended for approval: loading the wrapper from the base and filtering only the spec arguments of pnpm exec playwright test fixes the No tests found failure on older heads, the new tests keep main from naming a missing spec, and release checks still run every contract. Two optional follow-ups: the heading-links step writes should_run=true before its Playwright call, so an older head with Markdown in scope still fails at that step's if-no-files-found: error upload. The notice in skip-absent-specs.sh also says a missing spec "was added to main" even when the pull request deleted it, so wording it as "not in this pull request's head" would stay accurate.

[Automated review]

Comment thread .github/scripts/skip-absent-specs.sh Outdated
-*) ;;
*.spec.ts | *.spec.tsx | *.spec.js | *.spec.mjs)
if [ ! -e "$arg" ]; then
echo "::notice title=Spec not in this PR head::${arg} was added to main after this pull request branched; rebase to run it."

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 text is printed for every absent spec, including one this pull request deleted while its step still names it. The test join catches that case through "names only spec files that exist", but this notice would point the author at main. Reporting what was observed stays accurate either way, for example: ${arg} is not in this pull request's head; if it was added to main after this branch, rebase to run it.

…the head

An older head with Markdown in scope set should_run=true, the wrapper then
skipped the absent spec, and the upload's if-no-files-found: error failed the
step. The notice now says the spec is not in this pull request's head, which
also holds when the pull request deleted it.

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

Recommended for approval: loading the wrapper from the base and filtering only the spec arguments of pnpm exec playwright test fixes the No tests found failure on older heads, the heading-links step now promises its upload only when its spec is in the head, and release checks still run every contract. One optional follow-up: the wrapper is read from pull_request.base.sha, which can lag main (on this pull request's own run it was five commits behind the workflow being executed), so a pull request opened before this lands may still fail unwrapped; reading it from github.sha or the base branch's current tip would reach those too. This branch's own pr-a11y failure at the Lab reorder-grip pinch-zoom contract is the failure being fixed and clears with a rebase onto main.

[Automated review]

Comment thread .github/workflows/ci.yml Outdated
- name: Skip contract specs the PR head predates
if: github.event_name == 'pull_request'
env:
BASE_SHA: ${{ github.event.pull_request.base.sha }}

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 reads the wrapper from pull_request.base.sha, but the steps it serves come from the test merge with the current main. On this pull request's own run the two differed: BASE_SHA was the main commit the pull request was opened on, five commits behind the ci.yml the job executed, and the API still reports that base after the later push. So after this lands, an older pull request whose recorded base predates it can still get the warning below and fail with No tests found until it rebases. Reading the wrapper from github.sha (the test merge) or from the base branch's current tip would reach those pull requests too; the BASE_SHA assertion in ci-test-routing.test.mjs would move with it.

…the PR's base

pull_request.base.sha can lag main, so a pull request opened before this
lands would read a base without the wrapper and fail unwrapped. github.sha is
the merge commit the steps themselves come from, so it always has the wrapper
those steps rely on.

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

Recommended for approval: the wrapper is now read from the test merge commit, so it reaches open pull requests whose head and recorded base both predate it, and this pull request's own pr-a11y run skipped the reorder-grip spec its head lacks with a notice and passed. One optional follow-up: the description still says the step loads the wrapper from BASE_SHA and quotes the old notice wording, and its "Not covered" note could add that a contract main renames or moves after a branch point is skipped the same way as a new one.

[Automated review]

@cixzhang
cixzhang merged commit a061fcb into meta:main Oct 24, 2026
59 checks passed
@vjeux
vjeux deleted the ci/pr-a11y-absent-specs branch October 24, 2026 19:38

This branch was successfully deployed

1 active deployment
Preview — cff15aef Deployed Oct 24, 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.

2 participants