mirror of
https://github.com/gravitational/teleport.git
synced 2026-10-11 22:49:54 +00:00
Add allowunused tag for bypassing knip (#483)
Export-Source-Commit: 8bb674e4622791c809493020a4fb86cb0e451e08
This commit is contained in:
@@ -2,6 +2,7 @@
|
||||
"$schema": "./node_modules/oxlint/configuration_schema.json",
|
||||
"plugins": ["typescript", "react", "jest", "import"],
|
||||
"jsPlugins": [
|
||||
"./web/scripts/oxlint/allowunused-todo.mjs",
|
||||
"eslint-plugin-unused-imports",
|
||||
"eslint-plugin-storybook",
|
||||
"eslint-plugin-testing-library",
|
||||
@@ -29,6 +30,7 @@
|
||||
"jest": "readonly"
|
||||
},
|
||||
"rules": {
|
||||
"teleport/allowunused-todo": "error",
|
||||
"constructor-super": "error",
|
||||
"for-direction": "error",
|
||||
"no-async-promise-executor": "error",
|
||||
|
||||
@@ -176,6 +176,10 @@
|
||||
"project": ["{tests,helpers,config}/**/*.{ts,tsx,js,mjs}"]
|
||||
}
|
||||
},
|
||||
// Exports tagged @allowunused are excluded from the unused-exports report. The tag must name
|
||||
// an owner responsible for removing it: /** @allowunused TODO(github-username): reason */
|
||||
// (the format is enforced by the teleport/allowunused-todo oxlint rule).
|
||||
"tags": ["-allowunused"],
|
||||
"ignoreBinaries": [
|
||||
// Run by .github/workflows/doc-tests.yaml against the separately checked out docs site.
|
||||
"spellcheck",
|
||||
|
||||
@@ -195,6 +195,20 @@ pnpm format # format all files
|
||||
pnpm format-check # check without writing
|
||||
```
|
||||
|
||||
### Unused Exports
|
||||
|
||||
[Knip](https://knip.dev/) runs in CI as part of `pnpm lint` and fails on exports that nothing
|
||||
imports. If an unused export has to stay (for example, an upcoming PR depends on it), tag it:
|
||||
|
||||
```ts
|
||||
/** @allowunused TODO(your-github-username): remove once X lands. */
|
||||
export function futureThing() {}
|
||||
```
|
||||
|
||||
The owner is required so suppressions don't accumulate with nobody responsible for removing them.
|
||||
A lint rule (`teleport/allowunused-todo`) enforces the format. Knip only reads JSDoc, so the tag
|
||||
must be in a `/** */` comment attached to the export.
|
||||
|
||||
### MFA Development
|
||||
|
||||
#### Local cluster with nip.io
|
||||
|
||||
@@ -0,0 +1,72 @@
|
||||
/**
|
||||
* Teleport
|
||||
* Copyright (C) 2026 Gravitational, Inc.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
// This plugin ensures that @allowunused tags are JSDoc comments with a TODO(owner): reason format,
|
||||
// so knip can read them and they don't accumulate without an owner to remove them.
|
||||
|
||||
const GITHUB_USERNAME = '[A-Za-z\\d](?:[A-Za-z\\d]|-(?=[A-Za-z\\d])){0,38}';
|
||||
const VALID_ALLOWUNUSED = new RegExp(
|
||||
`^@allowunused[^\\S\\r\\n]+TODO\\(${GITHUB_USERNAME}\\):[^\\S\\r\\n]*\\S`
|
||||
);
|
||||
|
||||
const allowunusedTodo = {
|
||||
meta: {
|
||||
docs: {
|
||||
description:
|
||||
'Require @allowunused knip suppressions to be JSDoc comments with an owner: /** @allowunused TODO(github-username): reason */',
|
||||
},
|
||||
messages: {
|
||||
notJsdoc:
|
||||
'knip only reads @allowunused from a /** JSDoc */ comment attached to the export, it has no effect here.',
|
||||
badFormat:
|
||||
'@allowunused must name an owner responsible for removing it: /** @allowunused TODO(github-username): reason */',
|
||||
},
|
||||
},
|
||||
create(context) {
|
||||
return {
|
||||
Program() {
|
||||
for (const comment of context.sourceCode.getAllComments()) {
|
||||
const isJsdoc =
|
||||
comment.type === 'Block' && comment.value.startsWith('*');
|
||||
|
||||
if (!isJsdoc) {
|
||||
if (/^\s*@allowunused/i.test(comment.value)) {
|
||||
context.report({ loc: comment.loc, messageId: 'notJsdoc' });
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if (
|
||||
comment.value
|
||||
.matchAll(/@allowunused/gi)
|
||||
.some(
|
||||
match =>
|
||||
!VALID_ALLOWUNUSED.test(comment.value.slice(match.index))
|
||||
)
|
||||
) {
|
||||
context.report({ loc: comment.loc, messageId: 'badFormat' });
|
||||
}
|
||||
}
|
||||
},
|
||||
};
|
||||
},
|
||||
};
|
||||
|
||||
export default {
|
||||
meta: { name: 'teleport' },
|
||||
rules: { 'allowunused-todo': allowunusedTodo },
|
||||
};
|
||||
Reference in New Issue
Block a user