Skip to content

Commit 15afd97

Browse files
[ESLint] Adds --max-warnings flag to next lint (#26697)
Adds `--max-warnings` flag to `next lint` to enable setting of a maximum warning threshold. Fixes #26671
1 parent 956bc2f commit 15afd97

File tree

6 files changed

+89
-7
lines changed

6 files changed

+89
-7
lines changed

packages/next/cli/next-lint.ts

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ const nextLint: cliCommand = (argv) => {
5555
'--ignore-path': String,
5656
'--no-ignore': Boolean,
5757
'--quiet': Boolean,
58+
'--max-warnings': Number,
5859
'--no-inline-config': Boolean,
5960
'--report-unused-disable-directives': String,
6061
'--cache': Boolean,
@@ -108,6 +109,7 @@ const nextLint: cliCommand = (argv) => {
108109
109110
Handling warnings:
110111
--quiet Report errors only - default: false
112+
--max-warnings Int Number of warnings to trigger nonzero exit code - default: -1
111113
112114
Inline configuration comments:
113115
--no-inline-config Prevent comments from changing config or rules
@@ -143,8 +145,16 @@ const nextLint: cliCommand = (argv) => {
143145
)
144146

145147
const reportErrorsOnly = Boolean(args['--quiet'])
146-
147-
runLintCheck(baseDir, lintDirs, false, eslintOptions(args), reportErrorsOnly)
148+
const maxWarnings = args['--max-warnings'] ?? -1
149+
150+
runLintCheck(
151+
baseDir,
152+
lintDirs,
153+
false,
154+
eslintOptions(args),
155+
reportErrorsOnly,
156+
maxWarnings
157+
)
148158
.then(async (lintResults) => {
149159
const lintOutput =
150160
typeof lintResults === 'string' ? lintResults : lintResults?.output

packages/next/lib/eslint/runLintCheck.ts

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import findUp from 'next/dist/compiled/find-up'
66
import semver from 'next/dist/compiled/semver'
77
import * as CommentJson from 'next/dist/compiled/comment-json'
88

9-
import { formatResults } from './customFormatter'
9+
import { LintResult, formatResults } from './customFormatter'
1010
import { writeDefaultConfig } from './writeDefaultConfig'
1111
import { existsSync, findPagesDir } from '../find-pages-dir'
1212
import {
@@ -29,7 +29,8 @@ async function lint(
2929
eslintrcFile: string | null,
3030
pkgJsonPath: string | null,
3131
eslintOptions: any = null,
32-
reportErrorsOnly: boolean = false
32+
reportErrorsOnly: boolean = false,
33+
maxWarnings: number = -1
3334
): Promise<
3435
| string
3536
| null
@@ -116,10 +117,16 @@ async function lint(
116117

117118
const formattedResult = formatResults(baseDir, results)
118119
const lintEnd = process.hrtime(lintStart)
120+
const totalWarnings = results.reduce(
121+
(sum: number, file: LintResult) => sum + file.warningCount,
122+
0
123+
)
119124

120125
return {
121126
output: formattedResult.output,
122-
isError: ESLint.getErrorResults(results)?.length > 0,
127+
isError:
128+
ESLint.getErrorResults(results)?.length > 0 ||
129+
(maxWarnings >= 0 && totalWarnings > maxWarnings),
123130
eventInfo: {
124131
durationInSeconds: lintEnd[0],
125132
eslintVersion: eslintVersion,
@@ -143,7 +150,8 @@ export async function runLintCheck(
143150
lintDirs: string[],
144151
lintDuringBuild: boolean = false,
145152
eslintOptions: any = null,
146-
reportErrorsOnly: boolean = false
153+
reportErrorsOnly: boolean = false,
154+
maxWarnings: number = -1
147155
): ReturnType<typeof lint> {
148156
try {
149157
// Find user's .eslintrc file
@@ -205,7 +213,8 @@ export async function runLintCheck(
205213
eslintrcFile,
206214
pkgJsonPath,
207215
eslintOptions,
208-
reportErrorsOnly
216+
reportErrorsOnly,
217+
maxWarnings
209218
)
210219
} catch (err) {
211220
throw err
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
{
2+
"extends": "next",
3+
"root": true,
4+
"rules": {
5+
"@next/next/no-html-link-for-pages": 0,
6+
"@next/next/no-sync-scripts": 1
7+
}
8+
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
const About = () => (
2+
<div>
3+
<p>About</p>
4+
<script src="https://example.com" />
5+
</div>
6+
)
7+
8+
export default About
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
const Home = () => (
2+
<div>
3+
<p>Home</p>
4+
<script src="https://example.com" />
5+
</div>
6+
)
7+
8+
export default Home

test/integration/eslint/test/index.test.js

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ const dirIgnoreDuringBuilds = join(__dirname, '../ignore-during-builds')
1212
const dirCustomDirectories = join(__dirname, '../custom-directories')
1313
const dirConfigInPackageJson = join(__dirname, '../config-in-package-json')
1414
const dirInvalidEslintVersion = join(__dirname, '../invalid-eslint-version')
15+
const dirMaxWarnings = join(__dirname, '../max-warnings')
1516

1617
describe('ESLint', () => {
1718
describe('Next Build', () => {
@@ -188,5 +189,43 @@ describe('ESLint', () => {
188189
'Warning: External synchronous scripts are forbidden'
189190
)
190191
})
192+
193+
test('max warnings flag errors when warnings exceed threshold', async () => {
194+
const { stdout, stderr } = await nextLint(
195+
dirMaxWarnings,
196+
['--max-warnings', 1],
197+
{
198+
stdout: true,
199+
stderr: true,
200+
}
201+
)
202+
203+
expect(stderr).not.toEqual('')
204+
expect(stderr).toContain(
205+
'Warning: External synchronous scripts are forbidden'
206+
)
207+
expect(stdout).not.toContain(
208+
'Warning: External synchronous scripts are forbidden'
209+
)
210+
})
211+
212+
test('max warnings flag does not error when warnings do not exceed threshold', async () => {
213+
const { stdout, stderr } = await nextLint(
214+
dirMaxWarnings,
215+
['--max-warnings', 2],
216+
{
217+
stdout: true,
218+
stderr: true,
219+
}
220+
)
221+
222+
expect(stderr).toEqual('')
223+
expect(stderr).not.toContain(
224+
'Warning: External synchronous scripts are forbidden'
225+
)
226+
expect(stdout).toContain(
227+
'Warning: External synchronous scripts are forbidden'
228+
)
229+
})
191230
})
192231
})

0 commit comments

Comments
 (0)