Skip to content

Commit 7cc5a9e

Browse files
authored
add custom eslint rule to enforce use of our logger (#59032)
1 parent 53fc17e commit 7cc5a9e

File tree

11 files changed

+800
-0
lines changed

11 files changed

+800
-0
lines changed

eslint.config.ts

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import noOnlyTests from 'eslint-plugin-no-only-tests'
1212
import prettierPlugin from 'eslint-plugin-prettier'
1313
import prettier from 'eslint-config-prettier'
1414
import globals from 'globals'
15+
import customRules from 'eslint-plugin-custom-rules'
1516

1617
export default [
1718
{
@@ -57,6 +58,7 @@ export default [
5758
'@typescript-eslint': tseslint,
5859
'primer-react': primerReact,
5960
'jsx-a11y': jsxA11y,
61+
'custom-rules': customRules,
6062
},
6163
rules: {
6264
// ESLint recommended rules
@@ -98,6 +100,77 @@ export default [
98100
// Disabled rules to review
99101
'no-console': 'off', // 800+
100102
'@typescript-eslint/no-explicit-any': 'off',
103+
104+
// Custom rules (disabled by default for now)
105+
'custom-rules/use-custom-logger': 'off',
106+
},
107+
},
108+
109+
// Configuration for eslint-rules directory (CommonJS JavaScript files)
110+
{
111+
files: ['src/eslint-rules/**/*.js'],
112+
languageOptions: {
113+
ecmaVersion: 2022,
114+
sourceType: 'script',
115+
globals: {
116+
...globals.node,
117+
...globals.commonjs,
118+
...globals.es2020,
119+
},
120+
},
121+
plugins: {
122+
github,
123+
import: importPlugin,
124+
'eslint-comments': eslintComments,
125+
filenames,
126+
'no-only-tests': noOnlyTests,
127+
prettier: prettierPlugin,
128+
},
129+
rules: {
130+
// ESLint recommended rules
131+
...js.configs.recommended.rules,
132+
133+
// GitHub plugin recommended rules
134+
...github.configs.recommended.rules,
135+
136+
// Import plugin error rules
137+
...importPlugin.configs.errors.rules,
138+
139+
// Allow CommonJS in eslint rules
140+
'import/no-commonjs': 'off',
141+
142+
// Overrides
143+
'import/extensions': ['error', { json: 'always' }],
144+
'no-empty': ['error', { allowEmptyCatch: true }],
145+
'prefer-const': ['error', { destructuring: 'all' }],
146+
147+
// Disabled rules
148+
'i18n-text/no-en': 'off',
149+
'filenames/match-regex': 'off',
150+
camelcase: 'off',
151+
'no-console': 'off',
152+
},
153+
},
154+
155+
// Disable custom logger rule for logger implementation itself
156+
{
157+
files: ['src/observability/logger/**/*.{ts,js}'],
158+
rules: {
159+
'custom-rules/use-custom-logger': 'off',
160+
},
161+
},
162+
163+
// Override for scripts, tests, workflows, content-linter, and React files (disable custom logger rule)
164+
{
165+
files: [
166+
'**/scripts/**/*.{ts,js}',
167+
'**/tests/**/*.{ts,js}',
168+
'src/workflows/**/*.{ts,js}',
169+
'src/content-linter/**/*.{ts,js}',
170+
'**/*.{tsx,jsx}',
171+
],
172+
rules: {
173+
'custom-rules/use-custom-logger': 'off',
101174
},
102175
},
103176

package-lock.json

Lines changed: 13 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -292,6 +292,7 @@
292292
"eslint": "^9.33.0",
293293
"eslint-config-prettier": "^10.1.8",
294294
"eslint-import-resolver-typescript": "^4.4.2",
295+
"eslint-plugin-custom-rules": "file:src/eslint-rules",
295296
"eslint-plugin-escompat": "^3.11.4",
296297
"eslint-plugin-eslint-comments": "^3.2.0",
297298
"eslint-plugin-filenames": "^1.3.2",

src/eslint-rules/README.md

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
# Custom ESLint Rules
2+
3+
We can declare custom rules in this directory and import them from our ESLint config in [eslint.config.ts](../../eslint.config.ts)
4+
5+
Custom rules are useful for enforcing best practices and more effective than a "warning" comment since automated linter tests will fail if custom rules aren't followed.
6+
7+
**Note:** Custom rules must be written as JavaScript (`.js`) files, not TypeScript. ESLint loads custom rule plugins at runtime using Node's module system, which expects JavaScript. While the main ESLint config can be TypeScript, the rule implementations themselves need to be JavaScript.
8+
9+
## Creating a new rule
10+
11+
1. Create the rule in this directory
12+
2. Export it from [index.js](./index.js)
13+
3. Enable it in [eslint.config.ts](../../eslint.config.ts) under the `"rules"` key, e.g.
14+
15+
```typescript
16+
'custom-rules/use-custom-logger': 'error',
17+
```
18+
19+
Note that the rule is prepended with `custom-rules`
20+
21+
4. Please include a `README.md` in your rule's directory explaining why it is necessary and any times the rule can be ignored.

src/eslint-rules/index.js

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
// Export custom rules from here
2+
module.exports = {
3+
rules: {
4+
"use-custom-logger": require("./use-custom-logger/use-custom-logger"),
5+
},
6+
};

src/eslint-rules/package.json

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
{
2+
"name": "eslint-plugin-custom-rules",
3+
"type": "commonjs",
4+
"version": "1.0.0",
5+
"license": "MIT",
6+
"main": "index.js",
7+
"peerDependencies": {
8+
"eslint": "^8.0.0 || ^9.0.0"
9+
}
10+
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
# Use Custom Logger Rule
2+
3+
This rule enforces using `logger.<level>` instead of `console.log` in backend code.
4+
5+
Please see [the logger README](../../observability/logger/README.md) for more details.
6+
7+
## When to ignore
8+
9+
Anywhere that isn't server code doesn't need to use the `logger`. e.g. React components, GitHub Actions, and CLI scripts.
10+
11+
## Auto fix
12+
13+
This rule supports auto-fixing via `--fix`.
14+
15+
Run `npm run lint -- --fix` to apply the changes, but please make sure to double check that the automatic fix looks correct before committing.

0 commit comments

Comments
 (0)