Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
a071931
chore: add Endform as a pnpm dependency
augustoccesar Sep 10, 2026
ede7c23
test: configure Endform for a serial local-backend baseline
augustoccesar Sep 10, 2026
9dd4a99
ci: compare Playwright and Endform with one existing test
augustoccesar Sep 10, 2026
adaad37
test: wait for backend readiness before global setup
augustoccesar Sep 10, 2026
cd18bb0
test: allow 30 seconds for Endform navigation
augustoccesar Sep 11, 2026
32e5408
ci: expand the Endform comparison to workflow entry points
augustoccesar Sep 11, 2026
fa9422c
test: include workflow fixtures in Endform uploads
augustoccesar Sep 11, 2026
369ae98
ci: add credential CRUD to the Endform comparison
augustoccesar Sep 11, 2026
fa77113
test: run two Endform tests concurrently
augustoccesar Sep 11, 2026
202182f
test: run four Endform tests concurrently
augustoccesar Sep 11, 2026
f4e4f69
test: add canvas actions
augustoccesar Sep 11, 2026
67978da
test: add node configuration
augustoccesar Sep 11, 2026
677170b
test: add workflow execution to the Endform experiment
augustoccesar Sep 11, 2026
d4b266e
test: add user sessions to the Endform experiment
augustoccesar Sep 11, 2026
7fa3c28
test: allow 90 seconds for remote test execution
augustoccesar Sep 11, 2026
1fd9ae9
test: compare runners at concurrency four
augustoccesar Sep 11, 2026
5bb503d
test: match navigation limits in the runner comparison
augustoccesar Sep 14, 2026
7adea29
test: narrow global request interception
augustoccesar Sep 14, 2026
0152328
test: isolate Endform catch-all routing overhead
augustoccesar Sep 14, 2026
8047373
test: restore tracing after the routing experiment
augustoccesar Sep 14, 2026
d1bb77c
test: measure video recording overhead
augustoccesar Sep 14, 2026
9cfad6f
test: restore video after the performance experiment
augustoccesar Sep 14, 2026
a67ff8c
test: record backend capacity during runner comparisons
augustoccesar Sep 14, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
140 changes: 140 additions & 0 deletions .github/workflows/endform-experiment.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
name: 'Endform: Incremental experiment'

on:
push:
branches: [augustoccesar/endform-integration]

permissions:
contents: read

jobs:
baseline:
if: github.repository == 'endformdev/n8n'
name: '${{ matrix.runner }}: incremental suite'
runs-on: ubuntu-latest
timeout-minutes: 45
strategy:
fail-fast: false
max-parallel: 1
matrix:
runner: [playwright, endform]
env:
NODE_OPTIONS: '--max-old-space-size=6144'
N8N_BASE_URL: http://localhost:5680
RESET_E2E_DB: 'true'
N8N_SKIP_LICENSES: 'true'
PLAYWRIGHT_BROWSERS_PATH: '${{ github.workspace }}/packages/testing/playwright/.playwright-browsers'
steps:
- name: Checkout
uses: useblacksmith/checkout@bcec731f1eb1367240608d1c889a75b96db6ec53 # v1.5.0

- name: Install dependencies
uses: ./.github/actions/setup-nodejs
with:
build-command: ''

- name: Build
run: pnpm build > build.log 2>&1

- name: Record versions
working-directory: packages/testing/playwright
run: |
git rev-parse HEAD
node --version
pnpm --version
pnpm exec playwright --version
pnpm exec endform --version

- name: Check types and lint
working-directory: packages/testing/playwright
run: |
pnpm typecheck > typecheck.log 2>&1
pnpm lint > lint.log 2>&1

- name: Install Chromium
if: matrix.runner == 'playwright'
working-directory: packages/testing/playwright
run: pnpm exec playwright install chromium --with-deps

- name: Install resource monitor
run: |
sudo apt-get update -qq
sudo apt-get install -y sysstat procps iproute2

