fix(cli): case-insensitive SQL integration ID matching (#325)#401
fix(cli): case-insensitive SQL integration ID matching (#325)#401muunkky wants to merge 1 commit into
Conversation
Built-in integration IDs were compared case-sensitively while external IDs were deduplicated and keyed on their raw casing, even though the downstream env-var derivation and API fetch are case-insensitive. As a result the same integration referenced in different casing surfaced as two required/missing entries and triggered redundant credential fetches. - Add isBuiltinIntegration() in constants.ts, comparing against the canonical lowercase BUILTIN_INTEGRATIONS set case-insensitively, and route both call sites through it. - Guard a non-string sql_integration_id in checkMissingIntegrations instead of casting, so a malformed value never reaches toLowerCase(). - Deduplicate external IDs case-insensitively in collectRequiredIntegrationIds and key the configured/missing/usage collections in checkMissingIntegrations by lowercased id, preserving the first-seen original casing as the single display representative. Closes the gap left by deepnote#325, which normalized only the built-in check.
📝 WalkthroughWalkthroughThis PR implements case-insensitive matching for built-in SQL integration IDs across the CLI. It introduces an Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes 🚥 Pre-merge checks | ✅ 6✅ Passed checks (6 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@packages/cli/src/integrations/collect-integrations.test.ts`:
- Around line 59-62: The test "capstone: collects a mixed-case external
integration once, first-seen casing" is duplicated; remove the redundant test
case to avoid duplicate assertions. Locate the test block that calls
makeFileWithSqlBlocks(['My-Warehouse', 'my-warehouse']) and asserts
collectRequiredIntegrationIds(file) equals ['My-Warehouse'] and delete the
duplicate so only one instance of this test remains (the assertion uses
collectRequiredIntegrationIds and helper makeFileWithSqlBlocks).
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: ASSERTIVE
Plan: Pro
Run ID: d556b71d-413c-40be-8100-56d9f9bcccbf
📒 Files selected for processing (6)
packages/cli/src/constants.test.tspackages/cli/src/constants.tspackages/cli/src/integrations/collect-integrations.test.tspackages/cli/src/integrations/collect-integrations.tspackages/cli/src/utils/analysis.test.tspackages/cli/src/utils/analysis.ts
| it('capstone: collects a mixed-case external integration once, first-seen casing', () => { | ||
| const file = makeFileWithSqlBlocks(['My-Warehouse', 'my-warehouse']) | ||
| expect(collectRequiredIntegrationIds(file)).toEqual(['My-Warehouse']) | ||
| }) |
There was a problem hiding this comment.
Duplicate test case.
This test is identical to lines 44-47. Consider removing one.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@packages/cli/src/integrations/collect-integrations.test.ts` around lines 59 -
62, The test "capstone: collects a mixed-case external integration once,
first-seen casing" is duplicated; remove the redundant test case to avoid
duplicate assertions. Locate the test block that calls
makeFileWithSqlBlocks(['My-Warehouse', 'my-warehouse']) and asserts
collectRequiredIntegrationIds(file) equals ['My-Warehouse'] and delete the
duplicate so only one instance of this test remains (the assertion uses
collectRequiredIntegrationIds and helper makeFileWithSqlBlocks).
…fix shipped as PR deepnote#401)
Only the interesting assets: roadmap (yaml + rendered html), the EXTIDCI1 sprint cards, and the executor/reviewer/router/dispatcher agent artifacts. Scaffold (templates, hooks, configs) trimmed. Companion to deepnote#401 - not for merge.
Only the interesting assets: roadmap (yaml + rendered html), the EXTIDCI1 sprint cards, and the executor/reviewer/router/dispatcher agent artifacts. Scaffold (templates, hooks, configs) trimmed. Companion to deepnote#401 - not for merge.
Only the interesting assets: roadmap (yaml + rendered html), the EXTIDCI1 sprint cards, and the executor/reviewer/router/dispatcher agent artifacts. Scaffold (templates, hooks, configs) trimmed. Companion to deepnote#401 - not for merge.
Note
Maintainers — CI needs your approval to run. As a fork PR from a first-time contributor, the GitHub Actions workflows are held in
action_requireduntil a maintainer clicks "Approve and run workflows." Reproduced locally on this branch:pnpm --filter @deepnote/cli test→ 31/31 on the changed suites,tsc --noEmitclean, Biome clean on the changed files.Closes #325
What this does
Makes SQL integration ID matching case-insensitive across the CLI — for both built-in and external integrations — so a
sql_integration_idwritten in any casing is treated consistently.Today the matching is case-sensitive in a few places, which causes three observable problems:
BUILTIN_INTEGRATIONSholds canonical lowercase ids (deepnote-dataframe-sql,pandas-dataframe), checked with a rawSet.has. A block usingPandas-DataFrameisn't recognized as built-in, so it's collected as an external integration anddeepnote lintflags it as missing.My-Warehouseandmy-warehouseboth map to the one env varSQL_MY_WAREHOUSE, yet are collected as two required ids, reported twice as missing/configured, and fetched twice.metadata.sql_integration_idwas castas string; a non-string value would reach.toLowerCase()and throw.The change
One coherent fix, three parts:
isBuiltinIntegration(id)helper inconstants.ts(BUILTIN_INTEGRATIONS.has(id.toLowerCase())), routed through by both call sites. Single source of truth; mirrors the existing lowercase convention inintegrations/fetch-and-merge-integrations.ts.collectRequiredIntegrationIdsdedups case-insensitively viaMap<lowercased, firstSeenOriginal>and returns the first-seen original casing;checkMissingIntegrationskeys itsconfigured/missing/usagecollections by the lowercased id while displaying the first-seen casing. Same integration → collected once, reported once, fetched once.as stringcast becomes atypeof rawId === 'string'guard, so non-string metadata is ignored rather than crashing.Tests
Developed test-first (vitest), behavior-asserting:
constants.test.ts—isBuiltinIntegrationacross canonical / upper / mixed casing; false for externals and suffix collisions.collect-integrations.test.ts— mixed-case built-in not collected; external deduped to first-seen casing.analysis.test.ts— non-string id doesn't crash and isn't flagged; missing-summary dedup.checkForIssues, the functiondeepnote lintcalls): a project withPandas-DataFrame(built-in),My-Warehouseandmy-warehouse(one external, unset) →collectRequiredIntegrationIdsreturns exactly["My-Warehouse"]and lint'smissingsummary is exactly["My-Warehouse"].31/31 across the three suites;
tsc --noEmitclean; Biome clean on the changed files. Behavior is verified at thecheckForIssues/collectRequiredIntegrationIdslibrary boundary (what the lint command invokes); a CLI-binary end-to-end run additionally requires the toolkit analysis server and is out of scope for this change.Scope
Six files, all under
packages/cli/. No behavior change for ids already in consistent casing.Summary by CodeRabbit
Bug Fixes
Tests