MCPcopy Index your code
hub / github.com/deepnote/deepnote / lintFile

Function lintFile

packages/cli/src/commands/lint.ts:169–244  ·  view source on GitHub ↗
(path: string | undefined, options: LintOptions)

Source from the content-addressed store, hash-verified

167}
168
169async function lintFile(path: string | undefined, options: LintOptions): Promise<LintFileResult> {
170 // Loading `.env` and injecting integration env vars mutates `process.env`; restore it afterwards
171 // so a lint run is idempotent and doesn't clobber caller-provided env values (see withRestoredEnv).
172 return withRestoredEnv(async () => {
173 const { absolutePath } = await resolvePathToDeepnoteFile(path)
174 const fileDir = dirname(absolutePath)
175
176 const { file: deepnoteFile, warnings } = await loadAndResolveDeepnoteFile(absolutePath)
177 emitInitResolverWarnings(warnings, options.output === 'json')
178
179 // Load .env file so env: references in integrations can be resolved
180 dotenv.config({ path: join(fileDir, DEFAULT_ENV_FILE), quiet: true })
181
182 // Load and parse integrations file
183 const integrationsFilePath = options.integrationsFile ?? getDefaultIntegrationsFilePath(fileDir)
184
185 // If the user explicitly specified an integrations file, fail loudly when it's missing
186 // (an absent implicit default file is fine — integrations are optional in that case).
187 if (options.integrationsFile) {
188 try {
189 await fs.stat(integrationsFilePath)
190 } catch (error) {
191 if (isErrnoENOENT(error)) {
192 throw new FileResolutionError(`File not found: ${integrationsFilePath}`)
193 }
194 throw error
195 }
196 }
197
198 debug(`Loading integrations from: ${integrationsFilePath}`)
199 const parsedIntegrations = await parseIntegrationsFile(integrationsFilePath)
200
201 debug(`Parsed ${parsedIntegrations.integrations.length} integrations, ${parsedIntegrations.issues.length} issues`)
202
203 // Generate integration env vars and inject them into process.env so checkMissingIntegrations
204 // works correctly. Generation failures (e.g. invalid BigQuery/Spanner service_account JSON) are
205 // surfaced as configuration issues so a schema-valid-but-impossible to generate integration doesn't lint green.
206 const integrationsIssues = [...parsedIntegrations.issues]
207 if (parsedIntegrations.integrations.length > 0) {
208 const { envVars, issues } = generateIntegrationEnvVars(parsedIntegrations.integrations, fileDir)
209 integrationsIssues.push(...issues)
210 for (const { name, value } of envVars) {
211 process.env[name] = value
212 }
213 debug(
214 `Injected ${envVars.length} environment variables for ${parsedIntegrations.integrations.length} integrations`
215 )
216 }
217
218 debug(`Analyzing blocks...`)
219 const pythonInterpreter = options.python ? await resolvePythonExecutable(options.python) : undefined
220 const { lint } = await checkForIssues(deepnoteFile, {
221 notebook: options.notebook,
222 pythonInterpreter,
223 })
224
225 // Integration/config issues are hard errors (no severity field), so fold their count into
226 // both `errors` and `total` to keep `issueCount` consistent with `success` and the reported

Callers 1

createLintActionFunction · 0.85

Calls 11

emitInitResolverWarningsFunction · 0.90
isErrnoENOENTFunction · 0.90
debugFunction · 0.90
parseIntegrationsFileFunction · 0.90
resolvePythonExecutableFunction · 0.90
checkForIssuesFunction · 0.90
withRestoredEnvFunction · 0.85

Tested by

no test coverage detected