n8n/packages/testing/containers/helm-start-stack.ts

154 lines
5.2 KiB
TypeScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/usr/bin/env tsx
import { writeFileSync } from 'node:fs';
import { parseArgs } from 'node:util';
import { createHelmStack, type HelmStackMode } from './helm-stack';
const colors = {
reset: '\x1b[0m',
bright: '\x1b[1m',
green: '\x1b[32m',
yellow: '\x1b[33m',
blue: '\x1b[34m',
red: '\x1b[31m',
cyan: '\x1b[36m',
};
const log = {
info: (msg: string) => console.log(`${colors.blue}${colors.reset} ${msg}`),
success: (msg: string) => console.log(`${colors.green}${colors.reset} ${msg}`),
error: (msg: string) => console.error(`${colors.red}${colors.reset} ${msg}`),
header: (msg: string) => console.log(`\n${colors.bright}${colors.cyan}${msg}${colors.reset}\n`),
};
function showHelp() {
console.log(`
${colors.bright}n8n Helm Stack${colors.reset}
Start n8n via Helm chart in a K3s (lightweight Kubernetes) container.
${colors.yellow}Usage:${colors.reset}
pnpm stack:helm [options]
${colors.yellow}Options:${colors.reset}
--mode <mode> standalone (SQLite, default) or queue (PostgreSQL + Redis + workers)
--image <image> n8n Docker image (default: n8nio/n8n:local)
--chart-ref <ref> Git branch/tag for n8n-hosting repo (default: main)
--chart-repo <url> Git repo URL (default: https://github.com/n8n-io/n8n-hosting.git)
--k3s-image <image> K3s image (default: rancher/k3s:v1.32.2-k3s1)
--env <KEY=VALUE> Set environment variable in n8n pods (repeatable)
--url-file <path> Write URL to file when ready (for CI)
--help, -h Show this help
${colors.yellow}Examples:${colors.reset}
${colors.bright}# Start with default local image${colors.reset}
pnpm stack:helm
${colors.bright}# Test specific n8n version against specific chart${colors.reset}
pnpm stack:helm --image n8nio/n8n:1.80.0 --chart-ref v1.2.0
${colors.bright}# Queue mode (PostgreSQL + Redis + workers)${colors.reset}
pnpm stack:helm --mode queue --image n8nio/n8n:latest
${colors.bright}# E2E test mode (requires INCLUDE_TEST_CONTROLLER image)${colors.reset}
pnpm stack:helm --env E2E_TESTS=true --env NODE_ENV=development
${colors.bright}# CI mode (writes URL to file)${colors.reset}
pnpm stack:helm --url-file /tmp/n8n-url.txt &
${colors.yellow}Prerequisites:${colors.reset}
• Docker with privileged container support
• helm and kubectl CLIs installed locally
• n8n Docker image built locally (pnpm build:docker) or available on Docker Hub
• See HELM-TESTING.md for full requirements
${colors.yellow}Notes:${colors.reset}
• helm and kubectl run on your host (not inside K3s)
• Startup takes ~60-120s (K3s boot + image load + Helm install)
• After startup, use kubectl with KUBECONFIG printed below
• Press Ctrl+C to stop
`);
}
async function main() {
const { values } = parseArgs({
args: process.argv.slice(2),
options: {
help: { type: 'boolean', short: 'h' },
mode: { type: 'string' },
image: { type: 'string' },
'chart-ref': { type: 'string' },
'chart-repo': { type: 'string' },
'k3s-image': { type: 'string' },
env: { type: 'string', multiple: true },
'url-file': { type: 'string' },
'kubeconfig-file': { type: 'string' },
},
allowPositionals: false,
});
if (values.help) {
showHelp();
process.exit(0);
}
log.header('Starting n8n Helm Stack');
const mode = (values.mode as HelmStackMode) || undefined;
// Parse --env KEY=VALUE pairs into a record
const envOverrides: Record<string, string> = {};
for (const entry of values.env ?? []) {
const eqIndex = entry.indexOf('=');
if (eqIndex === -1) {
log.error(`Invalid --env format: "${entry}" (expected KEY=VALUE)`);
process.exit(1);
}
envOverrides[entry.slice(0, eqIndex)] = entry.slice(eqIndex + 1);
}
const stack = await createHelmStack({
n8nImage: values.image,
helmChartRef: values['chart-ref'],
helmChartRepo: values['chart-repo'],
k3sImage: values['k3s-image'],
mode,
env: Object.keys(envOverrides).length > 0 ? envOverrides : undefined,
});
log.header('Stack Ready');
log.success(`n8n URL: ${colors.bright}${colors.green}${stack.baseUrl}${colors.reset}`);
log.info(`Kubeconfig: ${colors.bright}${stack.kubeConfigPath}${colors.reset}`);
if (values['url-file']) {
writeFileSync(values['url-file'], stack.baseUrl);
log.info(`URL written to ${values['url-file']}`);
}
if (values['kubeconfig-file']) {
writeFileSync(values['kubeconfig-file'], stack.kubeConfigPath);
log.info(`Kubeconfig path written to ${values['kubeconfig-file']}`);
}
console.log('');
log.info('Debug with kubectl (context already active):');
log.info(` ${colors.bright}kubectl get pods${colors.reset}`);
log.info(` ${colors.bright}kubectl logs -l app.kubernetes.io/name=n8n${colors.reset}`);
console.log('');
log.info(`Cleanup: ${colors.bright}pnpm --filter n8n-containers stack:helm:clean${colors.reset}`);
console.log('');
if (envOverrides.E2E_TESTS === 'true') {
log.info('Run tests against this instance:');
log.info(
` ${colors.bright}N8N_BASE_URL=${stack.baseUrl} RESET_E2E_DB=true npx playwright test tests/e2e/building-blocks/ --workers=1${colors.reset}`,
);
}
// Container stays alive in Docker (Ryuk disabled) — clean up via stack:helm:clean.
}
main().catch((error) => {
log.error(`Failed to start: ${error instanceof Error ? error.message : String(error)}`);
process.exit(1);
});