- name: Run incremental suite
working-directory: packages/testing/playwright
env:
TEST_RUNNER: '${{ matrix.runner }}'
E2E_NAVIGATION_TIMEOUT: '30000'
E2E_REMOTE_RUNNER: "${{ matrix.runner == 'endform' && 'true' || 'false' }}"
ENDFORM_API_KEY: "${{ matrix.runner == 'endform' && secrets.ENDFORM_API_KEY || '' }}"
run: |
export TZ=UTC
{
echo "Logical CPUs: $(nproc)"
free -m
echo 'The first vmstat sample contains averages since boot.'
} > host-resources.log
vmstat -w -t 5 >> host-resources.log &
host_monitor_pid=$!
pidstat -h -u -r -d -p ALL 5 > process-resources.log &
process_monitor_pid=$!
(
while true; do
date -u '+%Y-%m-%dT%H:%M:%SZ'
ss -ltnp 'sport = :5680'
sleep 5
done
) > backend-listener.log &
listener_monitor_pid=$!
stop_monitors() {
kill "$host_monitor_pid" "$process_monitor_pid" "$listener_monitor_pid" 2>/dev/null || true
wait "$host_monitor_pid" "$process_monitor_pid" "$listener_monitor_pid" 2>/dev/null || true
}
trap stop_monitors EXIT

args=(
test --project=e2e
tests/e2e/building-blocks/workflow-entry-points.spec.ts
tests/e2e/credentials/crud.spec.ts
tests/e2e/building-blocks/canvas-actions.spec.ts
tests/e2e/building-blocks/node-details-configuration.spec.ts
tests/e2e/workflows/editor/execution/execution.spec.ts
tests/e2e/building-blocks/user-service.spec.ts
--retries=0
)
if [ "$TEST_RUNNER" = endform ]; then
args+=(--organization-id=2G1ZCj7X)
else
args+=(--workers=4)
fi
pnpm exec "$TEST_RUNNER" "${args[@]}" > experiment.log 2>&1

- name: Show log tails
if: always()
run: |
for log in build.log packages/testing/playwright/{typecheck,lint,experiment}.log; do
if [ -f "$log" ]; then
echo "::group::$log"
tail -n 50 "$log"
echo '::endgroup::'
fi
done

- name: Preserve evidence
if: always()
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
with:
name: 'endform-experiment-${{ matrix.runner }}-${{ github.run_attempt }}'
retention-days: 30
path: |
build.log
packages/testing/playwright/experiment.log
packages/testing/playwright/typecheck.log
packages/testing/playwright/lint.log
packages/testing/playwright/host-resources.log
packages/testing/playwright/process-resources.log
packages/testing/playwright/backend-listener.log
packages/testing/playwright/test-results/
packages/testing/playwright/test-results.json
packages/testing/playwright/playwright-report/
66 changes: 32 additions & 34 deletions packages/testing/playwright/config/intercepts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -116,8 +116,9 @@ export async function setupDefaultInterceptors(target: BrowserContext) {
});

