Skip to content

Commit

Permalink
docs: add maintainer guide (take two) (#5874)
Browse files Browse the repository at this point in the history
* docs: add maintainer guide

* Went over docs again

* Also updated .github/replies.yml

* Added docs/MAITENANCE.md too

* Apply suggestions from code review

Co-authored-by: Joshua Chen <sidachen2003@gmail.com>

* Tweaked issues ordering and intro

* Split up releases and versions; reworked

* Apply suggestions from code review

Co-authored-by: Brad Zacher <brad.zacher@gmail.com>

* Update docs/maintenance/RELEASES.md

* Ran Prettier on RELEASES.md

* Update docs/development/architecture/PACKAGES.md

Co-authored-by: Brad Zacher <brad.zacher@gmail.com>
Co-authored-by: Joshua Chen <sidachen2003@gmail.com>
  • Loading branch information
3 people committed Nov 3, 2022
1 parent 2d9a33c commit 9c130cc
Show file tree
Hide file tree
Showing 7 changed files with 309 additions and 0 deletions.
1 change: 1 addition & 0 deletions .cspell.json
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,7 @@
"transpiled",
"transpiles",
"transpiling",
"triaging",
"tsconfigs",
"tsutils",
"tsvfs",
Expand Down
19 changes: 19 additions & 0 deletions .github/replies.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,25 @@ replies:
\
If you need it sooner, please try the `canary` tag on NPM.
name: Fix Has Been Merged
- body: |
Thanks for the report @<reporter>!\
This might be a valid issue, but we can't tell because you haven't filled in enough information.\
Please fill in the rest of the issue template so we can take a look.\
Thanks!
name: Needs More Info
- body: |
Thanks for the report @<reporter>!\
I can't reproduce the issue using the repository you provided.\
Could you please comment with instructions on how to reproduce the issue?\
Thanks!
name: Needs Full Reproduction
- body: |
Thanks for the report @<reporter>!\
I can't reproduce the issue using the code you provided.\
Could you please create an isolated reproduction in our playground (https://typescript-eslint.io/play) and comment back when you've got one?\
We prefer an isolated reproduction so that we as volunteer maintainers can quickly reproduce the issue and more easily find the cause.\
Thanks!
name: Needs Playground Reproduction
- body: |
With any issue opened in this project — it either has visible progress in the form of an attached PR, or it has no progress.\
\
Expand Down
12 changes: 12 additions & 0 deletions docs/MAINTENANCE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
---
id: maintenance
sidebar_label: Maintenance Guide
title: Maintenance Guide
---

This is the maintainers guide to working on typescript-eslint.
It's intended for use by contributors who have been given access to at least triage issues and pull requests.
We keep it in the open for visibility into our processes.

> If you're reading this as a new maintainer: welcome!
> We're happy to have you! ❤️‍🔥
103 changes: 103 additions & 0 deletions docs/maintenance/ISSUES.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
---
id: issues
sidebar_label: Issue Management
title: Issue Management
---

This document serves as a guide for how you might manage issues, also known as issue triaging.

Use your best judgement when triaging issues, and most of all remember to be **kind, friendly, and encouraging** when responding to users.
Many users are new to open source and/or typed linting.
It's imperative we give them a positive, uplifting experience.

:::tip
If you're ever unsure on any part of issue management, don't hesitate to loop in a maintainer that has more context to help!
:::

## Issue Flow

:::note
We include a set of common responses to issues in [`.github/replies.yml`](https://github.com/typescript-eslint/typescript-eslint/blob/main/.github/replies.yml), intended to be used with the [Refined Saved Replies](https://github.com/JoshuaKGoldberg/refined-saved-replies) extension.
Don't treat these as exact responses you must use: they're just a starting copy+paste helper.
Please do adopt your specific responses to your personal tone and to match the thread for non-straightforward issues.
:::

[Issues pending triage](https://github.com/typescript-eslint/typescript-eslint/issues?q=is%3Aopen+is%3Aissue+label%3Atriage) are searchable the `triage` label.
That label is added automatically when a new issue is created.
Most issues go through the following review flow when created or updated:

1. A maintainer ensures the issue is valid:
- If the poster didn't fill out an appropriate template with enough information:
- Add the `please fill out the template` and `awaiting response` labels
- Ask the poster for more information using a _Needs More Info_ response
- If it's a duplicate of an issue that already exists:
- Add the `duplicate` label and remove the `bug` label
- If it's an obvious duplicate, post a _Clearly Duplicate Issue_ response
- If it's not an obvious duplicate, link to the existing issue and explain why
- If the code is working as intended:
- Add the `working as intended` label and remove the `bug` and `triage` labels
- If the behavior is due to the user doing something wrong, such as an incorrect config:
- Add the `fix: user error` label
- [This issue search has some examples of closing comments](https://github.com/typescript-eslint/typescript-eslint/issues?q=is%3Aissue+sort%3Aupdated-desc+label%3A%22fix%3A+user+error%22+is%3Aclosed)
- If the behavior is otherwise expected, [this issue search has some examples of closing comments](https://github.com/typescript-eslint/typescript-eslint/issues?q=is%3Aissue+sort%3Aupdated-desc+label%3A%22working+as+intended%22+-label%3A%22fix%3A+user+error%22+is%3Aclosed+)
- You needn't go into too much detail in your comment - just enough to explain it
2. If the report is valid, add the `accepting prs` label and remove the `triage` label
3. If you know the rough steps for a fix, consider writing a comment with links to codebase to help someone put together a fix
4. If you think that the fix is relatively straightforward, consider also adding the `good first issue` label

Whenever an issue is waiting for the reporter to provide more information, it should be given the `awaiting response` label.
When more information is provided:

- If you have time to go through the triage flow again, do so
- If you don't have time, add the `triage` label and remove the `awaiting response` label

:::tip
If your link is both a "permalink" (includes a commit hash instead of a branch name) and has a line number/line range then GitHub will embed the code in your comment.
When viewing a file in GitHub pressing `y` will update the URL to a "permalink" with the current commit hash, then you can select the relevant lines and paste that URL into the comment.
:::

### Determining Whether Code is Working As Intended

As you become more familiar with the codebase and how everything works, this will be easier to do intuitively, but to begin with, this will likely involve investigating the documentation, code, and tests to determine if it's a bug or working as intended.
In general, if there is a passing test or documented example that is the same as or similar to the repro code — that indicates it's working as intended.
If you can't find anything that matches, use your best judgement based on the spirit of the code.

### Looking for Duplicates

It's worth noting that, occasionally, a user will intentionally raise a duplicate issue because they feel the original issue was closed when it shouldn't have been.
If this is the case, you should read the original issue to gather context, understand the reason for it being closed, and determine if the new issue raises any new or relevant point that requires addressing.

## Skipping Steps

As you become more familiar with the codebase and how it's supposed to behave you'll be able to skip steps or do things out of order as you see fit.
For example, you may be able to identify if a bug report is "working as intended", or you might recognize an issue as a duplicate without having a completely filled-out issue.
In such cases you can forgo the back-and-forth and just skip to the closing steps.

## Specific Issue Types

### 🐛 Bug Reports

#### 🐞 "Simple" Bugs

A simple bug is a bug that can be reproduced in a single TS file plus an ESLint config (and possibly a TSConfig) - i.e. an issue reproducible on https://typescript-eslint.io/play.
The vast majority of bug reports fall into this category.

If you cannot reproduce the issue as described using the issue's provided playground reproduction, it has not provided enough information.
Consider using a specific response like the _Needs Playground Reproduction_ response.

#### 🦟 "Complex" Bugs

A complex bug is a bug that requires multiple files to reproduce.
This is the rarer case, but does happen when people are using library types or if there are issues when types are imported.

These bugs should be reported with a link to a GitHub repository that can be checked out to reproduce the issue.
If you cannot reproduce the issue as described using repository's README.md and issue description, it has not provided enough information.
Consider using a specific response like the _Needs Full Reproduction_ response.

### ✨ Rule Enhancements

TODO: This will be filled out... soon!

### 🚀 New Rules

TODO: This will be filled out... soon!
88 changes: 88 additions & 0 deletions docs/maintenance/RELEASES.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
---
id: releases
sidebar_label: Releases
title: Releases
---

## Canary

We release a canary version for each commit to `main` that passes all required checks. This release is performed automatically by the [`publish_canary_version` step](https://github.com/typescript-eslint/typescript-eslint/blob/5feb2dba9da2bd5e233451b7b0f1c99414b5aef9/.github/workflows/ci.yml#L234-L263).

This release is goes to the `canary` tag on npm and it is versioned as an incremental canary patch release on top of the current `latest` version. I.e. if the current version is `5.6.1`, then the first canary version will be `5.6.2-alpha.0`, the second `5.6.2-alpha.1`, and so on.

## Latest

We release a latest version every Monday at 1pm US Eastern time using the latest commit to `main` at that time. This release is performed automatically by a Github action located in a private repository. This release goes to the standard `latest` tag on npm.

See the [versioning](#versioning) section below for how the version number is calculated.

If there have been no commits that impact public-facing packages then a patch-level release shall be released.

Latest releases shall only ever be "minor" or "patch" releases.

## Major Releases

We currently do not have a set schedule around when major releases shall be performed; instead they are done as the need arises.

We keep a backlog of breaking issues as a milestone on GitHub that is named in the form `${major}.0.0`.
When we do do a major release, we release a release candidate version to the `rc-v${major}` tag on npm for each commit to the major branch.

### Major Release Steps

Our releases go through three groups of steps:

1. [Pre-Release Preparation]
1. [Merging Breaking Changes]
1. [Releasing the Version]

#### 1. Pre-Release Preparation

1. Create a milestone by the name of the release [example: [Milestone 6.0.0](https://github.com/typescript-eslint/typescript-eslint/milestone/8)].
1. If an issue for changes to recommended rule configs doesn't yet exist, create one [example: [Changes to the `recommended` sets for 5.0.0](https://github.com/typescript-eslint/typescript-eslint/issues/5900)].
1. Add any breaking changes intended for the release to that milestone.
1. Create two new branches off `main` in the project repository (not a personal fork):
- `v${major}`
- `v${major}-canary-auto-release`
1. Raise a PR from `v${major}-canary-auto-release` to `main` modifying the [`ci.yml` workflow](https://github.com/typescript-eslint/typescript-eslint/blob/main/.github/workflows/ci.yml) [example: [chore: add auto-canary release for v6](https://github.com/typescript-eslint/typescript-eslint/pull/5883)]:
- Under `pushes:` at the beginning of the file, add an `- v${major}` list item.
- Add a `publish_canary_version_v${major}` step the same as `publish_canary_version` except:
- Add the condition: `if: github.ref == 'refs/heads/v${major}'`.
- Its publish command should be `npx lerna publish premajor --loglevel=verbose --canary --exact --force-publish --yes --dist-tag rc-v${major}`.
- Merge this into `main` once reviewed and rebase the `v${major}` branch.

#### 2. Merging Breaking Changes

1. Send a PR from `v${major}` to `main` [example: [v6.0.0](https://github.com/typescript-eslint/typescript-eslint/pull/5886)].
1. Change all [breaking change PRs](https://github.com/typescript-eslint/typescript-eslint/issues?q=is%3Aissue+is%3Aopen+label%3A%22breaking+change%22) to target the `v${major}` branch.
- To signify these changes as breaking, the first line of the PR description must read as `BREAKING CHANGE:`, and second line should briefly summarize the changes.
- It is important to note that when merged the commit message must also include `BREAKING CHANGE:` as the first line in order for lerna to recognize it as a breaking change in the release notes. If you miss this it just means more manual work when writing the release documentation.
1. Wait until all required PRs have been merged
1. Let the release wait for **at least 1 week** to allow time for early adopters to help test it and discuss the changes.
- Promote it on the [`@tseslint`](https://twitter.com/tseslint) twitter to get some additional attention.
1. Once discussions have settled, rebase merge the PR on top of `main`.

:::note
_Non_-breaking changes can be merged to `main` or the major branch.
They don't need any special treatment.
:::

#### 3. Releasing the Version

1. Discuss with the maintainers to be ready for an [out-of-band](#out-of-band) release. Doing this manually helps ensure someone is on-hand to action any issues that might arise from the major release.
1. Prepare the release notes. Lerna will automatically generate the release notes on GitHub, however this will be disorganized and unhelpful for users. We need to reorganize the release notes so that breaking changes are placed at the top to make them most visible. If any migrations are required, we must list the steps to make it easy for users.

- Example release notes: [`v5.0.0`](https://github.com/typescript-eslint/typescript-eslint/releases/tag/v5.0.0), [`v4.0.0`](https://github.com/typescript-eslint/typescript-eslint/releases/tag/v4.0.0), [`v3.0.0`](https://github.com/typescript-eslint/typescript-eslint/releases/tag/v3.0.0)

1. Finally, tweet the release on the `@tseslint` twitter with a link to the GitHub release. Make sure you include additional information about the highlights of the release!

## Out-of-Band

We will do releases "out-of-band" (outside the [latest](#latest) schedule) for rare emergencies.
We assess need on a case-by-case basis though generally an emergency is defined as a critical regression specifically introduced in the latest release.

These releases are done manually by a maintainer with the required access privileges.

## Back-Porting Releases

We **_do not_** back port releases to previously released major/minor versions.
We only ever release forward.
72 changes: 72 additions & 0 deletions docs/maintenance/VERSIONING.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
---
id: versioning
sidebar_label: Versioning
title: Versioning
---

We follow [semantic versioning (semver)](https://semver.org).
This page exists to help set guidelines around when what we consider to fall within each of the semver categories.

All of the packages in this project are published with the same version number to make it easier to coordinate both releases and installations.

When considering whether a change should be counted as "breaking" we first need to consider what package(s) it impacts. For example breaking changes for the parser packages have a different standard to those for the ESLint plugins. This is because not only do they have _very_ different API surfaces, they also are consumed in very different ways.

Please note that the lists provided below are non-exhaustive and are intended to serve as examples to help guide maintainers when planning and reviewing changes.

## Internal packages

Any packages in this project that are not part of our public API surface (such as `eslint-plugin-internal` or `website`) shall not be considered when calculating new package versions.

## `ast-spec` and `visitor-keys`

A change to the AST **_shall_** be considered breaking if it:

- Removes or renames an existing AST Node.
- Removes or renames an existing property on an AST Node.
- Changes a type in a non-refining way (i.e. `string` to `number`).

A change to the AST **_shall not_** be considered breaking if it:

- Adds a new property to the AST.
- Adds a new node type to the AST.
- Adds a new node type to an existing union type.
- Refines a type to be more specific (i.e. `string` to `'literal' | 'union'`).
- Removes a type from a union that was erroneously added and did not match the runtime AST.

## `eslint-plugin` and `eslint-plugin-tslint`

A change to the plugins **_shall_** be considered breaking if it will require the user to change their config. More specifically:

- Removes or renames an option.
- Changes the default option of a rule.
- Changes a rule's schema to be stricter.
- Consumes type information to a rule that did not previously consume it.
- Removes or renames a rule.
- Changes any of the recommended configurations.
- Changes the default behavior of a rule in such a way that causes new reports in a large set of cases in an average codebase.

A change to the plugins **_shall not_** be considered breaking if it:

- Adds an option that by default does not remove existing functionality.
- Adds a rule.
- Deprecates a rule.
- Adds additional checks to an existing rule that causes new reports in a small-to-medium set of cases in an average codebase.
- Refactors a rule's code in a way that does not introduce additional reports.
- Changes to a rule's description or other metadata.
- Adds a fixer or suggestion fixer.
- Removes a fixer or suggestion fixer.
- Fixes incorrect behavior in a rule that may or may not introduce additional reports.

### `parser`, `typescript-estree`, `scope-manager`, `types`, `type-utils`, `utils`

A change to these packages **_shall_** be considered breaking if it:

- Changes the API surface in a backwards-incompatible way (remove or rename functions, types, etc).

A change to these packages **_shall not_** be considered breaking if it:

- Adds to the API surface (add functions, types, etc).
- Deprecates parts of the API surface.
- Adds **_optional_** arguments to functions or properties to input types.
- Adds additional properties to output types.
- Adds documentation in the form of JSDoc comments.
14 changes: 14 additions & 0 deletions packages/website/sidebars/sidebar.base.js
Original file line number Diff line number Diff line change
Expand Up @@ -52,5 +52,19 @@ module.exports = {
'development/custom-rules',
],
},
{
collapsible: false,
items: [
'maintenance/issues',
'maintenance/releases',
'maintenance/versioning',
],
label: 'Maintenance',
link: {
id: 'maintenance',
type: 'doc',
},
type: 'category',
},
],
};

0 comments on commit 9c130cc

Please sign in to comment.