Skip to content

feat(integrations): Add Google Cloud SQL database integration#406

Draft
sLightlyDev wants to merge 2 commits into
mainfrom
feat/cloud-sql-integration
Draft

feat(integrations): Add Google Cloud SQL database integration#406
sLightlyDev wants to merge 2 commits into
mainfrom
feat/cloud-sql-integration

Conversation

@sLightlyDev

@sLightlyDev sLightlyDev commented Jun 8, 2026

Copy link
Copy Markdown

Summary

Adds Google Cloud SQL as a database integration in the integration picker.

  • New configuration form: Name + Service Account JSON (validated), modeled on the existing Spanner integration form.
  • Service Account JSON is validated as parseable JSON at both the form and storage levels (rejects empty/whitespace-only and malformed input).
  • Adds the Cloud SQL icon and localized labels.

Implementation note

cloud-sql is not yet published in @deepnote/database-integrations, so this change includes a small, clearly-marked temporary local shim for the config type (and excludes it from environment-variable generation) so it ships self-contained. Once the type is published upstream, the shim can be removed and the dependency bumped as a follow-up.

Testing

No automated/staging test exists for the extension UI, so this was verified locally in the Extension Development Host (F5):

  1. Open a .deepnote project → Deepnote: Manage IntegrationsAdd New Integration.
  2. Confirm Google Cloud SQL appears under Databases with its icon/label.
  3. Open the form and check validation:
    • Malformed JSON → rejected
    • Whitespace-only → rejected
    • Valid JSON → accepted
  4. Save → appears in the integration list.
  5. Reload the window (Cmd+R) → integration persists.

Existing unit suite passes with no regressions (0 failing).

Summary by CodeRabbit

  • New Features
    • Added Google Cloud SQL as a selectable database integration with a dedicated configuration form (service account JSON input, validation, and “Learn more” link).
    • Cloud SQL now appears in integration selectors, icons/labels, and status displays.
    • Pending integrations (including Cloud SQL) are omitted from automatic environment-variable generation until supported.

Adds Cloud SQL to the integration picker with a name + service account
JSON form (validated), modeled on the Spanner integration. Includes a
temporary local shim for the cloud-sql config type until it is published
upstream in @deepnote/database-integrations.
@sLightlyDev sLightlyDev requested a review from a team as a code owner June 8, 2026 10:43
@coderabbitai

coderabbitai Bot commented Jun 8, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 7def6e84-036a-4733-aa07-a8cb5fb56cc4

📥 Commits

Reviewing files that changed from the base of the PR and between 8bbec38 and cac6958.

📒 Files selected for processing (3)
  • src/platform/notebooks/deepnote/integrationStorage.ts
  • src/platform/notebooks/deepnote/sqlIntegrationEnvironmentVariablesProvider.ts
  • src/webviews/webview-side/integrations/CloudSQLForm.tsx

📝 Walkthrough

Walkthrough

Adds Google Cloud SQL as a configurable integration: new type exports and unions, Zod metadata schema for service-account JSON, detection/manager updates to validate configurable types, env-var generation that skips pending integrations, localized UI strings and icons, and a new CloudSQLForm React component that validates service-account JSON and emits a CloudSqlIntegrationConfig on save.

Sequence Diagram

sequenceDiagram
  participant User as User
  participant Selector as IntegrationTypeSelector
  participant Form as CloudSQLForm
  participant Backend as IntegrationManager
  participant Storage as IntegrationStorage
  User->>Selector: choose 'cloud-sql'
  Selector->>Form: render CloudSQLForm
  User->>Form: enter name + service account JSON
  Form->>Form: validate JSON on keystroke
  User->>Form: click Save
  Form->>Form: require non-empty valid JSON
  Form->>Backend: onSave(CloudSqlIntegrationConfig)
  Backend->>Backend: validate type ∈ allDatabaseIntegrationTypes
  Backend->>Storage: persist config
  Storage->>Storage: validate with cloudSqlMetadataSchema
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~22 minutes

Possibly related PRs

  • deepnote/vscode-deepnote#160: Shares the integration-type refactor pattern; this PR extends it further with Cloud SQL type support and matching validation schemas.
🚥 Pre-merge checks | ✅ 4 | ❌ 2

❌ Failed checks (2 warnings)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 50.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Updates Docs ⚠️ Warning Cloud SQL integration feature lacks documentation updates. No changes to specs/INTEGRATIONS_CREDENTIALS.md, README.md, or other docs; Cloud SQL should be documented alongside BigQuery/Spanner. Update specs/INTEGRATIONS_CREDENTIALS.md to list 'cloud-sql' - Google Cloud SQL in the "Cloud Databases (service account/key-based auth)" section, and update README if integration list is maintained.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed Title clearly and concisely describes the main change: adding Google Cloud SQL as a database integration, matching the PR's primary objective.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.


Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 6

🤖 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 `@src/platform/notebooks/deepnote/integrationStorage.ts`:
- Around line 9-15: The import statements mix third-party and local modules;
reorder them so all third-party imports (e.g., z from 'zod' and
databaseMetadataSchemasByType from '`@deepnote/database-integrations`') appear
first, followed by local/project imports (e.g., allDatabaseIntegrationTypes,
ConfigurableDatabaseIntegrationConfig, DATAFRAME_SQL_INTEGRATION_ID from
'./integrationTypes'); update the import block to group external packages before
the relative './integrationTypes' import while keeping the same imported symbols
and names.
- Around line 18-35: The refine on cloudSqlMetadataSchema.service_account uses
the old Zod 3 `{ message: '...' }` option; update the second argument to use Zod
4's unified `error` option (e.g., replace the `{ message: 'Invalid JSON format'
}` object with an `{ error: { message: 'Invalid JSON format' } }` payload) so
the call to `.refine(...)` on the service_account validator conforms to Zod 4
error customization.

In `@src/platform/notebooks/deepnote/integrationTypes.ts`:
- Around line 85-88: The array allDatabaseIntegrationTypes is declared as
readonly string[] which widens and loses literal union types; change its
declaration to preserve literals by using a const assertion or a typed tuple
spread (e.g. readonly [...typeof databaseIntegrationTypes, ...typeof
PENDING_INTEGRATION_TYPES]) so TypeScript retains the exact string literals,
then export a union type like AllDatabaseIntegrationType = (typeof
allDatabaseIntegrationTypes)[number]; update references that currently cast
(e.g., uses in integrationManager and sqlCellStatusBarProvider) to use the new
union type instead of manual casts.

In
`@src/platform/notebooks/deepnote/sqlIntegrationEnvironmentVariablesProvider.ts`:
- Around line 129-149: Remove the redundant local alias `pendingTypes` and use
the module-level constant `PENDING_INTEGRATION_TYPES` directly: delete the
`const pendingTypes: readonly string[] = PENDING_INTEGRATION_TYPES;` declaration
and change the check `if (pendingTypes.includes(config.type))` to `if
(PENDING_INTEGRATION_TYPES.includes(config.type))` inside the loop in
SqlIntegrationEnvironmentVariablesProvider; leave the other logic (the
`isFederatedAuthMetadata` check and pushing into `projectIntegrationConfigs`)
unchanged.

In `@src/webviews/webview-side/integrations/CloudSQLForm.tsx`:
- Around line 72-95: The handler validates a trimmed service account but calls
onSave with the original untrimmed string; update the pendingConfig so the saved
value matches validation by replacing pendingConfig.metadata.service_account
with trimmedServiceAccount before calling onSave — either mutate a cloned object
(e.g., const next = { ...pendingConfig, metadata: { ...pendingConfig.metadata,
service_account: trimmedServiceAccount } } and pass next to onSave) or call the
appropriate setter (setPendingConfig) to persist the trimmed value, then call
onSave with that trimmed-version object from handleSubmit.
- Line 34: CloudSQLForm currently calls structuredClone(existingConfig)
unguarded; wrap that use with a runtime check like typeof structuredClone !==
'undefined' and fall back to a safe alternative (e.g.,
JSON.parse(JSON.stringify(existingConfig)) or a repo shared helper) so the
webview doesn't crash in environments without structuredClone; update the code
in CloudSQLForm (the place where structuredClone(existingConfig) is called) to
perform the typeof structuredClone check and use the fallback when undefined.
🪄 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: d6e9dfba-2a05-4f1c-ad6a-f5d23e634d5a

📥 Commits

Reviewing files that changed from the base of the PR and between 9c57186 and 8bbec38.

⛔ Files ignored due to path filters (1)
  • src/webviews/webview-side/integrations/icons/cloud-sql.svg is excluded by !**/*.svg
📒 Files selected for processing (14)
  • src/messageTypes.ts
  • src/notebooks/deepnote/integrations/integrationDetector.ts
  • src/notebooks/deepnote/integrations/integrationManager.ts
  • src/notebooks/deepnote/integrations/integrationWebview.ts
  • src/notebooks/deepnote/sqlCellStatusBarProvider.ts
  • src/platform/common/utils/localize.ts
  • src/platform/notebooks/deepnote/integrationStorage.ts
  • src/platform/notebooks/deepnote/integrationTypes.ts
  • src/platform/notebooks/deepnote/sqlIntegrationEnvironmentVariablesProvider.ts
  • src/webviews/webview-side/integrations/CloudSQLForm.tsx
  • src/webviews/webview-side/integrations/ConfigurationForm.tsx
  • src/webviews/webview-side/integrations/IntegrationTypeSelector.tsx
  • src/webviews/webview-side/integrations/integrationUtils.ts
  • src/webviews/webview-side/integrations/types.ts

Comment thread src/platform/notebooks/deepnote/integrationStorage.ts Outdated
Comment on lines +18 to +35
const cloudSqlMetadataSchema = z.object({
service_account: z
.string()
.trim()
.min(1)
.refine(
(value) => {
try {
JSON.parse(value);

return true;
} catch {
return false;
}
},
{ message: 'Invalid JSON format' }
)
});

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick | 🔵 Trivial | 💤 Low value

Consider Zod 4 unified error customization.

The .refine() uses { message: 'Invalid JSON format' } (Zod 3 style). Zod 4 introduces unified error customization via the error parameter for consistency across validators.

♻️ Optional Zod 4 refactor
 const cloudSqlMetadataSchema = z.object({
     service_account: z
         .string()
         .trim()
         .min(1)
         .refine(
             (value) => {
                 try {
                     JSON.parse(value);
-
                     return true;
                 } catch {
                     return false;
                 }
             },
-            { message: 'Invalid JSON format' }
+            { error: () => 'Invalid JSON format' }
         )
 });
🤖 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 `@src/platform/notebooks/deepnote/integrationStorage.ts` around lines 18 - 35,
The refine on cloudSqlMetadataSchema.service_account uses the old Zod 3 `{
message: '...' }` option; update the second argument to use Zod 4's unified
`error` option (e.g., replace the `{ message: 'Invalid JSON format' }` object
with an `{ error: { message: 'Invalid JSON format' } }` payload) so the call to
`.refine(...)` on the service_account validator conforms to Zod 4 error
customization.

Comment on lines +85 to +88
export const allDatabaseIntegrationTypes: readonly string[] = [
...databaseIntegrationTypes,
...PENDING_INTEGRATION_TYPES
];

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick | 🔵 Trivial | ⚡ Quick win

Type widening loses literal types.

allDatabaseIntegrationTypes is typed as readonly string[], which discards the literal union from the concatenation. TypeScript won't narrow types after .includes() checks, forcing explicit casts downstream (e.g., line 165 in integrationManager.ts, line 375 in sqlCellStatusBarProvider.ts).

Consider typing as readonly [...typeof databaseIntegrationTypes, ...typeof PENDING_INTEGRATION_TYPES] or use a const assertion to preserve literals:

-export const allDatabaseIntegrationTypes: readonly string[] = [
+export const allDatabaseIntegrationTypes = [
     ...databaseIntegrationTypes,
     ...PENDING_INTEGRATION_TYPES
-];
+] as const;

Then export a union type:

export type AllDatabaseIntegrationType = (typeof allDatabaseIntegrationTypes)[number];

This enables type narrowing without casts.

🤖 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 `@src/platform/notebooks/deepnote/integrationTypes.ts` around lines 85 - 88,
The array allDatabaseIntegrationTypes is declared as readonly string[] which
widens and loses literal union types; change its declaration to preserve
literals by using a const assertion or a typed tuple spread (e.g. readonly
[...typeof databaseIntegrationTypes, ...typeof PENDING_INTEGRATION_TYPES]) so
TypeScript retains the exact string literals, then export a union type like
AllDatabaseIntegrationType = (typeof allDatabaseIntegrationTypes)[number];
update references that currently cast (e.g., uses in integrationManager and
sqlCellStatusBarProvider) to use the new union type instead of manual casts.

Comment thread src/webviews/webview-side/integrations/CloudSQLForm.tsx Outdated
Comment thread src/webviews/webview-side/integrations/CloudSQLForm.tsx
@sLightlyDev sLightlyDev marked this pull request as draft June 9, 2026 08:17
@linear-code

linear-code Bot commented Jun 9, 2026

Copy link
Copy Markdown

SAL-112

- Move zod and @deepnote/database-integrations imports to third-party group
- Use Zod 4 string-param API for .refine() (deprecated message object)
- Remove redundant pendingTypes alias; inline cast on PENDING_INTEGRATION_TYPES
- Add structuredClone fallback in CloudSQLForm for older webview environments
- Save trimmed service_account value on form submit instead of raw input

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@codecov

codecov Bot commented Jun 9, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 0%. Comparing base (9c57186) to head (cac6958).
⚠️ Report is 1 commits behind head on main.
✅ All tests successful. No failed tests found.

Additional details and impacted files
@@     Coverage Diff     @@
##   main   #406   +/-   ##
===========================
===========================
🚀 New features to boost your workflow:
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant