Skip to main content

Dependency Version Upgrades

Renovate

We rely on renovate bot to automatically raise PRs to update our dependencies using this configuration.

Dependency Dashboard

Renovate is configured to manage a dependency dashboard issue which can be used to understand the tool's state:

  • What dependency bumps require approval for renovate to action (eg because they are major bumps)
  • What dependency bumps it is working on (i.e. pending)
  • What dependency bumps are currently open and awaiting review + merge
    • Note that renovate is an asynchronous tools so this list will lag behind a bit after you merge PRs
  • What dependency bumps have been ignored

Ticking a checkbox in this issue will cause renovate to action the dependency:

  • If you tick one in the "Pending Approval" list it will approve it and renovate will raise a PR.
  • If you tick one in the "Pending Status Checks" list it will cause renovate to create the PR before its internal status checks are complete.
  • If you tick one in the "Open" list it will cause renovate to rebase the PR (if there are no manual changes) or recreate the PR (if there are manual changes).
  • If you tick one in the "Ignored or Blocked" list it will cause renovate to recreate the PR.

Merging Renovate PRs

Renovate will not automatically merge its dependency PRs because we have branch protection turned on. Renovate PRs must go through the same workflow as human PRs: i.e. all PRs must be approved with passing status checks before they can be merged.

Renovate will automatically update a PR if there is a conflict with main. You can also force it to rebase a PR by ticking the box in the PR's description, or ticking the relevant box on the dependency dashboard.

You should generally avoid clicking the "Update branch" button in the Github UI as this will create a human commit - which cause renovate to treat the branch as "dirty" and it will no longer automatically. Only click it if you are planning on merging the PR manually ASAP.

Manual Dependency Updates

Occasionally it will be desirable to manually bump the dependencies in one commit rather than relying on renovate's many PRs. Doing so is just a matter of:

  1. git checkout main && git pull
  2. yarn install
  3. yarn update-interactive - this will start yarn's prompt to update the deps.
    1. Ignore the lines with * deps as these are intentionally set as such.
    2. Avoid changing the dep ranges like the complex range we have for TypeScript (eg >=4.7.4 <5.5.0).
    3. Once you're ready, hit enter and yarn will make the changes and rerun the install.
  4. Run all of the relevant checks locally so you can action any failures before raising a PR:
    1. yarn build
    2. yarn typecheck
    3. yarn lint
    4. yarn test
    5. yarn integration-test
  5. Create a new branch (a name like update-deps-20231201 is good just to keep it unique), create, and land a PR.

Babel

