Skip to content

Commit 91abea0

Browse files
authored
fix: improve error logging when failing to parse config file (#1423)
1 parent 31a1f95 commit 91abea0

File tree

6 files changed

+186
-18
lines changed

6 files changed

+186
-18
lines changed

.changeset/smart-pets-melt.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'lint-staged': patch
3+
---
4+
5+
Improve error logging when failing to read or parse a configuration file

lib/loadConfig.js

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import debug from 'debug'
77
import YAML from 'yaml'
88

99
import { dynamicImport } from './dynamicImport.js'
10+
import { failedToLoadConfig } from './messages.js'
1011
import { resolveConfig } from './resolveConfig.js'
1112
import {
1213
CONFIG_FILE_NAMES,
@@ -117,8 +118,8 @@ export const loadConfig = async ({ configPath, cwd }, logger) => {
117118

118119
return { config, filepath }
119120
} catch (error) {
120-
debugLog('Failed to load configuration!')
121-
logger.error(error)
121+
debugLog('Failed to load configuration from `%s` with error:\n', configPath, error)
122+
logger.error(failedToLoadConfig(configPath))
122123
return {}
123124
}
124125
}

lib/messages.js

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,3 +85,15 @@ export const RESTORE_STASH_EXAMPLE = ` Any lost modifications can be restored f
8585
`
8686

8787
export const CONFIG_STDIN_ERROR = chalk.redBright(`${error} Failed to read config from stdin.`)
88+
89+
export const failedToLoadConfig = (filepath) =>
90+
chalk.redBright(`${error} Failed to read config from file "${filepath}".`)
91+
92+
export const failedToParseConfig = (
93+
filepath,
94+
error
95+
) => `${chalk.redBright(`${error} Failed to parse config from file "${filepath}".`)}
96+
97+
${error}
98+
99+
See https://github.com/okonet/lint-staged#configuration.`

lib/validateConfig.js

Lines changed: 19 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import { inspect } from 'node:util'
44

55
import debug from 'debug'
66

7-
import { configurationError } from './messages.js'
7+
import { configurationError, failedToParseConfig } from './messages.js'
88
import { ConfigEmptyError, ConfigFormatError } from './symbols.js'
99
import { validateBraces } from './validateBraces.js'
1010

@@ -23,14 +23,7 @@ const TEST_DEPRECATED_KEYS = new Map([
2323
['relative', (key) => typeof key === 'boolean'],
2424
])
2525

26-
/**
27-
* Runs config validation. Throws error if the config is not valid.
28-
* @param {Object} config
29-
* @param {string} configPath
30-
* @param {Logger} logger
31-
* @returns {Object} config
32-
*/
33-
export const validateConfig = (config, configPath, logger) => {
26+
export const validateConfigLogic = (config, configPath, logger) => {
3427
debugLog('Validating config from `%s`...', configPath)
3528

3629
if (!config || (typeof config !== 'object' && typeof config !== 'function')) {
@@ -100,11 +93,7 @@ export const validateConfig = (config, configPath, logger) => {
10093
if (errors.length) {
10194
const message = errors.join('\n\n')
10295

103-
logger.error(`Could not parse lint-staged config.
104-
105-
${message}
106-
107-
See https://github.com/okonet/lint-staged#configuration.`)
96+
logger.error(failedToParseConfig(configPath, message))
10897

10998
throw new Error(message)
11099
}
@@ -114,3 +103,19 @@ See https://github.com/okonet/lint-staged#configuration.`)
114103

115104
return validatedConfig
116105
}
106+
107+
/**
108+
* Runs config validation. Throws error if the config is not valid.
109+
* @param {Object} config
110+
* @param {string} configPath
111+
* @param {Logger} logger
112+
* @returns {Object} config
113+
*/
114+
export const validateConfig = (config, configPath, logger) => {
115+
try {
116+
return validateConfigLogic(config, configPath, logger)
117+
} catch (error) {
118+
logger.error(failedToParseConfig(configPath, error))
119+
throw error
120+
}
121+
}

test/unit/__snapshots__/validateConfig.spec.js.snap

Lines changed: 144 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,10 +64,153 @@ exports[`validateConfig should throw when detecting deprecated advanced configur
6464

6565
exports[`validateConfig should throw when detecting deprecated advanced configuration 2`] = `
6666
"
67-
ERROR Could not parse lint-staged config.
67+
ERROR ✖ Validation Error:
68+
69+
Invalid value for 'chunkSize': 10
70+
71+
Advanced configuration has been deprecated.
72+
73+
✖ Validation Error:
74+
75+
Invalid value for 'concurrent': false
76+
77+
Advanced configuration has been deprecated.
78+
79+
✖ Validation Error:
80+
81+
Invalid value for 'globOptions': { matchBase: false }
82+
83+
Advanced configuration has been deprecated.
84+
85+
✖ Validation Error:
86+
87+
Invalid value for 'ignore': [ 'test.js' ]
88+
89+
Advanced configuration has been deprecated.
90+
91+
✖ Validation Error:
92+
93+
Invalid value for 'linters': { '*.js': [ 'eslint' ] }
94+
95+
Advanced configuration has been deprecated.
96+
97+
✖ Validation Error:
98+
99+
Invalid value for 'relative': true
100+
101+
Advanced configuration has been deprecated.
102+
103+
✖ Validation Error:
104+
105+
Invalid value for 'renderer': 'silent'
106+
107+
Advanced configuration has been deprecated.
108+
109+
✖ Validation Error:
110+
111+
Invalid value for 'subTaskConcurrency': 10
112+
113+
Advanced configuration has been deprecated. Failed to parse config from file ".lintstagedrc.json".
114+
115+
✖ Validation Error:
116+
117+
Invalid value for 'chunkSize': 10
118+
119+
Advanced configuration has been deprecated.
120+
121+
✖ Validation Error:
122+
123+
Invalid value for 'concurrent': false
124+
125+
Advanced configuration has been deprecated.
126+
127+
✖ Validation Error:
128+
129+
Invalid value for 'globOptions': { matchBase: false }
130+
131+
Advanced configuration has been deprecated.
132+
133+
✖ Validation Error:
134+
135+
Invalid value for 'ignore': [ 'test.js' ]
136+
137+
Advanced configuration has been deprecated.
68138
69139
✖ Validation Error:
70140
141+
Invalid value for 'linters': { '*.js': [ 'eslint' ] }
142+
143+
Advanced configuration has been deprecated.
144+
145+
✖ Validation Error:
146+
147+
Invalid value for 'relative': true
148+
149+
Advanced configuration has been deprecated.
150+
151+
✖ Validation Error:
152+
153+
Invalid value for 'renderer': 'silent'
154+
155+
Advanced configuration has been deprecated.
156+
157+
✖ Validation Error:
158+
159+
Invalid value for 'subTaskConcurrency': 10
160+
161+
Advanced configuration has been deprecated.
162+
163+
See https://github.com/okonet/lint-staged#configuration.
164+
ERROR Error: ✖ Validation Error:
165+
166+
Invalid value for 'chunkSize': 10
167+
168+
Advanced configuration has been deprecated.
169+
170+
✖ Validation Error:
171+
172+
Invalid value for 'concurrent': false
173+
174+
Advanced configuration has been deprecated.
175+
176+
✖ Validation Error:
177+
178+
Invalid value for 'globOptions': { matchBase: false }
179+
180+
Advanced configuration has been deprecated.
181+
182+
✖ Validation Error:
183+
184+
Invalid value for 'ignore': [ 'test.js' ]
185+
186+
Advanced configuration has been deprecated.
187+
188+
✖ Validation Error:
189+
190+
Invalid value for 'linters': { '*.js': [ 'eslint' ] }
191+
192+
Advanced configuration has been deprecated.
193+
194+
✖ Validation Error:
195+
196+
Invalid value for 'relative': true
197+
198+
Advanced configuration has been deprecated.
199+
200+
✖ Validation Error:
201+
202+
Invalid value for 'renderer': 'silent'
203+
204+
Advanced configuration has been deprecated.
205+
206+
✖ Validation Error:
207+
208+
Invalid value for 'subTaskConcurrency': 10
209+
210+
Advanced configuration has been deprecated. Failed to parse config from file ".lintstagedrc.json".
211+
212+
Error: ✖ Validation Error:
213+
71214
Invalid value for 'chunkSize': 10
72215
73216
Advanced configuration has been deprecated.

test/unit/loadConfig.spec.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,13 +48,15 @@ describe('loadConfig', () => {
4848
})
4949

5050
it('should not return config when YAML config file is invalid', async () => {
51-
expect.assertions(1)
51+
expect.assertions(2)
5252

5353
const { config } = await loadConfig(
5454
{ configPath: path.join(__dirname, '__mocks__', 'invalid-config-file.yml') },
5555
logger
5656
)
5757

58+
expect(logger.printHistory()).toMatch('Failed to read config from file')
59+
5860
expect(config).toBeUndefined()
5961
})
6062

0 commit comments

Comments
 (0)