Repository navigation
ci: add public TypeScript interface restrictiveness check - #9826
danieljbruce wants to merge 5 commits into
Conversation
There was a problem hiding this comment.
Code Review
This pull request introduces a new CI package, ci/breaking-change-check, to verify public interface restrictiveness and compilation. It updates the pnpm workspace and lockfile to include this package. Additionally, ci/run_conditional_tests.sh is updated to support a new --list-dirs option, integrate the ci directory into the conditional test execution flow (while exempting it from Windows, samples, and system tests), and refine change detection logic to ignore changes within ci/breaking-change-check and ci/run_conditional_tests.sh when determining if the entire test suite should run. There are no review comments, so I have no feedback to provide.
|
#9826 was previous written, but it is a bit too verbose. Let's minimize the changes to run_conditional_tests.sh. |
| commit_range="${GIT_DIFF_ARG%% -- *}" | ||
| set +e | ||
| git diff --quiet ${GIT_DIFF_ARG} ci | ||
| git diff --quiet ${commit_range} -- ci ':!ci/breaking-change-check' ':!ci/run_conditional_tests.sh' | ||
| changed=$? | ||
| set -e | ||
| if [[ "${changed}" -eq 0 ]]; then | ||
| echo "no change detected in ci" | ||
| else | ||
| echo "change detected in ci, we should test everything" | ||
| echo "result of git diff ${GIT_DIFF_ARG} ci:" | ||
| git diff ${GIT_DIFF_ARG} ci | ||
| echo "result of git diff ${commit_range} -- ci ':!ci/breaking-change-check' ':!ci/run_conditional_tests.sh':" | ||
| git diff ${commit_range} -- ci ':!ci/breaking-change-check' ':!ci/run_conditional_tests.sh' |
There was a problem hiding this comment.
[Generated] What these changes do and their impact on PR #9826:
1. Background: How ci/run_conditional_tests.sh handles changes in ci/
In normal PR presubmit runs (GIT_DIFF_ARG="HEAD^1"), ci/run_conditional_tests.sh checks each package directory d with git diff --quiet ${GIT_DIFF_ARG} ${d} so unit tests only run for packages modified by the PR. However, lines 105–117 check whether files under ci/ changed: if that git diff detects any change, the script logs "change detected in ci, we should test everything" and resets GIT_DIFF_ARG="", which causes the loop at lines 260–290 to schedule every package across the entire monorepo (~300+ packages across 5 shards × Node 22/24/26, Bun, and Windows).
2. Line-by-line explanation of the changes
commit_range="${GIT_DIFF_ARG%% -- *}"(line 105):- Extracts only the revision range before any
--pathspec separator inGIT_DIFF_ARG. - When
ci/run_conditional_tests.sh --strictis run with pathspec exclusions already inGIT_DIFF_ARG(such asGIT_DIFF_ARG="upstream/main...HEAD -- :!packages"), passing${GIT_DIFF_ARG}directly intogit diff --quiet ${GIT_DIFF_ARG} -- ci ...would pass two--separators togit diff(causinggit diffto treat the second--as a file path) or combine conflicting pathspecs. Stripping-- *preserves just the commit range (HEAD^1orupstream/main...HEAD).
- Extracts only the revision range before any
-- ci ':!ci/breaking-change-check' ':!ci/run_conditional_tests.sh'(lines 107, 114–115):- Adds Git negative pathspecs (
:!) to excludeci/breaking-change-checkandci/run_conditional_tests.shfrom theci/"test-everything" check. - Changes to shared test runner scripts in
ci/(such asci/run_single_test.shorci/export_test_telemetry.sh) still matchciand still trigger the full monorepo test suite (GIT_DIFF_ARG="").
- Adds Git negative pathspecs (
3. Impact on PR #9826
- Prevents a full-monorepo unit test explosion on this PR (and future PRs touching
ci/breaking-change-check): PR ci: add public TypeScript interface restrictiveness check #9826 adds the standaloneci/breaking-change-check/package (which is executed by its own.github/workflows/breaking-change-check.yamlworkflow and does not affect how other packages' unit tests run) and modifiesci/run_conditional_tests.sh. Without these exclusions, PR ci: add public TypeScript interface restrictiveness check #9826 itself would triggerGIT_DIFF_ARG=""inpresubmit,presubmit-bun, andpresubmit-windows, forcing CI to compile and run unit tests for every package in the monorepo across 5 shards instead of only testing the packages modified in the PR. - Relationship to stacked PR ci: run ci/ package unit tests in run_conditional_tests.sh #9827: In the initial commit of PR ci: add public TypeScript interface restrictiveness check #9826 (
f2c8a75143),ci/run_conditional_tests.shalso included broader changes (--list-dirsand addingcitosubdirsto run unit tests insideci/*packages). Commit2d67a7a63e([Address CI errors] ci: minimize run_conditional_tests.sh changes) moved those test-runner enhancements into stacked PR ci: run ci/ package unit tests in run_conditional_tests.sh #9827 (ci: run ci/ package unit tests in run_conditional_tests.sh), leaving only this minimal 7-line guard in PR ci: add public TypeScript interface restrictiveness check #9826.
There was a problem hiding this comment.
I don't like the fact that in this PR we have to change this file just because the new project lives in the CI folder. I think a better solution would just be to create an independent breaking-change folder.
There was a problem hiding this comment.
Moved breaking-change-check out of ci/ into core/test-utils/test/breaking-change-check.test.ts (commit b3194a5c03) and reverted all changes to ci/run_conditional_tests.sh, pnpm-workspace.yaml, and pnpm-lock.yaml so ci/run_conditional_tests.sh remains completely untouched.
…ls and revert run_conditional_tests.sh
| }, | ||
| "scripts": { | ||
| "test": "jest --coverage", | ||
| "check": "BREAKING_CHANGE_CHECK_MODE=diff jest --no-coverage test/breaking-change-check.test.ts -t \"git diff breaking-change gate\"", |
There was a problem hiding this comment.
Where is the --no-coverage flag coming from? (I thought it was a jest flag, but I didn't' see it in the jest documentation.
Also, if -t is the name of the test, we should ensure that it accurately captures what the test does. We need to make sure that anyone seeing failures for these tests understands the specific breaking changes we are looking for (e.g., TypeScript types, broken code, etc.).
There was a problem hiding this comment.
Good catches on both:
--no-coverage: Jest usesyargsunder the hood, which implicitly negates any boolean flag (--coverage) via--no-<flag>, even though the Jest CLI docs only document--coverage=false. Sincecore/test-utils/jest.config.jsdoesn't enable coverage by default anyway (only"test": "jest --coverage"does), I've removed--no-coveragein 87dd8f8.- Test naming and failure message: Agreed — I've updated
-tand thedescribe/itnames in 87dd8f8 to"public TypeScript interface breaking-change check"/"ensures exported TypeScript types, parameter types, return types, and public symbols do not break existing consumer code against the base branch", and included the full findings table and explanation (narrowed input/parameter types, widened return/output types, added required properties, or removed exports causing consumer TypeScript code to fail compilation) directly in the assertion failure message.

Description
Adds a TypeScript public interface restrictiveness check in
core/test-utils.Impact
Detects breaking changes when public TypeScript inputs narrow or outputs expand.
Testing
pnpm --dir core/test-utils testacross Node.js and Bun (4 passed, 4 totalsuites,35 passedtests,>28,000compiled consumer probes across public packages with<1%base invalid ratio).pnpm --dir core/test-utils run checkandnode ./bin/linter.mjs --strict.Note: this was opened in favour of #9825