// Pathname /api/health
// Use URL patterns so Playwright does not intercept unrelated asset requests.
await target.route(
(url) => url.pathname.endsWith('/api/health'),
/^https?:\/\/[^/?#]+\/(?:[^?#]*\/)?api\/health(?:[?#].*)?$/,
async (route: Route) => {
await route.fulfill({
contentType: 'application/json',
Expand All @@ -127,37 +128,34 @@ export async function setupDefaultInterceptors(target: BrowserContext) {
);

// Pathname /api/versions/*
await target.route(
(url) => url.pathname.startsWith('/api/versions/'),
async (route: Route) => {
await route.fulfill({
contentType: 'application/json',
body: JSON.stringify([
{
name: '1.45.1',
createdAt: '2023-08-18T11:53:12.857Z',
hasSecurityIssue: null,
hasSecurityFix: null,
securityIssueFixVersion: null,
hasBreakingChange: null,
documentationUrl: 'https://docs.n8n.io/release-notes/#n8n131',
nodes: [],
description: 'Includes <strong>bug fixes</strong>',
},
{
name: '1.0.5',
createdAt: '2023-07-24T10:54:56.097Z',
hasSecurityIssue: false,
hasSecurityFix: null,
securityIssueFixVersion: null,
hasBreakingChange: true,
documentationUrl: 'https://docs.n8n.io/release-notes/#n8n104',
nodes: [],
description:
'Includes <strong>core functionality</strong> and <strong>bug fixes</strong>',
},
]),
});
},
);
await target.route(/^https?:\/\/[^/?#]+\/api\/versions\//, async (route: Route) => {
await route.fulfill({
contentType: 'application/json',
body: JSON.stringify([
{
name: '1.45.1',
createdAt: '2023-08-18T11:53:12.857Z',
hasSecurityIssue: null,
hasSecurityFix: null,
securityIssueFixVersion: null,
hasBreakingChange: null,
documentationUrl: 'https://docs.n8n.io/release-notes/#n8n131',
nodes: [],
description: 'Includes <strong>bug fixes</strong>',
},
{
name: '1.0.5',
createdAt: '2023-07-24T10:54:56.097Z',
hasSecurityIssue: false,
hasSecurityFix: null,
securityIssueFixVersion: null,
hasBreakingChange: true,
documentationUrl: 'https://docs.n8n.io/release-notes/#n8n104',
nodes: [],
description:
'Includes <strong>core functionality</strong> and <strong>bug fixes</strong>',
},
]),
});
});
}
8 changes: 8 additions & 0 deletions packages/testing/playwright/endform.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
/* eslint-disable import-x/no-default-export */
import { defineEndformConfig } from 'endform';

export default defineEndformConfig({
additionalFiles: ['workflows/**/*'],
concurrentTestLimits: [{ scope: 'within-suite-run', limit: 4 }],
environmentVariables: ['N8N_BASE_URL', 'RESET_E2E_DB', 'E2E_REMOTE_RUNNER'],
});
1 change: 1 addition & 0 deletions packages/testing/playwright/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@
"autocannon": "^8.0.0",
"axe-core": "^4.13.0",
"axe-html-reporter": "^2.2.11",
"endform": "catalog:",
"eslint-plugin-playwright": "catalog:e2e",
"flatted": "catalog:",
"generate-schema": "2.6.0",
Expand Down
9 changes: 6 additions & 3 deletions packages/testing/playwright/playwright.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ if (BACKEND_URL && !SKIP_WEB_SERVER) {
}
webServer.push({
command: 'pnpm --dir ../../.. start',
url: `${BACKEND_URL}/favicon.ico`,
url: `${BACKEND_URL}/healthz/readiness`,
timeout: 30000,
reuseExistingServer: IS_DEV ? false : true,
env: {
Expand Down Expand Up @@ -112,7 +112,7 @@ export default defineConfig<CurrentsFixtures, CurrentsWorkerFixtures>({
forbidOnly: IS_CI,
retries: IS_CI ? 2 : 0,
workers: WORKERS,
timeout: 60000,
timeout: process.env.E2E_REMOTE_RUNNER === 'true' ? 90000 : 60000,
expect: {
timeout: EXPECT_TIMEOUT,
},
Expand All @@ -130,7 +130,10 @@ export default defineConfig<CurrentsFixtures, CurrentsWorkerFixtures>({
headless: process.env.SHOW_BROWSER !== 'true',
viewport: MACBOOK_WINDOW_SIZE,
actionTimeout: 20000, // TODO: We might need to make this dynamic for container tests if we have low resource containers etc
navigationTimeout: 10000,
navigationTimeout: Number(
process.env.E2E_NAVIGATION_TIMEOUT ??
(process.env.E2E_REMOTE_RUNNER === 'true' ? 30000 : 10000),
),
currentsFixturesEnabled: !!process.env.CI,
},

Expand Down
67 changes: 67 additions & 0 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions pnpm-workspace.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -286,6 +286,7 @@ catalog:
yaml: 2.8.3
zod: 3.25.76
zod-to-json-schema: 3.23.3
endform: 0.76.0

catalogMode: strict

Expand Down
Loading