Add allowunused tag for bypassing knip (#483)

Export-Source-Commit: 8bb674e4622791c809493020a4fb86cb0e451e08
This commit is contained in:
Ryan Clark
2026-08-25 11:35:10 -05:00
committed by Gus Rivera
parent 4acf3fa1b0
commit 64fc081821
4 changed files with 92 additions and 0 deletions
+2
View File
@@ -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",
+4
View File
@@ -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",
+14
View File
@@ -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
+72
View File
@@ -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 },
};