From 3b3219c73d90b894470229a50df6ebd635c66866 Mon Sep 17 00:00:00 2001 From: "dayuan.jiang" Date: Sun, 11 Oct 2026 14:56:57 +0900 Subject: [PATCH] ci: run the shell's browser tests on the packed tarball, publish on shared code changes The e2e job's first shard builds the MCP package, packs it, installs the tarball in an empty directory and runs packages/mcp-server/tests/e2e against the installed dist/index.js (MCP_SERVER_ENTRY), so a shell that builds but fails in the browser, or a tarball missing a runtime dependency, fails the PR. Its traces go with the Playwright report. The publish workflow also triggers on the web app code the shell is bundled from (components, contexts, hooks, lib, stores, globals.css) and the root lockfile. --- .github/workflows/publish-mcp.yml | 11 ++++++++++- .github/workflows/test.yml | 22 ++++++++++++++++++++- packages/mcp-server/tests/e2e/shell.spec.ts | 7 ++++--- 3 files changed, 35 insertions(+), 5 deletions(-) diff --git a/.github/workflows/publish-mcp.yml b/.github/workflows/publish-mcp.yml index f3e226ca..09a65628 100644 --- a/.github/workflows/publish-mcp.yml +++ b/.github/workflows/publish-mcp.yml @@ -1,7 +1,8 @@ name: Publish MCP Server # Publishes @next-ai-drawio/mcp-server to npm via OIDC trusted publishing -# (no token, no OTP). Triggers when packages/mcp-server changes on main; +# (no token, no OTP). Triggers when packages/mcp-server or the web app code +# bundled into the canvas shell (scripts/build-shell.mjs) changes on main; # skips silently if the package.json version is already on npm — so a # release is just "bump the version in a PR and merge". on: @@ -10,6 +11,14 @@ on: - main paths: - "packages/mcp-server/**" + # The canvas shell is bundled from these with the root's lockfile + - "components/**" + - "contexts/**" + - "hooks/**" + - "lib/**" + - "stores/**" + - "app/globals.css" + - "package-lock.json" workflow_dispatch: permissions: diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index f36935a4..52079d7e 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -93,10 +93,30 @@ jobs: env: CI: true + # The canvas shell in a browser, from the package as npm installs it: + # the packed tarball goes into an empty directory, its dist/index.js is + # started over stdio and headless Chromium opens the URL start_session + # returns (packages/mcp-server/tests/e2e). Chromium is installed above; + # the build shares the root build's draw.war download. + - name: Run the MCP shell E2E tests on the packed tarball + if: matrix.shard == 1 + run: | + npm --prefix packages/mcp-server ci + npm --prefix packages/mcp-server run build + npm pack ./packages/mcp-server --pack-destination "$RUNNER_TEMP/mcp-pack" + mkdir -p "$RUNNER_TEMP/mcp-install" + npm --prefix "$RUNNER_TEMP/mcp-install" install "$RUNNER_TEMP"/mcp-pack/*.tgz + MCP_SERVER_ENTRY="$RUNNER_TEMP/mcp-install/node_modules/@next-ai-drawio/mcp-server/dist/index.js" \ + npm --prefix packages/mcp-server run test:e2e + env: + CI: true + - name: Upload test results uses: actions/upload-artifact@v6 if: always() with: name: playwright-report-${{ matrix.shard }} - path: playwright-report/ + path: | + playwright-report/ + packages/mcp-server/test-results/ retention-days: 7 diff --git a/packages/mcp-server/tests/e2e/shell.spec.ts b/packages/mcp-server/tests/e2e/shell.spec.ts index ad4e70b9..b07b703d 100644 --- a/packages/mcp-server/tests/e2e/shell.spec.ts +++ b/packages/mcp-server/tests/e2e/shell.spec.ts @@ -1,7 +1,8 @@ /** * The canvas shell as start_session opens it with DRAWIO_PREVIEW_UI=shell: - * the built server (dist/index.js) runs over stdio as an MCP client would - * start it, and headless Chromium opens the URL it returns. + * the built server (dist/index.js, or the copy MCP_SERVER_ENTRY names: CI + * installs the packed tarball in an empty directory) runs over stdio as an + * MCP client would start it, and headless Chromium opens the URL it returns. */ import { mkdtempSync, readFileSync, rmSync } from "node:fs" import { tmpdir } from "node:os" @@ -21,7 +22,7 @@ test.beforeAll(async () => { dataDir = mkdtempSync(join(tmpdir(), "mcp-shell-e2e-")) const transport = new StdioClientTransport({ command: process.execPath, - args: [join(pkg, "dist/index.js")], + args: [process.env.MCP_SERVER_ENTRY ?? join(pkg, "dist/index.js")], env: { ...process.env, DRAWIO_DATA_DIR: dataDir,