mirror of
https://github.com/Abdulazizzn/n8n-enterprise-unlocked.git
synced 2025-12-17 18:12:04 +00:00
feat: setup nightly tests for postgres and mysql schemas (#4441)
* feat: unify Jest config * feat: simplify DB setup for tests * feat: setup nightly tests for postgres and mysql schemas
This commit is contained in:
committed by
GitHub
parent
5c9b40117a
commit
99157cf581
@@ -1,6 +1,3 @@
|
||||
import { exec as callbackExec } from 'child_process';
|
||||
import { promisify } from 'util';
|
||||
|
||||
import { UserSettings } from 'n8n-core';
|
||||
import { Connection, ConnectionOptions, createConnection, getConnection } from 'typeorm';
|
||||
|
||||
@@ -13,13 +10,7 @@ import { mysqlMigrations } from '../../../src/databases/migrations/mysqldb';
|
||||
import { postgresMigrations } from '../../../src/databases/migrations/postgresdb';
|
||||
import { sqliteMigrations } from '../../../src/databases/migrations/sqlite';
|
||||
import { hashPassword } from '../../../src/UserManagement/UserManagementHelper';
|
||||
import {
|
||||
BOOTSTRAP_MYSQL_CONNECTION_NAME,
|
||||
BOOTSTRAP_POSTGRES_CONNECTION_NAME,
|
||||
DB_INITIALIZATION_TIMEOUT,
|
||||
MAPPING_TABLES,
|
||||
MAPPING_TABLES_TO_CLEAR,
|
||||
} from './constants';
|
||||
import { DB_INITIALIZATION_TIMEOUT, MAPPING_TABLES, MAPPING_TABLES_TO_CLEAR } from './constants';
|
||||
import {
|
||||
randomApiKey,
|
||||
randomCredentialPayload,
|
||||
@@ -45,17 +36,16 @@ import type {
|
||||
MappingName,
|
||||
} from './types';
|
||||
|
||||
const exec = promisify(callbackExec);
|
||||
export type TestDBType = 'postgres' | 'mysql';
|
||||
|
||||
/**
|
||||
* Initialize one test DB per suite run, with bootstrap connection if needed.
|
||||
*/
|
||||
export async function init() {
|
||||
jest.setTimeout(DB_INITIALIZATION_TIMEOUT);
|
||||
const dbType = config.getEnv('database.type');
|
||||
|
||||
if (dbType === 'sqlite') {
|
||||
jest.setTimeout(DB_INITIALIZATION_TIMEOUT);
|
||||
|
||||
// no bootstrap connection required
|
||||
const testDbName = `n8n_test_sqlite_${randomString(6, 10)}_${Date.now()}`;
|
||||
await Db.init(getSqliteOptions({ name: testDbName }));
|
||||
@@ -65,10 +55,8 @@ export async function init() {
|
||||
}
|
||||
|
||||
if (dbType === 'postgresdb') {
|
||||
jest.setTimeout(DB_INITIALIZATION_TIMEOUT);
|
||||
|
||||
let bootstrapPostgres;
|
||||
const pgOptions = getBootstrapPostgresOptions();
|
||||
const pgOptions = getBootstrapDBOptions('postgres');
|
||||
|
||||
try {
|
||||
bootstrapPostgres = await createConnection(pgOptions);
|
||||
@@ -91,40 +79,32 @@ export async function init() {
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
const testDbName = `pg_${randomString(6, 10)}_${Date.now()}_n8n_test`;
|
||||
await bootstrapPostgres.query(`CREATE DATABASE ${testDbName};`);
|
||||
const testDbName = `postgres_${randomString(6, 10)}_${Date.now()}_n8n_test`;
|
||||
await bootstrapPostgres.query(`CREATE DATABASE ${testDbName}`);
|
||||
await bootstrapPostgres.close();
|
||||
|
||||
try {
|
||||
const schema = config.getEnv('database.postgresdb.schema');
|
||||
const exportPasswordCli = pgOptions.password
|
||||
? `export PGPASSWORD=${pgOptions.password} && `
|
||||
: '';
|
||||
await exec(
|
||||
`${exportPasswordCli} psql -h ${pgOptions.host} -U ${pgOptions.username} -d ${testDbName} -c "CREATE SCHEMA IF NOT EXISTS ${schema}";`,
|
||||
);
|
||||
} catch (error) {
|
||||
if (error instanceof Error && error.message.includes('command not found')) {
|
||||
console.error(
|
||||
'psql command not found. Make sure psql is installed and added to your PATH.',
|
||||
);
|
||||
}
|
||||
process.exit(1);
|
||||
const dbOptions = getDBOptions('postgres', testDbName);
|
||||
|
||||
if (dbOptions.schema !== 'public') {
|
||||
const { schema, migrations, ...options } = dbOptions;
|
||||
const connection = await createConnection(options);
|
||||
await connection.query(`CREATE SCHEMA IF NOT EXISTS "${schema}"`);
|
||||
await connection.close();
|
||||
}
|
||||
|
||||
await Db.init(getPostgresOptions({ name: testDbName }));
|
||||
await Db.init(dbOptions);
|
||||
|
||||
return { testDbName };
|
||||
}
|
||||
|
||||
if (dbType === 'mysqldb') {
|
||||
// initialization timeout in test/setup.ts
|
||||
|
||||
const bootstrapMysql = await createConnection(getBootstrapMySqlOptions());
|
||||
const bootstrapMysql = await createConnection(getBootstrapDBOptions('mysql'));
|
||||
|
||||
const testDbName = `mysql_${randomString(6, 10)}_${Date.now()}_n8n_test`;
|
||||
await bootstrapMysql.query(`CREATE DATABASE ${testDbName};`);
|
||||
await bootstrapMysql.query(`CREATE DATABASE ${testDbName}`);
|
||||
await bootstrapMysql.close();
|
||||
|
||||
await Db.init(getMySqlOptions({ name: testDbName }));
|
||||
await Db.init(getDBOptions('mysql', testDbName));
|
||||
|
||||
return { testDbName };
|
||||
}
|
||||
@@ -136,27 +116,7 @@ export async function init() {
|
||||
* Drop test DB, closing bootstrap connection if existing.
|
||||
*/
|
||||
export async function terminate(testDbName: string) {
|
||||
const dbType = config.getEnv('database.type');
|
||||
|
||||
if (dbType === 'sqlite') {
|
||||
await getConnection(testDbName).close();
|
||||
}
|
||||
|
||||
if (dbType === 'postgresdb') {
|
||||
await getConnection(testDbName).close();
|
||||
|
||||
const bootstrapPostgres = getConnection(BOOTSTRAP_POSTGRES_CONNECTION_NAME);
|
||||
await bootstrapPostgres.query(`DROP DATABASE ${testDbName}`);
|
||||
await bootstrapPostgres.close();
|
||||
}
|
||||
|
||||
if (dbType === 'mysqldb') {
|
||||
await getConnection(testDbName).close();
|
||||
|
||||
const bootstrapMySql = getConnection(BOOTSTRAP_MYSQL_CONNECTION_NAME);
|
||||
await bootstrapMySql.query(`DROP DATABASE ${testDbName}`);
|
||||
await bootstrapMySql.close();
|
||||
}
|
||||
await getConnection(testDbName).close();
|
||||
}
|
||||
|
||||
async function truncateMappingTables(
|
||||
@@ -277,6 +237,7 @@ function toTableName(sourceName: CollectionName | MappingName) {
|
||||
|
||||
return {
|
||||
Credentials: 'credentials_entity',
|
||||
CredentialUsage: 'credential_usage',
|
||||
Workflow: 'workflow_entity',
|
||||
Execution: 'execution_entity',
|
||||
Tag: 'tag_entity',
|
||||
@@ -714,100 +675,38 @@ export const getSqliteOptions = ({ name }: { name: string }): ConnectionOptions
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* Generate options for a bootstrap Postgres connection,
|
||||
* to create and drop test Postgres databases.
|
||||
*/
|
||||
export const getBootstrapPostgresOptions = () => {
|
||||
const username = config.getEnv('database.postgresdb.user');
|
||||
const password = config.getEnv('database.postgresdb.password');
|
||||
const host = config.getEnv('database.postgresdb.host');
|
||||
const port = config.getEnv('database.postgresdb.port');
|
||||
const schema = config.getEnv('database.postgresdb.schema');
|
||||
|
||||
return {
|
||||
name: BOOTSTRAP_POSTGRES_CONNECTION_NAME,
|
||||
type: 'postgres',
|
||||
database: 'postgres', // pre-existing default database
|
||||
host,
|
||||
port,
|
||||
username,
|
||||
password,
|
||||
schema,
|
||||
} as const;
|
||||
};
|
||||
|
||||
export const getPostgresOptions = ({ name }: { name: string }): ConnectionOptions => {
|
||||
const username = config.getEnv('database.postgresdb.user');
|
||||
const password = config.getEnv('database.postgresdb.password');
|
||||
const host = config.getEnv('database.postgresdb.host');
|
||||
const port = config.getEnv('database.postgresdb.port');
|
||||
const schema = config.getEnv('database.postgresdb.schema');
|
||||
|
||||
return {
|
||||
name,
|
||||
type: 'postgres',
|
||||
database: name,
|
||||
host,
|
||||
port,
|
||||
username,
|
||||
password,
|
||||
entityPrefix: '',
|
||||
schema,
|
||||
dropSchema: true,
|
||||
migrations: postgresMigrations,
|
||||
migrationsRun: true,
|
||||
migrationsTableName: 'migrations',
|
||||
entities: Object.values(entities),
|
||||
synchronize: false,
|
||||
logging: false,
|
||||
};
|
||||
};
|
||||
const baseOptions = (type: TestDBType) => ({
|
||||
host: config.getEnv(`database.${type}db.host`),
|
||||
port: config.getEnv(`database.${type}db.port`),
|
||||
username: config.getEnv(`database.${type}db.user`),
|
||||
password: config.getEnv(`database.${type}db.password`),
|
||||
schema: type === 'postgres' ? config.getEnv(`database.postgresdb.schema`) : undefined,
|
||||
});
|
||||
|
||||
/**
|
||||
* Generate options for a bootstrap MySQL connection,
|
||||
* to create and drop test MySQL databases.
|
||||
* Generate options for a bootstrap DB connection, to create and drop test databases.
|
||||
*/
|
||||
export const getBootstrapMySqlOptions = (): ConnectionOptions => {
|
||||
const username = config.getEnv('database.mysqldb.user');
|
||||
const password = config.getEnv('database.mysqldb.password');
|
||||
const host = config.getEnv('database.mysqldb.host');
|
||||
const port = config.getEnv('database.mysqldb.port');
|
||||
export const getBootstrapDBOptions = (type: TestDBType) =>
|
||||
({
|
||||
type,
|
||||
name: type,
|
||||
database: type,
|
||||
...baseOptions(type),
|
||||
} as const);
|
||||
|
||||
return {
|
||||
name: BOOTSTRAP_MYSQL_CONNECTION_NAME,
|
||||
database: BOOTSTRAP_MYSQL_CONNECTION_NAME,
|
||||
type: 'mysql',
|
||||
host,
|
||||
port,
|
||||
username,
|
||||
password,
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* Generate options for a MySQL database connection,
|
||||
* one per test suite run.
|
||||
*/
|
||||
export const getMySqlOptions = ({ name }: { name: string }): ConnectionOptions => {
|
||||
const username = config.getEnv('database.mysqldb.user');
|
||||
const password = config.getEnv('database.mysqldb.password');
|
||||
const host = config.getEnv('database.mysqldb.host');
|
||||
const port = config.getEnv('database.mysqldb.port');
|
||||
|
||||
return {
|
||||
name,
|
||||
database: name,
|
||||
type: 'mysql',
|
||||
host,
|
||||
port,
|
||||
username,
|
||||
password,
|
||||
migrations: mysqlMigrations,
|
||||
migrationsTableName: 'migrations',
|
||||
migrationsRun: true,
|
||||
};
|
||||
};
|
||||
const getDBOptions = (type: TestDBType, name: string) => ({
|
||||
type,
|
||||
name,
|
||||
database: name,
|
||||
...baseOptions(type),
|
||||
dropSchema: true,
|
||||
migrations: type === 'postgres' ? postgresMigrations : mysqlMigrations,
|
||||
migrationsRun: true,
|
||||
migrationsTableName: 'migrations',
|
||||
entities: Object.values(entities),
|
||||
synchronize: false,
|
||||
logging: false,
|
||||
});
|
||||
|
||||
// ----------------------------------
|
||||
// encryption
|
||||
|
||||
Reference in New Issue
Block a user