Skip to content

Commit

Permalink
Merge branch 'master' into ADO2-62-new-app-layout
Browse files Browse the repository at this point in the history
* master:
  refactor(core): Use `@/databases/` instead of `@db/` (no-changelog) (#10573)
  ci: Fix destroy benchmark env workflow (no-changelog) (#10572)
  feat: Add benchmarking of pooled sqlite (no-changelog) (#10550)
  refactor(editor): User journey link to n8n.io (#10331)
  fix(Wait Node): Prevent waiting until invalid date (#10523)
  refactor(core): Standardize filename casing for controllers and databases (no-changelog) (#10564)
  refactor(core): Allow custom types on getCredentials (no-changelog) (#10567)
  fix(editor): Scale output item selector input width with value (#10555)
  refactor(core): Delete InternalHooks (no-changelog) (#10561)
  fix(core): Make boolean config value parsing backward-compatible (#10560)
  fix(Google Sheets Trigger Node): Show sheet name is too long error (#10542)
  fix(editor): Ensure `Datatable` component renders `All` option (#10525)
  fix(core): Stop explicit redis client disconnect on shutdown (#10551)
  ci: Use correct branch for benchmark docker build workflow (no-changelog) (#10552)
  refactor(core): Separate listeners in scaling service (no-changelog) (#10487)
  • Loading branch information
MiloradFilipovic committed Aug 27, 2024
2 parents 9682c75 + ab98351 commit db69534
Show file tree
Hide file tree
Showing 521 changed files with 1,488 additions and 1,346 deletions.
7 changes: 3 additions & 4 deletions .github/workflows/benchmark-destroy-nightly.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ name: Destroy Benchmark Env

on:
schedule:
- cron: '30 4 * * *'
- cron: '0 1 * * *'
workflow_dispatch:

permissions:
Expand All @@ -25,16 +25,15 @@ jobs:
tenant-id: ${{ secrets.BENCHMARK_ARM_TENANT_ID }}
subscription-id: ${{ secrets.BENCHMARK_ARM_SUBSCRIPTION_ID }}

- run: Setup node
- run: corepack enable
- uses: actions/[email protected]
with:
node-version: 20.x
cache: pnpm
cache: 'pnpm'

- name: Install dependencies
run: pnpm install --frozen-lockfile

- name: Destroy cloud env
if: github.event.inputs.debug == 'true'
run: pnpm destroy-cloud-env
working-directory: packages/@n8n/benchmark
4 changes: 2 additions & 2 deletions .github/workflows/benchmark-nightly.yml
Original file line number Diff line number Diff line change
Expand Up @@ -60,10 +60,10 @@ jobs:

- name: Run the benchmark with debug logging
if: github.event.inputs.debug == 'true'
run: pnpm run-in-cloud sqlite --debug
run: pnpm run-in-cloud --debug
working-directory: packages/@n8n/benchmark

- name: Run the benchmark
if: github.event.inputs.debug != 'true'
run: pnpm run-in-cloud sqlite
run: pnpm run-in-cloud
working-directory: packages/@n8n/benchmark
2 changes: 1 addition & 1 deletion .github/workflows/docker-images-benchmark.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ on:
workflow_dispatch:
push:
branches:
- main
- master
paths:
- 'packages/@n8n/benchmark/**'
- 'pnpm-lock.yaml'
Expand Down
35 changes: 35 additions & 0 deletions cypress/e2e/46-n8n.io-iframe.cy.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import { WorkflowsPage } from '../pages';

const workflowsPage = new WorkflowsPage();

describe('n8n.io iframe', () => {
describe('when telemetry is disabled', () => {
it('should not load the iframe when visiting /home/workflows', () => {
cy.overrideSettings({ telemetry: { enabled: false } });

cy.visit(workflowsPage.url);

cy.get('iframe').should('not.exist');
});
});

describe('when telemetry is enabled', () => {
it('should load the iframe when visiting /home/workflows', () => {
const testInstanceId = 'test-instance-id';

cy.overrideSettings({ telemetry: { enabled: true }, instanceId: testInstanceId });

const testUserId = Cypress.env('currentUserId');

const iframeUrl = `https://n8n.io/self-install?instanceId=${testInstanceId}&userId=${testUserId}`;

cy.intercept(iframeUrl, (req) => req.reply(200)).as('iframeRequest');

cy.visit(workflowsPage.url);

cy.get('iframe').should('exist').and('have.attr', 'src', iframeUrl);

cy.wait('@iframeRequest').its('response.statusCode').should('eq', 200);
});
});
});
20 changes: 12 additions & 8 deletions cypress/support/commands.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,14 +59,18 @@ Cypress.Commands.add('waitForLoad', (waitForIntercepts = true) => {

Cypress.Commands.add('signin', ({ email, password }) => {
void Cypress.session.clearAllSavedSessions();
cy.session([email, password], () =>
cy.request({
method: 'POST',
url: `${BACKEND_BASE_URL}/rest/login`,
body: { email, password },
failOnStatusCode: false,
}),
);
cy.session([email, password], () => {
return cy
.request({
method: 'POST',
url: `${BACKEND_BASE_URL}/rest/login`,
body: { email, password },
failOnStatusCode: false,
})
.then((response) => {
Cypress.env('currentUserId', response.body.data.id);
});
});
});

Cypress.Commands.add('signinAsOwner', () => cy.signin(INSTANCE_OWNER));
Expand Down
58 changes: 43 additions & 15 deletions packages/@n8n/benchmark/scripts/runInCloud.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
// @ts-check
import fs from 'fs';
import minimist from 'minimist';
import { $, sleep, which } from 'zx';
import { sleep, which } from 'zx';
import path from 'path';
import { SshClient } from './sshClient.mjs';
import { TerraformClient } from './terraformClient.mjs';
Expand Down Expand Up @@ -61,7 +61,6 @@ async function ensureDependencies() {
}

/**
*
* @param {Config} config
* @param {BenchmarkEnv} benchmarkEnv
*/
Expand All @@ -86,7 +85,32 @@ async function runBenchmarksOnVm(config, benchmarkEnv) {
// Give some time for the VM to be ready
await sleep(1000);

console.log('Running benchmarks...');
if (config.n8nSetupToUse === 'all') {
const availableSetups = readAvailableN8nSetups();

for (const n8nSetup of availableSetups) {
await runBenchmarkForN8nSetup({
config,
sshClient,
scriptsDir,
n8nSetup,
});
}
} else {
await runBenchmarkForN8nSetup({
config,
sshClient,
scriptsDir,
n8nSetup: config.n8nSetupToUse,
});
}
}

/**
* @param {{ config: Config; sshClient: any; scriptsDir: string; n8nSetup: string; }} opts
*/
async function runBenchmarkForN8nSetup({ config, sshClient, scriptsDir, n8nSetup }) {
console.log(`Running benchmarks for ${n8nSetup}...`);
const runScriptPath = path.join(scriptsDir, 'runOnVm.mjs');

const flags = {
Expand All @@ -100,7 +124,7 @@ async function runBenchmarksOnVm(config, benchmarkEnv) {
.map(([key, value]) => `--${key}=${value}`)
.join(' ');

await sshClient.ssh(`npx zx ${runScriptPath} ${flagsString} ${config.n8nSetupToUse}`, {
await sshClient.ssh(`npx zx ${runScriptPath} ${flagsString} ${n8nSetup}`, {
// Test run should always log its output
verbose: true,
});
Expand Down Expand Up @@ -138,10 +162,15 @@ function readAvailableN8nSetups() {
* @returns {Promise<Config>}
*/
async function parseAndValidateConfig() {
const args = minimist(process.argv.slice(2), {
boolean: ['debug'],
const args = minimist(process.argv.slice(3), {
boolean: ['debug', 'help'],
});

if (args.help) {
printUsage();
process.exit(0);
}

const n8nSetupToUse = await getAndValidateN8nSetup(args);
const isVerbose = args.debug || false;
const n8nTag = args.n8nTag || process.env.N8N_DOCKER_TAG || 'latest';
Expand All @@ -163,10 +192,8 @@ async function parseAndValidateConfig() {
async function getAndValidateN8nSetup(args) {
// Last parameter is the n8n setup to use
const n8nSetupToUse = args._[args._.length - 1];

if (!n8nSetupToUse) {
printUsage();
process.exit(1);
if (!n8nSetupToUse || n8nSetupToUse === 'all') {
return 'all';
}

const availableSetups = readAvailableN8nSetups();
Expand All @@ -182,19 +209,20 @@ async function getAndValidateN8nSetup(args) {
function printUsage() {
const availableSetups = readAvailableN8nSetups();

console.log('Usage: zx scripts/runInCloud.mjs <n8n setup name>');
console.log(' eg: zx scripts/runInCloud.mjs sqlite');
console.log('Usage: zx scripts/runInCloud.mjs [n8n setup name]');
console.log(' eg: zx scripts/runInCloud.mjs');
console.log('');
console.log('Options:');
console.log(
` [n8n setup name] Against which n8n setup to run the benchmarks. One of: ${['all', ...availableSetups].join(', ')}. Default is all`,
);
console.log(' --debug Enable verbose output');
console.log(' --n8nTag Docker tag for n8n image. Default is latest');
console.log(' --benchmarkTag Docker tag for benchmark cli image. Default is latest');
console.log(
' --k6ApiToken API token for k6 cloud. Default is read from K6_API_TOKEN env var. If omitted, k6 cloud will not be used.',
' --k6ApiToken API token for k6 cloud. Default is read from K6_API_TOKEN env var. If omitted, k6 cloud will not be used',
);
console.log('');
console.log('Available setups:');
console.log(` ${availableSetups.join(', ')}`);
}

main().catch(console.error);
4 changes: 2 additions & 2 deletions packages/@n8n/benchmark/scripts/runOnVm/bootstrap.sh
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ CURRENT_USER=$(whoami)
# Mount the data disk
if [ -d "/n8n" ]; then
echo "Data disk already mounted. Clearing it..."
rm -rf /n8n/*
rm -rf /n8n/.[!.]*
sudo rm -rf /n8n/*
sudo rm -rf /n8n/.[!.]*
else
sudo mkdir -p /n8n
sudo parted /dev/sdc --script mklabel gpt mkpart xfspart xfs 0% 100%
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
services:
n8n:
image: ghcr.io/n8n-io/n8n:${N8N_VERSION:-latest}
environment:
- N8N_DIAGNOSTICS_ENABLED=false
- N8N_USER_FOLDER=/n8n
ports:
- 5678:5678
volumes:
- /n8n:/n8n
benchmark:
image: ghcr.io/n8n-io/n8n-benchmark:${N8N_BENCHMARK_VERSION:-latest}
depends_on:
- n8n
environment:
- N8N_BASE_URL=http://n8n:5678
- K6_API_TOKEN=${K6_API_TOKEN}
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ services:
environment:
- N8N_DIAGNOSTICS_ENABLED=false
- N8N_USER_FOLDER=/n8n
- DB_SQLITE_POOL_SIZE=3
- DB_SQLITE_ENABLE_WAL=true
ports:
- 5678:5678
volumes:
Expand Down
49 changes: 35 additions & 14 deletions packages/@n8n/benchmark/scripts/runOnVm/runOnVm.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -2,23 +2,19 @@
/**
* This script runs the benchmarks using a given docker compose setup
*/
// @ts-check
import path from 'path';
import { $, argv, fs } from 'zx';

import { $ } from 'zx';

const [n8nSetupToUse] = argv._;

if (!n8nSetupToUse) {
printUsage();
process.exit(1);
}

function printUsage() {
console.log('Usage: zx runOnVm.mjs <envName>');
console.log(' eg: zx runOnVm.mjs sqlite');
}
const paths = {
n8nSetupsDir: path.join(__dirname, 'n8nSetups'),
};

async function main() {
const composeFilePath = path.join(__dirname, 'n8nSetups', n8nSetupToUse);
const [n8nSetupToUse] = argv._;
validateN8nSetup(n8nSetupToUse);

const composeFilePath = path.join(paths.n8nSetupsDir, n8nSetupToUse);
const n8nTag = argv.n8nDockerTag || process.env.N8N_DOCKER_TAG || 'latest';
const benchmarkTag = argv.benchmarkDockerTag || process.env.BENCHMARK_DOCKER_TAG || 'latest';
const k6ApiToken = argv.k6ApiToken || process.env.K6_API_TOKEN || undefined;
Expand All @@ -30,6 +26,7 @@ async function main() {
N8N_VERSION: n8nTag,
BENCHMARK_VERSION: benchmarkTag,
K6_API_TOKEN: k6ApiToken,
N8N_BENCHMARK_SCENARIO_NAME_PREFIX: n8nSetupToUse,
},
});

Expand All @@ -52,4 +49,28 @@ async function dumpN8nInstanceLogs($$) {
await $$`docker-compose logs n8n`;
}

function printUsage() {
const availableSetups = getAllN8nSetups();
console.log('Usage: zx runOnVm.mjs <n8n setup to use>');
console.log(` eg: zx runOnVm.mjs ${availableSetups[0]}`);
console.log('');
console.log('Available setups:');
console.log(availableSetups.join(', '));
}

/**
* @returns {string[]}
*/
function getAllN8nSetups() {
return fs.readdirSync(paths.n8nSetupsDir);
}

function validateN8nSetup(givenSetup) {
const availableSetups = getAllN8nSetups();
if (!availableSetups.includes(givenSetup)) {
printUsage();
process.exit(1);
}
}

main();
1 change: 1 addition & 0 deletions packages/@n8n/benchmark/src/commands/run.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ export default class RunCommand extends Command {
email: config.get('n8n.user.email'),
password: config.get('n8n.user.password'),
},
config.get('scenarioNamePrefix'),
);

const allScenarios = scenarioLoader.loadAll(config.get('testScenariosPath'));
Expand Down
6 changes: 6 additions & 0 deletions packages/@n8n/benchmark/src/config/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,12 @@ const configSchema = {
},
},
},
scenarioNamePrefix: {
doc: 'Prefix for the scenario name',
format: String,
default: 'Unnamed',
env: 'N8N_BENCHMARK_SCENARIO_NAME_PREFIX',
},
k6: {
executablePath: {
doc: 'The path to the k6 binary',
Expand Down
Loading

0 comments on commit db69534

Please sign in to comment.