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

Function lintIntegrationsFile

packages/cli/src/commands/lint.ts:250–306  ·  view source on GitHub ↗

* Lint an integrations env yaml file directly (without a .deepnote notebook). * Validates the file structure, integration schemas, and env var references.

(filePath: string)

Source from the content-addressed store, hash-verified

248 * Validates the file structure, integration schemas, and env var references.
249 */
250async function lintIntegrationsFile(filePath: string): Promise<LintFileResult> {
251 const absolutePath = resolve(process.cwd(), filePath)
252
253 // Verify the file exists
254 try {
255 await fs.stat(absolutePath)
256 } catch (error) {
257 if (isErrnoENOENT(error)) {
258 throw new FileResolutionError(`File not found: ${absolutePath}`)
259 }
260 throw error
261 }
262
263 const fileDir = dirname(absolutePath)
264
265 // Loading `.env` mutates `process.env`; restore it afterwards so a lint run is idempotent and
266 // doesn't clobber caller-provided env values (see withRestoredEnv).
267 return withRestoredEnv(async () => {
268 // Load .env file so env: references in integrations can be resolved
269 dotenv.config({ path: join(fileDir, DEFAULT_ENV_FILE), quiet: true })
270
271 debug(`Linting integrations file: ${absolutePath}`)
272 const parsedIntegrations = await parseIntegrationsFile(absolutePath)
273
274 debug(`Parsed ${parsedIntegrations.integrations.length} integrations, ${parsedIntegrations.issues.length} issues`)
275
276 // Also run env var generation so schema-valid-but-impossible to generate integrations (e.g. invalid
277 // BigQuery/Spanner service_account JSON) are caught here too, not just on the .deepnote path.
278 const integrationsIssues = [...parsedIntegrations.issues]
279 if (parsedIntegrations.integrations.length > 0) {
280 const { issues } = generateIntegrationEnvVars(parsedIntegrations.integrations, fileDir)
281 integrationsIssues.push(...issues)
282 }
283
284 const hasErrors = integrationsIssues.length > 0
285
286 // Integration/config issues are hard errors (no severity field), so report them as errors in
287 // `issueCount` (there are no notebook issues on this path) to keep it consistent with `success`
288 // and `integrationsFile.issues`.
289 return {
290 path: absolutePath,
291 success: !hasErrors,
292 issueCount: { errors: integrationsIssues.length, warnings: 0, total: integrationsIssues.length },
293 issues: [],
294 // Emit empty integrations/inputs so the JSON shape matches the .deepnote path. There is no
295 // notebook on this path, so both are always empty — but keeping the keys present saves machine
296 // consumers from having to special-case the direct-YAML output.
297 integrations: { configured: [], missing: [] },
298 inputs: { total: 0, withValues: 0, needingValues: [] },
299 integrationsFile: {
300 path: absolutePath,
301 integrationCount: parsedIntegrations.integrations.length,
302 issues: integrationsIssues,
303 },
304 }
305 })
306}
307

Callers 1

createLintActionFunction · 0.85

Calls 5

isErrnoENOENTFunction · 0.90
debugFunction · 0.90
parseIntegrationsFileFunction · 0.90
withRestoredEnvFunction · 0.85

Tested by

no test coverage detected