Our published packages only depend on @babel/* packages as devDependencies. You can generally upgrade those dependencies with:

  1. yarn add -D @babel/code-frame @babel/core @babel/eslint-parser @babel/parser @babel/types
  2. npx nx run ast-spec:test -u

The fixtures under packages/ast-spec/ describe how the files are parsed under both Babel and our (TSESTree) parser.

ESLint

The typescript-eslint repository contains four kinds of version ranges for the eslint package:

  • Integration tests: Pinned to our lowest supported ESLint version
  • Packages with a * peerDependency version: These fall back to the explicit peerDependency versions
  • Packages with explicit peerDependency versions: The full range of supported ESLint major versions
  • Root package.json's' devDependency: A relatively recent release, used only for repository development
tip

Whenever you discover any new areas of work that are blocked by dropping an old ESLint version, such as new ESLint API deprecations, add a TODO comment that will be caught by the regular expressions under Removing Support for an Old ESLint Version.

Adding Support for a New ESLint Version

  1. Upgrade the root package.json devDependency to the latest ESLint
  2. Add the new major version to the explicit peerDependency versions
  3. Check eslint-visitor-keys for a new version to be upgraded to as well.
  4. Update Users > Dependency Versions > ESLint

Removing Support for an Old ESLint Version

  1. Increase the integration tests to the next lowest supported major version (*.0.0)
  2. Remove the old major versions from packages with explicit peerDependency versions
  3. Search for source code comments (excluding CHANGELOG.md files) that mention a now-unsupported version of ESLint.
    • For example, to remove support for v5, searches might include:
      • /eslint.*5/i
      • /todo.*eslint.*5/i
      • /todo.*eslint/i
  4. Update Users > Dependency Versions > ESLint

See chore: drop support for ESLint v6 for reference.

Node

The typescript-eslint repository contains three kinds of version ranges for Node:

  • .github/workflows/ci.yml's PRIMARY_NODE_VERSION: Set to the highest Node version we support
  • node-version: Set to a tuple of our [lowest, highest] supported versions for our unit tests in CI
  • engines field in all package.jsons: explicitly lists all supported Node ranges

Change those numbers accordingly when adding support for a new Node version or removing support for an old Node version.

See feat: drop support for node v12 + chore: test node v14 on ci.yml for reference.

TypeScript

Adding Support for a New TypeScript Version

We generally start the process of supporting a new TypeScript version just after the first beta release for that version is made available.

  1. Create and pin an issue with a title like TypeScript X.Y Support, accepting prs, AST, dependencies, and New TypeScript Version labels, and the following contents:

    1. A link to the TypeScript X.Y Iteration Plan issue from the Microsoft issue tracker

    2. The following text:

      This issue is just to track all of the new features and their implementation state in this project.
      As with all releases, we will not necessarily support all features until closer to the full release when everything the features are stabilised.

      _Please be patient._ ❤️
    3. A heading starting with 🔲 for each new TypeScript feature called out in the iteration plan that will impact us

    4. A heading titled 🔲 lib.d.ts Updates and the content We will need to regenerate our types within scope-manager

    5. A heading titled Other changes with no impact to us containing a list of other changes that we don't believe will impact us

  2. At this stage, it's fine to send and/or review PRs that implement necessary features, but wait to merge them until the new TypeScript version's RC is released

    • Whenever a PR is created, add (#1234) to its respective heading, and change the heading's emoji from 🔲 to 🏗
    • Search for expectBabelToNotSupport to see how to support syntaxes not yet supported by Babel
  3. Once the TypeScript RC version is released, start merging PRs

    • Whenever a PR is merged, change the respective heading's emoji from 🏗 to ✅
  4. Create a PR with a title like feat: update TypeScript to X.Y-rc and the following changes:

    • In the root package.json, add || X.Y.1-rc2 to the devDependency on typescript
    • Change the SUPPORTED_TYPESCRIPT_VERSIONS constant's < version to the next version of TypeScript
    • Change the SUPPORTED_PRERELEASE_RANGES constant to equal ['X.Y.1-rc']
    • Rename and update patches/typescript* to the new TypeScript version
    • Run yarn generate-lib to update scope-manager
  5. Once all PRs needed for the RC update PR are merged, merge the RC update PR

  6. Once TypeScript releases the stable X.Y version, create and merge a PR with a title like chore: bump TypeScript from X.YRC to X.Y and the following changes:

    • In the root package.json, remove || X.Y.1-rc2 from the dependency on typescript, and bump its < version to the next version of TypeScript
    • In the root package.json, change the resolutions on typescript to X.Y.3
    • Rename and update patches/typescript* to the new TypeScript version
    • Any other changes made necessary due to changes in TypeScript between the RC version and stable version
  7. Send a PR that updates this documentation page to point to your newer issues and PRs

    • Also update any of these steps if you go with a different process

See for reference (caveat: these don't follow the exact process described here):

Removing Support for an Old TypeScript Version

A single PR can remove support for old TypeScript versions as a breaking change:

  1. Update the root package.json devDependency
  2. Update the SUPPORTED_TYPESCRIPT_VERSIONS constant in warnAboutTSVersion.ts
  3. Update the versions constant in version-check.ts
  4. Update Users > Dependency Versions > TypeScript
  5. Update MIN_TS_VERSION_SEMVER in packages/website/src/components/OptionsSelector.tsx
  6. Search for source code comments (excluding CHANGELOG.md files) that mention a now-unsupported version of TypeScript.
    • For example, to remove support for v4.3, searches might include:
      • 4.3
      • /is.*4.*3/i
      • /semver.*4.*3/i
      • /semver.satisfies/
      • /todo.*ts/i
      • /todo.*typescript/i

See feat: bump minimum supported TS version to 4.2.4.