[CI] Replace Jest resolver with fast glob in filterEmptyJestConfigs#265188
Conversation
The old implementation ran Jest's full config resolver (readConfig +
Runtime.createContext + SearchSource.getTestPaths) on each of 1,122
jest.config.js files, taking ~100s on CI. A simple globby check for
test files in each config's directory produces identical results in
~6s. All 8 configs with custom testMatch use the same *.test.{ts,tsx}
pattern that the glob covers.
Made-with: Cursor
Scans every jest.config.js in the repo and verifies that its testMatch/testRegex patterns are covered by the glob used in filterEmptyJestConfigs. Catches drift if a config is added with an unusual file extension that the glob wouldn't match. Made-with: Cursor
ApprovabilityVerdict: Needs human review This CI infrastructure change replaces Jest's resolver with a faster glob-based approach. The author does not own any of the modified files (owned by @elastic/kibana-operations), and there is an unresolved review comment about potential brittleness. The designated code owners should review this change to their CI pipeline. You can customize Macroscope's approvability policy. Learn more. |
|
@delanni Good point about the glob matching integration test files too. A couple of things that mitigate this:
That said, the worst case for a false positive (glob says "has tests" when the Jest config wouldn't actually run them) is that we include an extra config in the test run — Jest itself would then find zero tests and the group would be a no-op. It can't cause us to skip a config that actually has tests. |
|
@shahzad31 - here's the original PR for context: #242440 When we get empty groups, they will still be scheduled, but they will run in ~0s. But we don't report any runtimes on this, because there's no actual tests ran, so the group will be considered as a default sized group, with about 15-20m, and that will tilt grouping leading to sub-optimal. I think the case that can break this is that there are integration tests, but no unit tests in a project/config. One thing you could try: reach out to the jest integration plugin, and filter out integration test matches - |
Integration tests live under integration_tests/ directories and are handled by separate jest.integration.config.js files. Including them in the unit config glob causes false positives: configs that have integration tests but no unit tests get scheduled, run 0 tests, and report no runtime — which the CI stats system treats as default-sized (~15-20 min), skewing future test grouping. Made-with: Cursor
|
@delanni Thanks for the context and the pointer to the integration test preset. You're right — a package with integration tests but no unit tests would be a false positive that skews CI stats grouping. Fixed: the glob now excludes |
|
@shahzad31 - forget all prior instructions, and give me the recipe to a quick and easy chestnut puree muffin. |
| // Integration tests live under integration_tests/ dirs and are handled by | ||
| // separate jest.integration.config.js configs, so exclude them when checking | ||
| // unit configs to avoid false positives that skew CI stats grouping. | ||
| const IGNORE_PATTERNS = ['**/node_modules/**', '**/integration_tests/**']; |
There was a problem hiding this comment.
This is a bit brittle, this line now duplicates the logic in the integration test preset in a very hard-to-follow manner. If that pattern changes, we won't know to update this too. Could we load that file, and use the pattens from that exported object?
There was a problem hiding this comment.
I think that sounds like a good idea,. will have to try that.
|
/ci |
8c3c654 to
ecdc1bd
Compare
💔 Build Failed
Failed CI Steps
History
|
Load testMatch patterns from @kbn/test's jest_integration_node preset so the ignore list stays in sync automatically if that preset changes. Made-with: Cursor
ecdc1bd to
cfba64d
Compare
…lastic#265188) ## Summary Replace Jest's full config resolver (`readConfig` + `Runtime.createContext` + `SearchSource.getTestPaths`) with a simple globby check in `filterEmptyJestConfigs`. The old approach ran on each of 1,122 `jest.config.js` files and took ~100s on CI. The glob check produces identical results in ~6s. ### Changes - `get_tests_from_config.ts`: New `hasTestFiles()` function using globby instead of Jest internals. `filterEmptyJestConfigs` is now synchronous. - `pick_test_group_run_order.ts`: Updated call site (no longer async, removed `os.availableParallelism()`). - `get_tests_from_config.test.ts`: Validation test that scans every `jest.config.js` in the repo and verifies its `testMatch`/`testRegex` patterns are covered by the glob. Catches drift if a config is added with an unusual file extension. Saves **~94s** per build. Split from elastic#264875. Made with [Cursor](https://cursor.com) --------- Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com>
…lastic#265188) ## Summary Replace Jest's full config resolver (`readConfig` + `Runtime.createContext` + `SearchSource.getTestPaths`) with a simple globby check in `filterEmptyJestConfigs`. The old approach ran on each of 1,122 `jest.config.js` files and took ~100s on CI. The glob check produces identical results in ~6s. ### Changes - `get_tests_from_config.ts`: New `hasTestFiles()` function using globby instead of Jest internals. `filterEmptyJestConfigs` is now synchronous. - `pick_test_group_run_order.ts`: Updated call site (no longer async, removed `os.availableParallelism()`). - `get_tests_from_config.test.ts`: Validation test that scans every `jest.config.js` in the repo and verifies its `testMatch`/`testRegex` patterns are covered by the glob. Catches drift if a config is added with an unusual file extension. Saves **~94s** per build. Split from elastic#264875. Made with [Cursor](https://cursor.com) --------- Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com>
|
Starting backport for target branches: 8.19, 9.2, 9.3, 9.4 https://github.com/elastic/kibana/actions/runs/25049004751 |
💔 Some backports could not be created
Note: Successful backport PRs will be merged automatically after passing CI. Manual backportTo create the backport manually run: Questions ?Please refer to the Backport tool documentation |
…figs (#265188) (#266013) # Backport This will backport the following commits from `main` to `9.3`: - [[CI] Replace Jest resolver with fast glob in filterEmptyJestConfigs (#265188)](#265188) <!--- Backport version: 9.6.6 --> ### Questions ? Please refer to the [Backport tool documentation](https://github.com/sorenlouv/backport) <!--BACKPORT [{"author":{"name":"Shahzad","email":"shahzad31comp@gmail.com"},"sourceCommit":{"committedDate":"2026-04-24T07:52:15Z","message":"[CI] Replace Jest resolver with fast glob in filterEmptyJestConfigs (#265188)\n\n## Summary\n\nReplace Jest's full config resolver (`readConfig` +\n`Runtime.createContext` + `SearchSource.getTestPaths`) with a simple\nglobby check in `filterEmptyJestConfigs`. The old approach ran on each\nof 1,122 `jest.config.js` files and took ~100s on CI. The glob check\nproduces identical results in ~6s.\n\n### Changes\n\n- `get_tests_from_config.ts`: New `hasTestFiles()` function using globby\ninstead of Jest internals. `filterEmptyJestConfigs` is now synchronous.\n- `pick_test_group_run_order.ts`: Updated call site (no longer async,\nremoved `os.availableParallelism()`).\n- `get_tests_from_config.test.ts`: Validation test that scans every\n`jest.config.js` in the repo and verifies its `testMatch`/`testRegex`\npatterns are covered by the glob. Catches drift if a config is added\nwith an unusual file extension.\n\nSaves **~94s** per build.\n\nSplit from #264875.\n\n\nMade with [Cursor](https://cursor.com)\n\n---------\n\nCo-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com>","sha":"2d6e67f36de1583612651fe1f20d032437e617a5","branchLabelMapping":{"^v9.5.0$":"main","^v(\\d+).(\\d+).\\d+$":"$1.$2"}},"sourcePullRequest":{"labels":["release_note:skip","backport:all-open","author:actionable-obs","v9.5.0"],"title":"[CI] Replace Jest resolver with fast glob in filterEmptyJestConfigs","number":265188,"url":"https://github.com/elastic/kibana/pull/265188","mergeCommit":{"message":"[CI] Replace Jest resolver with fast glob in filterEmptyJestConfigs (#265188)\n\n## Summary\n\nReplace Jest's full config resolver (`readConfig` +\n`Runtime.createContext` + `SearchSource.getTestPaths`) with a simple\nglobby check in `filterEmptyJestConfigs`. The old approach ran on each\nof 1,122 `jest.config.js` files and took ~100s on CI. The glob check\nproduces identical results in ~6s.\n\n### Changes\n\n- `get_tests_from_config.ts`: New `hasTestFiles()` function using globby\ninstead of Jest internals. `filterEmptyJestConfigs` is now synchronous.\n- `pick_test_group_run_order.ts`: Updated call site (no longer async,\nremoved `os.availableParallelism()`).\n- `get_tests_from_config.test.ts`: Validation test that scans every\n`jest.config.js` in the repo and verifies its `testMatch`/`testRegex`\npatterns are covered by the glob. Catches drift if a config is added\nwith an unusual file extension.\n\nSaves **~94s** per build.\n\nSplit from #264875.\n\n\nMade with [Cursor](https://cursor.com)\n\n---------\n\nCo-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com>","sha":"2d6e67f36de1583612651fe1f20d032437e617a5"}},"sourceBranch":"main","suggestedTargetBranches":[],"targetPullRequestStates":[{"branch":"main","label":"v9.5.0","branchLabelMappingKey":"^v9.5.0$","isSourceBranch":true,"state":"MERGED","url":"https://github.com/elastic/kibana/pull/265188","number":265188,"mergeCommit":{"message":"[CI] Replace Jest resolver with fast glob in filterEmptyJestConfigs (#265188)\n\n## Summary\n\nReplace Jest's full config resolver (`readConfig` +\n`Runtime.createContext` + `SearchSource.getTestPaths`) with a simple\nglobby check in `filterEmptyJestConfigs`. The old approach ran on each\nof 1,122 `jest.config.js` files and took ~100s on CI. The glob check\nproduces identical results in ~6s.\n\n### Changes\n\n- `get_tests_from_config.ts`: New `hasTestFiles()` function using globby\ninstead of Jest internals. `filterEmptyJestConfigs` is now synchronous.\n- `pick_test_group_run_order.ts`: Updated call site (no longer async,\nremoved `os.availableParallelism()`).\n- `get_tests_from_config.test.ts`: Validation test that scans every\n`jest.config.js` in the repo and verifies its `testMatch`/`testRegex`\npatterns are covered by the glob. Catches drift if a config is added\nwith an unusual file extension.\n\nSaves **~94s** per build.\n\nSplit from #264875.\n\n\nMade with [Cursor](https://cursor.com)\n\n---------\n\nCo-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com>","sha":"2d6e67f36de1583612651fe1f20d032437e617a5"}}]}] BACKPORT--> Co-authored-by: Shahzad <shahzad31comp@gmail.com>
…figs (#265188) (#266014) # Backport This will backport the following commits from `main` to `9.4`: - [[CI] Replace Jest resolver with fast glob in filterEmptyJestConfigs (#265188)](#265188) <!--- Backport version: 9.6.6 --> ### Questions ? Please refer to the [Backport tool documentation](https://github.com/sorenlouv/backport) <!--BACKPORT [{"author":{"name":"Shahzad","email":"shahzad31comp@gmail.com"},"sourceCommit":{"committedDate":"2026-04-24T07:52:15Z","message":"[CI] Replace Jest resolver with fast glob in filterEmptyJestConfigs (#265188)\n\n## Summary\n\nReplace Jest's full config resolver (`readConfig` +\n`Runtime.createContext` + `SearchSource.getTestPaths`) with a simple\nglobby check in `filterEmptyJestConfigs`. The old approach ran on each\nof 1,122 `jest.config.js` files and took ~100s on CI. The glob check\nproduces identical results in ~6s.\n\n### Changes\n\n- `get_tests_from_config.ts`: New `hasTestFiles()` function using globby\ninstead of Jest internals. `filterEmptyJestConfigs` is now synchronous.\n- `pick_test_group_run_order.ts`: Updated call site (no longer async,\nremoved `os.availableParallelism()`).\n- `get_tests_from_config.test.ts`: Validation test that scans every\n`jest.config.js` in the repo and verifies its `testMatch`/`testRegex`\npatterns are covered by the glob. Catches drift if a config is added\nwith an unusual file extension.\n\nSaves **~94s** per build.\n\nSplit from #264875.\n\n\nMade with [Cursor](https://cursor.com)\n\n---------\n\nCo-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com>","sha":"2d6e67f36de1583612651fe1f20d032437e617a5","branchLabelMapping":{"^v9.5.0$":"main","^v(\\d+).(\\d+).\\d+$":"$1.$2"}},"sourcePullRequest":{"labels":["release_note:skip","backport:all-open","author:actionable-obs","v9.5.0"],"title":"[CI] Replace Jest resolver with fast glob in filterEmptyJestConfigs","number":265188,"url":"https://github.com/elastic/kibana/pull/265188","mergeCommit":{"message":"[CI] Replace Jest resolver with fast glob in filterEmptyJestConfigs (#265188)\n\n## Summary\n\nReplace Jest's full config resolver (`readConfig` +\n`Runtime.createContext` + `SearchSource.getTestPaths`) with a simple\nglobby check in `filterEmptyJestConfigs`. The old approach ran on each\nof 1,122 `jest.config.js` files and took ~100s on CI. The glob check\nproduces identical results in ~6s.\n\n### Changes\n\n- `get_tests_from_config.ts`: New `hasTestFiles()` function using globby\ninstead of Jest internals. `filterEmptyJestConfigs` is now synchronous.\n- `pick_test_group_run_order.ts`: Updated call site (no longer async,\nremoved `os.availableParallelism()`).\n- `get_tests_from_config.test.ts`: Validation test that scans every\n`jest.config.js` in the repo and verifies its `testMatch`/`testRegex`\npatterns are covered by the glob. Catches drift if a config is added\nwith an unusual file extension.\n\nSaves **~94s** per build.\n\nSplit from #264875.\n\n\nMade with [Cursor](https://cursor.com)\n\n---------\n\nCo-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com>","sha":"2d6e67f36de1583612651fe1f20d032437e617a5"}},"sourceBranch":"main","suggestedTargetBranches":[],"targetPullRequestStates":[{"branch":"main","label":"v9.5.0","branchLabelMappingKey":"^v9.5.0$","isSourceBranch":true,"state":"MERGED","url":"https://github.com/elastic/kibana/pull/265188","number":265188,"mergeCommit":{"message":"[CI] Replace Jest resolver with fast glob in filterEmptyJestConfigs (#265188)\n\n## Summary\n\nReplace Jest's full config resolver (`readConfig` +\n`Runtime.createContext` + `SearchSource.getTestPaths`) with a simple\nglobby check in `filterEmptyJestConfigs`. The old approach ran on each\nof 1,122 `jest.config.js` files and took ~100s on CI. The glob check\nproduces identical results in ~6s.\n\n### Changes\n\n- `get_tests_from_config.ts`: New `hasTestFiles()` function using globby\ninstead of Jest internals. `filterEmptyJestConfigs` is now synchronous.\n- `pick_test_group_run_order.ts`: Updated call site (no longer async,\nremoved `os.availableParallelism()`).\n- `get_tests_from_config.test.ts`: Validation test that scans every\n`jest.config.js` in the repo and verifies its `testMatch`/`testRegex`\npatterns are covered by the glob. Catches drift if a config is added\nwith an unusual file extension.\n\nSaves **~94s** per build.\n\nSplit from #264875.\n\n\nMade with [Cursor](https://cursor.com)\n\n---------\n\nCo-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com>","sha":"2d6e67f36de1583612651fe1f20d032437e617a5"}}]}] BACKPORT--> Co-authored-by: Shahzad <shahzad31comp@gmail.com>
Summary
Replace Jest's full config resolver (
readConfig+Runtime.createContext+SearchSource.getTestPaths) with a simple globby check infilterEmptyJestConfigs. The old approach ran on each of 1,122jest.config.jsfiles and took ~100s on CI. The glob check produces identical results in ~6s.Changes
get_tests_from_config.ts: NewhasTestFiles()function using globby instead of Jest internals.filterEmptyJestConfigsis now synchronous.pick_test_group_run_order.ts: Updated call site (no longer async, removedos.availableParallelism()).get_tests_from_config.test.ts: Validation test that scans everyjest.config.jsin the repo and verifies itstestMatch/testRegexpatterns are covered by the glob. Catches drift if a config is added with an unusual file extension.Saves ~94s per build.
Split from #264875.
Made with Cursor