From 106143431c4fc86f356fc684bf36defe310f1b63 Mon Sep 17 00:00:00 2001 From: Oliver Stenbom Date: Fri, 16 Oct 2026 16:49:35 -0700 Subject: [PATCH 1/4] ci: run desktop smoke E2E on Endform in one job Adds a non-sharded workflow that builds the production e2e bundle, serves it through the existing webServer, and runs the smoke project on Endform with a configurable concurrency limit. Starts with a single test to validate the setup. Co-Authored-By: Claude Opus 5.5 Signed-off-by: Oliver Stenbom --- .github/workflows/endform-desktop-smoke.yml | 59 +++++++++++++++++++++ desktop/endform.config.ts | 11 ++++ desktop/playwright.endform.config.ts | 15 ++++++ 3 files changed, 85 insertions(+) create mode 100644 .github/workflows/endform-desktop-smoke.yml create mode 100644 desktop/endform.config.ts create mode 100644 desktop/playwright.endform.config.ts diff --git a/.github/workflows/endform-desktop-smoke.yml b/.github/workflows/endform-desktop-smoke.yml new file mode 100644 index 00000000000..12bfc1162f9 --- /dev/null +++ b/.github/workflows/endform-desktop-smoke.yml @@ -0,0 +1,59 @@ +name: Endform Desktop Smoke E2E +on: + pull_request: + workflow_dispatch: + inputs: + concurrency: + description: Max concurrent tests on Endform + default: "20" + grep: + description: Test title filter + default: "" + +permissions: + contents: read + id-token: write # Endform GitHub App OIDC + +concurrency: + group: endform-desktop-smoke-${{ github.ref }} + cancel-in-progress: true + +jobs: + smoke: + name: Desktop Smoke E2E (Endform) + runs-on: ubuntu-latest + timeout-minutes: 30 + env: + ENDFORM_CONCURRENCY: ${{ inputs.concurrency || '1' }} + ENDFORM_GREP: ${{ inputs.grep || 'loads the app shell with mocked channels' }} + steps: + - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 + - uses: cashapp/activate-hermit@cea9af7913204a965fd488637a8d1811bba2e616 # v1 + - name: Get pnpm store directory + id: pnpm-cache + run: echo "STORE_PATH=$(pnpm store path --silent)" >> "$GITHUB_OUTPUT" + - name: Restore pnpm store cache + uses: actions/cache/restore@caa296126883cff596d87d8935842f9db880ef25 # v5 + with: + path: ${{ steps.pnpm-cache.outputs.STORE_PATH }} + key: pnpm-${{ runner.os }}-${{ hashFiles('**/pnpm-lock.yaml') }} + restore-keys: pnpm-${{ runner.os }}- + - name: Install desktop dependencies + run: just desktop-install-ci + - name: Desktop E2E build + run: pnpm -C desktop build:e2e + - name: Desktop smoke e2e on Endform + working-directory: desktop + run: | + npx --yes endform@latest test \ + --config playwright.endform.config.ts \ + --project smoke \ + ${ENDFORM_GREP:+--grep "$ENDFORM_GREP"} + - name: Upload Playwright report + if: ${{ !cancelled() }} + uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7 + with: + name: endform-desktop-smoke-report + path: desktop/playwright-report + if-no-files-found: ignore + retention-days: 7 diff --git a/desktop/endform.config.ts b/desktop/endform.config.ts new file mode 100644 index 00000000000..d6014d8b26c --- /dev/null +++ b/desktop/endform.config.ts @@ -0,0 +1,11 @@ +// Endform reads this file only for `npx endform test`; local Playwright runs +// ignore it. ENDFORM_CONCURRENCY caps how many smoke tests share the local +// static server at once. +export default { + concurrentTestLimits: [ + { + scope: "within-suite-run", + limit: Number(process.env.ENDFORM_CONCURRENCY ?? "20"), + }, + ], +}; diff --git a/desktop/playwright.endform.config.ts b/desktop/playwright.endform.config.ts new file mode 100644 index 00000000000..f08e5614635 --- /dev/null +++ b/desktop/playwright.endform.config.ts @@ -0,0 +1,15 @@ +import { defineConfig } from "@playwright/test"; + +import baseConfig from "./playwright.config"; + +// Runs the desktop smoke project on Endform: one CI job, every test on its +// own machine, against the production `build:e2e` bundle served locally. +// Endform proxies the runners' traffic back to this `webServer`. +export default defineConfig({ + ...baseConfig, + fullyParallel: true, + retries: 2, + workers: undefined, + use: { ...baseConfig.use, trace: "retain-on-failure" }, + projects: baseConfig.projects?.filter(({ name }) => name === "smoke"), +}); From 6196007805f9b739e39cd469317834e5da355941 Mon Sep 17 00:00:00 2001 From: Oliver Stenbom Date: Fri, 16 Oct 2026 16:52:22 -0700 Subject: [PATCH 2/4] ci(endform): run 65 smoke tests at concurrency 10 Co-Authored-By: Claude Opus 5.5 Signed-off-by: Oliver Stenbom --- .github/workflows/endform-desktop-smoke.yml | 10 +++++----- desktop/playwright.endform.config.ts | 2 ++ 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/.github/workflows/endform-desktop-smoke.yml b/.github/workflows/endform-desktop-smoke.yml index 12bfc1162f9..1e2fe361b4d 100644 --- a/.github/workflows/endform-desktop-smoke.yml +++ b/.github/workflows/endform-desktop-smoke.yml @@ -6,8 +6,8 @@ on: concurrency: description: Max concurrent tests on Endform default: "20" - grep: - description: Test title filter + args: + description: Extra endform test arguments (file filters, --grep) default: "" permissions: @@ -24,8 +24,8 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 30 env: - ENDFORM_CONCURRENCY: ${{ inputs.concurrency || '1' }} - ENDFORM_GREP: ${{ inputs.grep || 'loads the app shell with mocked channels' }} + ENDFORM_CONCURRENCY: ${{ inputs.concurrency || '10' }} + ENDFORM_ARGS: ${{ inputs.args || '/smoke\.spec\.ts /badge\.spec\.ts /channel-mute\.spec\.ts /spoiler\.spec\.ts' }} steps: - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 - uses: cashapp/activate-hermit@cea9af7913204a965fd488637a8d1811bba2e616 # v1 @@ -48,7 +48,7 @@ jobs: npx --yes endform@latest test \ --config playwright.endform.config.ts \ --project smoke \ - ${ENDFORM_GREP:+--grep "$ENDFORM_GREP"} + $ENDFORM_ARGS - name: Upload Playwright report if: ${{ !cancelled() }} uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7 diff --git a/desktop/playwright.endform.config.ts b/desktop/playwright.endform.config.ts index f08e5614635..b8d4bf6f7ba 100644 --- a/desktop/playwright.endform.config.ts +++ b/desktop/playwright.endform.config.ts @@ -12,4 +12,6 @@ export default defineConfig({ workers: undefined, use: { ...baseConfig.use, trace: "retain-on-failure" }, projects: baseConfig.projects?.filter(({ name }) => name === "smoke"), + // http.server logs every request to stderr; keep the CI log readable. + webServer: { ...baseConfig.webServer, stderr: "ignore" }, }); From a67aa2dee8d1cf67d4d9588c7fed97797e0028f9 Mon Sep 17 00:00:00 2001 From: Oliver Stenbom Date: Fri, 16 Oct 2026 22:49:50 -0700 Subject: [PATCH 3/4] ci(endform): run full smoke suite at concurrency 50 Co-Authored-By: Claude Opus 5.5 Signed-off-by: Oliver Stenbom --- .github/workflows/endform-desktop-smoke.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/endform-desktop-smoke.yml b/.github/workflows/endform-desktop-smoke.yml index 1e2fe361b4d..231480d32a8 100644 --- a/.github/workflows/endform-desktop-smoke.yml +++ b/.github/workflows/endform-desktop-smoke.yml @@ -24,8 +24,8 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 30 env: - ENDFORM_CONCURRENCY: ${{ inputs.concurrency || '10' }} - ENDFORM_ARGS: ${{ inputs.args || '/smoke\.spec\.ts /badge\.spec\.ts /channel-mute\.spec\.ts /spoiler\.spec\.ts' }} + ENDFORM_CONCURRENCY: ${{ inputs.concurrency || '50' }} + ENDFORM_ARGS: ${{ inputs.args || '' }} steps: - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 - uses: cashapp/activate-hermit@cea9af7913204a965fd488637a8d1811bba2e616 # v1 From 93f84fc78bbd4223be5ffae06afd81a35ff204ef Mon Sep 17 00:00:00 2001 From: Oliver Stenbom Date: Fri, 16 Oct 2026 23:12:20 -0700 Subject: [PATCH 4/4] ci(endform): ship fs-read fixtures, snapshots, and @/ sources to runners Endform's additionalFiles treats dir/** as directories only, so match files explicitly. Co-Authored-By: Claude Opus 5.5 Signed-off-by: Oliver Stenbom --- desktop/endform.config.ts | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/desktop/endform.config.ts b/desktop/endform.config.ts index d6014d8b26c..0f2b900df65 100644 --- a/desktop/endform.config.ts +++ b/desktop/endform.config.ts @@ -2,6 +2,15 @@ // ignore it. ENDFORM_CONCURRENCY caps how many smoke tests share the local // static server at once. export default { + // Files specs read through fs or resolve through tsconfig `@/` paths, + // which Endform's import tracing does not pick up on its own. + additionalFiles: [ + "tsconfig.json", + "src/**/*", + "src-tauri/tauri.conf.json", + "tests/fixtures/*", + "tests/e2e/*-snapshots/*", + ], concurrentTestLimits: [ { scope: "within-suite-run",