Skip to content

chore(lint): lint per package to avoid the typescript-eslint project-service ceiling - #3317

Open
kriskowal wants to merge 1 commit into
masterfrom
chore/lint-eslint-per-package-batches
Open

chore(lint): lint per package to avoid the typescript-eslint project-service ceiling#3317
kriskowal wants to merge 1 commit into
masterfrom
chore/lint-eslint-per-package-batches

Conversation

@kriskowal

@kriskowal kriskowal commented Jul 2, 2026

Copy link
Copy Markdown
Member

Problem

On large PRs, the root yarn lint:eslint (eslint .) fails with parsing errors on the alphabetically-last packages packages/where/** and packages/zip/**:

0:0  error  Parsing error: ESLint was configured to run on
`<tsconfigRootDir>/packages/where/test/where-endo-cache.test.js`
using `parserOptions.project`:
However, none of those TSConfigs include this file.

Each package's tsconfig.json plainly includes those files (where/zip lint clean when linted on their own), and the base branch lints green, so this is not a config-glob gap or a per-PR code defect. It is a typescript-eslint project-service scaling ceiling: a single eslint . builds one project service that must hold every package's TypeScript program at once, and past a size this monorepo crosses on large PRs the service drops its tail. Two independent large PRs hit the identical where/zip tail-drop with entirely different diffs and neither touches those packages, i.e. size-driven, not diff-driven.

Fix

yarn lint:eslint now delegates to scripts/eslint-repo.mjs, which lints packages/* in bounded buckets of ESLINT_BUCKET_SIZE packages per process (default 10) plus one batch per top-level non-package directory. Each bucket's project service holds only a handful of package programs, far under the whole-repo count that dropped its tail, so the ceiling can never be reached regardless of repository size, while a handful of processes (rather than one per package) amortize ESLint startup. Each bucket is a fresh eslint child process, which the isolation depends on: typescript-eslint's TypeScript program cache is module-global, so linting the buckets in one process would re-accumulate every package's program and re-cross the ceiling.

Coverage matches eslint .: the union of the buckets' directory arguments is exactly packages/* plus every top-level non-package directory, the same paths eslint . walks. Extra args are forwarded, so scripts/eslint-repo.mjs --fix fixes the whole repo. ESLINT_BUCKET_SIZE (default 10) tunes packages-per-process.

Verification

Ran node scripts/eslint-repo.mjs on this branch (against current master): completes green, 0 errors (only the pre-existing compartment-mapper/src/types/policy-schema.ts jsdoc/check-tag-names warning), covering packages/* including where/zip.

@changeset-bot

changeset-bot Bot commented Jul 2, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: a0dee9b

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 0 packages

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@kriskowal
kriskowal requested a review from boneskull July 2, 2026 15:02
…ript-eslint project-service ceiling

`yarn lint:eslint` no longer runs a single `eslint .` over the whole repo. A
single run builds one typescript-eslint project service that must hold every
package's TypeScript program at once; past a scale this monorepo crosses on
large PRs, that service drops its alphabetically-last packages
(`packages/where`, `packages/zip`), reporting every file as "none of those
TSConfigs include this file" even though each package lints clean on its own.

`yarn lint:eslint` now delegates to `scripts/eslint-repo.mjs`, which lints
packages in bounded buckets (`ESLINT_BUCKET_SIZE`, default 10) in a fresh
child process each, plus one batch for the repository-root files. Each
project service then holds only a bucket's worth of programs, far under the
whole-repo count that dropped its tail, while a handful of processes amortize
ESLint startup. Coverage and rules are unchanged; only the grouping into
processes differs.

Ferried from endojs/endo-but-for-bots#594.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant