From 68ce14d4e872f4e3ad11e0066ba00bdb23adff32 Mon Sep 17 00:00:00 2001 From: Jorge Calvar Date: Fri, 6 Feb 2026 14:00:08 +0100 Subject: [PATCH 1/7] ci: add playground integration tests job Signed-off-by: Jorge Calvar --- .github/workflows/ci.yml | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 29ecfc5..4818abc 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -77,6 +77,30 @@ jobs: - name: Run Tests run: pnpm test + playground-integration-test: + name: Playground Integration Tests + needs: detect-changes + if: needs.detect-changes.outputs.appkit == 'true' + runs-on: + group: databricks-protected-runner-group + labels: linux-ubuntu-latest + + steps: + - uses: actions/checkout@v4 + - uses: pnpm/action-setup@v4 + - uses: actions/setup-node@v4 + with: + node-version: 20 + cache: 'pnpm' + - name: Install dependencies + run: pnpm install --frozen-lockfile + - name: Install Playwright Browsers + run: pnpm --filter=dev-playground exec playwright install --with-deps chromium + - name: Build packages + run: pnpm build + - name: Run Integration Tests + run: pnpm --filter=dev-playground test:integration + docs-build: name: Docs Build needs: detect-changes From 3b41b75c8c7be6b4a6ef921d1ec98f79dc400d61 Mon Sep 17 00:00:00 2001 From: Jorge Calvar Date: Fri, 6 Feb 2026 14:18:52 +0100 Subject: [PATCH 2/7] chore: trigger CI Signed-off-by: Jorge Calvar From 4b5057f7dc060e2d1733d641a24db5956c19385c Mon Sep 17 00:00:00 2001 From: Jorge Calvar Date: Fri, 6 Feb 2026 15:18:39 +0100 Subject: [PATCH 3/7] ci: skip ServiceContext initialization in CI Signed-off-by: Jorge Calvar --- packages/appkit/src/core/appkit.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/packages/appkit/src/core/appkit.ts b/packages/appkit/src/core/appkit.ts index c34588e..cbaf9e7 100644 --- a/packages/appkit/src/core/appkit.ts +++ b/packages/appkit/src/core/appkit.ts @@ -149,7 +149,9 @@ export class AppKit { // Initialize ServiceContext for Databricks client management // This provides the service principal client and shared resources - await ServiceContext.initialize(); + if (!process.env.CI) { + await ServiceContext.initialize(); + } const rawPlugins = config.plugins as T; const preparedPlugins = AppKit.preparePlugins(rawPlugins); From 3fe0e485b1684e5c48a7a4a396c995ddd3f75bb5 Mon Sep 17 00:00:00 2001 From: Jorge Calvar Date: Fri, 6 Feb 2026 17:37:09 +0100 Subject: [PATCH 4/7] feat: allow passing a WorkspaceClient to createApp for e2e testing Signed-off-by: Jorge Calvar --- apps/dev-playground/playwright.config.ts | 8 +++++++ apps/dev-playground/server/index.ts | 12 ++++++++++ .../appkit/src/context/service-context.ts | 23 ++++++++++++------- packages/appkit/src/core/appkit.ts | 7 +++--- 4 files changed, 39 insertions(+), 11 deletions(-) diff --git a/apps/dev-playground/playwright.config.ts b/apps/dev-playground/playwright.config.ts index b0ca6f9..17fab71 100644 --- a/apps/dev-playground/playwright.config.ts +++ b/apps/dev-playground/playwright.config.ts @@ -22,5 +22,13 @@ export default defineConfig({ url: "http://localhost:8000", reuseExistingServer: !process.env.CI, timeout: 120 * 1000, + env: { + ...process.env, + ...(process.env.CI && { + APPKIT_E2E_TEST: "true", + DATABRICKS_WAREHOUSE_ID: "e2e-mock", + DATABRICKS_WORKSPACE_ID: "e2e-mock", + }), + }, }, }); diff --git a/apps/dev-playground/server/index.ts b/apps/dev-playground/server/index.ts index ed3fdac..a56ba4a 100644 --- a/apps/dev-playground/server/index.ts +++ b/apps/dev-playground/server/index.ts @@ -1,7 +1,18 @@ import { analytics, createApp, server } from "@databricks/appkit"; +import { WorkspaceClient } from "@databricks/sdk-experimental"; import { reconnect } from "./reconnect-plugin"; import { telemetryExamples } from "./telemetry-example-plugin"; +function createMockClient() { + const client = new WorkspaceClient({ + host: "http://localhost", + token: "e2e", + authType: "pat", + }); + client.currentUser.me = async () => ({ id: "e2e-test-user" }); + return client; +} + createApp({ plugins: [ server({ autoStart: false }), @@ -9,6 +20,7 @@ createApp({ telemetryExamples(), analytics({}), ], + ...(process.env.APPKIT_E2E_TEST && { client: createMockClient() }), }).then((appkit) => { appkit.server .extend((app) => { diff --git a/packages/appkit/src/context/service-context.ts b/packages/appkit/src/context/service-context.ts index 0304196..ee4b245 100644 --- a/packages/appkit/src/context/service-context.ts +++ b/packages/appkit/src/context/service-context.ts @@ -57,8 +57,13 @@ export class ServiceContext { /** * Initialize the service context. Should be called once at app startup. * Safe to call multiple times - will return the same instance. + * + * @param client - Optional pre-configured WorkspaceClient to use instead + * of creating one from environment credentials. */ - static async initialize(): Promise { + static async initialize( + client?: WorkspaceClient, + ): Promise { if (ServiceContext.instance) { return ServiceContext.instance; } @@ -67,7 +72,7 @@ export class ServiceContext { return ServiceContext.initPromise; } - ServiceContext.initPromise = ServiceContext.createContext(); + ServiceContext.initPromise = ServiceContext.createContext(client); ServiceContext.instance = await ServiceContext.initPromise; return ServiceContext.instance; } @@ -147,19 +152,21 @@ export class ServiceContext { return getClientOptions(); } - private static async createContext(): Promise { - const client = new WorkspaceClient({}, getClientOptions()); + private static async createContext( + client?: WorkspaceClient, + ): Promise { + const wsClient = client ?? new WorkspaceClient({}, getClientOptions()); - const warehouseId = ServiceContext.getWarehouseId(client); - const workspaceId = ServiceContext.getWorkspaceId(client); - const currentUser = await client.currentUser.me(); + const warehouseId = ServiceContext.getWarehouseId(wsClient); + const workspaceId = ServiceContext.getWorkspaceId(wsClient); + const currentUser = await wsClient.currentUser.me(); if (!currentUser.id) { throw ConfigurationError.resourceNotFound("Service user ID"); } return { - client, + client: wsClient, serviceUserId: currentUser.id, warehouseId, workspaceId, diff --git a/packages/appkit/src/core/appkit.ts b/packages/appkit/src/core/appkit.ts index cbaf9e7..ed226b3 100644 --- a/packages/appkit/src/core/appkit.ts +++ b/packages/appkit/src/core/appkit.ts @@ -1,3 +1,4 @@ +import type { WorkspaceClient } from "@databricks/sdk-experimental"; import type { BasePlugin, CacheConfig, @@ -141,6 +142,7 @@ export class AppKit { plugins?: T; telemetry?: TelemetryConfig; cache?: CacheConfig; + client?: WorkspaceClient; } = {}, ): Promise> { // Initialize core services @@ -149,9 +151,7 @@ export class AppKit { // Initialize ServiceContext for Databricks client management // This provides the service principal client and shared resources - if (!process.env.CI) { - await ServiceContext.initialize(); - } + await ServiceContext.initialize(config?.client); const rawPlugins = config.plugins as T; const preparedPlugins = AppKit.preparePlugins(rawPlugins); @@ -190,6 +190,7 @@ export async function createApp< plugins?: T; telemetry?: TelemetryConfig; cache?: CacheConfig; + client?: WorkspaceClient; } = {}, ): Promise> { return AppKit._createApp(config); From b99c40193f6cacdfa7921d0dac69a0c93d9a3667 Mon Sep 17 00:00:00 2001 From: Jorge Calvar Date: Fri, 6 Feb 2026 17:41:37 +0100 Subject: [PATCH 5/7] chore: trigger CI Signed-off-by: Jorge Calvar From c5002ce6e79d61817853272e4a8fdf0b3a39c9c5 Mon Sep 17 00:00:00 2001 From: Jorge Calvar Date: Fri, 6 Feb 2026 17:53:07 +0100 Subject: [PATCH 6/7] refactor: move e2e env vars from playwright config to CI workflow Signed-off-by: Jorge Calvar --- .github/workflows/ci.yml | 4 ++++ apps/dev-playground/playwright.config.ts | 8 -------- 2 files changed, 4 insertions(+), 8 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 4818abc..2a655d4 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -100,6 +100,10 @@ jobs: run: pnpm build - name: Run Integration Tests run: pnpm --filter=dev-playground test:integration + env: + APPKIT_E2E_TEST: 'true' + DATABRICKS_WAREHOUSE_ID: e2e-mock + DATABRICKS_WORKSPACE_ID: e2e-mock docs-build: name: Docs Build diff --git a/apps/dev-playground/playwright.config.ts b/apps/dev-playground/playwright.config.ts index 17fab71..b0ca6f9 100644 --- a/apps/dev-playground/playwright.config.ts +++ b/apps/dev-playground/playwright.config.ts @@ -22,13 +22,5 @@ export default defineConfig({ url: "http://localhost:8000", reuseExistingServer: !process.env.CI, timeout: 120 * 1000, - env: { - ...process.env, - ...(process.env.CI && { - APPKIT_E2E_TEST: "true", - DATABRICKS_WAREHOUSE_ID: "e2e-mock", - DATABRICKS_WORKSPACE_ID: "e2e-mock", - }), - }, }, }); From f9c47fdbf2f5c08000b87c0674dd647e2b154c43 Mon Sep 17 00:00:00 2001 From: Jorge Calvar Date: Fri, 6 Feb 2026 18:02:57 +0100 Subject: [PATCH 7/7] docs: regenerate API docs for createApp client param Signed-off-by: Jorge Calvar --- docs/docs/api/appkit/Function.createApp.md | 4 +++- pnpm-lock.yaml | 6 +++--- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/docs/docs/api/appkit/Function.createApp.md b/docs/docs/api/appkit/Function.createApp.md index 35128e0..85e7fa2 100644 --- a/docs/docs/api/appkit/Function.createApp.md +++ b/docs/docs/api/appkit/Function.createApp.md @@ -3,6 +3,7 @@ ```ts function createApp(config: { cache?: CacheConfig; + client?: WorkspaceClient; plugins?: T; telemetry?: TelemetryConfig; }): Promise>; @@ -20,8 +21,9 @@ Bootstraps AppKit with the provided configuration. | Parameter | Type | | ------ | ------ | -| `config` | \{ `cache?`: [`CacheConfig`](Interface.CacheConfig.md); `plugins?`: `T`; `telemetry?`: [`TelemetryConfig`](Interface.TelemetryConfig.md); \} | +| `config` | \{ `cache?`: [`CacheConfig`](Interface.CacheConfig.md); `client?`: `WorkspaceClient`; `plugins?`: `T`; `telemetry?`: [`TelemetryConfig`](Interface.TelemetryConfig.md); \} | | `config.cache?` | [`CacheConfig`](Interface.CacheConfig.md) | +| `config.client?` | `WorkspaceClient` | | `config.plugins?` | `T` | | `config.telemetry?` | [`TelemetryConfig`](Interface.TelemetryConfig.md) | diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 72bcd8e..587a1d2 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -18088,7 +18088,7 @@ snapshots: dom-helpers@5.2.1: dependencies: - '@babel/runtime': 7.28.4 + '@babel/runtime': 7.28.6 csstype: 3.1.3 dom-serializer@1.4.1: @@ -19268,7 +19268,7 @@ snapshots: history@4.10.1: dependencies: - '@babel/runtime': 7.28.4 + '@babel/runtime': 7.28.6 loose-envify: 1.4.0 resolve-pathname: 3.0.0 tiny-invariant: 1.3.3 @@ -21986,7 +21986,7 @@ snapshots: react-transition-group@4.4.5(react-dom@19.2.0(react@19.2.0))(react@19.2.0): dependencies: - '@babel/runtime': 7.28.4 + '@babel/runtime': 7.28.6 dom-helpers: 5.2.1 loose-envify: 1.4.0 prop-types: 15.8.1